问:
Storing custom objects with Core Data
I'm trying to store a NSMutableArray consisting of VOs (NameVO) with Core Data but getting the following exception thrown:

```<code>'NSInvalidArgumentException', reason: '-[NameVO encodeWithCoder:]: unrecognized selector sent to instance 0x1096400a0'
</code>```

My NameVO is just a simple value object, extending NSObject and contains two fields, a string and a NSMutableArray that itself contains strings. It also contains a compare function.

I'm trying to prepare this to be stored as a CD transformable attribute type with ('names' is my NameVO array):

```<code>NSData *tempNamesData = [NSKeyedArchiver archivedDataWithRootObject:names];
</code>```

My question is: what do I need to do to make NameVO be accepted by NSKeyedArchiver to convert it successfully to a NSData?

I don't want NameVO to extend NSManagedObject because then I cannot instantiate and init it directly.

答:
Now that we're in 2017, it's best to use the safer NSSecureCoding protocol instead of the older, less safe NSCoding protocol. The implementation changes are minimal:

1) ensure that your class declares its conformation to NSSecureCoding

```<code>@interface MyClass : NSObject<NSSecureCoding>

@property (nonatomic, strong) NSNumber *numberProperty;
@property (nonatomic, strong) NSString *stringProperty;

@end
</code>```

2) NSSecureCoding protocol houses the same two instance methods methods in the NSCoding protocol, plus an additional class method, +supportsSecureCoding. You'll need to add that method, as well as slightly modify your -initWithCoder: method.

```<code>@implementation MyClass

// New Method for NSSecureCoding. Return YES.
+ (BOOL)supportsSecureCoding {

    return YES;

}

// Your Encode Method Can Stay The Same, though I would use NSStringFromSelector whenever possible to get the keys to ensure you're always getting what you're looking for.

- (void)encodeWithCoder:(NSCoder *)aCoder {

    [aCoder encodeObject:self.numberProperty forKey:NSStringFromSelector(@selector(numberProperty))];
    [aCoder encodeObject:self.stringProperty forKey:NSStringFromSelector(@selector(stringProperty))];

}

// Slightly updated decode option

- (instancetype)initWithCoder:(NSCoder *)aDecoder {

    self = [super init];

    if (self) {

        self.numberProperty = [aDecoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(numberProperty))];
        self.stringProperty = [aDecoder decodeObjectOfClass:[NSString class] forKey:NSStringFromSelector(@selector(stringProperty))];

    }

}

@end
</code>```

Notice that NSCoder's -decodeObjectOfClass:withKey: requires you to specify the class that you're expecting to receive. This is a much safer way to do things.

Then, to store this decodable object in CoreData, simply create a Managed object that contains an NSData attribute and some identifying information (a string, a date, an id, or a number or something)

```<code>@interface MyClassMO : NSManagedObject

@property (nonatomic, strong) NSString *identifier;
@property (nonatomic, strong) NSData *data;

@end

@implementation MyClassMO

@dynamic identifier;
@dynamic data;

@end
</code>```

In practice, it would look something like this:

```<code>- (void)storeObject:(MyClass *)object withIdentifier:(NSString *)identifier {

    NSData *objectData = [NSKeyedArchived archivedDataWithRootObject:object];

    NSManagedObjectContext *moc = ... // retrieve your context

    // this implementation relies on new NSManagedObject initializers in the iOS 10 SDK, but you can create it any way you typically create managed objects
    MyClassMO *managedObject = [[MyClassMO alloc] initWithContext:moc];

    managedObject.data = objectData;
    managedObject.identifier = identifier;

    NSError *error;

    [moc save:&error];

}

- (MyClass *)retrieveObjectWithIdentifier(NSString *)identifier {

    NSManagedObject *moc = ... // retrieve your context

    // This also relies on iOS 10 SDK's new factory methods available on NSManagedObject. You can create your request any way you typically do;
    NSFetchRequest *request = [MyClassMO fetchRequest];

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"identifier = %@", identifier];

    request.predicate = predicate;

    NSError *error;

    NSArray<MyClassMO *> *results = [moc executeFetchRequest:request withError:&error];

    // if you're only storing one object per identifier, this array should only be 1 object long. if not, you'll need to decide which object you're looking for. you also might want to implement an overwrite policy or a delete before store type thing.

    MyClassMO *managedObject = results.firstObject;

    NSData *objectData = managedObject.data;

    MyClass *object = [NSKeyedUnarchiver unarchiveObject:objectData];

    return object;

}
</code>```

This solution is obviously a bit of an oversimplification, how and when you store stuff in the db is up to your needs, but the main idea is that, you'll need to make sure your custom class conforms to NSSecureCoding, and that you'll need to make a separate Managed Object class to store and retrieve your data.

Title: Storing custom objects with Core Data

Body:
I'm trying to store a NSMutableArray consisting of VOs (NameVO) with Core Data but getting the following exception thrown:

'NSInvalidArgumentException', reason: '-[NameVO encodeWithCoder:]: unrecognized selector sent to instance 0x1096400a0'

My NameVO is just a simple value object, extending NSObject and contains two fields, a string and a NSMutableArray that itself contains strings. It also contains a compare function.

I'm trying to prepare this to be stored as a CD transformable attribute type with ('names' is my NameVO array):

NSData *tempNamesData = [NSKeyedArchiver archivedDataWithRootObject:names];

My question is: what do I need to do to make NameVO be accepted by NSKeyedArchiver to convert it successfully to a NSData?

I don't want NameVO to extend NSManagedObject because then I cannot instantiate and init it directly.

Body:
Now that we're in 2017, it's best to use the safer NSSecureCoding protocol instead of the older, less safe NSCoding protocol. The implementation changes are minimal:

1) ensure that your class declares its conformation to NSSecureCoding

@interface MyClass : NSObject<NSSecureCoding>

@property (nonatomic, strong) NSNumber *numberProperty;
@property (nonatomic, strong) NSString *stringProperty;

@end

2) NSSecureCoding protocol houses the same two instance methods methods in the NSCoding protocol, plus an additional class method, +supportsSecureCoding. You'll need to add that method, as well as slightly modify your -initWithCoder: method.

@implementation MyClass

// New Method for NSSecureCoding. Return YES.
+ (BOOL)supportsSecureCoding {

    return YES;

}

// Your Encode Method Can Stay The Same, though I would use NSStringFromSelector whenever possible to get the keys to ensure you're always getting what you're looking for.

- (void)encodeWithCoder:(NSCoder *)aCoder {

    [aCoder encodeObject:self.numberProperty forKey:NSStringFromSelector(@selector(numberProperty))];
    [aCoder encodeObject:self.stringProperty forKey:NSStringFromSelector(@selector(stringProperty))];

}

// Slightly updated decode option

- (instancetype)initWithCoder:(NSCoder *)aDecoder {

    self = [super init];

    if (self) {

        self.numberProperty = [aDecoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(numberProperty))];
        self.stringProperty = [aDecoder decodeObjectOfClass:[NSString class] forKey:NSStringFromSelector(@selector(stringProperty))];

    }

}

@end

Notice that NSCoder's -decodeObjectOfClass:withKey: requires you to specify the class that you're expecting to receive. This is a much safer way to do things.

Then, to store this decodable object in CoreData, simply create a Managed object that contains an NSData attribute and some identifying information (a string, a date, an id, or a number or something)

@interface MyClassMO : NSManagedObject

@property (nonatomic, strong) NSString *identifier;
@property (nonatomic, strong) NSData *data;

@end

@implementation MyClassMO

@dynamic identifier;
@dynamic data;

@end

In practice, it would look something like this:

- (void)storeObject:(MyClass *)object withIdentifier:(NSString *)identifier {

    NSData *objectData = [NSKeyedArchived archivedDataWithRootObject:object];

    NSManagedObjectContext *moc = ... // retrieve your context

    // this implementation relies on new NSManagedObject initializers in the iOS 10 SDK, but you can create it any way you typically create managed objects
    MyClassMO *managedObject = [[MyClassMO alloc] initWithContext:moc];

    managedObject.data = objectData;
    managedObject.identifier = identifier;

    NSError *error;

    [moc save:&error];

}

- (MyClass *)retrieveObjectWithIdentifier(NSString *)identifier {

    NSManagedObject *moc = ... // retrieve your context

    // This also relies on iOS 10 SDK's new factory methods available on NSManagedObject. You can create your request any way you typically do;
    NSFetchRequest *request = [MyClassMO fetchRequest];

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"identifier = %@", identifier];

    request.predicate = predicate;

    NSError *error;

    NSArray<MyClassMO *> *results = [moc executeFetchRequest:request withError:&error];

    // if you're only storing one object per identifier, this array should only be 1 object long. if not, you'll need to decide which object you're looking for. you also might want to implement an overwrite policy or a delete before store type thing.

    MyClassMO *managedObject = results.firstObject;

    NSData *objectData = managedObject.data;

    MyClass *object = [NSKeyedUnarchiver unarchiveObject:objectData];

    return object;

}

This solution is obviously a bit of an oversimplification, how and when you store stuff in the db is up to your needs, but the main idea is that, you'll need to make sure your custom class conforms to NSSecureCoding, and that you'll need to make a separate Managed Object class to store and retrieve your data.


来源: stackexchange

问:
Android: CollapsingToolbarLayout with ImageView Toolbar background
I would like to implement a CollapsingToolbarLayout like this:

The challenge here is that I need to have a custom Toolbar with a gif as background and therefore I need an ImageView as background for the Toolbar. You can see my implementation in the following xml:

```<code><?xml version="1.0" encoding="utf-8"?>
</code>```

```<code><android.support.design.widget.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:fitsSystemWindows="true"
    android:background="@color/colorAccent"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

    <android.support.design.widget.CollapsingToolbarLayout
        android:id="@+id/htab_collapse_toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true"
        app:contentScrim="@color/colorAccent"
        app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

        <!-- Container which should be scrolled parallax and contains the image gallery -->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:fitsSystemWindows="true"
            app:layout_collapseMode="parallax">

            <RelativeLayout
                android:id="@+id/image_layer"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">

                <android.support.v4.view.ViewPager
                    android:id="@+id/image_gallery"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="@color/colorAccent"
                    android:layout_marginTop="?attr/actionBarSize"/>

                <LinearLayout
                    android:id="@+id/image_indicators"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal"
                    android:padding="@dimen/defaultPadding"
                    android:gravity="center"
                    android:layout_alignParentBottom="true"/>
            </RelativeLayout>
        </LinearLayout>

        <!-- Container which contains the background for the toolbar and the toolbar itself  -->
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:layout_collapseMode="pin">

            <ImageView
                android:id="@+id/toolbar_background"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:scaleType="centerCrop"
                android:layout_gravity="top"
                android:background="@color/colorPrimaryLight"/>

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize">

                <de.views.CustomTextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textAllCaps="true"
                    android:textColor="#FF0000"
                    android:textStyle="bold"
                    android:gravity="center"
                    android:maxLines="1"
                    android:ellipsize="end"
                    android:layout_gravity="center"
                    android:id="@+id/toolbar_title"
                    tools:text="Restauranttitel"/>
            </android.support.v7.widget.Toolbar>
        </RelativeLayout>

        <!-- Tablayout -->
        <android.support.design.widget.TabLayout
            android:id="@+id/tab_layout"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:layout_gravity="bottom"
            app:tabBackground="@drawable/selected_tab_background"
            app:tabIndicatorColor="@android:color/transparent"
            app:tabGravity="fill"
            app:tabMode="fixed"
            app:tabMaxWidth="2000dp"/> <!-- we need to set this value to a very big value so that a single tab gets displayed over the full width too -->

    </android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>

<FrameLayout
    android:id="@+id/activity_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</code>```

With this implementation the whole view is scrolling and neither the Toolbar nor the TabLayout gets pinned to the top of the screen.

I've worked through lots of tutorials and stackoverflow answers, f.e.

https://antonioleiva.com/collapsing-toolbar-layout/

http://blog.iamsuleiman.com/parallax-scrolling-tabs-design-support-library/

They all gave nice explanations on how to work with CollapsingToolbarLayout. I think the problem of my implementation is the RelativeLayout containing the ImageView and the Toolbar. When removing the RelativeLayout and the ImageView and set the collapseMode of Toolbar to 'pin' everything worked as expected and both the Toolbar and Tablayout gets pinned at the top of the screen if the user is scrolling. But unfortunately I need to have the ImageView above the toolbar to be able to load a GIF as Toolbar background.

Maybe one of you got an awesome idea on how to solve this issue. Or you've another idea how I can achieve the desired behaviour? Please let me know :)

Update: I've created an example project (https://drive.google.com/open?id=0B1aHkcAaWIA-dHBTZnUyeUt3eTQ) with which you can reproduce the wrong scroll behaviour.

答:
#. Here I used CollapsingToolbarLayout height as 300dp which is the sum of  Toolbar, ImageSlider and TabLayout height. Used app:titleEnabled="false" to hide CollapsingToolbar title.

#. Inside CollapsingToolbarLayout, added RelativeLayout as a container of ViewPager(images) and LinearLayout(indicator). Added attribute android:layout_marginTop="?attr/actionBarSize" to place it below ToolBar and
added app:layout_collapseMode="parallax" to show parallax effect during scroll.

#. Below RelativeLayout, added an ImageView to show GIF image on it. Added attribute android:layout_height="?attr/actionBarSize" to make its height as Toolbar height. Added attribute app:layout_collapseMode="pin" to keep the ImageView fixed at top and visible before or after scroll.

#. Added Toolbar below ImageView to show Toolbar over ImageView. As I did not set any background color to Toolbar, it will work as transparent. Like ImageView, added app:layout_collapseMode="pin" to Toolbar to pin it always at top. Added attribute android:layout_height="104dp", to show Tablayout below Toolbar during collapsed state. Here 104dp is Toolbar height(56dp ) + Tablayout height(48dp).

#. Finally added TabLayout below Toolbar and added attribute android:layout_gravity="bottom" to show it at the bottom of CollapsingToolbarLayout.

Here is the simplified working XML:

```<code><?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/coordinator_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/htab_collapse_toolbar"
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:fitsSystemWindows="true"
            app:titleEnabled="false"
            app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

            <!-- Image slider container -->
            <RelativeLayout
                android:id="@+id/image_layer"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_marginTop="?attr/actionBarSize"
                app:layout_collapseMode="parallax">

                <!-- ViewPager -->
                <android.support.v4.view.ViewPager
                    android:id="@+id/image_gallery"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"/>

                <!-- Pager Indicator Container -->
                <LinearLayout
                    android:id="@+id/image_indicators"
                    android:layout_width="100dp"
                    android:layout_height="wrap_content"
                    android:layout_alignParentBottom="true"
                    android:layout_centerHorizontal="true"
                    android:layout_marginBottom="56dp"
                    android:orientation="horizontal"
                    android:padding="8dp"
                    android:gravity="center"
                    android:background="@color/black"/>
            </RelativeLayout>

            <!-- Toolbar background  :: GIF -->
            <ImageView
                android:id="@+id/toolbar_background"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:scaleType="centerCrop"
                app:layout_collapseMode="pin"
                android:src="@drawable/dummy"/>

            <!-- Toolbar -->
            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="104dp"
                android:minHeight="?attr/actionBarSize"
                app:layout_collapseMode="pin">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textAllCaps="true"
                    android:textColor="#000"
                    android:textStyle="bold"
                    android:gravity="center"
                    android:maxLines="1"
                    android:ellipsize="end"
                    android:layout_gravity="top"
                    android:id="@+id/toolbar_title"
                    android:text="Restaurant Title"/>
            </android.support.v7.widget.Toolbar>

            <!-- TabLayout -->
            <android.support.design.widget.TabLayout
                android:id="@+id/tab_layout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="bottom"
                app:tabBackground="@android:color/holo_red_dark"
                app:tabIndicatorColor="@android:color/transparent"
                app:tabGravity="fill"
                app:tabMode="fixed"
                app:tabMaxWidth="2000dp"/>
        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>

    <!-- Container for TAB'S Fragments -->
    <android.support.v4.view.ViewPager
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</android.support.design.widget.CoordinatorLayout>
</code>```

OUTPUT:

FYI, as you are using custom Toolbar with TextView, you have to hide default title of ActionBar. To do this use below codes in your Activity:

```<code>    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    getSupportActionBar().setTitle("");
</code>```

Hope this will help~

ContentLicense: CC BY-SA 3.0

Body:
I would like to implement a CollapsingToolbarLayout like this:

The challenge here is that I need to have a custom Toolbar with a gif as background and therefore I need an ImageView as background for the Toolbar. You can see my implementation in the following xml:

<?xml version="1.0" encoding="utf-8"?>

<android.support.design.widget.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:fitsSystemWindows="true"
    android:background="@color/colorAccent"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

    <android.support.design.widget.CollapsingToolbarLayout
        android:id="@+id/htab_collapse_toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true"
        app:contentScrim="@color/colorAccent"
        app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:fitsSystemWindows="true"
            app:layout_collapseMode="parallax">

            <RelativeLayout
                android:id="@+id/image_layer"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">

                <android.support.v4.view.ViewPager
                    android:id="@+id/image_gallery"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="@color/colorAccent"
                    android:layout_marginTop="?attr/actionBarSize"/>

                <LinearLayout
                    android:id="@+id/image_indicators"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal"
                    android:padding="@dimen/defaultPadding"
                    android:gravity="center"
                    android:layout_alignParentBottom="true"/>
            </RelativeLayout>
        </LinearLayout>

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:layout_collapseMode="pin">

            <ImageView
                android:id="@+id/toolbar_background"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:scaleType="centerCrop"
                android:layout_gravity="top"
                android:background="@color/colorPrimaryLight"/>

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize">

                <de.views.CustomTextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textAllCaps="true"
                    android:textColor="#FF0000"
                    android:textStyle="bold"
                    android:gravity="center"
                    android:maxLines="1"
                    android:ellipsize="end"
                    android:layout_gravity="center"
                    android:id="@+id/toolbar_title"
                    tools:text="Restauranttitel"/>
            </android.support.v7.widget.Toolbar>
        </RelativeLayout>

        <android.support.design.widget.TabLayout
            android:id="@+id/tab_layout"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:layout_gravity="bottom"
            app:tabBackground="@drawable/selected_tab_background"
            app:tabIndicatorColor="@android:color/transparent"
            app:tabGravity="fill"
            app:tabMode="fixed"
            app:tabMaxWidth="2000dp"/>

    </android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>

<FrameLayout
    android:id="@+id/activity_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

With this implementation the whole view is scrolling and neither the Toolbar nor the TabLayout gets pinned to the top of the screen.

I've worked through lots of tutorials and stackoverflow answers, f.e.

https://antonioleiva.com/collapsing-toolbar-layout/

http://blog.iamsuleiman.com/parallax-scrolling-tabs-design-support-library/

They all gave nice explanations on how to work with CollapsingToolbarLayout. I think the problem of my implementation is the RelativeLayout containing the ImageView and the Toolbar. When removing the RelativeLayout and the ImageView and set the collapseMode of Toolbar to 'pin' everything worked as expected and both the Toolbar and Tablayout gets pinned at the top of the screen if the user is scrolling. But unfortunately I need to have the ImageView above the toolbar to be able to load a GIF as Toolbar background.

Maybe one of you got an awesome idea on how to solve this issue. Or you've another idea how I can achieve the desired behaviour? Please let me know :)

Update: I've created an example project (https://drive.google.com/open?id=0B1aHkcAaWIA-dHBTZnUyeUt3eTQ) with which you can reproduce the wrong scroll behaviour.

Body:
#. Here I used CollapsingToolbarLayout height as 300dp which is the sum of  Toolbar, ImageSlider and TabLayout height. Used app:titleEnabled="false" to hide CollapsingToolbar title.

#. Inside CollapsingToolbarLayout, added RelativeLayout as a container of ViewPager(images) and LinearLayout(indicator). Added attribute android:layout_marginTop="?attr/actionBarSize" to place it below ToolBar and
added app:layout_collapseMode="parallax" to show parallax effect during scroll.

#. Below RelativeLayout, added an ImageView to show GIF image on it. Added attribute android:layout_height="?attr/actionBarSize" to make its height as Toolbar height. Added attribute app:layout_collapseMode="pin" to keep the ImageView fixed at top and visible before or after scroll.

#. Added Toolbar below ImageView to show Toolbar over ImageView. As I did not set any background color to Toolbar, it will work as transparent. Like ImageView, added app:layout_collapseMode="pin" to Toolbar to pin it always at top. Added attribute android:layout_height="104dp", to show Tablayout below Toolbar during collapsed state. Here 104dp is Toolbar height(56dp ) + Tablayout height(48dp).

#. Finally added TabLayout below Toolbar and added attribute android:layout_gravity="bottom" to show it at the bottom of CollapsingToolbarLayout.

Here is the simplified working XML:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/coordinator_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/htab_collapse_toolbar"
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:fitsSystemWindows="true"
            app:titleEnabled="false"
            app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

            <!-- Image slider container -->
            <RelativeLayout
                android:id="@+id/image_layer"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_marginTop="?attr/actionBarSize"
                app:layout_collapseMode="parallax">

                <!-- ViewPager -->
                <android.support.v4.view.ViewPager
                    android:id="@+id/image_gallery"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"/>

                <!-- Pager Indicator Container -->
                <LinearLayout
                    android:id="@+id/image_indicators"
                    android:layout_width="100dp"
                    android:layout_height="wrap_content"
                    android:layout_alignParentBottom="true"
                    android:layout_centerHorizontal="true"
                    android:layout_marginBottom="56dp"
                    android:orientation="horizontal"
                    android:padding="8dp"
                    android:gravity="center"
                    android:background="@color/black"/>
            </RelativeLayout>

            <!-- Toolbar background  :: GIF -->
            <ImageView
                android:id="@+id/toolbar_background"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:scaleType="centerCrop"
                app:layout_collapseMode="pin"
                android:src="@drawable/dummy"/>

            <!-- Toolbar -->
            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="104dp"
                android:minHeight="?attr/actionBarSize"
                app:layout_collapseMode="pin">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textAllCaps="true"
                    android:textColor="#000"
                    android:textStyle="bold"
                    android:gravity="center"
                    android:maxLines="1"
                    android:ellipsize="end"
                    android:layout_gravity="top"
                    android:id="@+id/toolbar_title"
                    android:text="Restaurant Title"/>
            </android.support.v7.widget.Toolbar>

            <!-- TabLayout -->
            <android.support.design.widget.TabLayout
                android:id="@+id/tab_layout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="bottom"
                app:tabBackground="@android:color/holo_red_dark"
                app:tabIndicatorColor="@android:color/transparent"
                app:tabGravity="fill"
                app:tabMode="fixed"
                app:tabMaxWidth="2000dp"/>
        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>

    <!-- Container for TAB'S Fragments -->
    <android.support.v4.view.ViewPager
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</android.support.design.widget.CoordinatorLayout>

OUTPUT:

FYI, as you are using custom Toolbar with TextView, you have to hide default title of ActionBar. To do this use below codes in your Activity:

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    getSupportActionBar().setTitle("");

Hope this will help~

ContentLicense: CC BY-SA 4.0


问:
Use of def, val, and var in scala
```<code>class Person(val name:String,var age:Int )
def person = new Person("Kumar",12)
person.age = 20
println(person.age)
</code>```

These lines of code outputs 12, even though person.age=20 was successfully executed. I found that this happens because I used def in def person = new Person("Kumar",12). If I use var or val the output is 20. I understand the default is val in scala. This:

```<code>def age = 30
age = 45
</code>```

...gives a compilation error because it is a val by default. Why do the first set of lines above not work properly, and yet also don't error?

答:
With

```<code>def person = new Person("Kumar", 12)
</code>```

you are defining a function/lazy variable which always returns a new Person instance with name "Kumar" and age 12. This is totally valid and the compiler has no reason to complain. Calling person.age will return the age of this newly created Person instance, which is always 12.

When writing

```<code>person.age = 45
</code>```

you assign a new value to the age property in class Person, which is valid since age is declared as var. The compiler will complain if you try to reassign person with a new Person object like

```<code>person = new Person("Steve", 13)  // Error
</code>```

Title: Use of def, val, and var in scala

Body:
class Person(val name:String,var age:Int )
def person = new Person("Kumar",12)
person.age = 20
println(person.age)

These lines of code outputs 12, even though person.age=20 was successfully executed. I found that this happens because I used def in def person = new Person("Kumar",12). If I use var or val the output is 20. I understand the default is val in scala. This:

def age = 30
age = 45

...gives a compilation error because it is a val by default. Why do the first set of lines above not work properly, and yet also don't error?

Body:
With

def person = new Person("Kumar", 12)

you are defining a function/lazy variable which always returns a new Person instance with name "Kumar" and age 12. This is totally valid and the compiler has no reason to complain. Calling person.age will return the age of this newly created Person instance, which is always 12.

When writing

person.age = 45

you assign a new value to the age property in class Person, which is valid since age is declared as var. The compiler will complain if you try to reassign person with a new Person object like

person = new Person("Steve", 13)  // Error

ContentLicense: CC BY-SA 2.5


问:
Where could I download libjingle_peerconnection.jar source code
I'm experimenting with WebRTC from Android, so far using libjingle from this repo had made me successfully creates a native android app that broadcast a WebRTC video to my webapp rendered in browser (check my project here), or the other way around (check my project here)

But now I want to make some changes or maybe extend some functions to enable me to render MediaStream into android default VideoView. So I look for this library's source code in their repo but I couldn't find it (the source jars are all empty).

Does anybody knows where to acquire it?

Thanks

答:
It looks you are using years old libjingle repo.
Follow the official WebRTC build instructions for Android to build latest code base.

You need a Ubuntu OS to build the WebRTC jar/aar for android.

Generating gradle to build the demo app in AndroidStudio:

```<code>build/android/gradle/generate_gradle.py --output-directory $PWD/out/Debug --target "//webrtc/examples:AppRTCMobile" --use-gradle-process-resources --split-projects
</code>```

Generating WebRTC Framework to link in any other native App:

```<code>./tools_webrtc/android/build_aar.py
</code>```

This command will generate libwebrtc.aar, it will contain all the dependent(.jar/.so) files. Just import this .aar into your existing App.

You may need to change your app code, to make compatible with latest WebRTC API's.

  See Demo & API source.

Then you can play with VideoRender & SurfaceViewRenderer

Body:
It looks you are using years old libjingle repo.
Follow the official WebRTC build instructions for Android to build latest code base.

You need a Ubuntu OS to build the WebRTC jar/aar for android.

Generating gradle to build the demo app in AndroidStudio:

build/android/gradle/generate_gradle.py --output-directory $PWD/out/Debug --target "//webrtc/examples:AppRTCMobile" --use-gradle-process-resources --split-projects

Generating WebRTC Framework to link in any other native App:

./tools_webrtc/android/build_aar.py

This command will generate libwebrtc.aar, it will contain all the dependent(.jar/.so) files. Just import this .aar into your existing App.

You may need to change your app code, to make compatible with latest WebRTC API's.

  See Demo & API source.

Then you can play with VideoRender & SurfaceViewRenderer


问:
How to make slant lines for rows in html

I want to know how to add slant row starting and ending in HTML and css.

答:
The element you are looking for is called slopy elements. Here's a nice snippet from tympanus.net

.se-container {
  display: block;
  width: 100%;
  overflow: hidden;
  padding-top: 150px;
}

.se-slope {
  margin: 0 -50px;
  -webkit-transform-origin: left center;
  -moz-transform-origin: left center;
  -o-transform-origin: left center;
  -ms-transform-origin: left center;
  transform-origin: left center;
}

.se-slope:nth-child(odd) {
  background: #000;
  -webkit-transform: rotate(5deg);
  -moz-transform: rotate(5deg);
  -o-transform: rotate(5deg);
  -ms-transform: rotate(5deg);
  transform: rotate(5deg);
  margin-top: -200px;
  box-shadow: 0px -1px 3px rgba(0, 0, 0, 0.4);
}

.se-slope:nth-child(even) {
  background: #e90089;
  -webkit-transform: rotate(-5deg);
  -moz-transform: rotate(-5deg);
  -o-transform: rotate(-5deg);
  -ms-transform: rotate(-5deg);
  transform: rotate(-5deg);
  box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.4) inset;
}

.se-content {
  margin: 0 auto;
}

.se-content h3 {
  font-size: 60px;
  position: relative;
  display: inline-block;
  padding: 10px 30px 8px 30px;
  height: 80px;
  background: #000;
  line-height: 80px;
  margin-bottom: 20px;
  font-family: 'Bitter', 'Trebuchet MS', Arial;
  text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.9);
}

.se-content h3:before {
  content: '';
  width: 0;
  height: 0;
  border-top: 38px solid transparent;
  border-bottom: 60px solid transparent;
  border-right: 60px solid black;
  position: absolute;
  left: -59px;
  top: 0px;
}

.se-content h3:after {
  content: '';
  width: 0;
  height: 0;
  border-top: 38px solid transparent;
  border-bottom: 60px solid transparent;
  border-left: 60px solid black;
  position: absolute;
  right: -59px;
  top: 0px;
}

.se-slope:nth-child(odd) .se-content h3:before,
.se-slope:nth-child(odd) .se-content h3:after {
  border-right-color: #e90089;
  border-left-color: #e90089;
}

.se-content p {
  width: 75%;
  max-width: 500px;
  margin: 0 auto;
  font-style: italic;
  font-size: 18px;
  line-height: 24px;
  padding-top: 10px;
}

.se-content p:first-letter {
  font-size: 40px;
  font-family: 'Adobe Garamond Pro', Garamond, Palatino, 'Palatino Linotype', Times, 'Times New Roman', Georgia, serif;
}

.se-slope:nth-child(odd) .se-content {
  -webkit-transform: rotate(-5deg);
  -moz-transform: rotate(-5deg);
  -o-transform: rotate(-5deg);
  -ms-transform: rotate(-5deg);
  transform: rotate(-5deg);
  color: #e90089;
  padding: 130px 100px 250px 100px;
}

.se-slope:nth-child(even) .se-content {
  -webkit-transform: rotate(5deg);
  -moz-transform: rotate(5deg);
  -o-transform: rotate(5deg);
  -ms-transform: rotate(5deg);
  transform: rotate(5deg);
  color: #000;
  padding: 150px 100px 250px 100px;
}

.se-slope:nth-child(odd) .se-content h3 {
  background: #e90089;
  color: #000;
}

.se-slope:nth-child(even) .se-content h3 {
  background: #000;
  color: #e90089;
}

/* Media Queries */

@media screen and (max-width: 1010px) {
  .se-content h3 {
    font-size: 40px;
  }
}

@media screen and (max-width: 767px) {
  .se-content h3 {
    font-size: 20px;
  }
}

@media screen and (max-width: 400px) {
  .se-content h3 {
    font-size: 20px;
    line-height: 20px;
    padding-top: 30px;
    height: 60px;
  }
  .se-content p {
    width: 95%;
  }
  .se-slope:nth-child(odd) .se-content,
  .se-slope:nth-child(even) .se-content {
    padding-left: 60px;
    padding-right: 60px;
  }
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><div class="container">

  <section class="se-container">
    <div class="se-slope">
      <article class="se-content">
        <h3>Section 1</h3>
        <p>LOL LOL LOL LOL
        </p>
      </article>
    </div>
    <div class="se-slope">
      <article class="se-content">
        <h3>Section 2</h3>
        <p>LOL LOL LOL LOL </p>
      </article>
    </div>
    <div class="se-slope">
      <article class="se-content">
        <h3>Section 3</h3>
        <p>LOL LOL LOL LOL </p>
      </article>
    </div>
    <div class="se-slope">
      <article class="se-content">
        <h3>Section 2</h3>
        <p>LOL LOL LOL LOL</p>
      </article>
    </div>

  </section>
</div></code>```

Body:
The element you are looking for is called slopy elements. Here's a nice snippet from tympanus.net

.se-container {
  display: block;
  width: 100%;
  overflow: hidden;
  padding-top: 150px;
}

.se-slope {
  margin: 0 -50px;
  -webkit-transform-origin: left center;
  -moz-transform-origin: left center;
  -o-transform-origin: left center;
  -ms-transform-origin: left center;
  transform-origin: left center;
}

.se-slope:nth-child(odd) {
  background: #000;
  -webkit-transform: rotate(5deg);
  -moz-transform: rotate(5deg);
  -o-transform: rotate(5deg);
  -ms-transform: rotate(5deg);
  transform: rotate(5deg);
  margin-top: -200px;
  box-shadow: 0px -1px 3px rgba(0, 0, 0, 0.4);
}

.se-slope:nth-child(even) {
  background: #e90089;
  -webkit-transform: rotate(-5deg);
  -moz-transform: rotate(-5deg);
  -o-transform: rotate(-5deg);
  -ms-transform: rotate(-5deg);
  transform: rotate(-5deg);
  box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.4) inset;
}

.se-content {
  margin: 0 auto;
}

.se-content h3 {
  font-size: 60px;
  position: relative;
  display: inline-block;
  padding: 10px 30px 8px 30px;
  height: 80px;
  background: #000;
  line-height: 80px;
  margin-bottom: 20px;
  font-family: 'Bitter', 'Trebuchet MS', Arial;
  text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.9);
}

.se-content h3:before {
  content: '';
  width: 0;
  height: 0;
  border-top: 38px solid transparent;
  border-bottom: 60px solid transparent;
  border-right: 60px solid black;
  position: absolute;
  left: -59px;
  top: 0px;
}

.se-content h3:after {
  content: '';
  width: 0;
  height: 0;
  border-top: 38px solid transparent;
  border-bottom: 60px solid transparent;
  border-left: 60px solid black;
  position: absolute;
  right: -59px;
  top: 0px;
}

.se-slope:nth-child(odd) .se-content h3:before,
.se-slope:nth-child(odd) .se-content h3:after {
  border-right-color: #e90089;
  border-left-color: #e90089;
}

.se-content p {
  width: 75%;
  max-width: 500px;
  margin: 0 auto;
  font-style: italic;
  font-size: 18px;
  line-height: 24px;
  padding-top: 10px;
}

.se-content p:first-letter {
  font-size: 40px;
  font-family: 'Adobe Garamond Pro', Garamond, Palatino, 'Palatino Linotype', Times, 'Times New Roman', Georgia, serif;
}

.se-slope:nth-child(odd) .se-content {
  -webkit-transform: rotate(-5deg);
  -moz-transform: rotate(-5deg);
  -o-transform: rotate(-5deg);
  -ms-transform: rotate(-5deg);
  transform: rotate(-5deg);
  color: #e90089;
  padding: 130px 100px 250px 100px;
}

.se-slope:nth-child(even) .se-content {
  -webkit-transform: rotate(5deg);
  -moz-transform: rotate(5deg);
  -o-transform: rotate(5deg);
  -ms-transform: rotate(5deg);
  transform: rotate(5deg);
  color: #000;
  padding: 150px 100px 250px 100px;
}

.se-slope:nth-child(odd) .se-content h3 {
  background: #e90089;
  color: #000;
}

.se-slope:nth-child(even) .se-content h3 {
  background: #000;
  color: #e90089;
}

/* Media Queries */

@media screen and (max-width: 1010px) {
  .se-content h3 {
    font-size: 40px;
  }
}

@media screen and (max-width: 767px) {
  .se-content h3 {
    font-size: 20px;
  }
}

@media screen and (max-width: 400px) {
  .se-content h3 {
    font-size: 20px;
    line-height: 20px;
    padding-top: 30px;
    height: 60px;
  }
  .se-content p {
    width: 95%;
  }
  .se-slope:nth-child(odd) .se-content,
  .se-slope:nth-child(even) .se-content {
    padding-left: 60px;
    padding-right: 60px;
  }
}

<div class="container">

  <section class="se-container">
    <div class="se-slope">
      <article class="se-content">
        <h3>Section 1</h3>
        <p>LOL LOL LOL LOL
        </p>
      </article>
    </div>
    <div class="se-slope">
      <article class="se-content">
        <h3>Section 2</h3>
        <p>LOL LOL LOL LOL </p>
      </article>
    </div>
    <div class="se-slope">
      <article class="se-content">
        <h3>Section 3</h3>
        <p>LOL LOL LOL LOL </p>
      </article>
    </div>
    <div class="se-slope">
      <article class="se-content">
        <h3>Section 2</h3>
        <p>LOL LOL LOL LOL</p>
      </article>
    </div>

  </section>
</div>


问:
How to implement "Contact Us" view with a default Email destination address
I am trying to build up a Contact Us View in one iOS project,  What I am trying to do is:

Put a Text Viewin a view controller, which will capture and save users' writing.
If users press send button, the view controller will send the Email or message to customer service. How to implement this or any SDK recommended?

Thanks in advance.

答: MFMailComposeViewController is fully dedicated for this. it has built in what you are trying to make. So don't write code to take this hassle. Let Apple do it for you. :)


问:
Dice rolling outputs
I have finished this code but I need help understanding why the outputs aren't the same as desired. Here is my code. Also my professor said to use a seed of 237.

```<code>import random
rng = random.Random()
rng.seed(237)

NumberOfRolls = int(input("How many dice?:"))
NumberOfFaces = int(input("How many sides of each dice?:"))
numberOfTrials = int(input('How many trials? Enter:'))

# Set the number of elements in the list
#def throwDice():
def throwDice(NumberOfRolls):
    return random.randrange(1,NumberOfFaces)

def rollAllDice(NumberOfRolls):
  sum = 0;
  for i in range(NumberOfRolls):
    v = throwDice(NumberOfRolls);
    sum = sum + v;
    # print(v);
  return sum;

# perform simulation, record and print frequencies
index = (NumberOfRolls*NumberOfFaces)+1;
frequency = [0]*index
rel_frequency_list = [0]*index
exp_prob_list =[0]*index

for i in range(numberOfTrials):
  ind = rollAllDice(NumberOfRolls);
  frequency[ind] = frequency[ind]+1;
# end for
print()
#print("Frequencies:")

# calculate relative frequencies, probabilities and errors
relativeFrequency = [0, 0]
probability = [0,0]
error = [0,0]
for i in range(2, len(frequency)):
  rel_frequency_list[i] = frequency[i]/numberOfTrials;
  exp_prob_list[i] = frequency[i]/100;

#print(relativeFrequency)
#print(probability)
#print(error)
print()

# print results
f1 = "{0:<10}{1:<22}{2:<22}{3:<22}"
f2 = 71*"-"
f3 = "{0:>3}       {1:<22.15f}{2:<22.15f}{3:<.15f}"
print(f1.format("Sum","Frequency","Relative Frequency","Experimental Probability"))
print(f2)
for i in range(NumberOfRolls, len(frequency)):
   print(f3.format(i, frequency[i], rel_frequency_list[i], exp_prob_list[i]),"%")
#end for
</code>```

This is my output for 3 dice , 6 sides, 10,000 trials

```<code>Sum       Frequency             Relative Frequency    Experimental Probability

-----------------------------------------------------------------------
  3       75.000000000000000    0.007500000000000     0.750000000000000 %
  4       232.000000000000000   0.023200000000000     2.320000000000000 %
  5       454.000000000000000   0.045400000000000     4.540000000000000 %
  6       831.000000000000000   0.083100000000000     8.310000000000000 %
  7       1214.000000000000000  0.121400000000000     12.140000000000001 %
  8       1468.000000000000000  0.146800000000000     14.680000000000000 %
  9       1491.000000000000000  0.149100000000000     14.910000000000000 %
 10       1445.000000000000000  0.144500000000000     14.449999999999999 %
 11       1157.000000000000000  0.115700000000000     11.570000000000000 %
 12       828.000000000000000   0.082800000000000     8.279999999999999 %
 13       476.000000000000000   0.047600000000000     4.760000000000000 %
 14       230.000000000000000   0.023000000000000     2.300000000000000 %
 15       99.000000000000000    0.009900000000000     0.990000000000000 %
 16       0.000000000000000     0.000000000000000     0.000000000000000 %
 17       0.000000000000000     0.000000000000000     0.000000000000000 %
 18       0.000000000000000     0.000000000000000     0.000000000000000 %
</code>```

This is the desired (same outputs):

```<code>Sum Frequency Relative Frequency Experimental Probability
----------------------------------------------------------------------
 3 45 0.00450 0.45 %
 4 126 0.01260 1.26 %
 5 281 0.02810 2.81 %
 6 494 0.04940 4.94 %
 7 677 0.06770 6.77 %
 8 968 0.09680 9.68 %
 9 1191 0.11910 11.91 %
 10 1257 0.12570 12.57 %
 11 1257 0.12570 12.57 %
 12 1164 0.11640 11.64 %
 13 932 0.09320 9.32 %
 14 683 0.06830 6.83 %
 15 469 0.04690 4.69 %
 16 282 0.02820 2.82 %
 17 122 0.01220 1.22 %
 18 52 0.00520 0.52 %
</code>```

答:
Here is a reorganized version:</p>

```<code>from random import Random

def get_int(prompt):
    while True:
        try:
            return int(input(prompt))
        except ValueError:
            pass

class Dice:
    def __init__(self, num_dice, num_faces, seed=None):
        self.num_dice = num_dice
        self.num_faces = num_faces
        self.rng = Random()
        if seed is not None:
            self.rng.seed(seed)

    def roll(self):
        return sum(self.rng.randint(1, self.num_faces) for _ in range(self.num_dice))

    def histogram(self, num_trials):
        hist = [0] * (self.num_dice * self.num_faces + 1)
        for _ in range(num_trials):
            hist[self.roll()] += 1
        return hist

def main():
    num_dice = get_int("How many dice? ")
    num_faces = get_int("How many sides on each die? ")
    num_trials = get_int("How many trials? ")

    dice = Dice(num_dice, num_faces, 237)
    hist = dice.histogram(num_trials)

    print("Sum Frequency Relative Frequency Experimental Probability")
    print("-" * 70)

    lo = num_dice
    hi = num_dice * num_faces
    for n in range(lo, hi + 1):
        freq = hist[n]
        rfreq = freq / num_trials
        print("{:d} {:d} {:0.5f} {:0.2f} %".format(n, freq, rfreq, 100. * rfreq))

if __name__ == "__main__":
    main()
</code>```

Title: Dice rolling outputs

Body:
I have finished this code but I need help understanding why the outputs aren't the same as desired. Here is my code. Also my professor said to use a seed of 237.

import random
rng = random.Random()
rng.seed(237)

NumberOfRolls = int(input("How many dice?:"))
NumberOfFaces = int(input("How many sides of each dice?:"))
numberOfTrials = int(input('How many trials? Enter:'))

# Set the number of elements in the list
#def throwDice():
def throwDice(NumberOfRolls):
    return random.randrange(1,NumberOfFaces)

def rollAllDice(NumberOfRolls):
  sum = 0;
  for i in range(NumberOfRolls):
    v = throwDice(NumberOfRolls);
    sum = sum + v;
    # print(v);
  return sum;

# perform simulation, record and print frequencies
index = (NumberOfRolls*NumberOfFaces)+1;
frequency = [0]*index
rel_frequency_list = [0]*index
exp_prob_list =[0]*index

for i in range(numberOfTrials):
  ind = rollAllDice(NumberOfRolls);
  frequency[ind] = frequency[ind]+1;
# end for
print()
#print("Frequencies:")

# calculate relative frequencies, probabilities and errors
relativeFrequency = [0, 0]
probability = [0,0]
error = [0,0]
for i in range(2, len(frequency)):
  rel_frequency_list[i] = frequency[i]/numberOfTrials;
  exp_prob_list[i] = frequency[i]/100;

#print(relativeFrequency)
#print(probability)
#print(error)
print()

# print results
f1 = "{0:<10}{1:<22}{2:<22}{3:<22}"
f2 = 71*"-"
f3 = "{0:>3}       {1:<22.15f}{2:<22.15f}{3:<.15f}"
print(f1.format("Sum","Frequency","Relative Frequency","Experimental Probability"))
print(f2)
for i in range(NumberOfRolls, len(frequency)):
   print(f3.format(i, frequency[i], rel_frequency_list[i], exp_prob_list[i]),"%")
#end for

This is my output for 3 dice , 6 sides, 10,000 trials

Sum       Frequency             Relative Frequency    Experimental Probability

-----------------------------------------------------------------------
  3       75.000000000000000    0.007500000000000     0.750000000000000 %
  4       232.000000000000000   0.023200000000000     2.320000000000000 %
  5       454.000000000000000   0.045400000000000     4.540000000000000 %
  6       831.000000000000000   0.083100000000000     8.310000000000000 %
  7       1214.000000000000000  0.121400000000000     12.140000000000001 %
  8       1468.000000000000000  0.146800000000000     14.680000000000000 %
  9       1491.000000000000000  0.149100000000000     14.910000000000000 %
 10       1445.000000000000000  0.144500000000000     14.449999999999999 %
 11       1157.000000000000000  0.115700000000000     11.570000000000000 %
 12       828.000000000000000   0.082800000000000     8.279999999999999 %
 13       476.000000000000000   0.047600000000000     4.760000000000000 %
 14       230.000000000000000   0.023000000000000     2.300000000000000 %
 15       99.000000000000000    0.009900000000000     0.990000000000000 %
 16       0.000000000000000     0.000000000000000     0.000000000000000 %
 17       0.000000000000000     0.000000000000000     0.000000000000000 %
 18       0.000000000000000     0.000000000000000     0.000000000000000 %

This is the desired (same outputs):

Sum Frequency Relative Frequency Experimental Probability
----------------------------------------------------------------------
 3 45 0.00450 0.45 %
 4 126 0.01260 1.26 %
 5 281 0.02810 2.81 %
 6 494 0.04940 4.94 %
 7 677 0.06770 6.77 %
 8 968 0.09680 9.68 %
 9 1191 0.11910 11.91 %
 10 1257 0.12570 12.57 %
 11 1257 0.12570 12.57 %
 12 1164 0.11640 11.64 %
 13 932 0.09320 9.32 %
 14 683 0.06830 6.83 %
 15 469 0.04690 4.69 %
 16 282 0.02820 2.82 %
 17 122 0.01220 1.22 %
 18 52 0.00520 0.52 %

Body:
Here is a reorganized version:

from random import Random

def get_int(prompt):
    while True:
        try:
            return int(input(prompt))
        except ValueError:
            pass

class Dice:
    def __init__(self, num_dice, num_faces, seed=None):
        self.num_dice = num_dice
        self.num_faces = num_faces
        self.rng = Random()
        if seed is not None:
            self.rng.seed(seed)

    def roll(self):
        return sum(self.rng.randint(1, self.num_faces) for _ in range(self.num_dice))

    def histogram(self, num_trials):
        hist = [0] * (self.num_dice * self.num_faces + 1)
        for _ in range(num_trials):
            hist[self.roll()] += 1
        return hist

def main():
    num_dice = get_int("How many dice? ")
    num_faces = get_int("How many sides on each die? ")
    num_trials = get_int("How many trials? ")

    dice = Dice(num_dice, num_faces, 237)
    hist = dice.histogram(num_trials)

    print("Sum Frequency Relative Frequency Experimental Probability")
    print("-" * 70)

    lo = num_dice
    hi = num_dice * num_faces
    for n in range(lo, hi + 1):
        freq = hist[n]
        rfreq = freq / num_trials
        print("{:d} {:d} {:0.5f} {:0.2f} %".format(n, freq, rfreq, 100. * rfreq))

if __name__ == "__main__":
    main()


问:
Change DOM content through .firstChild property
I am trying to select an element by its relation with the rest of this DOM:

```<code><div id="dad">
    <p>son</p>
    <p>son</p>
</div>
</code>```

As seen here:

```<code>let daddy = document.getElementById('dad');
daddy.firstChild.textContent = "Im first";
</code>```

What JS makes is, instead of changing its inner HTML, inserting the string as the first element of the 'dad'
.

This makes sense but, how can I make use of this property to select this first child and replace its content? Instead of inserting content as the element's first child.

答:
The first child of #dad is a text node, because there are whitespaces between
 and
. If you remove that whitespaces, it works fine:

let daddy = document.getElementById('dad');
daddy.firstChild.textContent = "Im first";```
<pre class="snippet-code-html lang-html prettyprint-override"><code><div id="dad"><p>son</p><p>son</p></div></code>```

Or you can use firstElementChild property:

let daddy = document.getElementById('dad');
daddy.firstElementChild.textContent = "Im first";```
<pre class="snippet-code-html lang-html prettyprint-override"><code><div id="dad">
    <p>son</p>
    <p>son</p>
</div></code>```

Body:
I am trying to select an element by its relation with the rest of this DOM:

son

son

As seen here:

let daddy = document.getElementById('dad');
daddy.firstChild.textContent = "Im first";

What JS makes is, instead of changing its inner HTML, inserting the string as the first element of the 'dad'
.

This makes sense but, how can I make use of this property to select this first child and replace its content? Instead of inserting content as the element's first child.

Body:
The first child of #dad is a text node, because there are whitespaces between <div id="dad"> and <p>. If you remove that whitespaces, it works fine:

let daddy = document.getElementById('dad');
daddy.firstChild.textContent = "Im first";

<div id="dad"><p>son</p><p>son</p></div>

Or you can use firstElementChild property:

let daddy = document.getElementById('dad');
daddy.firstElementChild.textContent = "Im first";

<div id="dad">
    <p>son</p>
    <p>son</p>
</div>


问:
Recursive Sierpinsky Triangle - StackOverflow error
I got my code running so far, except for the recursive part. I get a StackOverflow error and I really don't get why, or how to fix it. When I work through the code it seems logically fine.</p>

```<code>public class SierpinskiTriangle {
public static int SIZE = 1000;

JFrame frame;
JPanel panel;

@SuppressWarnings("serial")
public void display() {
    frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    panel = new JPanel() {
        @Override
        public void paint(Graphics g) {
            super.paint(g);
            paintSierpinskiTriangle(20, 20, 360, (Graphics2D)g);
        }
    };
    panel.addComponentListener(new ComponentAdapter() {
        @Override
        public void componentResized(ComponentEvent e) {
            panel.repaint();
        }
    });
    frame.setLayout(new BorderLayout());
    frame.add(panel, BorderLayout.CENTER);
    frame.pack();
    frame.setSize(SIZE, SIZE);
    frame.setVisible(true);
}

public static void main(String[] args) {
    SierpinskiTriangle triangle = new SierpinskiTriangle();
    triangle.display();
}

public static void paintSierpinskiTriangle(int x, int y, int s, Graphics2D g) {
    g.drawLine(x, y, x+s, y);
    g.drawLine(x, y, x, y+s);
    g.drawLine(x+s, y, x, y+s);

    paintSierpinskiTriangle(x, y, s/2, g);
    paintSierpinskiTriangle(x+s/2, y, s/2, g);
    paintSierpinskiTriangle(x, y+s/2, s/2, g);

}
}
</code>```

答:
You need to add some conditions to return from the paintSierpinskiTrianglemethod.

Without any conditions, it will keep calling itself infinitely, even if s = 0, which is what causes the Error.

Body:
I got my code running so far, except for the recursive part. I get a StackOverflow error and I really don't get why, or how to fix it. When I work through the code it seems logically fine.

public class SierpinskiTriangle {
public static int SIZE = 1000;

JFrame frame;
JPanel panel;

@SuppressWarnings("serial")
public void display() {
    frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    panel = new JPanel() {
        @Override
        public void paint(Graphics g) {
            super.paint(g);
            paintSierpinskiTriangle(20, 20, 360, (Graphics2D)g);
        }
    };
    panel.addComponentListener(new ComponentAdapter() {
        @Override
        public void componentResized(ComponentEvent e) {
            panel.repaint();
        }
    });
    frame.setLayout(new BorderLayout());
    frame.add(panel, BorderLayout.CENTER);
    frame.pack();
    frame.setSize(SIZE, SIZE);
    frame.setVisible(true);
}

public static void main(String[] args) {
    SierpinskiTriangle triangle = new SierpinskiTriangle();
    triangle.display();
}

public static void paintSierpinskiTriangle(int x, int y, int s, Graphics2D g) {
    g.drawLine(x, y, x+s, y);
    g.drawLine(x, y, x, y+s);
    g.drawLine(x+s, y, x, y+s);

    paintSierpinskiTriangle(x, y, s/2, g);
    paintSierpinskiTriangle(x+s/2, y, s/2, g);
    paintSierpinskiTriangle(x, y+s/2, s/2, g);

}
}


问:
Merge List of maps updating values
I am trying to merge a list of dictionaries. Every dictionary in the list is nested and I need to sum the values on every element in the list. For example;

```<code>samples = [
  %{team1: %{a: 5, f: 0, n_games: 1}, team2: %{a: 0, f: 2, n_games: 1}},
  %{team1: %{a: 1, f: 2, n_games: 1}, team2: %{a: 4, f: 3, n_games: 1}}
]
</code>```

Would need to return

```<code>%{team1: %{a: 6, f: 2, n_games: 2}, team2: %{a: 4, f: 5, n_games: 2}}
</code>```

I would love to share any code I have, but I honestly don't have anything to share since I don't know the approach to these kind of problems in Elixir.

答:
You can use a combination of Enum.reduce/2 and Map.merge/3. In Map.merge/3, the callback should add the three fields of both the values.

```<code>samples = [
  %{team1: %{a: 5, f: 0, n_games: 1}, team2: %{a: 0, f: 2, n_games: 1}},
  %{team1: %{a: 1, f: 2, n_games: 1}, team2: %{a: 4, f: 3, n_games: 1}}
]

samples
|> Enum.reduce(fn x, acc ->
  Map.merge(x, acc, fn _key, %{a: a1, f: f1, n_games: ng1}, %{a: a2, f: f2, n_games: ng2} ->
    %{a: a1 + a2, f: f1 + f2, n_games: ng1 + ng2}
  end)
end)
|> IO.inspect
</code>```

Output:

```<code>%{team1: %{a: 6, f: 2, n_games: 2}, team2: %{a: 4, f: 5, n_games: 2}}
</code>```

If you don't want to hardcode the list of keys in the map and just want to add all the values, you can do this instead:

```<code>|> Enum.reduce(fn x, acc ->
  Map.merge(x, acc, fn _key, map1, map2 ->
    for {k, v1} <- map1, into: %{}, do: {k, v1 + map2[k]}
  end)
end)
</code>```

Title: Merge List of maps updating values

Body:
I am trying to merge a list of dictionaries. Every dictionary in the list is nested and I need to sum the values on every element in the list. For example;

samples = [
  %{team1: %{a: 5, f: 0, n_games: 1}, team2: %{a: 0, f: 2, n_games: 1}},
  %{team1: %{a: 1, f: 2, n_games: 1}, team2: %{a: 4, f: 3, n_games: 1}}
]

Would need to return

%{team1: %{a: 6, f: 2, n_games: 2}, team2: %{a: 4, f: 5, n_games: 2}}

I would love to share any code I have, but I honestly don't have anything to share since I don't know the approach to these kind of problems in Elixir.

Body:
You can use a combination of Enum.reduce/2 and Map.merge/3. In Map.merge/3, the callback should add the three fields of both the values.

samples = [
  %{team1: %{a: 5, f: 0, n_games: 1}, team2: %{a: 0, f: 2, n_games: 1}},
  %{team1: %{a: 1, f: 2, n_games: 1}, team2: %{a: 4, f: 3, n_games: 1}}
]

samples
|> Enum.reduce(fn x, acc ->
  Map.merge(x, acc, fn _key, %{a: a1, f: f1, n_games: ng1}, %{a: a2, f: f2, n_games: ng2} ->
    %{a: a1 + a2, f: f1 + f2, n_games: ng1 + ng2}
  end)
end)
|> IO.inspect

Output:

%{team1: %{a: 6, f: 2, n_games: 2}, team2: %{a: 4, f: 5, n_games: 2}}

If you don't want to hardcode the list of keys in the map and just want to add all the values, you can do this instead:

|> Enum.reduce(fn x, acc ->
  Map.merge(x, acc, fn _key, map1, map2 ->
    for {k, v1} <- map1, into: %{}, do: {k, v1 + map2[k]}
  end)
end)


问:
Unable to pull from private docker hub registry on kubernetes
I'm running a k8 cluster on google container engine. I'm having trouble getting it to pull images from a private docker repo.

I get the following when trying to boot:

Name:  ds-expected-date
Namespace: default
Node:  gke-ds-cluster-1-default-pool-8980b100-l64j/10.132.0.3
Start Time: Wed, 24 May 2017 13:24:11 +0100
Labels:  <none>
Annotations: kubernetes.io/limit-ranger=LimitRanger plugin set: cpu request for container ds-expected-date-flask
Status:  Pending
IP:  10.40.0.23
Controllers: <none>
Containers:
  ds-expected-date-flask:
    Container ID:
    Image:  fluidy/ds-expected-date:latest
    Image ID:
    Port:
    State:  Waiting
      Reason:  ImagePullBackOff
    Ready:  False
    Restart Count: 0
    Requests:
      cpu:  100m
    Environment: <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-h340m (ro)
Conditions:
  Type  Status
  Initialized  True
  Ready  False
  PodScheduled  True
Volumes:
  default-token-h340m:
    Type: Secret (a volume populated by a Secret)
    SecretName: default-token-h340m
    Optional: false
QoS Class: Burstable
Node-Selectors: <none>
Tolerations: <none>
Events:
  FirstSeen LastSeen Count From       SubObjectPath    Type  Reason  Message
  --------- -------- ----- ----       -------------    -------- ------  -------
  21s  21s  1 default-scheduler          Normal  Scheduled Successfully assigned ds-expected-date to gke-ds-cluster-1-default-pool-8980b100-l64j
  18s  18s  1 kubelet, gke-ds-cluster-1-default-pool-8980b100-l64j spec.containers{ds-expected-date-flask} Normal  BackOff  Back-off pulling image "fluidy/ds-expected-date:latest"
  18s  18s  1 kubelet, gke-ds-cluster-1-default-pool-8980b100-l64j      Warning  FailedSync Error syncing pod, skipping: failed to "StartContainer" for "ds-expected-date-flask" with ImagePullBackOff: "Back-off pulling image \"fluidy/ds-expected-date:latest\""

  20s 6s 2 kubelet, gke-ds-cluster-1-default-pool-8980b100-l64j spec.containers{ds-expected-date-flask} Normal Pulling  pulling image "fluidy/ds-expected-date:latest"
  19s 5s 2 kubelet, gke-ds-cluster-1-default-pool-8980b100-l64j spec.containers{ds-expected-date-flask} Warning Failed  Failed to pull image "fluidy/ds-expected-date:latest": Error response from daemon: unauthorized: authentication required
  19s 5s 2 kubelet, gke-ds-cluster-1-default-pool-8980b100-l64j      Warning FailedSync Error syncing pod, skipping: failed to "StartContainer" for "ds-expected-date-flask" with ErrImagePull: "Error response from daemon: unauthorized: authentication required"```

I have followed all the instructions on the docs page. I'm confident my registry secret is being read - if I put duff credentials in it, the error changes to 'invalid user name or password'.

答:
You have not configured your cluster to pull private images from Docker Hub with your credentials.

Read and apply this guide: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/

Google Container Engine can automatically pull from Google Container Registry (http://gcr.io), consider using that without pulling images from a private registry.

Body:
I'm running a k8 cluster on google container engine. I'm having trouble getting it to pull images from a private docker repo.

I get the following when trying to boot:

Name:  ds-expected-date
Namespace: default
Node:  gke-ds-cluster-1-default-pool-8980b100-l64j/10.132.0.3
Start Time: Wed, 24 May 2017 13:24:11 +0100
Labels:  <none>
Annotations: kubernetes.io/limit-ranger=LimitRanger plugin set: cpu request for container ds-expected-date-flask
Status:  Pending
IP:  10.40.0.23
Controllers: <none>
Containers:
  ds-expected-date-flask:
    Container ID:
    Image:  fluidy/ds-expected-date:latest
    Image ID:
    Port:
    State:  Waiting
      Reason:  ImagePullBackOff
    Ready:  False
    Restart Count: 0
    Requests:
      cpu:  100m
    Environment: <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-h340m (ro)
Conditions:
  Type  Status
  Initialized  True
  Ready  False
  PodScheduled  True
Volumes:
  default-token-h340m:
    Type: Secret (a volume populated by a Secret)
    SecretName: default-token-h340m
    Optional: false
QoS Class: Burstable
Node-Selectors: <none>
Tolerations: <none>
Events:
  FirstSeen LastSeen Count From       SubObjectPath    Type  Reason  Message
  --------- -------- ----- ----       -------------    -------- ------  -------
  21s  21s  1 default-scheduler          Normal  Scheduled Successfully assigned ds-expected-date to gke-ds-cluster-1-default-pool-8980b100-l64j
  18s  18s  1 kubelet, gke-ds-cluster-1-default-pool-8980b100-l64j spec.containers{ds-expected-date-flask} Normal  BackOff  Back-off pulling image "fluidy/ds-expected-date:latest"
  18s  18s  1 kubelet, gke-ds-cluster-1-default-pool-8980b100-l64j      Warning  FailedSync Error syncing pod, skipping: failed to "StartContainer" for "ds-expected-date-flask" with ImagePullBackOff: "Back-off pulling image \"fluidy/ds-expected-date:latest\""

  20s 6s 2 kubelet, gke-ds-cluster-1-default-pool-8980b100-l64j spec.containers{ds-expected-date-flask} Normal Pulling  pulling image "fluidy/ds-expected-date:latest"
  19s 5s 2 kubelet, gke-ds-cluster-1-default-pool-8980b100-l64j spec.containers{ds-expected-date-flask} Warning Failed  Failed to pull image "fluidy/ds-expected-date:latest": Error response from daemon: unauthorized: authentication required
  19s 5s 2 kubelet, gke-ds-cluster-1-default-pool-8980b100-l64j      Warning FailedSync Error syncing pod, skipping: failed to "StartContainer" for "ds-expected-date-flask" with ErrImagePull: "Error response from daemon: unauthorized: authentication required"

I have followed all the instructions on the docs page. I'm confident my registry secret is being read - if I put duff credentials in it, the error changes to 'invalid user name or password'.


问:
Is it possible to use 1 Kubernetes ingress object to route traffic to k8s services in different clusters?
I have the following setup:
  k8s cluster A, containing service SA
  k8s cluster B, containing service SB, and an HTTP ingress that routes traffic to SB

Is it possible to add service SA as the backend service for one of the path of the ingress? If so, how do I refer to it in the ingress configuration file? (using selectors in the usual way doesn't work, presumably because we are in different clusters)

答:
Just to add a little to what Robert stated above. First, you are going to want to specify a specific nodePort in your NodePort service. Then, use that port number for the "named port" and in the healthcheck. Finally the firewall rule that you create also has to allow that port.

As a beginner, I did find that using the Console made it much easier to configure.


问:
switch command in C# not working
I'm new to C# and I'm practising by coding a simple Rock, Paper Scissors game, however I have a problem with my "switch" command.
I want the user to input either Rock, Paper or Scissors, and then take the input and go to a particular case, however I can't figure out how to do it.</p>

```<code>    {
        //random number generator
            Random random = new Random();
            int randomNumber = random.Next(1,4);

        //user input
            Console.WriteLine("PLease Enter Rock, Paper or Scissors");
            string input = Console.ReadLine();

        //compare input and random number
        switch (input)
        {
            case Rock:
                if (randomNumber == 1)
                {
                    Console.WriteLine("It's a draw, computer also chose Rock");
                }
                else if (randomNumber == 2)
                {
                    Console.WriteLine("You loose, computer chose Paper");
                }
                else if (randomNumber == 3)
                {
                    Console.WriteLine("You win, computer chose Scissors");
                }
                break;

            case Paper:
                if (randomNumber == 1)
                {
                    Console.WriteLine("You win, computer chose Rock");
                }
                else if (randomNumber == 2)
                {
                    Console.WriteLine("It's a draw, computer also chose Paper");
                }
                else if (randomNumber == 3)
                {
                    Console.WriteLine("You loose, computer chose Scissors");

                }
                break;

            case Scissors:
                if (randomNumber == 1)
                {
                    Console.WriteLine("You loose, computer chose Rock");
                }
                else if (randomNumber == 2)
                {
                    Console.WriteLine("You win, computer chose Paper");
                }
                else if (randomNumber == 3)
                {
                    Console.WriteLine("It's a draw, computer chose Scissors");

                }
                break;
        }
</code>```

答:
You have to write the cases as string:</p>

```<code>...
case "Rock":
...
</code>```

Title: switch command in C# not working

Body:
I'm new to C# and I'm practising by coding a simple Rock, Paper Scissors game, however I have a problem with my "switch" command.
I want the user to input either Rock, Paper or Scissors, and then take the input and go to a particular case, however I can't figure out how to do it.

    {
        //random number generator
            Random random = new Random();
            int randomNumber = random.Next(1,4);

        //user input
            Console.WriteLine("PLease Enter Rock, Paper or Scissors");
            string input = Console.ReadLine();

        //compare input and random number
        switch (input)
        {
            case Rock:
                if (randomNumber == 1)
                {
                    Console.WriteLine("It's a draw, computer also chose Rock");
                }
                else if (randomNumber == 2)
                {
                    Console.WriteLine("You loose, computer chose Paper");
                }
                else if (randomNumber == 3)
                {
                    Console.WriteLine("You win, computer chose Scissors");
                }
                break;

            case Paper:
                if (randomNumber == 1)
                {
                    Console.WriteLine("You win, computer chose Rock");
                }
                else if (randomNumber == 2)
                {
                    Console.WriteLine("It's a draw, computer also chose Paper");
                }
                else if (randomNumber == 3)
                {
                    Console.WriteLine("You loose, computer chose Scissors");

                }
                break;

            case Scissors:
                if (randomNumber == 1)
                {
                    Console.WriteLine("You loose, computer chose Rock");
                }
                else if (randomNumber == 2)
                {
                    Console.WriteLine("You win, computer chose Paper");
                }
                else if (randomNumber == 3)
                {
                    Console.WriteLine("It's a draw, computer chose Scissors");

                }
                break;
        }

Body:
You have to write the cases as string:

...
case "Rock":
...


问:
How to replace occurrences with javascript inside delimiters?
How to replace all occurrences that are within two characters.
Example:

```<code>I love :octocat: beach and you do :joy: not like it
</code>```

Replace with a url that will be generated based on what's inside the delimiters

```<code>I love [img of octocat] beach and you do [img of joy] not like it
</code>```

Javascript needs to capture what's inside : and replace

I've tried several things without success. can anybody help me?

答:
Shrtfrm:

```<code>"I love :octocat: beach and you do :joy: not like it".split(":").map((el,i)=>i%2===0?el:{"octocat":"hello","joy":"test"}[el]||el).join("");
</code>```

Simply split, replace and join again.

http://jsbin.com/moxexilica/edit?console

Explanation:

```<code>.split(":")
//returns: ["I love ","octocat"," beach and you do ","joy"," not like it"]
.map((el,i)=>i%2===0?el
//leave the strings outside (indexes 0,2,4) as they are
:el{"octocat":"hello","joy":"test"}[el]
//replace the others (indexes 1,3) with the value in the object so:
// octocat => hello
//joy => test
||el
//if it does not exist e. g. ':test:' fall back to 'test'
//now weve got:
//["I love ","hello"," beach and you do ","test"," not like it"]
.join("")
//a string
</code>```

Extracted to a function:

```<code>function replace(str,replacer){
  return str.split(":").map((el,i)=>i%2===0?el:replacer[el]||el).join("");
}
</code>```

So you can do:

```<code>alert(replace("I love :octocat: beach and you do :joy: not like it", {octocat:"manly",joy:"not"}));
</code>```

With images:

```<code>document.body.innerHTML=replace(document.body.innerHTML, {octocat:"<img src='octocat.png' />",joy:"<img src='joy.png' />"});
</code>```

Note that ":" is not a good delemiter. You may use a more uncommon one like %% or !! ...

Body:
How to replace all occurrences that are within two characters.
Example:

I love :octocat: beach and you do :joy: not like it

Replace with a url that will be generated based on what's inside the delimiters

I love [img of octocat] beach and you do [img of joy] not like it

Javascript needs to capture what's inside : and replace

I've tried several things without success. can anybody help me?

Body:
Shrtfrm:

"I love :octocat: beach and you do :joy: not like it".split(":").map((el,i)=>i%2===0?el:{"octocat":"hello","joy":"test"}[el]||el).join("");

Simply split, replace and join again.

http://jsbin.com/moxexilica/edit?console

Explanation:

.split(":")
//returns: ["I love ","octocat"," beach and you do ","joy"," not like it"]
.map((el,i)=>i%2===0?el
//leave the strings outside (indexes 0,2,4) as they are
:el{"octocat":"hello","joy":"test"}[el]
//replace the others (indexes 1,3) with the value in the object so:
// octocat => hello
//joy => test
||el
//if it does not exist e. g. ':test:' fall back to 'test'
//now weve got:
//["I love ","hello"," beach and you do ","test"," not like it"]
.join("")
//a string

Extracted to a function:

function replace(str,replacer){
  return str.split(":").map((el,i)=>i%2===0?el:replacer[el]||el).join("");
}

So you can do:

alert(replace("I love :octocat: beach and you do :joy: not like it", {octocat:"manly",joy:"not"}));

With images:

document.body.innerHTML=replace(document.body.innerHTML, {octocat:"<img src='octocat.png' />",joy:"<img src='joy.png' />"});

Note that ":" is not a good delemiter. You may use a more uncommon one like %% or !! ...


问:
service not working between two controllers getting undefined
I am showing employee record using AngularJS. I am using two  views to show data, I am using two views emp-box.htm and its respective controller(empController) and in this controller employeeBoxController I am fetching data from service, I want the result which is obtained in employeeBoxController to be used in empController and show in view (emp-list.htm), I created a service eService

```<code>app.service('dataService',function() {

  var s = {};

  this.setData = function(data,key) {
    s[key]=data;
  },
  this.getData = function(key) {
    return s[key];
  }
  this.hello = function() {
    return 'hello';
  }
})
</code>```

for fetching result and setting data in employeeBoxController and getting in empController but when I fetch the data using console.log(dataService.getData('result')); in empController i get undefined

The employeeBoxController is

```<code>app.controller("employeeBoxController", ['$scope', 'employeeService',
  'dataService', function($scope, employeeService, dataService) {
  $scope.getEmployeeDetails = function(eid) {
    $scope.isLoading = false;
    employeeService.getDetails($scope.eid).then(function(result) {
      dataService.setData(result, 'result');
      $scope.isLoading = true;
      console.log(dataService.getData('result'));
    })
  }
}])
</code>```

The empController is :-

```<code>app.controller("empController", ['$scope', 'employeeService', 'dataService',
  function($scope, employeeService, dataService) {

    $scope.result = dataService.getData('result');
    //console.log(dataService.hello());

    console.log(dataService.getData('result'));

    console.log(dataService.hello());
  }
])
</code>```

The service class  employeeService is :-

```<code>  app.config(["employeeServiceProvider",function(employeeServiceProvider){
      employeeServiceProvider.config('http://localhost:8080/pos');
  }]);

  app.provider("employeeService",function(){
    var myurl='';

    this.config=function(eurl){
      myurl=eurl;
    }

    this.$get=['$http','$log',function($http,$log){
      var employeeobj={};
      employeeobj.getDetails=function(eid){
        return $http.get(myurl+'/getEmployees/'+eid);
    }

  return employeeobj;
    }];
  });
</code>```

emp-box.htm is:-

```<code>    <div>
  Enter the id: <input type="text" ng-model="eid"/>
  <button ng-click="getEmployeeDetails()">show</button>
   </div>
   emp-list.htm is:-
       <div class="panel panel-primary">
       <div class="panel-body" style="text-align:center; margin:0 auto">
      <h3>Employee Data</h3>
      </div>
     </div>
      <div class="panel panel-primary">
        <div class="panel-body">
      <!--  <div ng-show="!isLoading" style="color:red">
      <span class="glyphicon glyphicon-time"></span>Loading...
      </div>-->
     <table class="table table-hover">
     <thead>
      <tr>
      <th>ID</th>
      <th>Name</th>
      <th>empno</th>
      <th>salary</th>
      </tr>
    </thead>
     <tbody>
      <tr ng-repeat="oemp in result.data">

      <td>{{oemp.eid}}</td>
      <td>{{oemp.name}}</td>
      <td>{{oemp.empno}}</td>
      <td>{{oemp.sal}}</td>
    </tr>
  </tbody>

    </table>
  </div>
  </div>
</code>```

答:
From what I understand you're trying to cache your API results in another service, so you don't have to call the API again in another controller. Also, empController is executed first, and when you're doing dataService.getData('result') the API response of setting it isn't received yet which in turn is called from another service. I would suggest you combine these 2 services, so that instead of caching the exact values in service, you can cache the API call itself, and in case where cache doesn't contain your data, make an API call and cache it.

Here's something I'd make, say CacheAPIService.

```<code>app.factory('CacheAPIService', ['$http', function($http) {
  var cache = {};
  return {
    get: function(api) {
     if(angular.isUndefined(cache[api])) {
       cache[api] =  $http.get(api); //storing in cache while making API call
     }
     return cache[api]; //Return from cache
    },
    clear: function(api) {
        delete cache[api];
    }
  }
}]);
</code>```

So, whenever you need to make an cache an API  call, use this service in addition to making API call it'll also cache it. And, if it is already cached, no new API call is made. Benefits is you'll never run into cases where it return's undefined, as you are returning promise.

In your 1st controller, updated code becomes:

```<code>app.controller("employeeBoxController", ['$scope', 'CacheAPIService', function($scope, CacheAPIService) {
  $scope.getEmployeeDetails = function(eid) {
    $scope.isLoading = true;
    var endpoint = 'api/endpoint/'+$scope.eid;    //Replace with your API endpoint
    CacheAPIService.get(endpoint).then(function(result) {
      $scope.isLoading = false;
      console.log(dataService.getData('result'));
    })
  }
}]);
</code>```

Here, 1st API call is made and is cached. Take a look at your other controller:

```<code>app.controller("empController", ['$scope', 'CacheAPIService', function($scope, CacheAPIService) {
  CacheAPIService.get(endpoint).then(function(data) {
    var endpoint = 'api/endpoint/'+$scope.eid; //your API endpoint
    console.log('data =', data);
  });

}]);
</code>```

Here, you still use the same service, but it'll be cached, and if not cached, it'll make API call and cache that promise. Here I've directly used API endpoint as key for storing in cache. This way you don't have to provide unique keys every time, as endpoint itself is unique.

Note that in cases where you want to delete cached data, when making POST or PUT call, you can call CacheAPIService.clear(apiEndpoint) to clear details from cache.

Body:
I am showing employee record using AngularJS. I am using two  views to show data, I am using two views emp-box.htm and its respective controller(empController) and in this controller employeeBoxController I am fetching data from service, I want the result which is obtained in employeeBoxController to be used in empController and show in view (emp-list.htm), I created a service eService

app.service('dataService',function() {

  var s = {};

  this.setData = function(data,key) {
    s[key]=data;
  },
  this.getData = function(key) {
    return s[key];
  }
  this.hello = function() {
    return 'hello';
  }
})

for fetching result and setting data in employeeBoxController and getting in empController but when I fetch the data using console.log(dataService.getData('result')); in empController i get undefined

The employeeBoxController is

app.controller("employeeBoxController", ['$scope', 'employeeService',
  'dataService', function($scope, employeeService, dataService) {
  $scope.getEmployeeDetails = function(eid) {
    $scope.isLoading = false;
    employeeService.getDetails($scope.eid).then(function(result) {
      dataService.setData(result, 'result');
      $scope.isLoading = true;
      console.log(dataService.getData('result'));
    })
  }
}])

The empController is :-

app.controller("empController", ['$scope', 'employeeService', 'dataService',
  function($scope, employeeService, dataService) {

    $scope.result = dataService.getData('result');
    //console.log(dataService.hello());

    console.log(dataService.getData('result'));

    console.log(dataService.hello());
  }
])

The service class  employeeService is :-

  app.config(["employeeServiceProvider",function(employeeServiceProvider){
      employeeServiceProvider.config('http://localhost:8080/pos');
  }]);

  app.provider("employeeService",function(){
    var myurl='';

    this.config=function(eurl){
      myurl=eurl;
    }

    this.$get=['$http','$log',function($http,$log){
      var employeeobj={};
      employeeobj.getDetails=function(eid){
        return $http.get(myurl+'/getEmployees/'+eid);
    }

  return employeeobj;
    }];
  });

emp-box.htm is:-

  Enter the id: <input type="text" ng-model="eid"/>
  <button ng-click="getEmployeeDetails()">show</button>

   emp-list.htm is:-

Employee Data

      ID
      Name
      empno
      salary

      {{oemp.eid}}
      {{oemp.name}}
      {{oemp.empno}}
      {{oemp.sal}}

Body:
From what I understand you're trying to cache your API results in another service, so you don't have to call the API again in another controller. Also, empController is executed first, and when you're doing dataService.getData('result') the API response of setting it isn't received yet which in turn is called from another service. I would suggest you combine these 2 services, so that instead of caching the exact values in service, you can cache the API call itself, and in case where cache doesn't contain your data, make an API call and cache it.

Here's something I'd make, say CacheAPIService.

app.factory('CacheAPIService', ['$http', function($http) {
  var cache = {};
  return {
    get: function(api) {
     if(angular.isUndefined(cache[api])) {
       cache[api] =  $http.get(api); //storing in cache while making API call
     }
     return cache[api]; //Return from cache
    },
    clear: function(api) {
        delete cache[api];
    }
  }
}]);

So, whenever you need to make an cache an API  call, use this service in addition to making API call it'll also cache it. And, if it is already cached, no new API call is made. Benefits is you'll never run into cases where it return's undefined, as you are returning promise.

In your 1st controller, updated code becomes:

app.controller("employeeBoxController", ['$scope', 'CacheAPIService', function($scope, CacheAPIService) {
  $scope.getEmployeeDetails = function(eid) {
    $scope.isLoading = true;
    var endpoint = 'api/endpoint/'+$scope.eid;    //Replace with your API endpoint
    CacheAPIService.get(endpoint).then(function(result) {
      $scope.isLoading = false;
      console.log(dataService.getData('result'));
    })
  }
}]);

Here, 1st API call is made and is cached. Take a look at your other controller:

app.controller("empController", ['$scope', 'CacheAPIService', function($scope, CacheAPIService) {
  CacheAPIService.get(endpoint).then(function(data) {
    var endpoint = 'api/endpoint/'+$scope.eid; //your API endpoint
    console.log('data =', data);
  });

}]);

Here, you still use the same service, but it'll be cached, and if not cached, it'll make API call and cache that promise. Here I've directly used API endpoint as key for storing in cache. This way you don't have to provide unique keys every time, as endpoint itself is unique.

Note that in cases where you want to delete cached data, when making POST or PUT call, you can call CacheAPIService.clear(apiEndpoint) to clear details from cache.


问:
jQuery hasClass and if
I have a problem with jquery hasClass.

```<code>$(document).ready(function () {

var body = $('body'),
    leftPane = $('.pane-left');

leftPane.on('click', function () {

    body.removeClass('left-closed');
    body.addClass('left-open');
    $('.pane-left h2').fadeIn(600);

    setTimeout(function() {
        rightPane.fadeOut(0);
        $('.pane-left-wrap').fadeIn(100);
        $('.pane-left-wrap .secondary-nav li:first-child').fadeIn(100);
        $('.pane-left-wrap .secondary-nav li:nth-child(2)').fadeIn(600);
        $('.pane-left-wrap .secondary-nav li:nth-child(3)').fadeIn(1200);
        $('.pane-left-wrap .secondary-nav li:nth-child(4)').fadeIn(1800);
        $('.pane-left-wrap .secondary-nav li:nth-child(5)').fadeIn(2400);
    }, 600);

});

if(body.hasClass('left-open')) {

    leftPane.on('click', function () {

        body.removeClass('left-open');
        body.addClass('left-closed');
        $('.pane-left h2').fadeOut(600);

    });

}

});
</code>```

I click pane-left and left-open is added to my body tag. Then i click again but the code inside my if() is unreachable. Why is that?

答:
It sounds like this is what your looking for <em>(cleaned up version)</em> and .toggleClass(); seems more suitable for your scenario. </p>

```<code>if ($('body').hasClass("left-open")) {
    $('#leftPaneElem').click(function() {

         body.toggleClass('left-closed');

          // more stuff

    });
}
</code>```

Title: jQuery hasClass and if

Body:
I have a problem with jquery hasClass.

$(document).ready(function () {

var body = $('body'),
    leftPane = $('.pane-left');

leftPane.on('click', function () {

    body.removeClass('left-closed');
    body.addClass('left-open');
    $('.pane-left h2').fadeIn(600);

    setTimeout(function() {
        rightPane.fadeOut(0);
        $('.pane-left-wrap').fadeIn(100);
        $('.pane-left-wrap .secondary-nav li:first-child').fadeIn(100);
        $('.pane-left-wrap .secondary-nav li:nth-child(2)').fadeIn(600);
        $('.pane-left-wrap .secondary-nav li:nth-child(3)').fadeIn(1200);
        $('.pane-left-wrap .secondary-nav li:nth-child(4)').fadeIn(1800);
        $('.pane-left-wrap .secondary-nav li:nth-child(5)').fadeIn(2400);
    }, 600);

});

if(body.hasClass('left-open')) {

    leftPane.on('click', function () {

        body.removeClass('left-open');
        body.addClass('left-closed');
        $('.pane-left h2').fadeOut(600);

    });

}

});

I click pane-left and left-open is added to my body tag. Then i click again but the code inside my if() is unreachable. Why is that?

Body:
It sounds like this is what your looking for (cleaned up version) and .toggleClass(); seems more suitable for your scenario.

if ($('body').hasClass("left-open")) {
    $('#leftPaneElem').click(function() {

         body.toggleClass('left-closed');

          // more stuff

    });
}


问:
Appending the datetime to the end of every line in a 600 million row file
I have a 680 million rows (19gig) file that I need the datetime appended onto every line. I get this file every night and I have to add the time that I processed it to the end of each line. I have tried many ways to do this including sed/awk and loading it into a SQL database with the last column being defaulted to the current timestamp.

I was wondering if there is a fast way to do this? My fastest way so far takes two hours and that is just not fast enough given the urgency of the information in this file.  It is a flat CSV file.

edit1:

Here's what I've done so far:

```<code>awk -v date="$(date +"%Y-%m-%d %r")" '{ print $0","date}' lrn.ae.txt > testoutput.txt
</code>```

Time = 117 minutes

```<code>perl -ne 'chomp; printf "%s.pdf\n", $_' EXPORT.txt > testoutput.txt
</code>```

Time = 135 minutes

```<code>mysql load data local infile '/tmp/input.txt' into table testoutput
</code>```

Time = 211 minutes

答:
Another alternative to test is

```<code>$ date +"%Y-%m-%d %r" > timestamp
$ join -t, -j9999 file timestamp | cut -d, -f2-
</code>```

or time stamp can be generated in place as well <(date +"%Y-%m-%d %r")

join creates a cross product of the first file and second file using the non-existing field (9999), and since second file is only one line, practically appending it to the first file.  Need the cut to get rid of the empty key field generated by join

Body:
I have a 680 million rows (19gig) file that I need the datetime appended onto every line. I get this file every night and I have to add the time that I processed it to the end of each line. I have tried many ways to do this including sed/awk and loading it into a SQL database with the last column being defaulted to the current timestamp.

I was wondering if there is a fast way to do this? My fastest way so far takes two hours and that is just not fast enough given the urgency of the information in this file.  It is a flat CSV file.

edit1:

Here's what I've done so far:

awk -v date="$(date +"%Y-%m-%d %r")" '{ print $0","date}' lrn.ae.txt > testoutput.txt

Time = 117 minutes

perl -ne 'chomp; printf "%s.pdf\n", $_' EXPORT.txt > testoutput.txt

Time = 135 minutes

mysql load data local infile '/tmp/input.txt' into table testoutput

Time = 211 minutes

Body:
Another alternative to test is

$ date +"%Y-%m-%d %r" > timestamp
$ join -t, -j9999 file timestamp | cut -d, -f2-

or time stamp can be generated in place as well <(date +"%Y-%m-%d %r")

join creates a cross product of the first file and second file using the non-existing field (9999), and since second file is only one line, practically appending it to the first file.  Need the cut to get rid of the empty key field generated by join