问:
Create a template for general use
I have created a RadCartesianChart to plot a bar series. The xaml code is:

```<code><Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfApplication1"
    xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <telerik:RadCartesianChart x:Name="chart" Width="400" Height="300">
        <telerik:RadCartesianChart.VerticalAxis>
            <telerik:LinearAxis/>
        </telerik:RadCartesianChart.VerticalAxis>
        <telerik:RadCartesianChart.HorizontalAxis>
            <telerik:CategoricalAxis/>
        </telerik:RadCartesianChart.HorizontalAxis>
        <telerik:RadCartesianChart.Series>
            <telerik:BarSeries CategoryBinding="Category" ValueBinding="Value" ItemsSource="{Binding}">
                <telerik:BarSeries.DefaultVisualStyle>
                    <Style TargetType="Border">
                        <Setter Property="Background" Value="{Binding DataItem.Color}" />
                    </Style>
                </telerik:BarSeries.DefaultVisualStyle>
            </telerik:BarSeries>
        </telerik:RadCartesianChart.Series>
    </telerik:RadCartesianChart>
</Grid>
</code>```

And the code behind

```<code>using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = GetData(12);
        }

        public static List<ChartData> GetData(int dataSize)
        {
            Random rnd = new Random();
            var result = new List<ChartData>();

            for (int i = 0; i < dataSize; i++)
            {
                result.Add(new ChartData()
                {
                    Category = i,
                    Value = rnd.Next(1, 100),
                    Color = new SolidColorBrush(
                        Color.FromArgb(255, (byte)rnd.Next(0, 256), (byte)rnd.Next(0, 256), (byte)rnd.Next(0, 256)))
                });
            }

            return result;
        }
    }

    public class ChartData : INotifyPropertyChanged
    {
        private int _category;
        public int Category
        {
            get { return this._category; }
            set { this._category = value;
this.OnPropertyChanged("Category"); }
        }

        private double _value;
        public double Value
        {
            get { return this._value; }
            set { this._value = value; this.OnPropertyChanged("Value"); }
        }

        private Brush _color;
        public Brush Color
        {
            get { return this._color; }
            set { this._color = value; this.OnPropertyChanged("Color"); }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}
</code>```

My question is how to use the user control as a template? The reason is that we have very similar cases to plot. Do we need to create many user control for each individual controls or we can create a template to reference it?

I am not strong on contentpresenter or ContentControl or ControlTemplate something like.

答:
Declare a Style, for example in App.xaml:

```<code><Style x:Key="myStyle" TargetType="telerik:RadCartesianChart">
    <Setter Property="Width" Value="400" />
    <Setter Property="Width" Value="100" />
    <Setter Property="VerticalAxis">
        <Setter.Value>
            <telerik:LinearAxis/>
        </Setter.Value>
    </Setter>
    <Setter Property="HorizontalAxis">
        <Setter.Value>
            <telerik:CategoricalAxis/>
        </Setter.Value>
    </Setter>
    <Setter Property="Series">
        <Setter.Value>
            <telerik:BarSeries CategoryBinding="Category" ValueBinding="Value" ItemsSource="{Binding}">
                <telerik:BarSeries.DefaultVisualStyle>
                    <Style TargetType="Border">
                        <Setter Property="Background" Value="{Binding DataItem.Color}" />
                    </Style>
                </telerik:BarSeries.DefaultVisualStyle>
            </telerik:BarSeries>
        </Setter.Value>
    </Setter>
</Style>
</code>```

...and apply the Style to any RadCartesianChart using the x:Key:

```<code><telerik:RadCartesianChart x:Name="chart" Style="{StaticResource myStyle}" />
</code>```

Title: Create a template for general use

Body:
I have created a RadCartesianChart to plot a bar series. The xaml code is:

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfApplication1"
    xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <telerik:RadCartesianChart x:Name="chart" Width="400" Height="300">
        <telerik:RadCartesianChart.VerticalAxis>
            <telerik:LinearAxis/>
        </telerik:RadCartesianChart.VerticalAxis>
        <telerik:RadCartesianChart.HorizontalAxis>
            <telerik:CategoricalAxis/>
        </telerik:RadCartesianChart.HorizontalAxis>
        <telerik:RadCartesianChart.Series>
            <telerik:BarSeries CategoryBinding="Category" ValueBinding="Value" ItemsSource="{Binding}">
                <telerik:BarSeries.DefaultVisualStyle>

                </telerik:BarSeries.DefaultVisualStyle>
            </telerik:BarSeries>
        </telerik:RadCartesianChart.Series>
    </telerik:RadCartesianChart>
</Grid>

And the code behind

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = GetData(12);
        }

        public static List<ChartData> GetData(int dataSize)
        {
            Random rnd = new Random();
            var result = new List<ChartData>();

            for (int i = 0; i < dataSize; i++)
            {
                result.Add(new ChartData()
                {
                    Category = i,
                    Value = rnd.Next(1, 100),
                    Color = new SolidColorBrush(
                        Color.FromArgb(255, (byte)rnd.Next(0, 256), (byte)rnd.Next(0, 256), (byte)rnd.Next(0, 256)))
                });
            }

            return result;
        }
    }

    public class ChartData : INotifyPropertyChanged
    {
        private int _category;
        public int Category
        {
            get { return this._category; }
            set { this._category = value;
this.OnPropertyChanged("Category"); }
        }

        private double _value;
        public double Value
        {
            get { return this._value; }
            set { this._value = value; this.OnPropertyChanged("Value"); }
        }

        private Brush _color;
        public Brush Color
        {
            get { return this._color; }
            set { this._color = value; this.OnPropertyChanged("Color"); }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

My question is how to use the user control as a template? The reason is that we have very similar cases to plot. Do we need to create many user control for each individual controls or we can create a template to reference it?

I am not strong on contentpresenter or ContentControl or ControlTemplate something like.

Body:
Declare a Style, for example in App.xaml:

<Style x:Key="myStyle" TargetType="telerik:RadCartesianChart">
    <Setter Property="Width" Value="400" />
    <Setter Property="Width" Value="100" />
    <Setter Property="VerticalAxis">
        <Setter.Value>
            <telerik:LinearAxis/>
        </Setter.Value>
    </Setter>
    <Setter Property="HorizontalAxis">
        <Setter.Value>
            <telerik:CategoricalAxis/>
        </Setter.Value>
    </Setter>
    <Setter Property="Series">
        <Setter.Value>
            <telerik:BarSeries CategoryBinding="Category" ValueBinding="Value" ItemsSource="{Binding}">
                <telerik:BarSeries.DefaultVisualStyle>
                    <Style TargetType="Border">
                        <Setter Property="Background" Value="{Binding DataItem.Color}" />
                    </Style>
                </telerik:BarSeries.DefaultVisualStyle>
            </telerik:BarSeries>
        </Setter.Value>
    </Setter>
</Style>

...and apply the Style to any RadCartesianChart using the x:Key:

<telerik:RadCartesianChart x:Name="chart" Style="{StaticResource myStyle}" />


来源: stackexchange

问:
Firebase - How do I make a new table/structure?
So I am currently developing an API which gets data from Firebase and depending on that data the button changes its color. However, when I tried to make a new structure for my buttons. It won't let me make one.

I tried the answers here: How to insert data of two tables in Firebase? and here: How can I create an empty table from android app in Firebase? but neither did work for me.

Here's my sample code:

```<code>public class Normal extends AppCompatActivity {

    Button suite, normal, room1;
    private DrawerLayout mDrawerLayout;
    private ActionBarDrawerToggle mToggle;
    private DatabaseReference mFirebaseDatabase1;
    private FirebaseDatabase mFirebaseInstance;

    //FIREBASE AUTH FIELDS

    DatabaseReference mSearchedLocationReference;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_normal);

        mFirebaseInstance = FirebaseDatabase.getInstance();

        //FIREBASE
        mFirebaseDatabase1 = mFirebaseInstance.getReference("Rooms");
        mSearchedLocationReference = mFirebaseDatabase1.child("Room1").child("RoomStatus");

        //ASSIGN ID's

        room1 = (Button) findViewById(R.id.room2);

        room1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mFirebaseDatabase1.child("Rooms").child("Room1").child("RoomStatus").setValue("Green");
                startActivity(new Intent(Normal.this, room2.class));
            }
        });

        mSearchedLocationReference.addValueEventListener(new ValueEventListener() { //attach listener

            @Override
            public void onDataChange(DataSnapshot dataSnapshot) { //something changed!
                for (DataSnapshot locationSnapshot : dataSnapshot.getChildren()) {
                    String location = locationSnapshot.getValue().toString();
                    Log.d("Locations updated", "location: " + location); //log
                    if ( location.equals("Green")){
                        room1.setBackgroundColor(Color.GREEN);
                    }else if ( location.equals("Red")){
                        room1.setBackgroundColor(Color.RED);

                    }
                    else{
                        room1.setBackgroundColor(Color.YELLOW);

                    }
                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) { //update UI here if error occurred.

            }
        });

    }
}
</code>```

PS: I created the User structure (which is for my login) on another class.

答:
What i think is going wrong is that an array is returning and its last item is green

```<code>for (DataSnapshot locationSnapshot : dataSnapshot.getChildren())
</code>```

that is not letting you change the color of the button .

we will be able to help you if you show the model of your database .

ContentLicense: CC BY-SA 3.0

Body:
So I am currently developing an API which gets data from Firebase and depending on that data the button changes its color. However, when I tried to make a new structure for my buttons. It won't let me make one.

I tried the answers here: How to insert data of two tables in Firebase? and here: How can I create an empty table from android app in Firebase? but neither did work for me.

Here's my sample code:

public class Normal extends AppCompatActivity {

    Button suite, normal, room1;
    private DrawerLayout mDrawerLayout;
    private ActionBarDrawerToggle mToggle;
    private DatabaseReference mFirebaseDatabase1;
    private FirebaseDatabase mFirebaseInstance;

    //FIREBASE AUTH FIELDS

    DatabaseReference mSearchedLocationReference;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_normal);

        mFirebaseInstance = FirebaseDatabase.getInstance();

        //FIREBASE
        mFirebaseDatabase1 = mFirebaseInstance.getReference("Rooms");
        mSearchedLocationReference = mFirebaseDatabase1.child("Room1").child("RoomStatus");

        //ASSIGN ID's

        room1 = (Button) findViewById(R.id.room2);

        room1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mFirebaseDatabase1.child("Rooms").child("Room1").child("RoomStatus").setValue("Green");
                startActivity(new Intent(Normal.this, room2.class));
            }
        });

        mSearchedLocationReference.addValueEventListener(new ValueEventListener() { //attach listener

            @Override
            public void onDataChange(DataSnapshot dataSnapshot) { //something changed!
                for (DataSnapshot locationSnapshot : dataSnapshot.getChildren()) {
                    String location = locationSnapshot.getValue().toString();
                    Log.d("Locations updated", "location: " + location); //log
                    if ( location.equals("Green")){
                        room1.setBackgroundColor(Color.GREEN);
                    }else if ( location.equals("Red")){
                        room1.setBackgroundColor(Color.RED);

                    }
                    else{
                        room1.setBackgroundColor(Color.YELLOW);

                    }
                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) { //update UI here if error occurred.

            }
        });

    }
}

PS: I created the User structure (which is for my login) on another class.

Body:
What i think is going wrong is that an array is returning and its last item is green

for (DataSnapshot locationSnapshot : dataSnapshot.getChildren())

that is not letting you change the color of the button .

we will be able to help you if you show the model of your database .


问:
MySql, can anyone suggest how to improve my query / index?
Can anyone suggest how I can improve my query, its used for a site map and theres 80000 pages, hence the limit.

Heres my query

```<code>SELECT PageName
FROM pads
WHERE RemoveMeDate = '2001-01-01 00:00:00'
ORDER BY PadID DESC
LIMIT 20000 , 30000
</code>```

Heres my EXPLAIN

Heres the indexes I have already

答:
you should look into "force index" or "use index" if correct indexes are not being automatically selected.

http://dev.mysql.com/doc/refman/5.1/en/index-hints.html

ContentLicense: CC BY-SA 2.5

Body:
Can anyone suggest how I can improve my query, its used for a site map and theres 80000 pages, hence the limit.

Heres my query

SELECT PageName
FROM pads
WHERE RemoveMeDate = '2001-01-01 00:00:00'
ORDER BY PadID DESC
LIMIT 20000 , 30000

Heres my EXPLAIN

Heres the indexes I have already


问:
How to check if a key/value pair exists in a Dictionary?
How can one check if a key/value pair exists in a Dictionary<TKey,TValue>? I'm able to check if a key or value exist, using ContainsKey and ContainsValue, but I'm unsure of how to check if a key/value pair exist.

答:
Generic version of Jon Skeet's answer</p>

```<code>        public bool ContainsKeyValue<TKey, TVal>(Dictionary<TKey, TVal> dictionnaire,
                                             TKey expectedKey,
                                             TVal expectedValue) where TVal : IComparable
    {
        TVal actualValue;

        if (!dictionnaire.TryGetValue(expectedKey, out actualValue))
        {
            return false;
        }
        return actualValue.CompareTo(expectedValue) == 0;
    }
</code>```

ContentLicense: CC BY-SA 4.0

Body:
Generic version of Jon Skeet's answer

        public bool ContainsKeyValue<TKey, TVal>(Dictionary<TKey, TVal> dictionnaire,
                                             TKey expectedKey,
                                             TVal expectedValue) where TVal : IComparable
    {
        TVal actualValue;

        if (!dictionnaire.TryGetValue(expectedKey, out actualValue))
        {
            return false;
        }
        return actualValue.CompareTo(expectedValue) == 0;
    }


问:
console.log prints changed state before changing
I'm trying to rearrange div's with React/Redux via Drag&Drop and there is a strange behavoir that i cant explain. I have the following reducer (reduced version for readability)

There are 5 "console.log" around the middle of the code. When i log state or structs the chrome console will print the already rearrange version. why?

```<code>export default function reducer(
    state={
        structures: [],
        elementUniqueCounter: 0,
        hoveredElement: null,
        DnD: {
            dragContent: null,
            dragOverContent: null,
            dragContentTop: true,
            dragStructure: null,
            dragOverStructure: null,
            dragStructureTop: true,
            content: null,
            mousepositon: {}
        }
    }, action) {
    let DnD = Object.assign({}, state.DnD);
    let structs = state.structures.slice();
    switch (action.type) {
        case "STOP_DRAG_CONTENT":
            let cindex_source;
            let index_source;
            let cindex_target;
            let index_target;
            let foundTarget = false;
            let foundSource = false;

            structs.map(function (struct, index) {
                struct.content.map(function (content, cindex) {
                    if(content.id === DnD.dragOverContent.props.id) {
                        cindex_target = cindex;
                        index_target = index;
                        foundTarget = true;
                    }
                    if(content.id === DnD.dragContent.props.id) {
                        cindex_source = cindex;
                        index_source = index;
                        foundSource = true;
                    }
                });
            });
            console.log(state);
            console.log(index_source);
            console.log(cindex_source);
            console.log(index_target);
            console.log(cindex_target);
            if(index_source !== undefined && cindex_source !== undefined && index_target !== undefined && cindex_target !== undefined) {
                let copy = structs[index_source].content.slice(cindex_source, cindex_source+1)[0];
                copy.content = DnD.content;
                structs[index_source].content.splice(cindex_source, 1);
                if (DnD.dragContentTop) {
                    structs[index_target].content.splice(cindex_target+1, 0, copy);
                } else {
                    structs[index_target].content.splice(cindex_target, 0, copy);
                }
            }

            DnD = {
                dragContent: null,
                dragOverContent: null,
                dragContentTop: true,
                dragStructure: null,
                dragOverStructure: null,
                dragStructureTop: true,
                content: null,
                mousepositon: {}
            };
            return {...state, DnD: DnD, structures: structs};

    }

    return state
}
</code>```

答:
It's not that it is printing the rearranged version before it happens. It is that it is printing an object that you are mutating. By the time you look at the object in the console the mutation has already occurred.

The use of splice is mutating.

```<code>structs[index_source].content.splice(cindex_source, 1);
if (DnD.dragContentTop) {
    structs[index_target].content.splice(cindex_target+1, 0, copy);
} else {
    structs[index_target].content.splice(cindex_target, 0, copy);
}
</code>```

EDIT:

The above mutation is actually mutating the nested properties of state.structures. This is happening because .slice() returns a shallow copy of the original object.

The slice() method returns a shallow copy of a portion of an array into a new array object selected from begin to end (end not included). The original array will not be modified.

The objects in the shallow copy are just pointers to the objects in state.structures. So when you use .splice(), you mutate those referenced values.

Here is a snippet to illustrate this. Run it an look at the console.log.

const people = [
 {
  name: "Joe",
  age: "52"
 },
 {
  name: "Sally",
  age: "48"
 }

];

const clonedPeople = people.slice();

console.log("people === clonedPeople: ", people === clonedPeople);
console.log("people[0] === clonedPeople[0]: ", people[0] === clonedPeople[0]);

const deeplyClonedPeople = JSON.parse(JSON.stringify(people));

console.log("people[0] === deeplyClonedPeople[0]: ", people[0] === deeplyClonedPeople[0]);```

Hope this helps!

Body:
I'm trying to rearrange div's with React/Redux via Drag&Drop and there is a strange behavoir that i cant explain. I have the following reducer (reduced version for readability)

There are 5 "console.log" around the middle of the code. When i log state or structs the chrome console will print the already rearrange version. why?

export default function reducer(
    state={
        structures: [],
        elementUniqueCounter: 0,
        hoveredElement: null,
        DnD: {
            dragContent: null,
            dragOverContent: null,
            dragContentTop: true,
            dragStructure: null,
            dragOverStructure: null,
            dragStructureTop: true,
            content: null,
            mousepositon: {}
        }
    }, action) {
    let DnD = Object.assign({}, state.DnD);
    let structs = state.structures.slice();
    switch (action.type) {
        case "STOP_DRAG_CONTENT":
            let cindex_source;
            let index_source;
            let cindex_target;
            let index_target;
            let foundTarget = false;
            let foundSource = false;

            structs.map(function (struct, index) {
                struct.content.map(function (content, cindex) {
                    if(content.id === DnD.dragOverContent.props.id) {
                        cindex_target = cindex;
                        index_target = index;
                        foundTarget = true;
                    }
                    if(content.id === DnD.dragContent.props.id) {
                        cindex_source = cindex;
                        index_source = index;
                        foundSource = true;
                    }
                });
            });
            console.log(state);
            console.log(index_source);
            console.log(cindex_source);
            console.log(index_target);
            console.log(cindex_target);
            if(index_source !== undefined && cindex_source !== undefined && index_target !== undefined && cindex_target !== undefined) {
                let copy = structs[index_source].content.slice(cindex_source, cindex_source+1)[0];
                copy.content = DnD.content;
                structs[index_source].content.splice(cindex_source, 1);
                if (DnD.dragContentTop) {
                    structs[index_target].content.splice(cindex_target+1, 0, copy);
                } else {
                    structs[index_target].content.splice(cindex_target, 0, copy);
                }
            }

            DnD = {
                dragContent: null,
                dragOverContent: null,
                dragContentTop: true,
                dragStructure: null,
                dragOverStructure: null,
                dragStructureTop: true,
                content: null,
                mousepositon: {}
            };
            return {...state, DnD: DnD, structures: structs};

    }

    return state
}

Body:
It's not that it is printing the rearranged version before it happens. It is that it is printing an object that you are mutating. By the time you look at the object in the console the mutation has already occurred.

The use of splice is mutating.

structs[index_source].content.splice(cindex_source, 1);
if (DnD.dragContentTop) {
    structs[index_target].content.splice(cindex_target+1, 0, copy);
} else {
    structs[index_target].content.splice(cindex_target, 0, copy);
}

EDIT:

The above mutation is actually mutating the nested properties of state.structures. This is happening because .slice() returns a shallow copy of the original object.

The slice() method returns a shallow copy of a portion of an array into a new array object selected from begin to end (end not included). The original array will not be modified.

The objects in the shallow copy are just pointers to the objects in state.structures. So when you use .splice(), you mutate those referenced values.

Here is a snippet to illustrate this. Run it an look at the console.log.

const people = [
 {
  name: "Joe",
  age: "52"
 },
 {
  name: "Sally",
  age: "48"
 }

];

const clonedPeople = people.slice();

console.log("people === clonedPeople: ", people === clonedPeople);
console.log("people[0] === clonedPeople[0]: ", people[0] === clonedPeople[0]);

const deeplyClonedPeople = JSON.parse(JSON.stringify(people));

console.log("people[0] === deeplyClonedPeople[0]: ", people[0] === deeplyClonedPeople[0]);

Hope this helps!


问:
FirebaseRecyclerAdapter with empty view
I know there are lot of ways to have an empty view for a RecyclerView. But my question is for FirebaseRecyclerView.

My layout is:

```<code><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.v7.widget.RecyclerView
    android:id="@+id/feed_recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scrollbars="vertical" />

<ProgressBar
    android:id="@+id/feed_loading"
    style="?android:attr/progressBarStyle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:visibility="gone"/>
</RelativeLayout>
</code>```

So I am showing Loading ProgressBar before the RecyclerView fills its items. Now what if server doesn't have any item. In this situation my RecyclerView is empty always and my Loading ProgressBar always visible to user.

So instead of showing the ProgressBar for indefinite period, I want to show some empty layout. E.g. "No Data Found" or something similar message.

The final result should be: ProgressBar should be shown until data is loaded to RecyclerView and once data is loaded ProgressBar should be invisible. But if no data is present in server, some empty layout should be shown instead of ProgressBar.

In normal RecyclerView, we have a dataset (some ArrayList, etc) and if it is empty then we can show that empty layout. But in case of FirebaseRecyclerAdapter, I dont have the reference of Snapshot in my Activity or Context. Nor I have any callback which tells me that no data is present in server.

Any workaround will help a lot.

答:
Answer from: https://stackoverflow.com/a/40204298/2170278

the FirebaseUI adapters nowadays have an onDataChanged() method that you can override to detect when they're done loading a set of data.

See the source code on github. From there:

This method will be triggered each time updates from the database have been completely processed. So the first time this method is called, the initial data has been loaded - including the case when no data at all is available. Each next time the method is called, a complete update (potentially consisting of updates to multiple child items) has been completed.

You would typically override this method to hide a loading indicator (after the initial load) or to complete a batch update to a UI element.

The FirebaseUI sample app overrides onDataChanged() to hide its "loading" indicator:

```<code>public void onDataChanged() {
    // If there are no chat messages, show a view that invites the user to add a message.
    mEmptyListMessage.setVisibility(getItemCount() == 0 ? View.VISIBLE : View.GONE);
}
</code>```

Title: FirebaseRecyclerAdapter with empty view

Body:
I know there are lot of ways to have an empty view for a RecyclerView. But my question is for FirebaseRecyclerView.

My layout is:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.v7.widget.RecyclerView
    android:id="@+id/feed_recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scrollbars="vertical" />

<ProgressBar
    android:id="@+id/feed_loading"
    style="?android:attr/progressBarStyle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:visibility="gone"/>
</RelativeLayout>

So I am showing Loading ProgressBar before the RecyclerView fills its items. Now what if server doesn't have any item. In this situation my RecyclerView is empty always and my Loading ProgressBar always visible to user.

So instead of showing the ProgressBar for indefinite period, I want to show some empty layout. E.g. "No Data Found" or something similar message.

The final result should be: ProgressBar should be shown until data is loaded to RecyclerView and once data is loaded ProgressBar should be invisible. But if no data is present in server, some empty layout should be shown instead of ProgressBar.

In normal RecyclerView, we have a dataset (some ArrayList, etc) and if it is empty then we can show that empty layout. But in case of FirebaseRecyclerAdapter, I dont have the reference of Snapshot in my Activity or Context. Nor I have any callback which tells me that no data is present in server.

Any workaround will help a lot.

Body:
Answer from: https://stackoverflow.com/a/40204298/2170278

the FirebaseUI adapters nowadays have an onDataChanged() method that you can override to detect when they're done loading a set of data.

See the source code on github. From there:

This method will be triggered each time updates from the database have been completely processed. So the first time this method is called, the initial data has been loaded - including the case when no data at all is available. Each next time the method is called, a complete update (potentially consisting of updates to multiple child items) has been completed.

You would typically override this method to hide a loading indicator (after the initial load) or to complete a batch update to a UI element.

The FirebaseUI sample app overrides onDataChanged() to hide its "loading" indicator:

public void onDataChanged() {
    // If there are no chat messages, show a view that invites the user to add a message.
    mEmptyListMessage.setVisibility(getItemCount() == 0 ? View.VISIBLE : View.GONE);
}


问:
Copy rows into same table, but change value of one field
I have a list of values:

```<code>(56957,85697,56325,45698,21367,56397,14758,39656)
</code>```

and a 'template' row in a table.

I want to do this:

```<code>for value in valuelist:
{
insert into table1 (field1, field2, field3, field4)
select value1, value2, value3, (value)
from table1
where ID = (ID of template row)
}
</code>```

I know how I would do this in code, like c# for instance, but I'm not sure how to 'loop' this while passing in a new value to the insert statement. (i know that code makes no sense, just trying to convey what I'm trying to accomplish.

答:
There is no need to loop here, SQL is a set based language and you apply your operations to entire sets of data all at once as opposed to looping through row by row.

insert statements can come from either an explicit list of values or from the result of a regular select statement, for example:

```<code>insert into table1(col1, col2)
select col3
      ,col4
from table2;
</code>```

There is nothing stopping you selecting your data from the same place you are inserting to, which will duplicate all your data:

```<code>insert into table1(col1, col2)
select col1
      ,col2
from table1;
</code>```

If you want to edit one of these column values - say by incrementing the value currently held, you simply apply this logic to your select statement and make sure the resultant dataset matches your target table in number of columns and data types:

```<code>insert into table1(col1, col2)
select col1
      ,col2+1 as col2
from table1;
</code>```

Optionally, if you only want to do this for a subset of those values, just add a standard where clause:

```<code>insert into table1(col1, col2)
select col1
      ,col2+1 as col2
from table1
where col1 = <your value>;
</code>```

Now if this isn't enough for you to work it out by yourself, you can join your dataset to you values list to get a version of the data to be inserted for each value in that list.  Because you want each row to join to each value, you can use a cross join:

```<code>declare @v table(value int);
insert into @v values(56957),(85697),(56325),(45698),(21367),(56397),(14758),(39656);

insert into table1(col1, col2, value)
select t.col1
      ,t.col2
      ,v.value
from table1 as t
    cross join @v as v
</code>```

Body:
I have a list of values:

(56957,85697,56325,45698,21367,56397,14758,39656)

and a 'template' row in a table.

I want to do this:

for value in valuelist:
{
insert into table1 (field1, field2, field3, field4)
select value1, value2, value3, (value)
from table1
where ID = (ID of template row)
}

I know how I would do this in code, like c# for instance, but I'm not sure how to 'loop' this while passing in a new value to the insert statement. (i know that code makes no sense, just trying to convey what I'm trying to accomplish.

Body:
There is no need to loop here, SQL is a set based language and you apply your operations to entire sets of data all at once as opposed to looping through row by row.

insert statements can come from either an explicit list of values or from the result of a regular select statement, for example:

insert into table1(col1, col2)
select col3
      ,col4
from table2;

There is nothing stopping you selecting your data from the same place you are inserting to, which will duplicate all your data:

insert into table1(col1, col2)
select col1
      ,col2
from table1;

If you want to edit one of these column values - say by incrementing the value currently held, you simply apply this logic to your select statement and make sure the resultant dataset matches your target table in number of columns and data types:

insert into table1(col1, col2)
select col1
      ,col2+1 as col2
from table1;

Optionally, if you only want to do this for a subset of those values, just add a standard where clause:

insert into table1(col1, col2)
select col1
      ,col2+1 as col2
from table1
where col1 = <your value>;

Now if this isn't enough for you to work it out by yourself, you can join your dataset to you values list to get a version of the data to be inserted for each value in that list.  Because you want each row to join to each value, you can use a cross join:

declare @v table(value int);
insert into @v values(56957),(85697),(56325),(45698),(21367),(56397),(14758),(39656);

insert into table1(col1, col2, value)
select t.col1
      ,t.col2
      ,v.value
from table1 as t
    cross join @v as v


问:
Dynamics Ax: Alert when any record changes
I want to send an alert in Ax, when any field in the vendor table changes (and on create/delete of a record).

In the alert, I would like to include the previous and current value.

But, it appears that you can't set alerts for when any field in a table changes, but need to set one up for EVERY FIELD?!  I hope I am mistaken.

And how can I send this notification to a group of people

答:
I  do agree with suggestion of Skaue.you just write and class to send the mail of changes in vend table.
and execute this class on update method of vendtable.

thanks and Regards,
Deepak Kumar


问:
Chaining string operations on Pandas Series
I recently found out about the str method for Pandas series and it's great! However if I want to chain operations (say, a couple replace and a strip) I need to keep calling str after every operation, making it not the most elegant code.

For example, lets say my column names contain spaces and periods and I want to replace them by underscores. I might also want to strip any leftover underscores. If I wanted to do this using str methods, is there any way of avoiding having to run:

df.columns.str.replace(' ', '_').str.replace('.', '_').str.strip('_')

Thanks!

答:
I think need str repeat for each .str function, it is per design.

But here is possible use only one replace:

```<code>df = pd.DataFrame(columns=['aa dd', 'dd.d_', 'd._'])

print (df)
Empty DataFrame
Columns: [aa dd, dd.d_, d._]
Index: []

print (df.columns.str.replace('[\s+.]', '_').str.strip('_'))
Index(['aa_dd', 'dd_d', 'd'], dtype='object')
</code>```

Body:
I think need str repeat for each .str function, it is per design.

But here is possible use only one replace:

df = pd.DataFrame(columns=['aa dd', 'dd.d_', 'd._'])

print (df)
Empty DataFrame
Columns: [aa dd, dd.d_, d._]
Index: []

print (df.columns.str.replace('[\s+.]', '_').str.strip('_'))
Index(['aa_dd', 'dd_d', 'd'], dtype='object')


问:
While sending mail with javamail on google app engine I get Error: HTTP method POST is not supported by this URL
When i use form sending data to servlet which uses function from bean to send email and everything is on GAE i get this massage: "Error: 405 HTTP method POST is not supported by this URL". Please help me, what is wrong here, because i can't find any solution for few days.

Form:

```<code><form action="/SendEmailServlet" method="POST">
  <table>
    <tr>
      <td><b>To:</b></td>
      <td><input type="text" id="to" name="to" size="75" value="email"></td>
    </tr>
    <tr>
      <td><b>Subject:</b></td>
      <td><input type="text" id="subject" name="subject" size="75" value="test">
      </td>
    </tr>
    <tr>
      <td><b>Message:</b></td>
      <td><input type="text" id="content" name="content" value="test" size="75"></td>
    </tr>
    <tr>
      <td></td>
      <td><input type="submit" value="Send"></td>
    </tr>
  </table>
</form>
</code>```

Servlet:

```<code>@WebServlet(name = "/SendEmailServlet", urlPatterns = {"/SendEmailServlet"})
public class SendEmailServlet extends HttpServlet {
@EJB
private EmailSessionBean emailBean;

protected void processRequest(HttpServletRequest request,
        HttpServletResponse response) throws ServletException, IOException, MessagingException{

    String toAddress = request.getParameter("to");
    String subject = request.getParameter("subject");
    String content = request.getParameter("content");

        emailBean.sendEmail(toAddress,subject,content);

        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();

        try {
          out.println("<html>");
          out.println("<head>");
          out.println("<titleServlet SendEmailServlet</title>");
          out.println("</head>");
          out.println("<body>");
          out.println("<h1> Form Submitted</h1>");
          out.println("</body>");
          out.println("</html>");
        } finally {
          out.close();
        }
}
</code>```

}

Bean is working well I suppose, because when I use it in main function I receive mail.

答:
You probably need to override the doPost method in your HttpServlet to be able to accept a POST:

https://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServlet.html#doPost-javax.servlet.http.HttpServletRequest-javax.servlet.http.HttpServletResponse-

Body:
When i use form sending data to servlet which uses function from bean to send email and everything is on GAE i get this massage: "Error: 405 HTTP method POST is not supported by this URL". Please help me, what is wrong here, because i can't find any solution for few days.

Form:

<form action="/SendEmailServlet" method="POST">

      To:
      <input type="text" id="to" name="to" size="75" value="email">

      Subject:
      <input type="text" id="subject" name="subject" size="75" value="test">

      Message:
      <input type="text" id="content" name="content" value="test" size="75">

      <input type="submit" value="Send">

</form>

Servlet:

@WebServlet(name = "/SendEmailServlet", urlPatterns = {"/SendEmailServlet"})
public class SendEmailServlet extends HttpServlet {
@EJB
private EmailSessionBean emailBean;

protected void processRequest(HttpServletRequest request,
        HttpServletResponse response) throws ServletException, IOException, MessagingException{

    String toAddress = request.getParameter("to");
    String subject = request.getParameter("subject");
    String content = request.getParameter("content");

        emailBean.sendEmail(toAddress,subject,content);

        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();

        try {
          out.println("");
          out.println("");
          out.println("<titleServlet SendEmailServlet</title>");
          out.println("");
          out.println("");
          out.println("
 Form Submitted
");
          out.println("");
          out.println("");
        } finally {
          out.close();
        }
}

}

Bean is working well I suppose, because when I use it in main function I receive mail.


问:
Underlying element not clickable
I have to render two elements in two different (bootstrap's) rows, the bottom one must be behind the topmost. I can't understand why the underlying one is not catching pointer events.

.smaller-square {
  width: 50px;
  height: 50px;
  background-color: yellow
}

.bigger-square {
  width: 100px;
  height: 100px;
  background-color: green
}

.overlay {
  z-index: 0;
}

.underlay {
  z-index: -1;
  position: relative;
  top: -5px;
  left: 0px;
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container">
  <div class="row overlay">
  <div class="smaller-square" onclick="alert('yellow');">
  </div>
  </div>
  <div class="row underlay">
  <div class="bigger-square" onclick="alert('green');">
  </div>
  </div>
</div></code>```

答:
Declare position: relativeto the containing element .container so that you can apply a stacking context to it by declaring a z-index property.

You don't even need the z-index property declared on the sibling element .overlay since it is not a "positioned element" - which is to say it is positioned static and not absolute (absolute & fixed) or relative. So z-index would not apply.

.smaller-square {
  width: 50px;
  height: 50px;
  background-color: yellow
}

.bigger-square {
  width: 100px;
  height: 100px;
  background-color: green
}

.overlay {
/* redundant unless you declare a position property for this element
   that is not "static" - which is the default positioning for any element */
  z-index: 0;
}

.underlay {
  z-index: -1;
  position: relative;
  top: -5px;
  left: 0px;
}

/* Additional */

.container {
  position: relative;
  z-index: 1;
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" rel="stylesheet" />
<div class="container">
  <div class="row overlay">
    <div class="smaller-square" onclick="alert('yellow');">
    </div>
  </div>
  <div class="row underlay">
    <div class="bigger-square" onclick="alert('green');">
    </div>
  </div>
</div></code>```

Title: Underlying element not clickable

Body:
I have to render two elements in two different (bootstrap's) rows, the bottom one must be behind the topmost. I can't understand why the underlying one is not catching pointer events.

.smaller-square {
  width: 50px;
  height: 50px;
  background-color: yellow
}

.bigger-square {
  width: 100px;
  height: 100px;
  background-color: green
}

.overlay {
  z-index: 0;
}

.underlay {
  z-index: -1;
  position: relative;
  top: -5px;
  left: 0px;
}

<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" rel="stylesheet"/>

Body:
Declare position: relativeto the containing element .container so that you can apply a stacking context to it by declaring a z-index property.

You don't even need the z-index property declared on the sibling element .overlay since it is not a "positioned element" - which is to say it is positioned static and not absolute (absolute & fixed) or relative. So z-index would not apply.

.smaller-square {
  width: 50px;
  height: 50px;
  background-color: yellow
}

.bigger-square {
  width: 100px;
  height: 100px;
  background-color: green
}

.overlay {
/* redundant unless you declare a position property for this element
   that is not "static" - which is the default positioning for any element */
  z-index: 0;
}

.underlay {
  z-index: -1;
  position: relative;
  top: -5px;
  left: 0px;
}

/* Additional */

.container {
  position: relative;
  z-index: 1;
}

<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" rel="stylesheet" />
<div class="container">
  <div class="row overlay">
    <div class="smaller-square" onclick="alert('yellow');">
    </div>
  </div>
  <div class="row underlay">
    <div class="bigger-square" onclick="alert('green');">
    </div>
  </div>
</div>


问:
AppleScript how to get current display resolution?
I'm trying to get the current display resolution of both of my displays depending on where the mouse cursor is.

i.e. when the mouse cursor is on the first display I want to get the resolution of this display.

With a shell script I can get both resolutions:

```<code>set screenWidth to (do shell script "system_profiler SPDisplaysDataType | grep Resolution | awk '{print $2}'")
</code>```

But I don't get which display is currently "active".

Any ideas?

答:
On my machine system_profiler takes nearly a second to return a reply. For my purposes, that way too long.

Pre-10.12, I used ASObjC Runner but apparently that no longer works.

This is much faster for me:

tell application "Finder" to get bounds of window of desktop

(Taken from https://superuser.com/a/735330/64606)

Body:
I'm trying to get the current display resolution of both of my displays depending on where the mouse cursor is.

i.e. when the mouse cursor is on the first display I want to get the resolution of this display.

With a shell script I can get both resolutions:

set screenWidth to (do shell script "system_profiler SPDisplaysDataType | grep Resolution | awk '{print $2}'")

But I don't get which display is currently "active".

Any ideas?


问:
Unable to build mex file
I've followed the MATLAB example for creating a mex file from here https://uk.mathworks.com/help/matlab/matlab_external/standalone-example.html

The source code it produces is as follows

```<code>#include "mex.h"

/* The computational routine */
void arrayProduct(double x, double *y, double *z, mwSize n)
{
    mwSize i;
    /* multiply each element y by x */
    for (i=0; i<n; i++) {
        z[i] = x * y[i];
    }
}

/* The gateway function */
void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[])
{
    double multiplier;              /* input scalar */
    double *inMatrix;               /* 1xN input matrix */
    size_t ncols;                   /* size of matrix */
    double *outMatrix;              /* output matrix */

    /* check for proper number of arguments */
    if(nrhs!=2) {
        mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nrhs","Two inputs required.");
    }
    if(nlhs!=1) {
        mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nlhs","One output required.");
    }
    /* make sure the first input argument is scalar */
    if( !mxIsDouble(prhs[0]) ||
         mxIsComplex(prhs[0]) ||
         mxGetNumberOfElements(prhs[0])!=1 ) {
        mexErrMsgIdAndTxt("MyToolbox:arrayProduct:notScalar","Input multiplier must be a scalar.");
    }

    /* make sure the second input argument is type double */
    if( !mxIsDouble(prhs[1]) ||
         mxIsComplex(prhs[1])) {
        mexErrMsgIdAndTxt("MyToolbox:arrayProduct:notDouble","Input matrix must be type double.");
    }

    /* check that number of rows in second input argument is 1 */
    if(mxGetM(prhs[1])!=1) {
        mexErrMsgIdAndTxt("MyToolbox:arrayProduct:notRowVector","Input must be a row vector.");
    }

    /* get the value of the scalar input  */
    multiplier = mxGetScalar(prhs[0]);

    /* create a pointer to the real data in the input matrix  */
    inMatrix = mxGetPr(prhs[1]);

    /* get dimensions of the input matrix */
    ncols = mxGetN(prhs[1]);

    /* create the output matrix */
    plhs[0] = mxCreateDoubleMatrix(1,(mwSize)ncols,mxREAL);

    /* get a pointer to the real data in the output matrix */
    outMatrix = mxGetPr(plhs[0]);

    /* call the computational routine */
    arrayProduct(multiplier,inMatrix,outMatrix,(mwSize)ncols);
}
</code>```

When I run the command mex arrayProduct.cpp (the name of my file), I get the following error:

Building with 'Microsoft Visual C++ 2017'.
  Error using mex
  LINK : error LNK2001: unresolved external symbol mexfilerequiredapiversion
  arrayProduct.lib : fatal error LNK1120: 1 unresolved externals

I'm using MATLAB 2015b 32-bit, with the Visual Studio 2017 C++ compiler. Is there some preliminary set-up required for making mex files that isn't mentioned in the MATLAB tutorial?

答:
The youngest supported compiler for MATLAB R2015b is MSVC Professional 2015. Also, R2015b is the latest version with 32-bit support. Your compiler is probably MSVC 2017, 64-bit.

Try to install .NET4 + SDK 7.1, select that in MATLAB, and re-run your mex command. That is an officially supported compiler for R2015b, and I expect that that solves your problem.

Note: for me, .NET4 refused to install because it detected a previously installed framework, but this answer resolved that problem for me.

Title: Unable to build mex file

Body:
I've followed the MATLAB example for creating a mex file from here https://uk.mathworks.com/help/matlab/matlab_external/standalone-example.html

The source code it produces is as follows

#include "mex.h"

/* The computational routine */
void arrayProduct(double x, double *y, double *z, mwSize n)
{
    mwSize i;
    /* multiply each element y by x */
    for (i=0; i<n; i++) {
        z[i] = x * y[i];
    }
}

/* The gateway function */
void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[])
{
    double multiplier;              /* input scalar */
    double *inMatrix;               /* 1xN input matrix */
    size_t ncols;                   /* size of matrix */
    double *outMatrix;              /* output matrix */

    /* check for proper number of arguments */
    if(nrhs!=2) {
        mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nrhs","Two inputs required.");
    }
    if(nlhs!=1) {
        mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nlhs","One output required.");
    }
    /* make sure the first input argument is scalar */
    if( !mxIsDouble(prhs[0]) ||
         mxIsComplex(prhs[0]) ||
         mxGetNumberOfElements(prhs[0])!=1 ) {
        mexErrMsgIdAndTxt("MyToolbox:arrayProduct:notScalar","Input multiplier must be a scalar.");
    }

    /* make sure the second input argument is type double */
    if( !mxIsDouble(prhs[1]) ||
         mxIsComplex(prhs[1])) {
        mexErrMsgIdAndTxt("MyToolbox:arrayProduct:notDouble","Input matrix must be type double.");
    }

    /* check that number of rows in second input argument is 1 */
    if(mxGetM(prhs[1])!=1) {
        mexErrMsgIdAndTxt("MyToolbox:arrayProduct:notRowVector","Input must be a row vector.");
    }

    /* get the value of the scalar input  */
    multiplier = mxGetScalar(prhs[0]);

    /* create a pointer to the real data in the input matrix  */
    inMatrix = mxGetPr(prhs[1]);

    /* get dimensions of the input matrix */
    ncols = mxGetN(prhs[1]);

    /* create the output matrix */
    plhs[0] = mxCreateDoubleMatrix(1,(mwSize)ncols,mxREAL);

    /* get a pointer to the real data in the output matrix */
    outMatrix = mxGetPr(plhs[0]);

    /* call the computational routine */
    arrayProduct(multiplier,inMatrix,outMatrix,(mwSize)ncols);
}

When I run the command mex arrayProduct.cpp (the name of my file), I get the following error:

Building with 'Microsoft Visual C++ 2017'.
  Error using mex
  LINK : error LNK2001: unresolved external symbol mexfilerequiredapiversion
  arrayProduct.lib : fatal error LNK1120: 1 unresolved externals

I'm using MATLAB 2015b 32-bit, with the Visual Studio 2017 C++ compiler. Is there some preliminary set-up required for making mex files that isn't mentioned in the MATLAB tutorial?


问:
How to parse the bcompare xml report using DOM/SAX or any parser in java
In our project, we wants to generate the excel report from xml which has all differences of two folders.

I tried to get the full path of a file from xml nodes, but i am confusing with node names because all parent nodes(foldercomp) have same name.

And can create xsd for this xml format , inner classes with same class names are not accepting in xsd complex types.

Can you please help me on this

Below is the bcompare xml report:

```<code><?xml version="1.0" encoding="utf-8"?>
<bcreport created="16-11-2017 20:20:54">
<foldercomp>
    <ltpath>E:\compare\CODE1</ltpath>
    <rtpath>E:\compare\CODE2</rtpath>
    <mode>Differences</mode>
    <foldercomp>
        <lt>
            <name>Dir1</name>
            <size>696</size>
        </lt>
        <rt>
            <name>Dir1</name>
            <size>846</size>
        </rt>
        <foldercomp>
            <lt>
                <name>Dir3</name>
                <size>424</size>
            </lt>
            <rt>
                <name>Dir3</name>
                <size>431</size>
            </rt>
            <foldercomp>
                <lt>
                    <name>Dir4</name>
                    <size>281</size>
                </lt>
                <rt>
                    <name>Dir4</name>       <!-- E:\compare\CODE2\Dir1\Dir3\Dir4  -->
                    <size>288</size>
                </rt>
                <filecomp status="rtnewer">
                    <lt>
                        <name>File5 (2).txt</name>  <!-- E:\compare\CODE1\Dir1\Dir3\Dir4\File5 (2).txt -->
                        <size>139</size>
                    </lt>
                    <rt>
                        <name>File5 (2).txt</name>   <!-- E:\compare\CODE2\Dir1\Dir3\Dir4\File5 (2).txt -->
                        <size>146</size>
                    </rt>
                </filecomp>
            </foldercomp>
        </foldercomp>
        <filecomp status="rtonly">
            <rt>
                <name>File1 (1).txt</name>  <!-- E:\compare\CODE2\File1 (1).txt -->
                <size>143</size>
            </rt>
        </filecomp>
    </foldercomp>
    <foldercomp>
        <lt>
            <name>Dir2</name>
            <size>286</size>
        </lt>
        <rt>
            <name>Dir2</name>
            <size>296</size>
        </rt>
        <filecomp status="rtnewer">
            <lt>
                <name>File2.txt</name>   <!-- E:\compare\CODE1\Dir2\File2.txt -->
                <size>143</size>
            </lt>
            <rt>
                <name>File2.txt</name>   <!-- E:\compare\CODE2\Dir2\File2.txt -->
                <size>153</size>
            </rt>
        </filecomp>
    </foldercomp>
    <filecomp status="rtnewer">
        <lt>
            <name>File1 (2).txt</name>   <!-- E:\compare\CODE1\File1 (2).txt -->
            <size>132</size>
        </lt>
        <rt>
            <name>File1 (2).txt</name>  <!-- -E:\compare\CODE1\File1 (2).txt -->
            <size>139</size>
        </rt>
    </filecomp>
    <filecomp status="rtnewer">
        <lt>
            <name>File1 (3).txt</name>   <!-- E:\compare\CODE1\File1 (3).txt -->
            <size>144</size>
        </lt>
        <rt>
            <name>File1 (3).txt</name>  <!-- E:\compare\CODE2\File1 (3).txt -->
            <size>150</size>
        </rt>
    </filecomp>
</foldercomp>
</code>```

lt - CODE1, rt- CODE2, foldercomp and filecomp tags for diff in folder and file

答:
The XML output makes sense to me. What I understand from this is:

```<code>Dir1
 |
 +-- Dir3
 |    |
 |    +Dir4
 |      |
 |      +File5
(etc)
</code>```

A folder may have more folders, and a folder may have many files. For each comparison, there is left and right items. So,what you need to do is to re-think about your strategy of parsing. Each foldercomp has at least 2 (and possibly more) children, and each filecomp tag has two (or more) children.

If I were you, I would use foldercomp and filecomp  open tags to increment row and column value by 1, close tags to decrement column while incrementing row by 1 in a similar fashion. And lt and rt open tags to increment row values (not column) and ignore close tag of the same. I would print folder and file names in bold, and leave the differences in normal.

The status on filecomp give you an idea about the nature of the difference. So, if it is rtnew, it means, it is added. I would use green etc.

It should be too hard to implement it via sax parser.

I hope it makes sense.

EDIT:

If you need example code for SAX parser, here it is.

I have given you the lead but I won't do your job. Sorry.

EDIT2:

Using SAX parser is really easy. Check out the documentation and example above.

Think about parsing XML with a sax parser is as a switch/case statement. When current tag is something, do what you need to do, when something else, do whatever is needed etc. You may need to keep the context as well.

```<code>switch(tag){

  foldercomp:
    ops
  filecomp:
    ops
  rt:
    ops
  lt:
    ops

}
</code>```

Try it yourself to see. If you run into wall by implementing it, fellow stackoverflow users, including myself would be pleased to help. But you need to try first.

Cheers.

Body:
In our project, we wants to generate the excel report from xml which has all differences of two folders.

I tried to get the full path of a file from xml nodes, but i am confusing with node names because all parent nodes(foldercomp) have same name.

And can create xsd for this xml format , inner classes with same class names are not accepting in xsd complex types.

Can you please help me on this

Below is the bcompare xml report:

<?xml version="1.0" encoding="utf-8"?>
<bcreport created="16-11-2017 20:20:54">
<foldercomp>
    <ltpath>E:\compare\CODE1</ltpath>
    <rtpath>E:\compare\CODE2</rtpath>
    <mode>Differences</mode>
    <foldercomp>
        <lt>
            <name>Dir1</name>
            <size>696</size>
        </lt>
        <rt>
            <name>Dir1</name>
            <size>846</size>
        </rt>
        <foldercomp>
            <lt>
                <name>Dir3</name>
                <size>424</size>
            </lt>
            <rt>
                <name>Dir3</name>
                <size>431</size>
            </rt>
            <foldercomp>
                <lt>
                    <name>Dir4</name>
                    <size>281</size>
                </lt>
                <rt>
                    <name>Dir4</name>
                    <size>288</size>
                </rt>
                <filecomp status="rtnewer">
                    <lt>
                        <name>File5 (2).txt</name>
                        <size>139</size>
                    </lt>
                    <rt>
                        <name>File5 (2).txt</name>
                        <size>146</size>
                    </rt>
                </filecomp>
            </foldercomp>
        </foldercomp>
        <filecomp status="rtonly">
            <rt>
                <name>File1 (1).txt</name>
                <size>143</size>
            </rt>
        </filecomp>
    </foldercomp>
    <foldercomp>
        <lt>
            <name>Dir2</name>
            <size>286</size>
        </lt>
        <rt>
            <name>Dir2</name>
            <size>296</size>
        </rt>
        <filecomp status="rtnewer">
            <lt>
                <name>File2.txt</name>
                <size>143</size>
            </lt>
            <rt>
                <name>File2.txt</name>
                <size>153</size>
            </rt>
        </filecomp>
    </foldercomp>
    <filecomp status="rtnewer">
        <lt>
            <name>File1 (2).txt</name>
            <size>132</size>
        </lt>
        <rt>
            <name>File1 (2).txt</name>
            <size>139</size>
        </rt>
    </filecomp>
    <filecomp status="rtnewer">
        <lt>
            <name>File1 (3).txt</name>
            <size>144</size>
        </lt>
        <rt>
            <name>File1 (3).txt</name>
            <size>150</size>
        </rt>
    </filecomp>
</foldercomp>

lt - CODE1, rt- CODE2, foldercomp and filecomp tags for diff in folder and file

Body:
The XML output makes sense to me. What I understand from this is:

Dir1
 |
 +-- Dir3
 |    |
 |    +Dir4
 |      |
 |      +File5
(etc)

A folder may have more folders, and a folder may have many files. For each comparison, there is left and right items. So,what you need to do is to re-think about your strategy of parsing. Each foldercomp has at least 2 (and possibly more) children, and each filecomp tag has two (or more) children.

If I were you, I would use foldercomp and filecomp  open tags to increment row and column value by 1, close tags to decrement column while incrementing row by 1 in a similar fashion. And lt and rt open tags to increment row values (not column) and ignore close tag of the same. I would print folder and file names in bold, and leave the differences in normal.

The status on filecomp give you an idea about the nature of the difference. So, if it is rtnew, it means, it is added. I would use green etc.

It should be too hard to implement it via sax parser.

I hope it makes sense.

EDIT:

If you need example code for SAX parser, here it is.

I have given you the lead but I won't do your job. Sorry.

EDIT2:

Using SAX parser is really easy. Check out the documentation and example above.

Think about parsing XML with a sax parser is as a switch/case statement. When current tag is something, do what you need to do, when something else, do whatever is needed etc. You may need to keep the context as well.

switch(tag){

  foldercomp:
    ops
  filecomp:
    ops
  rt:
    ops
  lt:
    ops

}

Try it yourself to see. If you run into wall by implementing it, fellow stackoverflow users, including myself would be pleased to help. But you need to try first.

Cheers.


问:
Azure SQL: Cannot connect via JDBC from Google Sheets
Trying to connect to Azure SQL from Google Sheets.

This is the code i'm using:

```<code>  var address = 'thedb.database.windows.net';
  var user = 'myuser';
  var userPwd = 'mypassword';
  var db = 'myDB';
  var instanceUrl = 'jdbc:sqlserver://' + address;
  var dbUrl = 'jdbc:sqlserver://' + address + ':1433;DatabaseName='+db;

function createDatabase() {
  var conn = Jdbc.getConnection(instanceUrl, user, userPwd);
  conn.createStatement().execute('CREATE DATABASE Test_table');
}
</code>```

However, this does not work.

The error i'm getting is below:

Azure has been configured with the IP range for Google sheets in the firewall rules:

As indicated in their documents:
https://firebase.google.com/docs/reference/rest/database/

Yet it does not work. Any ideas?

答:
Unfortunately you cannot rely on the IP address of an Azure SQL Database since the IP can change at any time as explained here.

If you still have to use IP addresses to connect to Azure SQL Database then you will have to add the whole set of Azure Datacenter IP Ranges since and endpoint of Azure SQL Database could be located on any of those IP addresses.

Body:
Trying to connect to Azure SQL from Google Sheets.

This is the code i'm using:

  var address = 'thedb.database.windows.net';
  var user = 'myuser';
  var userPwd = 'mypassword';
  var db = 'myDB';
  var instanceUrl = 'jdbc:sqlserver://' + address;
  var dbUrl = 'jdbc:sqlserver://' + address + ':1433;DatabaseName='+db;

function createDatabase() {
  var conn = Jdbc.getConnection(instanceUrl, user, userPwd);
  conn.createStatement().execute('CREATE DATABASE Test_table');
}

However, this does not work.

The error i'm getting is below:

Azure has been configured with the IP range for Google sheets in the firewall rules:

As indicated in their documents:
https://firebase.google.com/docs/reference/rest/database/

Yet it does not work. Any ideas?


问:
Using NSDictionary with added WebAPI Parameters
I'll preface by saying that I'm a little new to swift and have only taken a couple introductory courses that have lead me to building/modifying my current app. I've been having a bit of an issue with the login function on my app. I recently made some minor changes (adding a couple fields to the to the API and to the front end app to match, one being category) and I have started to see an error stating that there was an uncaught exception due to attempting to insert a non-property list object before the app crashes. I have been since trying to change the structure (using chain ifs and guard) and Type (to NSMutableDictionary) as well as setup some logic to catch the Null value that looks to be being passed with no luck.

This is the JSON plus error from the console:

```<code> Attempt to set a non-property-list object {
    imagePath = "<null>";
    email = "xxxx@xxxx.com";
    firstname = xxxx;
    id = 1;
    lastname = xxxxx;
    category = 1;
    message = "Logged in successfully";
    status = 200;
    username = xxxxxx;
 } as an NSUserDefaults/CFPreferences value for key parseJSON
 [7286:636470] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to insert non-property list object {
     ava = "<null>";
     email = "xxxxxxx@xxxxx.com";
     firstname = xxxx;
     id = 1;
     lastname = xxxxx;
     category = 1;
     message = "Logged in successfully";
     status = 200;
     username = xxxxxx;
 } for key parseJSON'
</code>```

This is the setup I have for the object.

```<code> //stores all information about current member
 var member : NSDictionary?

 @UIApplicationMain
 class AppDelegate: UIResponder, UIApplicationDelegate {

 var window: UIWindow?

 // image to be animated
 let backgroundImg = UIImageView()

 // boolean to check is erroView is currently showing or not
 var infoViewIsShowing = false

 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    // load content in member var
    member = UserDefaults.standard.value(forKey: "parseJSON") as? NSDictionary

    // if member has been logged in/registered, keep them logged in
    if member != nil {

        let id = member!["id"] as? String
        if id != nil {
            login()
        }

    }

    return true
 }
</code>```

This is an example method that I'm using to get/use the JSON for this:

```<code>    // if text is entered

        // remove keyboard
        self.view.endEditing(true)

        // shortcuts
        let username = usernameTxt.text!.lowercased()
        let password = passwordTxt.text!

        // send request to API
        // set url
        let url = URL(string: "http://xxxx.xxx/xxxx/login.php")!

        // request url
        var request = URLRequest(url: url)

        // POST to the API
        request.httpMethod = "POST"

        // append body to url
        let body = "username=\(username)&password=\(password)"

        // append body to request
        request.httpBody = body.data(using: .utf8)

        // launch session
        URLSession.shared.dataTask(with: request) { data, response, error in

            // if there's no error
            if error == nil {

                do {
                    let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary

                    guard let parseJSON = json else {
                        print("Error while parsing")
                        return
                    }

                    // remove keyboard

                    let id = parseJSON["id"] as? String

                    // successfully logged in
                    if id != nil {

                        // save member information from host
                        UserDefaults.standard.set(parseJSON, forKey: "parseJSON")
                        member = UserDefaults.standard.value(forKey: "parseJSON") as? NSDictionary

                        // go to home page
                        DispatchQueue.main.async(execute: {
                            appDelegate.login()
                        })

                    // error
                    } else {

                        // get queue to send issue info to member
                        DispatchQueue.main.async(execute: {
                            let message = parseJSON["message"] as! String
                            appDelegate.infoView(message: message, color: colorSmoothRed)
                        })
                        return

                    }

                } catch {

                    // get queue to send issue info to member
                    DispatchQueue.main.async(execute: {
                        let message = "\(error)"
                        appDelegate.infoView(message: message, color: colorSmoothRed)
                    })
                    return

                }

            } else {

                // queue to send issue info to member
                DispatchQueue.main.async(execute: {
                    let message = error!.localizedDescription
                    appDelegate.infoView(message: message, color: colorSmoothRed)
                })
                return

            }
</code>```

The field that is returning the null value is a VARCHAR field in the DB. All other fields, except ID and Category (which are both INT), are VARCHAR as well. If there is any other needed information please let me know.

Thank you in advance!

答:
I found that the method I was using was only applicable in older versions of swift. I have since updated the code to parse json using:

```<code> member = parseJSON
</code>```

And now it looks to be working as intended.

Body:
I'll preface by saying that I'm a little new to swift and have only taken a couple introductory courses that have lead me to building/modifying my current app. I've been having a bit of an issue with the login function on my app. I recently made some minor changes (adding a couple fields to the to the API and to the front end app to match, one being category) and I have started to see an error stating that there was an uncaught exception due to attempting to insert a non-property list object before the app crashes. I have been since trying to change the structure (using chain ifs and guard) and Type (to NSMutableDictionary) as well as setup some logic to catch the Null value that looks to be being passed with no luck.

This is the JSON plus error from the console:

 Attempt to set a non-property-list object {
    imagePath = "<null>";
    email = "xxxx@xxxx.com";
    firstname = xxxx;
    id = 1;
    lastname = xxxxx;
    category = 1;
    message = "Logged in successfully";
    status = 200;
    username = xxxxxx;
 } as an NSUserDefaults/CFPreferences value for key parseJSON
 [7286:636470] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to insert non-property list object {
     ava = "<null>";
     email = "xxxxxxx@xxxxx.com";
     firstname = xxxx;
     id = 1;
     lastname = xxxxx;
     category = 1;
     message = "Logged in successfully";
     status = 200;
     username = xxxxxx;
 } for key parseJSON'

This is the setup I have for the object.

 //stores all information about current member
 var member : NSDictionary?

 @UIApplicationMain
 class AppDelegate: UIResponder, UIApplicationDelegate {

 var window: UIWindow?

 // image to be animated
 let backgroundImg = UIImageView()

 // boolean to check is erroView is currently showing or not
 var infoViewIsShowing = false

 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    // load content in member var
    member = UserDefaults.standard.value(forKey: "parseJSON") as? NSDictionary

    // if member has been logged in/registered, keep them logged in
    if member != nil {

        let id = member!["id"] as? String
        if id != nil {
            login()
        }

    }

    return true
 }

This is an example method that I'm using to get/use the JSON for this:

    // if text is entered

        // remove keyboard
        self.view.endEditing(true)

        // shortcuts
        let username = usernameTxt.text!.lowercased()
        let password = passwordTxt.text!

        // send request to API
        // set url
        let url = URL(string: "http://xxxx.xxx/xxxx/login.php")!

        // request url
        var request = URLRequest(url: url)

        // POST to the API
        request.httpMethod = "POST"

        // append body to url
        let body = "username=\(username)&password=\(password)"

        // append body to request
        request.httpBody = body.data(using: .utf8)

        // launch session
        URLSession.shared.dataTask(with: request) { data, response, error in

            // if there's no error
            if error == nil {

                do {
                    let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary

                    guard let parseJSON = json else {
                        print("Error while parsing")
                        return
                    }

                    // remove keyboard

                    let id = parseJSON["id"] as? String

                    // successfully logged in
                    if id != nil {

                        // save member information from host
                        UserDefaults.standard.set(parseJSON, forKey: "parseJSON")
                        member = UserDefaults.standard.value(forKey: "parseJSON") as? NSDictionary

                        // go to home page
                        DispatchQueue.main.async(execute: {
                            appDelegate.login()
                        })

                    // error
                    } else {

                        // get queue to send issue info to member
                        DispatchQueue.main.async(execute: {
                            let message = parseJSON["message"] as! String
                            appDelegate.infoView(message: message, color: colorSmoothRed)
                        })
                        return

                    }

                } catch {

                    // get queue to send issue info to member
                    DispatchQueue.main.async(execute: {
                        let message = "\(error)"
                        appDelegate.infoView(message: message, color: colorSmoothRed)
                    })
                    return

                }

            } else {

                // queue to send issue info to member
                DispatchQueue.main.async(execute: {
                    let message = error!.localizedDescription
                    appDelegate.infoView(message: message, color: colorSmoothRed)
                })
                return

            }

The field that is returning the null value is a VARCHAR field in the DB. All other fields, except ID and Category (which are both INT), are VARCHAR as well. If there is any other needed information please let me know.

Thank you in advance!

Body:
I found that the method I was using was only applicable in older versions of swift. I have since updated the code to parse json using:

 member = parseJSON

And now it looks to be working as intended.


问:
Opening Mongo Shell using Chef
I am using chef scripts to install mongo, configure the replication and run some db initialize scripts (load("initializeScript.js"))

Mongo gets installed without any issue now but for configuring the replica members I need open mongo shell and  run commands like:

```<code>rs.initiate() and rs.add("SERVER DETAILS")
</code>```

I am trying to do it this way

```<code> mongo_shell_command = 'mongo -ssl --sslPEMKeyFile ' +node['mongo']['ssl']['dir'] +node['hostname'] + '.pem --sslCAFile ' + node['mongo']['ssl']['dir'] + node['mongo']['cert'] + ' --sslAllowInvalidHostnames'

execute 'mongo_shell' do
        command mongo_shell_command
    end

    execute 'mongo_replicaSet' do
        command "mongo --eval rs.execute()"
        only_if { ::File.exist?(node['mongo']['config']) }
    end
execute 'initialize_db' do
             command "mongo --eval \"load(\"initializeScript.js\")\""
            cwd node['mongo']['script']['dir']
        end
</code>```

But this fails.

Is there any other way to open mongo shell using chef and execute these commands

答:
After some R & D, I figured the way to do so.

No need to specifically open mongo shell.

use --eval in the end and directly run the command.

Need to provide delay between
resources because the initialization takes a few seconds in mongo.

Title: Opening Mongo Shell using Chef

Body:
I am using chef scripts to install mongo, configure the replication and run some db initialize scripts (load("initializeScript.js"))

Mongo gets installed without any issue now but for configuring the replica members I need open mongo shell and  run commands like:

rs.initiate() and rs.add("SERVER DETAILS")

I am trying to do it this way

 mongo_shell_command = 'mongo -ssl --sslPEMKeyFile ' +node['mongo']['ssl']['dir'] +node['hostname'] + '.pem --sslCAFile ' + node['mongo']['ssl']['dir'] + node['mongo']['cert'] + ' --sslAllowInvalidHostnames'

execute 'mongo_shell' do
        command mongo_shell_command
    end

    execute 'mongo_replicaSet' do
        command "mongo --eval rs.execute()"
        only_if { ::File.exist?(node['mongo']['config']) }
    end
execute 'initialize_db' do
             command "mongo --eval \"load(\"initializeScript.js\")\""
            cwd node['mongo']['script']['dir']
        end

But this fails.

Is there any other way to open mongo shell using chef and execute these commands


问:
How to sort table using PhP $PDO
i have the following function defined to create a html table using the data fetched from the database. I dont know how to use a new variable $orderby to order the results from the table as using ORDER BY firstname. I tried to do it several times and i failed. Any ideas?

```<code>function htmlTable( $pdo, $table, $orderby) {

 $sql = "DESCRIBE `".$table."`";
    $stmt = $pdo->query( $sql);

    print "<table>";
    print "<tr>";
    foreach( $stmt as $v) {
        print "<th>".$v['Field']."</th>";
    }
    print "</tr>";

    $sql = "SELECT * FROM `".$table."`";
    // specify only an associative array to be returned
    $stmt = $pdo->query( $sql, PDO::FETCH_ASSOC);

    foreach( $stmt as $row) {
        print "<tr>";
        foreach( $row as $v) {

            print "<td>".$v."</td>";

        }
        print "</tr>";
    }
    print "</table>";
}
</code>```

答:
You need to add that variable to your query:

```<code>$sql = "SELECT * FROM {$table} {$orderby};";
</code>```

read more about basic sql query structure:
https://www.w3schools.com/sql/sql_orderby.asp

Title: How to sort table using PhP $PDO

Body:
i have the following function defined to create a html table using the data fetched from the database. I dont know how to use a new variable $orderby to order the results from the table as using ORDER BY firstname. I tried to do it several times and i failed. Any ideas?

function htmlTable( $pdo, $table, $orderby) {

 $sql = "DESCRIBE `".$table."`";
    $stmt = $pdo->query( $sql);

    print "
";
    print "
";
    foreach( $stmt as $v) {
        print "".$v['Field']."	";
    }
    print "
";

    $sql = "SELECT * FROM `".$table."`";
    // specify only an associative array to be returned
    $stmt = $pdo->query( $sql, PDO::FETCH_ASSOC);

    foreach( $stmt as $row) {
        print "
";
        foreach( $row as $v) {

            print "".$v."	";

        }
        print "
";
    }
    print "
";
}

Body:
You need to add that variable to your query:

$sql = "SELECT * FROM {$table} {$orderby};";

read more about basic sql query structure:
https://www.w3schools.com/sql/sql_orderby.asp


问:
Q-learning vs dynamic programming
Is the classic Q-learning algorithm, using lookup table (instead of function approximation), equivalent to dynamic programming?</p>

答:
Dynamic Programming is an umbrella encompassing many algorithms. Q-Learning is a specific algorithm. So, no, it is not the same.

Also, if you mean Dynamic Programming as in Value Iteration or Policy Iteration, still not the same. These algorithms are "planning" methods. You have to give them a transition and a reward function and they will iteratively compute a value function and an optimal policy.

Q-Learning is a model-free reinforcement learning method. This one is "model-free", not because it doesn't use a machine learning model or anything like that, but because they don't require, and don't use a model of the environment, also known as MDP, to obtain an optimal policy. You also have "model-based" methods. These, unlike Dynamic Programming methods, are based on learning a model, not simply using one. And, unlike model-free methods, don't throw away samples after estimating values, they instead try to reconstruct the transition and reward function to get better performance.

Model-based methods combine model-free and planning algorithms to get same good results with less amount of samples than required by model-free methods (Q-Learning), and without needing a model like Dynamic Programming methods (Value/Policy Iteration).

Title: Q-learning vs dynamic programming


问:
Specifying a string value in the type definition for the Elixir typespecs
Is it possible to define a type as follows:

```<code>defmodule Role do
  use Exnumerator, values: ["admin", "regular", "restricted"]

  @type t :: "admin" | "regular" | "restricted"

  @spec default() :: t
  def default() do
    "regular"
  end
end
</code>```

to make a better analyze for the code like:

```<code>@type valid_attributes :: %{optional(:email) => String.t,
                            optional(:password) => String.t,
                            optional(:role) => Role.t}

@spec changeset(User.t, valid_attributes) :: Ecto.Changeset.t
def changeset(%User{} = user, attrs = %{}) do
  # ...
end

# ...

User.changeset(%User{}, %{role: "superadmin"}) |> Repo.insert()
</code>```

I know that I can define this type as @type t :: String.t, but then, Dialyzer won't complain about using a different value than possible (possible from the application point of view).

I didn't saw any hints about this use case in the documentation for the Typespecs, but maybe I'm missing something.

答:
It is not possible to use binary values in the described way. However, similar behavior can be achieved using atoms and - in my case - a custom Ecto type:

```<code>defmodule Role do
  @behaviour Ecto.Type

  @type t :: :admin | :regular | :restricted
  @valid_binary_values ["admin", "regular", "restricter"]

  @spec default() :: t
  def default(), do: :regular

  @spec valid_values() :: list(t)
  def valid_values(), do: Enum.map(@valid_values, &String.to_existing_atom/1)

  @spec type() :: atom()
  def type(), do: :string

  @spec cast(term()) :: {:ok, atom()} | :error
  def cast(value) when is_atom(value), do: {:ok, value}
  def cast(value) when value in @valid_binary_values, do: {:ok, String.to_existing_atom(value)}
  def cast(_value), do: :error

  @spec load(String.t) :: {:ok, atom()}
  def load(value), do: {:ok, String.to_existing_atom(value)}

  @spec dump(term()) :: {:ok, String.t} | :error
  def dump(value) when is_atom(value), do: {:ok, Atom.to_string(value)}
  def dump(_), do: :error
end
</code>```

It allows to use the following code:

```<code>defmodule User do
  use Ecto.Schema

  import Ecto.Changeset

  @type t :: %User{}
  @type valid_attributes :: %{optional(:email) => String.t,
                              optional(:password) => String.t,
                              optional(:role) => Role.t}

  @derive {Poison.Encoder, only: [:email, :id, :role]}
  schema "users" do
    field :email, :string
    field :password, :string, virtual: true
    field :password_hash, :string
    field :role, Role, default: Role.default()

    timestamps()
  end

  @spec changeset(User.t, valid_attributes) :: Ecto.Changeset.t
  def changeset(%User{} = user \\ %User{}, attrs = %{}) do
  # ...
end
</code>```

This way, Dialyzer will catch an invalid user's role:

```<code>User.changeset(%User{}, %{role: :superadmin}) |> Repo.insert()
</code>```

Unfortunately, it forces using atoms in place of strings in the application. It can be problematic if we already have a big code base or if we need plenty of possible values (the limit of atoms in the system and the the fact that they are not garbage collected).

Body:
Is it possible to define a type as follows:

defmodule Role do
  use Exnumerator, values: ["admin", "regular", "restricted"]

  @type t :: "admin" | "regular" | "restricted"

  @spec default() :: t
  def default() do
    "regular"
  end
end

to make a better analyze for the code like:

@type valid_attributes :: %{optional(:email) => String.t,
                            optional(:password) => String.t,
                            optional(:role) => Role.t}

@spec changeset(User.t, valid_attributes) :: Ecto.Changeset.t
def changeset(%User{} = user, attrs = %{}) do
  # ...
end

# ...

User.changeset(%User{}, %{role: "superadmin"}) |> Repo.insert()

I know that I can define this type as @type t :: String.t, but then, Dialyzer won't complain about using a different value than possible (possible from the application point of view).

I didn't saw any hints about this use case in the documentation for the Typespecs, but maybe I'm missing something.

Body:
It is not possible to use binary values in the described way. However, similar behavior can be achieved using atoms and - in my case - a custom Ecto type:

defmodule Role do
  @behaviour Ecto.Type

  @type t :: :admin | :regular | :restricted
  @valid_binary_values ["admin", "regular", "restricter"]

  @spec default() :: t
  def default(), do: :regular

  @spec valid_values() :: list(t)
  def valid_values(), do: Enum.map(@valid_values, &String.to_existing_atom/1)

  @spec type() :: atom()
  def type(), do: :string

  @spec cast(term()) :: {:ok, atom()} | :error
  def cast(value) when is_atom(value), do: {:ok, value}
  def cast(value) when value in @valid_binary_values, do: {:ok, String.to_existing_atom(value)}
  def cast(_value), do: :error

  @spec load(String.t) :: {:ok, atom()}
  def load(value), do: {:ok, String.to_existing_atom(value)}

  @spec dump(term()) :: {:ok, String.t} | :error
  def dump(value) when is_atom(value), do: {:ok, Atom.to_string(value)}
  def dump(_), do: :error
end

It allows to use the following code:

defmodule User do
  use Ecto.Schema

  import Ecto.Changeset

  @type t :: %User{}
  @type valid_attributes :: %{optional(:email) => String.t,
                              optional(:password) => String.t,
                              optional(:role) => Role.t}

  @derive {Poison.Encoder, only: [:email, :id, :role]}
  schema "users" do
    field :email, :string
    field :password, :string, virtual: true
    field :password_hash, :string
    field :role, Role, default: Role.default()

    timestamps()
  end

  @spec changeset(User.t, valid_attributes) :: Ecto.Changeset.t
  def changeset(%User{} = user \\ %User{}, attrs = %{}) do
  # ...
end

This way, Dialyzer will catch an invalid user's role:

User.changeset(%User{}, %{role: :superadmin}) |> Repo.insert()

Unfortunately, it forces using atoms in place of strings in the application. It can be problematic if we already have a big code base or if we need plenty of possible values (the limit of atoms in the system and the the fact that they are not garbage collected).


问:
SQL - How can I use UNION to join three INNER JOIN results into a single results table?
For the table:

```<code>assistants_rating(
id INT PRIMARY KEY auto_increment,
assistant_id INT(11),
rating INT(1)
)
</code>```

And another table of assistants which contains a name. My query goes as follows:

```<code>(SELECT assistants.name AS assist_name , count(rating) AS OneStar FROM assistants_rating
INNER JOIN assistants on assistants.assistant_id = assistants_rating.assistant_id WHERE rating = 1)

UNION

(SELECT assistants.name AS assist_name , count(rating) AS TwoStar FROM assistants_rating
INNER JOIN assistants on assistants.assistant_id = assistants_rating.assistant_id WHERE rating = 2)

UNION

(SELECT assistants.name AS assist_name , count(rating) AS ThreeStar FROM assistants_rating
INNER JOIN assistants on assistants.assistant_id = assistants_rating.assistant_id WHERE rating = 3)

GROUP BY assistants.name,OneStar,TwoStar,ThreeStar;
</code>```

Let's say I have the assistants named Bob and Sophie, the query should return:

```<code>assist_name   OneStar    TwoStar    ThreeStar

  Bob            9         18          52

 Sophie          15        8           61
</code>```

But instead I'm getting a SQL syntax error, which is weird because when I do each of them alone , they work properly and that leads me to believe that my syntax is good. Not only that, but my queries with the UNION work if I only do TwoStar and ThreeStar together but not with OneStar and TwoStar.

I'm so confused; why doesn't this work?

答:
You can use CASE instead of Union

```<code>SELECT assistants.name AS assist_name,
       SUM(CASE WHEN rating =1 THEN 1 ELSE 0 END) AS OneStar,
       SUM(CASE WHEN rating =2 THEN 1 ELSE 0 END) AS TwoStar,
       SUM(CASE WHEN rating =3 THEN 1 ELSE 0 END) AS ThreeStar
FROM assistants_rating
INNER JOIN assistants on assistants.assistant_id = assistants_rating.assistant_id
GROUP BY assistants.name
</code>```

Body:
For the table:

assistants_rating(
id INT PRIMARY KEY auto_increment,
assistant_id INT(11),
rating INT(1)
)

And another table of assistants which contains a name. My query goes as follows:

(SELECT assistants.name AS assist_name , count(rating) AS OneStar FROM assistants_rating
INNER JOIN assistants on assistants.assistant_id = assistants_rating.assistant_id WHERE rating = 1)

UNION

(SELECT assistants.name AS assist_name , count(rating) AS TwoStar FROM assistants_rating
INNER JOIN assistants on assistants.assistant_id = assistants_rating.assistant_id WHERE rating = 2)

UNION

(SELECT assistants.name AS assist_name , count(rating) AS ThreeStar FROM assistants_rating
INNER JOIN assistants on assistants.assistant_id = assistants_rating.assistant_id WHERE rating = 3)

GROUP BY assistants.name,OneStar,TwoStar,ThreeStar;

Let's say I have the assistants named Bob and Sophie, the query should return:

assist_name   OneStar    TwoStar    ThreeStar

  Bob            9         18          52

 Sophie          15        8           61

But instead I'm getting a SQL syntax error, which is weird because when I do each of them alone , they work properly and that leads me to believe that my syntax is good. Not only that, but my queries with the UNION work if I only do TwoStar and ThreeStar together but not with OneStar and TwoStar.

I'm so confused; why doesn't this work?

Body:
You can use CASE instead of Union

SELECT assistants.name AS assist_name,
       SUM(CASE WHEN rating =1 THEN 1 ELSE 0 END) AS OneStar,
       SUM(CASE WHEN rating =2 THEN 1 ELSE 0 END) AS TwoStar,
       SUM(CASE WHEN rating =3 THEN 1 ELSE 0 END) AS ThreeStar
FROM assistants_rating
INNER JOIN assistants on assistants.assistant_id = assistants_rating.assistant_id
GROUP BY assistants.name