问:
how to add button click event in android studio
So I have done some research, and after defining you button as an object by the code

```<code>private Button buttonname;
buttonname = (Button) findViewById(R.id.buttonnameinandroid) ;
</code>```

here is my problem

```<code>buttonname.setOnClickListener(this); //as I understand it, the "**this**" denotes the current `view(focus)` in the android program
</code>```

then your OnClick() event...

Problem:

When I type in the "this", it says:

```<code>setOnClickListener (Android.View.view.OnClickListener) in View cannot be applied to (com.helloandroidstudio.MainActivity)
</code>```

I have no idea why?

here is the code from the .java file

```<code>import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends ActionBarActivity {

    private Button btnClick;
    private EditText Name, Date;
    private TextView msg, NameOut, DateOut;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        btnClick = (Button) findViewById(R.id.button) ;
        btnClick.setOnClickListener(this);
        Name = (EditText) findViewById(R.id.textenter) ;
        Date = (EditText) findViewById(R.id.editText) ;
        msg = (TextView) findViewById(R.id.txtviewOut) ;
        NameOut = (TextView) findViewById(R.id.txtoutName) ;
        DateOut = (TextView) findViewById(R.id.txtOutDate) ;
        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.container, new PlaceholderFragment())
                    .commit();
        }
    }

    public void onClick(View v)
    {
        if (v == btnClick)
        {
            if (Name.equals("") == false && Date.equals("") == false)
            {
                NameOut = Name;
                DateOut = Date;
                msg.setVisibility(View.VISIBLE);
            }
            else
            {
                msg.setText("Please complete both fields");
                msg.setVisibility(View.VISIBLE);
            }
        }
        return;

    }
</code>```

答:
Different ways to handle button event</p>

```<code>Button btn1 = (Button)findViewById(R.id.button1);
btn1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            Toast.makeText(context, "Button 1",
     Toast.LENGTH_LONG).show();
        }
    });
</code>```

<p>[Check this article for more details about button event handlers] </p>

Body:
So I have done some research, and after defining you button as an object by the code

private Button buttonname;
buttonname = (Button) findViewById(R.id.buttonnameinandroid) ;

here is my problem

buttonname.setOnClickListener(this); //as I understand it, the "**this**" denotes the current `view(focus)` in the android program

then your OnClick() event...

Problem:

When I type in the "this", it says:

setOnClickListener (Android.View.view.OnClickListener) in View cannot be applied to (com.helloandroidstudio.MainActivity)

I have no idea why?

here is the code from the .java file

import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends ActionBarActivity {

    private Button btnClick;
    private EditText Name, Date;
    private TextView msg, NameOut, DateOut;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        btnClick = (Button) findViewById(R.id.button) ;
        btnClick.setOnClickListener(this);
        Name = (EditText) findViewById(R.id.textenter) ;
        Date = (EditText) findViewById(R.id.editText) ;
        msg = (TextView) findViewById(R.id.txtviewOut) ;
        NameOut = (TextView) findViewById(R.id.txtoutName) ;
        DateOut = (TextView) findViewById(R.id.txtOutDate) ;
        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.container, new PlaceholderFragment())
                    .commit();
        }
    }

    public void onClick(View v)
    {
        if (v == btnClick)
        {
            if (Name.equals("") == false && Date.equals("") == false)
            {
                NameOut = Name;
                DateOut = Date;
                msg.setVisibility(View.VISIBLE);
            }
            else
            {
                msg.setText("Please complete both fields");
                msg.setVisibility(View.VISIBLE);
            }
        }
        return;

    }

Body:
Different ways to handle button event

Button btn1 = (Button)findViewById(R.id.button1);
btn1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            Toast.makeText(context, "Button 1",
     Toast.LENGTH_LONG).show();
        }
    });

[Check this article for more details about button event handlers]


来源: stackexchange

问:
Convert NetCDF file to CSV or text using Python
I'm trying to convert a netCDF file to either a CSV or text file using Python. I have read this post but I am still missing a step (I'm new to Python). It's a dataset including latitude, longitude, time and precipitation data.

This is my code so far:

```<code>import netCDF4
import pandas as pd

precip_nc_file = 'file_path'
nc = netCDF4.Dataset(precip_nc_file, mode='r')

nc.variables.keys()

lat = nc.variables['lat'][:]
lon = nc.variables['lon'][:]
time_var = nc.variables['time']
dtime = netCDF4.num2date(time_var[:],time_var.units)
precip = nc.variables['precip'][:]
</code>```

I am not sure how to proceed from here, though I understand it's a matter of creating a dataframe with pandas.

答:
Depending on your requirements, you may be able to use Numpy's savetxt method:

```<code>import numpy as np

np.savetxt('lat.csv', lat, delimiter=',')
np.savetxt('lon.csv', lon, delimiter=',')
np.savetxt('precip.csv', precip, delimiter=',')
</code>```

This will output the data without any headings or index column, however.

If you do need those features, you can construct a DataFrame and save it as CSV as follows:

```<code>df_lat = pd.DataFrame(data=lat, index=dtime)
df_lat.to_csv('lat.csv')

# and the same for `lon` and `precip`.
</code>```

Note: here, I assume that the date/time index runs along the first dimension of the data.

ContentLicense: CC BY-SA 3.0

Body:
I'm trying to convert a netCDF file to either a CSV or text file using Python. I have read this post but I am still missing a step (I'm new to Python). It's a dataset including latitude, longitude, time and precipitation data.

This is my code so far:

import netCDF4
import pandas as pd

precip_nc_file = 'file_path'
nc = netCDF4.Dataset(precip_nc_file, mode='r')

nc.variables.keys()

lat = nc.variables['lat'][:]
lon = nc.variables['lon'][:]
time_var = nc.variables['time']
dtime = netCDF4.num2date(time_var[:],time_var.units)
precip = nc.variables['precip'][:]

I am not sure how to proceed from here, though I understand it's a matter of creating a dataframe with pandas.

Body:
Depending on your requirements, you may be able to use Numpy's savetxt method:

import numpy as np

np.savetxt('lat.csv', lat, delimiter=',')
np.savetxt('lon.csv', lon, delimiter=',')
np.savetxt('precip.csv', precip, delimiter=',')

This will output the data without any headings or index column, however.

If you do need those features, you can construct a DataFrame and save it as CSV as follows:

df_lat = pd.DataFrame(data=lat, index=dtime)
df_lat.to_csv('lat.csv')

# and the same for `lon` and `precip`.

Note: here, I assume that the date/time index runs along the first dimension of the data.


问:
How can I send a notification whenever I make a new Firebase Hosting deployment?
I have a small, internal Firebase App used for work. It is critical that users of this app always receive the most recently deployed code. If they have the page open and I make a new deployment to Firebase, I want to send a message to all of these clients that I can receive in my client-side code and then display a notification for. I am assuming that I would use Firebase Cloud Messaging to dispatch the message.

Is there a good way for me to do this with Firebase? Is there an event for this in the Cloud Functions feature? I've scoured the documentation but I cannot find any reference to an event that would let me do this.

答:
For the time being, I am having Travis CI use curl to send an API request that will update a latest_commit_hash property in my database. My client-side code will observe this value and notify users appropriately when it changes.

Update: Turns out that I don't even need to use curl, I can just do the following:

```<code>firebase database:set --token "$FIREBASE_TOKEN" --data \"$TRAVIS_COMMIT\" --confirm /deploy_commit_hash
</code>```

Body:
For the time being, I am having Travis CI use curl to send an API request that will update a latest_commit_hash property in my database. My client-side code will observe this value and notify users appropriately when it changes.

Update: Turns out that I don't even need to use curl, I can just do the following:

firebase database:set --token "$FIREBASE_TOKEN" --data \"$TRAVIS_COMMIT\" --confirm /deploy_commit_hash


问:
Cleaner / smarter way to use a for loop
I have a DataGridView with 35 columns and I was wondering how to programmatically do a FOR loop to set the header text alignment to center only from column 4 through 20.  I know how to do it column by column but I'm sure there must be a faster / smarter way to do it.  See below the code I'm using:</p>

```<code>alunos_detDataGridView.Columns[4].HeaderCell.Style.Alignment = DataGridViewContentAlignment.BottomCenter;
alunos_detDataGridView.Columns[5].HeaderCell.Style.Alignment = DataGridViewContentAlignment.BottomCenter;
</code>```

答:
```<code>Enumerable.Range(4,16).ToList().ForEach(i=> alunos_detDataGridView.Columns[i].HeaderCell.Style.Alignment = DataGridViewContentAlignment.BottomCenter);
</code>```

Any kind of loop will solve your problem

Title: Cleaner / smarter way to use a for loop

Body:
I have a DataGridView with 35 columns and I was wondering how to programmatically do a FOR loop to set the header text alignment to center only from column 4 through 20.  I know how to do it column by column but I'm sure there must be a faster / smarter way to do it.  See below the code I'm using:

alunos_detDataGridView.Columns[4].HeaderCell.Style.Alignment = DataGridViewContentAlignment.BottomCenter;
alunos_detDataGridView.Columns[5].HeaderCell.Style.Alignment = DataGridViewContentAlignment.BottomCenter;

Body:
Enumerable.Range(4,16).ToList().ForEach(i=> alunos_detDataGridView.Columns[i].HeaderCell.Style.Alignment = DataGridViewContentAlignment.BottomCenter);

Any kind of loop will solve your problem


问:
How to add a new column to an existing DataFrame?
I have the following indexed DataFrame with named columns and rows not- continuous numbers:

```<code>          a         b         c         d
2  0.671399  0.101208 -0.181532  0.241273
3  0.446172 -0.243316  0.051767  1.577318
5  0.614758  0.075793 -0.451460 -0.012493
</code>```

I would like to add a new column, 'e', to the existing data frame and do not want to change anything in the data frame (i.e., the new column always has the same length as the DataFrame).

```<code>0   -0.335485
1   -1.166658
2   -0.385571
dtype: float64
</code>```

How can I add column e to the above example?

答:
First create a python's list_of_e that has relevant data.

Use this:
    df['e'] = list_of_e

ContentLicense: CC BY-SA 4.0

Body:
I have the following indexed DataFrame with named columns and rows not- continuous numbers:

          a         b         c         d
2  0.671399  0.101208 -0.181532  0.241273
3  0.446172 -0.243316  0.051767  1.577318
5  0.614758  0.075793 -0.451460 -0.012493

I would like to add a new column, 'e', to the existing data frame and do not want to change anything in the data frame (i.e., the new column always has the same length as the DataFrame).

0   -0.335485
1   -1.166658
2   -0.385571
dtype: float64

How can I add column e to the above example?


问:
Swagger UI Bad Request URL Generation
I've been using swagger for some time now and I have now ran into a problem where the generated request URL puts my optional parameters in the request. This is not happening on other projects I have that are using the same annotations, swagger version, and swagger maven version.

Here is a code snippet inside my @Controller

```<code>private static final String BY_USERNAME = "byUsername";
private static final String BY_NAME = "byName";
private static final String BY_PHONENUMBER = "byPhoneNumber";
private static final String BY_USERTYPENAME = "byUserTypeName";
private static final String BY_ACTIVE = "byActive";
private static final String BY_ACTIVE_AND_AVAILABLE = "byActiveAndAvailable";
@ApiOperation(value = "Read User(s)", notes = "notes removed so post wont be so long", consumes = "application/x-www-form-urlencoded")
@RequestMapping(value = "", method = RequestMethod.GET, consumes = "application/x-www-form-urlencoded")
@ApiImplicitParam(value = "Authorization Token", name = TokenAuthenticationService.HEADER_STRING, dataType = "String", paramType = "header")
@ApiResponses(value = { @ApiResponse(message = "successful read call", code = 200), @ApiResponse(message = "bad parameter provided", code = 400) })
public Page<User> readUser(
                @ApiParam(name = "queryType", value = "type of query", allowableValues = BY_USERNAME + "," + BY_NAME + "," + BY_PHONENUMBER + ","
                                + BY_USERTYPENAME + "," + BY_ACTIVE + "," + BY_ACTIVE_AND_AVAILABLE) @RequestParam(value = "queryType", required = true) String queryType,
                @ApiParam(name = "username", value = "username of user") @RequestParam(value = "username", required = false) String username,
                @ApiParam(name = "name", value = "name of user(s)") @RequestParam(value = "name", required = false) String name,
                @ApiParam(name = "phoneNumber", value = "phone number of user(s)") @RequestParam(value = "phoneNumber", required = false) String phoneNumber,
                @ApiParam(name = "userTypeName", value = "user type name of user(s)") @RequestParam(value = "userTypeName", required = false) String userTypeName,
                @ApiParam(name = "active", value = "active status of user(s)") @RequestParam(value = "active", required = false) Boolean active,
                @ApiParam(name = "available", value = "available status of user(s)") @RequestParam(value = "available", required = false) Boolean available,
                Pageable pageable) {
</code>```

This is very basic swagger annotations. The problem is the resulting URL in the swagger-ui looks like this:

When I attempt to use it, it puts these inside the REST request.

This of course causes spring to throw exceptions about invalid characters

I tried searching all over the internet, swagger pages, and here on stackoverflow and I could not find any mention of this error. The very weird thing is, if I change the RequestMethod to be POST it works as it should. Seems to be a bug in swagger-ui handling optional parameters. Anyone else ran into this? Is there a fix besides making the request method POST?

EDIT: The "consumes = "application/x-www-form-urlencoded"" was not in my original code. I've been debugging this and adding stuff to try and make it work lol.

Versions used:

springfox-swagger2 version 2.6.1

springfox-swagger-ui version 2.6.1

答:
What version of the swagger-ui are you using?

Since you have enableUrlTemplating(true) in your docket you need to use the appropriate implementation of swagger-ui that supports it.

For Gradle:

```<code>compile group: 'io.springfox.ui', name: 'springfox-swagger-ui-rfc6570', version: '1.0.0'
</code>```

For Maven:

```<code><!-- https://mvnrepository.com/artifact/io.springfox.ui/springfox-swagger-ui-rfc6570 -->
<dependency>
    <groupId>io.springfox.ui</groupId>
    <artifactId>springfox-swagger-ui-rfc6570</artifactId>
    <version>1.0.0</version>
</dependency>
</code>```

Docket supports url templating (see #21), however it is still in incubation and not officially supported by the swagger 2.0 specification. So the choices you have are:

make enableUrlTemplating(false). In which case everything will work with the exception that if you have multiple paths with different query parameters, only one of them would show up.

e.g. if you have the following urls
http://example.org/customers?firstName=A&lastName=B findCustomersByName
http://example.org/customers?email=a@b.com findCustomersByEmail

Only one of them will show up.

Keep enableUrlTemplating(true) but change the swagger-ui you're using to the one above.

Title: Swagger UI Bad Request URL Generation

Body:
I've been using swagger for some time now and I have now ran into a problem where the generated request URL puts my optional parameters in the request. This is not happening on other projects I have that are using the same annotations, swagger version, and swagger maven version.

Here is a code snippet inside my @Controller

private static final String BY_USERNAME = "byUsername";
private static final String BY_NAME = "byName";
private static final String BY_PHONENUMBER = "byPhoneNumber";
private static final String BY_USERTYPENAME = "byUserTypeName";
private static final String BY_ACTIVE = "byActive";
private static final String BY_ACTIVE_AND_AVAILABLE = "byActiveAndAvailable";
@ApiOperation(value = "Read User(s)", notes = "notes removed so post wont be so long", consumes = "application/x-www-form-urlencoded")
@RequestMapping(value = "", method = RequestMethod.GET, consumes = "application/x-www-form-urlencoded")
@ApiImplicitParam(value = "Authorization Token", name = TokenAuthenticationService.HEADER_STRING, dataType = "String", paramType = "header")
@ApiResponses(value = { @ApiResponse(message = "successful read call", code = 200), @ApiResponse(message = "bad parameter provided", code = 400) })
public Page<User> readUser(
                @ApiParam(name = "queryType", value = "type of query", allowableValues = BY_USERNAME + "," + BY_NAME + "," + BY_PHONENUMBER + ","
                                + BY_USERTYPENAME + "," + BY_ACTIVE + "," + BY_ACTIVE_AND_AVAILABLE) @RequestParam(value = "queryType", required = true) String queryType,
                @ApiParam(name = "username", value = "username of user") @RequestParam(value = "username", required = false) String username,
                @ApiParam(name = "name", value = "name of user(s)") @RequestParam(value = "name", required = false) String name,
                @ApiParam(name = "phoneNumber", value = "phone number of user(s)") @RequestParam(value = "phoneNumber", required = false) String phoneNumber,
                @ApiParam(name = "userTypeName", value = "user type name of user(s)") @RequestParam(value = "userTypeName", required = false) String userTypeName,
                @ApiParam(name = "active", value = "active status of user(s)") @RequestParam(value = "active", required = false) Boolean active,
                @ApiParam(name = "available", value = "available status of user(s)") @RequestParam(value = "available", required = false) Boolean available,
                Pageable pageable) {

This is very basic swagger annotations. The problem is the resulting URL in the swagger-ui looks like this:

When I attempt to use it, it puts these inside the REST request.

This of course causes spring to throw exceptions about invalid characters

I tried searching all over the internet, swagger pages, and here on stackoverflow and I could not find any mention of this error. The very weird thing is, if I change the RequestMethod to be POST it works as it should. Seems to be a bug in swagger-ui handling optional parameters. Anyone else ran into this? Is there a fix besides making the request method POST?

EDIT: The "consumes = "application/x-www-form-urlencoded"" was not in my original code. I've been debugging this and adding stuff to try and make it work lol.

Versions used:

springfox-swagger2 version 2.6.1

springfox-swagger-ui version 2.6.1

Body:
What version of the swagger-ui are you using?

Since you have enableUrlTemplating(true) in your docket you need to use the appropriate implementation of swagger-ui that supports it.

For Gradle:

compile group: 'io.springfox.ui', name: 'springfox-swagger-ui-rfc6570', version: '1.0.0'

For Maven:

<!-- https://mvnrepository.com/artifact/io.springfox.ui/springfox-swagger-ui-rfc6570 -->
<dependency>
    <groupId>io.springfox.ui</groupId>
    <artifactId>springfox-swagger-ui-rfc6570</artifactId>
    <version>1.0.0</version>
</dependency>

Docket supports url templating (see #21), however it is still in incubation and not officially supported by the swagger 2.0 specification. So the choices you have are:

make enableUrlTemplating(false). In which case everything will work with the exception that if you have multiple paths with different query parameters, only one of them would show up.

e.g. if you have the following urls
http://example.org/customers?firstName=A&lastName=B findCustomersByName
http://example.org/customers?email=a@b.com findCustomersByEmail

Only one of them will show up.

Keep enableUrlTemplating(true) but change the swagger-ui you're using to the one above.


问:
Windows executable fails to start despite having correct DLLs in root directory
My ultra simple 2D game Caventure depends on sdl-2 and sdl-ttf.

When compiled, the directory looks like

```<code>Caventure.exe
libfreetype-6.dll
notomono-regular.ttf
SDL2.dll
SDL2_ttf.dll
zlib1.dll
</code>```

I'm using Microsoft Visual Studio 2015. I've been following Lazy Foo's tutorials on building with Windows and even after following the steps, it doesn't work. Here's what I've done:

Linked the compiler to include and library directories in x64.

Linked the libraries.

Copied the libraries to C:\Windows\SysWOW64.

Included <Windows.h>.

Used compatibility mode.

Tested it in the Visual Studio IDE, including with the debugger.

When I open it, it immediately closes, it doesn't return any error.

Here's the main source file:

```<code>#include <stdio.h>
#include <stdexcept>
#include <Windows.h>
#include <SDL.h>
#include <SDL_ttf.h>

#include "TextMenu.h"
#include "TextBox.h"

#include "Graphics.h"
#include "Event.h"

// Screen dimensions, constants
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
// 600 for ground, 280 for output, 20 for input

Graphics Global;
Event Loop;

void Init(Graphics& Global)
{
    if (SDL_Init(SDL_INIT_VIDEO) > 0)
    {
        throw(::std::runtime_error("SDL failed to initialise! ERROR: "));
    }
    Global.Window = SDL_CreateWindow("Caventure",
        SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        SCREEN_WIDTH,
        SCREEN_HEIGHT,
        SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
    if (Global.Window == NULL)
    {
        throw(::std::runtime_error("Window failed to initialise! ERROR: "));
    }
    Global.ScreenSurface = SDL_GetWindowSurface(Global.Window);
    if (Global.ScreenSurface == NULL)
    {
        throw(::std::runtime_error("Surface failed to initialise! ERROR: "));
    }
    Global.Renderer = SDL_CreateRenderer(Global.Window, -1, 0);
    if (Global.Renderer == NULL)
    {
        throw(::std::runtime_error("Renderer could not be initialised! ERROR: "));
    }
    if (TTF_Init() > 0)
    {
        throw(::std::runtime_error("TTF could not be initialised! ERROR: "));
    }
}

void UpdateMedia(Graphics& Global)
{
    SDL_GetWindowSize(Global.Window, &Global.width, &Global.height);

    // Set geomtry dimensions, apart from rcTextInput.
    Global.rcGround = { 0, 0, Global.width, (Global.height / 3) * 2 };
    Global.rcTextOutput = { 0, (Global.height / 3) * 2, Global.width, Global.height - 40 };
    Global.rcTextOutputGrd = { 0, (Global.height / 3) * 2, Global.width, Global.height - 40 };

    Global.SpriteDefaultX = Global.width / 2;
    Global.SpriteDefaultY = Global.height / 2;
};

void LoadMedia(Graphics& Global)
{
    UpdateMedia(Global);

    Global.rcSprite = { Global.SpriteDefaultX, Global.SpriteDefaultY, 4, 4 };

    Global.Font = TTF_OpenFont("src/graphics/resources/notomono-regular.ttf", 14);
    if (Global.Font == NULL)
    {
        throw(::std::runtime_error("Font failed to load! ERROR: "));
    }

    SDL_SetTextInputRect(&Global.rcTextInput);
}

void InputLoop(Graphics& Global, Event& Loop)
{
    if (Loop.event.type == SDL_QUIT)
    {
        Loop.bQuit = true;
    }
    else if (Loop.event.type == SDL_KEYDOWN)
    {
        // Sprite movement
        switch (Loop.event.key.keysym.sym)
        {
        case SDLK_UP:
            Global.rcSprite.y -= 5;
            break;

        case SDLK_DOWN:
            Global.rcSprite.y += 5;
            break;

        case SDLK_LEFT:
            Global.rcSprite.x -= 5;
            break;

        case SDLK_RIGHT:
            Global.rcSprite.x += 5;
            break;
        }

        // Backspace handler
        if (Loop.event.key.keysym.sym == SDLK_BACKSPACE && Loop.InputText.length() > 0)
        {
            Loop.InputText.pop_back();
            if (Loop.InputText.length() == 0)
            {
                Loop.InputText = " ";
            }
        }

        // Creates new line of text
        else if (Loop.event.key.keysym.sym == SDLK_RETURN && Loop.InputText.length() != 0 && Loop.InputText != " ")
        {
            Global.Menu.NewBox(Loop.InputText);
            Loop.bRenderText = true;
            Loop.InputText = " ";
        }
    }
    else if (Loop.event.type == SDL_TEXTINPUT)
    {
        Loop.InputText += Loop.event.text.text;
    }
}

void RenderLoop(Graphics& Global, Event& Loop)
{
    UpdateMedia(Global);

    // Renders sprite movement
    if (Global.rcSprite.x < 0 || Global.rcSprite.y < 0 || Global.rcSprite.y > Global.rcGround.h || Global.rcSprite.x > Global.rcGround.w)
    {
        Global.rcSprite.x = Global.SpriteDefaultX;
        Global.rcSprite.y = Global.SpriteDefaultY;
    }

    // Sets background to black
    SDL_SetRenderDrawColor(Global.Renderer, 0x00, 0x00, 0x00, 0x00);
    SDL_RenderClear(Global.Renderer);

    // Renders background of sprite to black
    SDL_RenderFillRect(Global.Renderer, &Global.rcGround);
    SDL_BlitSurface(Global.CurrentSurface, NULL, Global.ScreenSurface, &Global.rcGround);

    // Renders background of text box to grey
    SDL_SetRenderDrawColor(Global.Renderer, 0x40, 0x40, 0x40, 0x40);
    SDL_RenderFillRect(Global.Renderer, &Global.rcTextOutputGrd);
    SDL_BlitSurface(Global.CurrentSurface, NULL, Global.ScreenSurface, &Global.rcTextOutputGrd);

    SDL_SetRenderDrawColor(Global.Renderer, 0x00, 0x00, 0x00, 0x00);
    // Renders text input
    Global.TextInput.Render(Global.Renderer, Global.Font, Loop.InputText.c_str(), Global.TextColor);
    Global.rcTextInput = { 0, Global.height - 20, Global.TextInput.GetWidth(), Global.TextInput.GetHeight() };
    SDL_RenderCopy(Global.Renderer, Global.TextInput.GetTexture(), NULL, &Global.rcTextInput);

    // Renders text output
    if (Loop.bRenderText)
    {
        Global.Menu.Update(Global.Renderer, Global.Font, Global.TextColor, Global.rcTextOutput);
    }
    SDL_RenderSetClipRect(Global.Renderer, NULL);

    // Renders text box background edges white
    SDL_SetRenderDrawColor(Global.Renderer, 0xFF, 0xFF, 0xFF, 0xFF);
    SDL_RenderDrawLine(Global.Renderer, 0, (Global.height / 3) * 2, Global.width, (Global.height / 3) * 2);
    SDL_RenderDrawLine(Global.Renderer, 0, Global.height - 20, Global.width, Global.height - 20);

    // Renders sprite
    SDL_RenderFillRect(Global.Renderer, &Global.rcSprite);
    SDL_BlitSurface(Global.CurrentSurface, NULL, Global.ScreenSurface, &Global.rcSprite);

    // Presents render
    SDL_RenderPresent(Global.Renderer);
}

void Quit(Graphics& Global)
{
    // Deallocate memory
    SDL_DestroyWindow(Global.Window);
    SDL_DestroyRenderer(Global.Renderer);
    TTF_CloseFont(Global.Font);
    Global.Window = NULL;
    Global.Renderer = NULL;
    Global.Font = NULL;

    // Quit SDL subsystems
    TTF_Quit();
    SDL_Quit();
}

int main(int argc, char *argv[])
{
    try
    {
        Init(Global);
        LoadMedia(Global);
        SDL_StartTextInput();
        while (!Loop.bQuit)
        {
            while (SDL_PollEvent(&Loop.event) != 0)
            {
                InputLoop(Global, Loop);
                RenderLoop(Global, Loop);
            }
        }
        SDL_StopTextInput();
    }
    catch (std::runtime_error const& msg)
    {
        printf("%s", msg.what());
        if (SDL_GetError() != NULL)
        {
            printf("%s", SDL_GetError());
        }
        else if (TTF_GetError() != NULL)
        {
            printf("%s", TTF_GetError());
        }
        else
        {
            printf("%s", "NULL");
        }
        Quit(Global);
        return EXIT_FAILURE;
    }
    Quit(Global);
    return EXIT_SUCCESS;
}
</code>```

答:
Four suggestions:

Check the windows event log.

Run it in a debugger.

Start it from the windows command line.

Add logging.

Body:
My ultra simple 2D game Caventure depends on sdl-2 and sdl-ttf.

When compiled, the directory looks like

Caventure.exe
libfreetype-6.dll
notomono-regular.ttf
SDL2.dll
SDL2_ttf.dll
zlib1.dll

I'm using Microsoft Visual Studio 2015. I've been following Lazy Foo's tutorials on building with Windows and even after following the steps, it doesn't work. Here's what I've done:

Linked the compiler to include and library directories in x64.

Linked the libraries.

Copied the libraries to C:\Windows\SysWOW64.

Included <Windows.h>.

Used compatibility mode.

Tested it in the Visual Studio IDE, including with the debugger.

When I open it, it immediately closes, it doesn't return any error.

Here's the main source file:

#include <stdio.h>
#include <stdexcept>
#include <Windows.h>
#include <SDL.h>
#include <SDL_ttf.h>

#include "TextMenu.h"
#include "TextBox.h"

#include "Graphics.h"
#include "Event.h"

// Screen dimensions, constants
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
// 600 for ground, 280 for output, 20 for input

Graphics Global;
Event Loop;

void Init(Graphics& Global)
{
    if (SDL_Init(SDL_INIT_VIDEO) > 0)
    {
        throw(::std::runtime_error("SDL failed to initialise! ERROR: "));
    }
    Global.Window = SDL_CreateWindow("Caventure",
        SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        SCREEN_WIDTH,
        SCREEN_HEIGHT,
        SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
    if (Global.Window == NULL)
    {
        throw(::std::runtime_error("Window failed to initialise! ERROR: "));
    }
    Global.ScreenSurface = SDL_GetWindowSurface(Global.Window);
    if (Global.ScreenSurface == NULL)
    {
        throw(::std::runtime_error("Surface failed to initialise! ERROR: "));
    }
    Global.Renderer = SDL_CreateRenderer(Global.Window, -1, 0);
    if (Global.Renderer == NULL)
    {
        throw(::std::runtime_error("Renderer could not be initialised! ERROR: "));
    }
    if (TTF_Init() > 0)
    {
        throw(::std::runtime_error("TTF could not be initialised! ERROR: "));
    }
}

void UpdateMedia(Graphics& Global)
{
    SDL_GetWindowSize(Global.Window, &Global.width, &Global.height);

    // Set geomtry dimensions, apart from rcTextInput.
    Global.rcGround = { 0, 0, Global.width, (Global.height / 3) * 2 };
    Global.rcTextOutput = { 0, (Global.height / 3) * 2, Global.width, Global.height - 40 };
    Global.rcTextOutputGrd = { 0, (Global.height / 3) * 2, Global.width, Global.height - 40 };

    Global.SpriteDefaultX = Global.width / 2;
    Global.SpriteDefaultY = Global.height / 2;
};

void LoadMedia(Graphics& Global)
{
    UpdateMedia(Global);

    Global.rcSprite = { Global.SpriteDefaultX, Global.SpriteDefaultY, 4, 4 };

    Global.Font = TTF_OpenFont("src/graphics/resources/notomono-regular.ttf", 14);
    if (Global.Font == NULL)
    {
        throw(::std::runtime_error("Font failed to load! ERROR: "));
    }

    SDL_SetTextInputRect(&Global.rcTextInput);
}

void InputLoop(Graphics& Global, Event& Loop)
{
    if (Loop.event.type == SDL_QUIT)
    {
        Loop.bQuit = true;
    }
    else if (Loop.event.type == SDL_KEYDOWN)
    {
        // Sprite movement
        switch (Loop.event.key.keysym.sym)
        {
        case SDLK_UP:
            Global.rcSprite.y -= 5;
            break;

        case SDLK_DOWN:
            Global.rcSprite.y += 5;
            break;

        case SDLK_LEFT:
            Global.rcSprite.x -= 5;
            break;

        case SDLK_RIGHT:
            Global.rcSprite.x += 5;
            break;
        }

        // Backspace handler
        if (Loop.event.key.keysym.sym == SDLK_BACKSPACE && Loop.InputText.length() > 0)
        {
            Loop.InputText.pop_back();
            if (Loop.InputText.length() == 0)
            {
                Loop.InputText = " ";
            }
        }

        // Creates new line of text
        else if (Loop.event.key.keysym.sym == SDLK_RETURN && Loop.InputText.length() != 0 && Loop.InputText != " ")
        {
            Global.Menu.NewBox(Loop.InputText);
            Loop.bRenderText = true;
            Loop.InputText = " ";
        }
    }
    else if (Loop.event.type == SDL_TEXTINPUT)
    {
        Loop.InputText += Loop.event.text.text;
    }
}

void RenderLoop(Graphics& Global, Event& Loop)
{
    UpdateMedia(Global);

    // Renders sprite movement
    if (Global.rcSprite.x < 0 || Global.rcSprite.y < 0 || Global.rcSprite.y > Global.rcGround.h || Global.rcSprite.x > Global.rcGround.w)
    {
        Global.rcSprite.x = Global.SpriteDefaultX;
        Global.rcSprite.y = Global.SpriteDefaultY;
    }

    // Sets background to black
    SDL_SetRenderDrawColor(Global.Renderer, 0x00, 0x00, 0x00, 0x00);
    SDL_RenderClear(Global.Renderer);

    // Renders background of sprite to black
    SDL_RenderFillRect(Global.Renderer, &Global.rcGround);
    SDL_BlitSurface(Global.CurrentSurface, NULL, Global.ScreenSurface, &Global.rcGround);

    // Renders background of text box to grey
    SDL_SetRenderDrawColor(Global.Renderer, 0x40, 0x40, 0x40, 0x40);
    SDL_RenderFillRect(Global.Renderer, &Global.rcTextOutputGrd);
    SDL_BlitSurface(Global.CurrentSurface, NULL, Global.ScreenSurface, &Global.rcTextOutputGrd);

    SDL_SetRenderDrawColor(Global.Renderer, 0x00, 0x00, 0x00, 0x00);
    // Renders text input
    Global.TextInput.Render(Global.Renderer, Global.Font, Loop.InputText.c_str(), Global.TextColor);
    Global.rcTextInput = { 0, Global.height - 20, Global.TextInput.GetWidth(), Global.TextInput.GetHeight() };
    SDL_RenderCopy(Global.Renderer, Global.TextInput.GetTexture(), NULL, &Global.rcTextInput);

    // Renders text output
    if (Loop.bRenderText)
    {
        Global.Menu.Update(Global.Renderer, Global.Font, Global.TextColor, Global.rcTextOutput);
    }
    SDL_RenderSetClipRect(Global.Renderer, NULL);

    // Renders text box background edges white
    SDL_SetRenderDrawColor(Global.Renderer, 0xFF, 0xFF, 0xFF, 0xFF);
    SDL_RenderDrawLine(Global.Renderer, 0, (Global.height / 3) * 2, Global.width, (Global.height / 3) * 2);
    SDL_RenderDrawLine(Global.Renderer, 0, Global.height - 20, Global.width, Global.height - 20);

    // Renders sprite
    SDL_RenderFillRect(Global.Renderer, &Global.rcSprite);
    SDL_BlitSurface(Global.CurrentSurface, NULL, Global.ScreenSurface, &Global.rcSprite);

    // Presents render
    SDL_RenderPresent(Global.Renderer);
}

void Quit(Graphics& Global)
{
    // Deallocate memory
    SDL_DestroyWindow(Global.Window);
    SDL_DestroyRenderer(Global.Renderer);
    TTF_CloseFont(Global.Font);
    Global.Window = NULL;
    Global.Renderer = NULL;
    Global.Font = NULL;

    // Quit SDL subsystems
    TTF_Quit();
    SDL_Quit();
}

int main(int argc, char *argv[])
{
    try
    {
        Init(Global);
        LoadMedia(Global);
        SDL_StartTextInput();
        while (!Loop.bQuit)
        {
            while (SDL_PollEvent(&Loop.event) != 0)
            {
                InputLoop(Global, Loop);
                RenderLoop(Global, Loop);
            }
        }
        SDL_StopTextInput();
    }
    catch (std::runtime_error const& msg)
    {
        printf("%s", msg.what());
        if (SDL_GetError() != NULL)
        {
            printf("%s", SDL_GetError());
        }
        else if (TTF_GetError() != NULL)
        {
            printf("%s", TTF_GetError());
        }
        else
        {
            printf("%s", "NULL");
        }
        Quit(Global);
        return EXIT_FAILURE;
    }
    Quit(Global);
    return EXIT_SUCCESS;
}


问:
Number of query values and destination fields are not the same (Union)
Running into this SQL error - number of query values and destination fields are not the same (Union). Using an Access database. The programList table has just two fields in it - userID and programID. Using parameters in my cs file. Here is the complete method:</p>

```<code>public void AddProgramList (string program, int userID)
{
    dbConnection.Open();

    string sqlStmt = "INSERT INTO programs (program) ";
    sqlStmt += "VALUES (@program)";
    string sqlStmt2 = "INSERT INTO programList (userID, programID) " +
                      "SELECT userID " +
                      "FROM users" +
                      "WHERE userID = @userID " +
                      "UNION " +
                      "SELECT programID " +
                      "FROM programs" +
                      "WHERE program = @program;";

    OleDbCommand dbCommand = new OleDbCommand(sqlStmt, dbConnection);

    OleDbParameter param = new OleDbParameter("@program", program);

    dbCommand.Parameters.Add(param);

    dbCommand.Parameters.Add(new OleDbParameter("@userID", userID));

    OleDbCommand dbCommand2 = new OleDbCommand(sqlStmt2, dbConnection);

    OleDbParameter param2 = new OleDbParameter("@program", program);

    dbCommand2.Parameters.Add(param2);

    dbCommand2.Parameters.Add(new OleDbParameter("@userID", userID));

    dbCommand.ExecuteNonQuery();

    dbCommand2.ExecuteNonQuery();

    dbConnection.Close();
}
</code>```

答:
If you printed out the SQL, you would see:

```<code>INSERT INTO programList (userID, programID) " +
SELECT userID FROM usersWHERE userID = @userID UNION SELECT programID FROM programsWHERE program = @program;
</code>```

The error should be pretty obvious.  You probably don't have a table called usersWHERE.

As I look at the problem, you are trying to insert two columns.  So, I think you intend:

```<code>INSERT INTO programList (userID, programID)
    SELECT userID, programID
    FROM users, programs
    WHERE userID = @userID AND program = @program;
</code>```

Or, more simply:

```<code>INSERT INTO programList (userID, programID)
    SELECT @userID, programid
    FROM programs
    WHERE program = @program;
</code>```

Body:
Running into this SQL error - number of query values and destination fields are not the same (Union). Using an Access database. The programList table has just two fields in it - userID and programID. Using parameters in my cs file. Here is the complete method:

public void AddProgramList (string program, int userID)
{
    dbConnection.Open();

    string sqlStmt = "INSERT INTO programs (program) ";
    sqlStmt += "VALUES (@program)";
    string sqlStmt2 = "INSERT INTO programList (userID, programID) " +
                      "SELECT userID " +
                      "FROM users" +
                      "WHERE userID = @userID " +
                      "UNION " +
                      "SELECT programID " +
                      "FROM programs" +
                      "WHERE program = @program;";

    OleDbCommand dbCommand = new OleDbCommand(sqlStmt, dbConnection);

    OleDbParameter param = new OleDbParameter("@program", program);

    dbCommand.Parameters.Add(param);

    dbCommand.Parameters.Add(new OleDbParameter("@userID", userID));

    OleDbCommand dbCommand2 = new OleDbCommand(sqlStmt2, dbConnection);

    OleDbParameter param2 = new OleDbParameter("@program", program);

    dbCommand2.Parameters.Add(param2);

    dbCommand2.Parameters.Add(new OleDbParameter("@userID", userID));

    dbCommand.ExecuteNonQuery();

    dbCommand2.ExecuteNonQuery();

    dbConnection.Close();
}

Body:
If you printed out the SQL, you would see:

INSERT INTO programList (userID, programID) " +
SELECT userID FROM usersWHERE userID = @userID UNION SELECT programID FROM programsWHERE program = @program;

The error should be pretty obvious.  You probably don't have a table called usersWHERE.

As I look at the problem, you are trying to insert two columns.  So, I think you intend:

INSERT INTO programList (userID, programID)
    SELECT userID, programID
    FROM users, programs
    WHERE userID = @userID AND program = @program;

Or, more simply:

INSERT INTO programList (userID, programID)
    SELECT @userID, programid
    FROM programs
    WHERE program = @program;


问:
Code Push breaking jest tests for react-native
I have configured an app for code-push, it works well except for jest tests. It fails in rendering app for this error:

```<code>TypeError: Cannot read property 'CheckFrequency' of undefined

  at Object.<anonymous> (app/index.js:7:66)
  at Object.<anonymous> (index.ios.js:5:12)
  at Object.<anonymous> (__tests__/index.ios.js:4:12)
</code>```

in this line:

```<code>const codePushOptions = { checkFrequency: codePush.CheckFrequency.MANUAL };
</code>```

The test code is:

```<code>import App from '../index.ios';

it('renders correctly', () => {
  const tree = renderer.create(
      <App />,
  );
});
</code>```

答:
In your tests, underneath your import App from '../index.ios';, add the following:

```<code>jest.mock('react-native-code-push', () => {
    return jest.fn(() => ({
        InstallMode: jest.fn(),
        CheckFrequency: jest.fn(),
        CodePushComponent: jest.fn(),
        codePushify: jest.fn()
    }));
});
</code>```

Body:
I have configured an app for code-push, it works well except for jest tests. It fails in rendering app for this error:

TypeError: Cannot read property 'CheckFrequency' of undefined

  at Object.<anonymous> (app/index.js:7:66)
  at Object.<anonymous> (index.ios.js:5:12)
  at Object.<anonymous> (__tests__/index.ios.js:4:12)

in this line:

const codePushOptions = { checkFrequency: codePush.CheckFrequency.MANUAL };

The test code is:

import App from '../index.ios';

it('renders correctly', () => {
  const tree = renderer.create(
      <App />,
  );
});

Body:
In your tests, underneath your import App from '../index.ios';, add the following:

jest.mock('react-native-code-push', () => {
    return jest.fn(() => ({
        InstallMode: jest.fn(),
        CheckFrequency: jest.fn(),
        CodePushComponent: jest.fn(),
        codePushify: jest.fn()
    }));
});


问:
How can I know the character set of HTML content by HTTP headers?
I know the parameter charset= in the HTTP header:Content-Type can be used to determine the character set of the HTML  content. But if the parameter is missing in the Content-Type header, how can I know the character set of the HTML content?

I also know there is tag such as

```<code>"meta charset="utf-8""
</code>```

in HTML that is used to specify the character set. But we get that tag only after parsing the HTML and parsing HTML needs to know the character set first.

答:
You're absolutely correct that you need to start parsing the HTML in order to see the <meta charset element.

But this is standardised behavior: you must follow an encoding sniffing algorithm which starts processing the HTML source until it knows the encoding, then reparses with the known encoding.  Obviously this imposes limitations as you imagine, so you should check out the specification as per Quentin's comment as there are a lot of cases you need to be aware of.

Basically, your sniffer needs to be able to recognise UTF-16 byte order marks if the content may be UTF-16 (or UCS-2).  And it needs to recognise "" in order to skip comments, and "<meta " or "<meta/" in order to identify the beginning of a meta element, which could use "http-equiv", "content" or "charset" tags.

When authoring HTML, you should ensure the <meta element is as early as possible in the file, within the first 1024 bytes, and preferably, before the first occurrence of any non-ASCII characters in the file.

Body:
I know the parameter charset= in the HTTP header:Content-Type can be used to determine the character set of the HTML  content. But if the parameter is missing in the Content-Type header, how can I know the character set of the HTML content?

I also know there is tag such as

"meta charset="utf-8""

in HTML that is used to specify the character set. But we get that tag only after parsing the HTML and parsing HTML needs to know the character set first.

Body:
You're absolutely correct that you need to start parsing the HTML in order to see the <meta charset element.

But this is standardised behavior: you must follow an encoding sniffing algorithm which starts processing the HTML source until it knows the encoding, then reparses with the known encoding.  Obviously this imposes limitations as you imagine, so you should check out the specification as per Quentin's comment as there are a lot of cases you need to be aware of.

Basically, your sniffer needs to be able to recognise UTF-16 byte order marks if the content may be UTF-16 (or UCS-2).  And it needs to recognise "<!--" and "-->" in order to skip comments, and "<meta " or "<meta/" in order to identify the beginning of a meta element, which could use "http-equiv", "content" or "charset" tags.

When authoring HTML, you should ensure the <meta element is as early as possible in the file, within the first 1024 bytes, and preferably, before the first occurrence of any non-ASCII characters in the file.


问:
Returning a view from a method by calling its method
I have a method in a controller named AspNetAssessment_QuestionController

```<code>public ActionResult Excel_Data(HttpPostedFileBase excelfile)
{
    if ( excelfile == null )
    {
        ViewBag.Error = "Please select an excel file";
        return View("Create");
    }
    else if (excelfile.FileName.EndsWith("xls") || excelfile.FileName.EndsWith("xlsx"))
    {
        return View("Index");
    }
    else
    {
        ViewBag.Error = "File type is incorrect";
        return View("Create");
    }
}
</code>```

Now when this method returns the view, the requested view needs some viewbag data to run its razor syntax, like in 'Create' and 'Index' both have:

```<code>@Html.DropDownList("ClassID", null, htmlAttributes: new { @class = "form-control" })
</code>```

As the system just return my view without hitting the method it is not able to get value of viewbag from the method of Create and Index.

I also added the routes so they hit their method in routes.config file as

```<code>routes.MapRoute(
                name: "AspNetAssessment_Question/Create",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "AspNetAssessment_Question", action = "Create", id = UrlParameter.Optional }
            );
</code>```

and same goes for index but when excel_data method return view I receive an error that Viewbag.propertyname data is missing on following url

```<code>http://localhost:1331/AspNetAssessment_Question/Excel_Data
</code>```

I even tried to call their methods like Create() instead of return view("Create") but it failed and didn't render the view.

The create method has two forms. One hits the method of Excel_data and other one call Create method

How can I hit their method and return the view from Excel_Data so that they get the viewbag data from their methods and from Excel_Data as well.

excel_data method assign viewbag.Error and in the method of create I have viewbag.ClassID and some more.

答:
If it's only the error message that you want to display, you could save them to session/cookie and use RedirectToAction return RedirectToAction("Create", "AspNetAssessment_QuestionController"); instead of return View("Create");.

Then in the Create/Index ActionResults, you could add something like this:

```<code>public ActionResult Create()
{
    ViewBag.Error = Session["ErrorMessage"].ToString();
    return View();
}
</code>```

Body:
I have a method in a controller named AspNetAssessment_QuestionController

public ActionResult Excel_Data(HttpPostedFileBase excelfile)
{
    if ( excelfile == null )
    {
        ViewBag.Error = "Please select an excel file";
        return View("Create");
    }
    else if (excelfile.FileName.EndsWith("xls") || excelfile.FileName.EndsWith("xlsx"))
    {
        return View("Index");
    }
    else
    {
        ViewBag.Error = "File type is incorrect";
        return View("Create");
    }
}

Now when this method returns the view, the requested view needs some viewbag data to run its razor syntax, like in 'Create' and 'Index' both have:

@Html.DropDownList("ClassID", null, htmlAttributes: new { @class = "form-control" })

As the system just return my view without hitting the method it is not able to get value of viewbag from the method of Create and Index.

I also added the routes so they hit their method in routes.config file as

routes.MapRoute(
                name: "AspNetAssessment_Question/Create",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "AspNetAssessment_Question", action = "Create", id = UrlParameter.Optional }
            );

and same goes for index but when excel_data method return view I receive an error that Viewbag.propertyname data is missing on following url

http://localhost:1331/AspNetAssessment_Question/Excel_Data

I even tried to call their methods like Create() instead of return view("Create") but it failed and didn't render the view.

The create method has two forms. One hits the method of Excel_data and other one call Create method

How can I hit their method and return the view from Excel_Data so that they get the viewbag data from their methods and from Excel_Data as well.

excel_data method assign viewbag.Error and in the method of create I have viewbag.ClassID and some more.

Body:
If it's only the error message that you want to display, you could save them to session/cookie and use RedirectToAction return RedirectToAction("Create", "AspNetAssessment_QuestionController"); instead of return View("Create");.

Then in the Create/Index ActionResults, you could add something like this:

public ActionResult Create()
{
    ViewBag.Error = Session["ErrorMessage"].ToString();
    return View();
}


问:
How to stub a function in a module?
I build express app, there is a route A use many middlewares:

```<code>// fblogin.js
const saveUser = require('./middlewares').saveUser;
const issueJWT = require('./middlewares').issueJWT;

const exchangeLongTimeToken = (a) => { //return promise to call API };
const retrieveUserInfo = (b) => { //return promise to call API };

const service = {
    exchangeLongTimeToken,
    retrieveUserInfo,
};

const asyncAll = (req, res) => {
    // use Promise.all() to get service.exchangeLongTimeToken
    // and service.retrieveUserInfo
};

router.post('/', [asyncAll, saveUser, issueJWT], (req, res) => {
    //some logic;
});

module.exports = { router, service };
</code>```

And this is my middlewares.js:

```<code>const saveUser = (req, res, next) => { //save user };
const issueJWT = (req, res, next) => { //issue jwt };

module.exports = { saveUser, issueJWT };
</code>```

It works well. But got problem when I tried to write the test.
This is my test, I use mocha, chai, supertest and sinon:

```<code>const sinon = require('sinon');
const middlewares = require('../../../../src/routes/api/auth/shared/middlewares');
const testData = require('../../testdata/data.json');
let app = require('../../../../src/config/expressapp').setupApp();
const request = require('supertest');
let service = require('../../../../src/routes/api/auth/facebook/fblogin').service;

describe('I want to test', () => {
    context('Let me test', function () {
        const testReq = {name: 'verySad'};

        beforeEach(() => {
            sinon.stub(middlewares, 'saveUser').callsFake((req, res, next)=>{
                console.log(req);
            });

            sinon.stub(service, 'exchangeLongTimeToken').callsFake((url) => {
                return Promise.resolve(testData.fbLongTimeToken);
            });

            sinon.stub(service, 'retrieveUserInfo').callsFake((url) => {
                return Promise.resolve(testData.fbUserInfo);
            });

        });

        it('Should return 400 when bad signedRequest', () => {

            return request(app).post(facebookAPI).send(testReq).then((response) => {
                response.status.should.be.equal(400);
            });
        });
});
</code>```

What is the problem

You could see that there are 3 stubs, 1 for middlewares.saveUser and 2 for services.XXXX which is in the same file of the route.

The problem is that, the 2 stubs works while the 1 for middlewares.saveUser not work, always trigger the original one.

I think it maybe that when I call the setupApp(), the express will load all the routers it needs, so mock it afterwards won't have a effect, but it
is strange that route.service could be mocked...

How to get the stub work?

The only way to get it work, is to put the stub at the top of test file, just after that middleware require.

I tried:

1. Use 3rd party modules like proxyquire, rewire

2. Use node's own delete require.cache[middlewares] and 'app' and re-require them.

3. Many other tricks.

4. Use jest's mock, but still only works if I put it at the top of the file.

What is the way of solving this problem without putting the stub at the top of the test file? Thanks!

答:
The solution in the question is a bit restricted, since the mock has polluted the whole test suites.

I end up by doing this, The logic is simple, we still need to mock the saveUser first, but then we require all the other variables into the test function rather than require them at the top of the file, more flexible this time. And I add a checkIfTheStubWorks method to check if the stub works, to make sure the whole test works.

```<code>const middlewares = require('../../../../src/routes/api/auth/shared/middlewares');
const removeEmptyProperty = require('../../../../src/utils/utils').removeEmptyProperty;

let app;
let service;
let request;

/*
 * The reason we need this is:
 * If the mock not works,
 * the whole test is meaningless
 */
const checkIfTheStubWorks = () => {
    expect(spy1).toHaveBeenCalled();
    expect(spy2).toHaveBeenCalled();
    expect(spy3).toHaveBeenCalled();
};

const loadAllModules = () => {
    service = require('../../../../src/routes/api/auth/facebook/fblogin').service;
    app = require('../../../../src/config/expressapp').setupApp();
    request = require('supertest')(app);
};

describe('Mock response from facebook', () => {
    let spy1 = {};
    let spy2 = {};
    let spy3 = {};
    const testReq = testData.fbShortToken;

beforeAll(() => {
    spy1 = jest.spyOn(middlewares, 'saveUser').mockImplementation((req, res, next) => {
        userToSaveOrUpdate = removeEmptyProperty(res.locals.user);
        next();
    });

    // It must be load here, in this order,
    // otherwise, the above mock won't work!
    loadAllModules();

    spy2 = jest.spyOn(service, 'exchangeLongTimeToken').mockImplementation((url) => {
        // mock it
    });

    spy3 = jest.spyOn(service, 'retrieveUserInfo').mockImplementation((url) => {
        // mock it
    });
});

afterAll(() => {
    spy1.mockRestore();
    spy2.mockRestore();
    spy3.mockRestore();
});

test('Return a JWT should have same length as facebook one', async () => {
    const response = await request.post(facebookAPI).send(testReq);
    // assert this, assert that
    checkIfTheStubWorks();
});
});
</code>```

Title: How to stub a function in a module?

Body:
I build express app, there is a route A use many middlewares:

// fblogin.js
const saveUser = require('./middlewares').saveUser;
const issueJWT = require('./middlewares').issueJWT;

const exchangeLongTimeToken = (a) => { //return promise to call API };
const retrieveUserInfo = (b) => { //return promise to call API };

const service = {
    exchangeLongTimeToken,
    retrieveUserInfo,
};

const asyncAll = (req, res) => {
    // use Promise.all() to get service.exchangeLongTimeToken
    // and service.retrieveUserInfo
};

router.post('/', [asyncAll, saveUser, issueJWT], (req, res) => {
    //some logic;
});

module.exports = { router, service };

And this is my middlewares.js:

const saveUser = (req, res, next) => { //save user };
const issueJWT = (req, res, next) => { //issue jwt };

module.exports = { saveUser, issueJWT };

It works well. But got problem when I tried to write the test.
This is my test, I use mocha, chai, supertest and sinon:

const sinon = require('sinon');
const middlewares = require('../../../../src/routes/api/auth/shared/middlewares');
const testData = require('../../testdata/data.json');
let app = require('../../../../src/config/expressapp').setupApp();
const request = require('supertest');
let service = require('../../../../src/routes/api/auth/facebook/fblogin').service;

describe('I want to test', () => {
    context('Let me test', function () {
        const testReq = {name: 'verySad'};

        beforeEach(() => {
            sinon.stub(middlewares, 'saveUser').callsFake((req, res, next)=>{
                console.log(req);
            });

            sinon.stub(service, 'exchangeLongTimeToken').callsFake((url) => {
                return Promise.resolve(testData.fbLongTimeToken);
            });

            sinon.stub(service, 'retrieveUserInfo').callsFake((url) => {
                return Promise.resolve(testData.fbUserInfo);
            });

        });

        it('Should return 400 when bad signedRequest', () => {

            return request(app).post(facebookAPI).send(testReq).then((response) => {
                response.status.should.be.equal(400);
            });
        });
});

What is the problem

You could see that there are 3 stubs, 1 for middlewares.saveUser and 2 for services.XXXX which is in the same file of the route.

The problem is that, the 2 stubs works while the 1 for middlewares.saveUser not work, always trigger the original one.

I think it maybe that when I call the setupApp(), the express will load all the routers it needs, so mock it afterwards won't have a effect, but it
is strange that route.service could be mocked...

How to get the stub work?

The only way to get it work, is to put the stub at the top of test file, just after that middleware require.

I tried:

1. Use 3rd party modules like proxyquire, rewire

2. Use node's own delete require.cache[middlewares] and 'app' and re-require them.

3. Many other tricks.

4. Use jest's mock, but still only works if I put it at the top of the file.

What is the way of solving this problem without putting the stub at the top of the test file? Thanks!

Body:
The solution in the question is a bit restricted, since the mock has polluted the whole test suites.

I end up by doing this, The logic is simple, we still need to mock the saveUser first, but then we require all the other variables into the test function rather than require them at the top of the file, more flexible this time. And I add a checkIfTheStubWorks method to check if the stub works, to make sure the whole test works.

const middlewares = require('../../../../src/routes/api/auth/shared/middlewares');
const removeEmptyProperty = require('../../../../src/utils/utils').removeEmptyProperty;

let app;
let service;
let request;

/*
 * The reason we need this is:
 * If the mock not works,
 * the whole test is meaningless
 */
const checkIfTheStubWorks = () => {
    expect(spy1).toHaveBeenCalled();
    expect(spy2).toHaveBeenCalled();
    expect(spy3).toHaveBeenCalled();
};

const loadAllModules = () => {
    service = require('../../../../src/routes/api/auth/facebook/fblogin').service;
    app = require('../../../../src/config/expressapp').setupApp();
    request = require('supertest')(app);
};

describe('Mock response from facebook', () => {
    let spy1 = {};
    let spy2 = {};
    let spy3 = {};
    const testReq = testData.fbShortToken;

beforeAll(() => {
    spy1 = jest.spyOn(middlewares, 'saveUser').mockImplementation((req, res, next) => {
        userToSaveOrUpdate = removeEmptyProperty(res.locals.user);
        next();
    });

    // It must be load here, in this order,
    // otherwise, the above mock won't work!
    loadAllModules();

    spy2 = jest.spyOn(service, 'exchangeLongTimeToken').mockImplementation((url) => {
        // mock it
    });

    spy3 = jest.spyOn(service, 'retrieveUserInfo').mockImplementation((url) => {
        // mock it
    });
});

afterAll(() => {
    spy1.mockRestore();
    spy2.mockRestore();
    spy3.mockRestore();
});

test('Return a JWT should have same length as facebook one', async () => {
    const response = await request.post(facebookAPI).send(testReq);
    // assert this, assert that
    checkIfTheStubWorks();
});
});


问:
Latest version of Xmarin.Forms.Maps breaks custom renderer
Trying to display a circle on a map using Custom Renderer. (Android)

Updated Xamarin.Forms.Maps to v2.3.3.175 and now I am getting error: CustomMapRenderer.OnElementChanged(ElementChangedEventArgs)': no suitable method found to override.

Worked previously with no issues. Even the sample from link below no longer works.
https://developer.xamarin.com/recipes/cross-platform/xamarin-forms/maps/map-overlay/circle/

Changing ElementChangedEventArgs<View> to ElementChangedEventArgs<Map> resolves the error but the renderer is never called so the circle is never shown.

Any ideas? Thanks in advance.

My Custom Android Renderer:

```<code>using Android.Gms.Maps;
using Android.Gms.Maps.Model;
using Xamarin.Forms;
using Xamarin.Forms.Maps.Android;
using GasFinder;
using MapOverlay.Droid;

[assembly: ExportRenderer(typeof(CustomMap),typeof(CustomMapRenderer))]
namespace MapOverlay.Droid {
    public class CustomMapRenderer:MapRenderer, IOnMapReadyCallback {
    GoogleMap map;
    CustomCircle circle;

    protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<View> e) {
        base.OnElementChanged(e);

        if(e.OldElement != null) {
            // Unsubscribe
        }

        if(e.NewElement != null) {
            var formsMap = (CustomMap)e.NewElement;
            circle = formsMap.Circle;
            ((MapView)Control).GetMapAsync(this);
        }
    }
    public void OnMapReady(GoogleMap googleMap) {
        map = googleMap;

        var circleOptions = new CircleOptions();
        circleOptions.InvokeCenter(new LatLng(circle.Position.Latitude,circle.Position.Longitude));
        circleOptions.InvokeRadius(circle.Radius);
        circleOptions.InvokeFillColor(0X233273b1);
        circleOptions.InvokeStrokeColor(0X64007eff);
        circleOptions.InvokeStrokeWidth(10);
        map.AddCircle(circleOptions);
    }
}
}
</code>```

CustomMap.cs is as follows:

```<code>using System.Collections.Generic;
using Xamarin.Forms.Maps;

namespace GasFinder {
    public class CustomMap:Map {
        public CustomCircle Circle { get; set; }
    }
}
</code>```

CustomCircle.cs is as follows:

```<code>using Xamarin.Forms.Maps;

namespace GasFinder {
    public class CustomCircle {
        public Position Position { get; set; }
        public double Radius { get; set; }
    }
}
</code>```

Code on my Page.xaml.cs is as follows:

```<code>var position = new Xamarin.Forms.Maps.Position(Search.loc.lat,Search.loc.lng);
customMap.Circle = new CustomCircle {
    Position = position,
    Radius = Settings.Distance*1000
};
</code>```

答:
using Xamarin.Forms.Maps v2.3.3.193</p>

```<code>protected override void OnElementChanged(ElementChangedEventArgs<Map> e) {
    base.OnElementChanged(e);
    if(e.OldElement != null) { }
    if(e.NewElement != null) {
        var formsMap = (CustomMap)e.NewElement;
        circle = formsMap.Circle;
        ((MapView)Control).GetMapAsync(this);
    }
}
</code>```

Body:
Trying to display a circle on a map using Custom Renderer. (Android)

Updated Xamarin.Forms.Maps to v2.3.3.175 and now I am getting error: CustomMapRenderer.OnElementChanged(ElementChangedEventArgs)': no suitable method found to override.

Worked previously with no issues. Even the sample from link below no longer works.
https://developer.xamarin.com/recipes/cross-platform/xamarin-forms/maps/map-overlay/circle/

Changing ElementChangedEventArgs<View> to ElementChangedEventArgs<Map> resolves the error but the renderer is never called so the circle is never shown.

Any ideas? Thanks in advance.

My Custom Android Renderer:

using Android.Gms.Maps;
using Android.Gms.Maps.Model;
using Xamarin.Forms;
using Xamarin.Forms.Maps.Android;
using GasFinder;
using MapOverlay.Droid;

[assembly: ExportRenderer(typeof(CustomMap),typeof(CustomMapRenderer))]
namespace MapOverlay.Droid {
    public class CustomMapRenderer:MapRenderer, IOnMapReadyCallback {
    GoogleMap map;
    CustomCircle circle;

    protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<View> e) {
        base.OnElementChanged(e);

        if(e.OldElement != null) {
            // Unsubscribe
        }

        if(e.NewElement != null) {
            var formsMap = (CustomMap)e.NewElement;
            circle = formsMap.Circle;
            ((MapView)Control).GetMapAsync(this);
        }
    }
    public void OnMapReady(GoogleMap googleMap) {
        map = googleMap;

        var circleOptions = new CircleOptions();
        circleOptions.InvokeCenter(new LatLng(circle.Position.Latitude,circle.Position.Longitude));
        circleOptions.InvokeRadius(circle.Radius);
        circleOptions.InvokeFillColor(0X233273b1);
        circleOptions.InvokeStrokeColor(0X64007eff);
        circleOptions.InvokeStrokeWidth(10);
        map.AddCircle(circleOptions);
    }
}
}

CustomMap.cs is as follows:

using System.Collections.Generic;
using Xamarin.Forms.Maps;

namespace GasFinder {
    public class CustomMap:Map {
        public CustomCircle Circle { get; set; }
    }
}

CustomCircle.cs is as follows:

using Xamarin.Forms.Maps;

namespace GasFinder {
    public class CustomCircle {
        public Position Position { get; set; }
        public double Radius { get; set; }
    }
}

Code on my Page.xaml.cs is as follows:

var position = new Xamarin.Forms.Maps.Position(Search.loc.lat,Search.loc.lng);
customMap.Circle = new CustomCircle {
    Position = position,
    Radius = Settings.Distance*1000
};

Body:
using Xamarin.Forms.Maps v2.3.3.193

protected override void OnElementChanged(ElementChangedEventArgs<Map> e) {
    base.OnElementChanged(e);
    if(e.OldElement != null) { }
    if(e.NewElement != null) {
        var formsMap = (CustomMap)e.NewElement;
        circle = formsMap.Circle;
        ((MapView)Control).GetMapAsync(this);
    }
}


问:
Deleting specific record from Access database on button click
I have a string that contains 9 characters, for example LON052012 (from London 23.05.2012. - day.month.year.). I want to delete all records from table in Access where all cities start with first three letters from that string and have those months and year (05.2007.).

This is the function:

```<code>private void button2_Click(object sender, EventArgs e)
    {
        if (textBox1.Text != "")
        {
            try
            {
                string sTown, s1, s2;
                sTown = textBox1.Text.Substring(0, 3);
                s1 = textBox1.Text.Substring(3, 2);
                s2 = textBox1.Text.Substring(5);

                string sDelete = "DELETE * FROM Country WHERE Town LIKE @p1 and month(TownDate) = @p2 and year(TownDate) = @p3";
                OleDbCommand komDelete = new OleDbCommand(sDelete, connection);
                komDelete.Parameters.AddWithValue("@p1", sTown + "*");
                komDelete.Parameters.AddWithValue("@p2", s1);
                komDelete.Parameters.AddWithValue("@p3", s2);
                connection.Open();
                komDelete.ExecuteNonQuery();
                MessageBox.Show("Deleted");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
            finally
            {
                connection.Close();
            }
        }
        else
        {
            MessageBox.Show("TextBox is empty!");
        }
    }
</code>```

This is how table Country looks like (CountryID, Town, TownDate):

It always says that the record is deleted even if it's not.

答:
Try this:

```<code>        if (textBox1.Text != "")
    {
        //retrieve data
        string sTown, sMonth, sYear;
        sTown = textBox1.Text.Substring(0, 3);
        sMonth = textBox1.Text.Substring(3, 2);
        sYear = textBox1.Text.Substring(5);

        //validate input
        bool valid_town = new Regex(@"[a-z]", RegexOptions.IgnoreCase).IsMatch(sTown) && new Regex(@"[^0-9]").IsMatch(sTown) && sTown.Length ==3;
        bool valid_month = new Regex(@"[0][1-9]|[1][0-2]").IsMatch(sMonth) && new Regex(@"[^a-z]", RegexOptions.IgnoreCase).IsMatch(sMonth) && sMonth.Length ==2;

        int year = 0;
        bool isNum = int.TryParse(sYear,out year);
        bool valid_year = new Regex(@"[^a-z]", RegexOptions.IgnoreCase).IsMatch(sYear) && sYear.Length == 4 && (isNum ? year > 1980 && year < 2100 : false);

        string newLine = System.Environment.NewLine;

        //if input valid
        if (valid_town && valid_month && valid_year)
        {
            //create sql statements
            string sWhere = String.Format("WHERE Town LIKE {0} and month(TownDate) = {1] and year(TownDate) = {2}", sTown,sMonth,sYear);
            string sCount = String.Format("SELECT COUNT(*) FROM Country {0}", sWhere);
            string sDelete = String.Format("DELETE * FROM Country {0}",sWhere);

            //counts; to be deleted, actually deleted
            int initialCount = 0;
            int deletedCount = 0;

            try
            {
                //create connection//NOTE: Using 'Use' statement will handle opening and closing. I dont know where you created your initial 'connection' object but it could cause you problems by haven a connection that is being used in multiple methods.
                using (OleDbCommand connection = new OleDbCommand(ConnectionString))
                {
                    //get total rows to be affected
                    connection.CommandText = sCount;
                    initialCount = connection.ExecuteNonQuery();

                    //delete rows and get delete count
                    connection.CommandText = sDelete;
                    deletedCount = connection.ExecuteNonQuery();
                    //display message
                    MessageBox.Show(String.Format("Found {0} rows to delete. {1}Deleted {2} rows.", initialCount, newLine, deletedCount));

                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
            finally
            {
                connection.Close();
            }
        }
        {
            //else; input not valid
            MessageBox.Show(String.Format("Failed validation of TextBox:{0}Country:{1}{2}Month{3}{4}Year{5}.", newLine, valid_town.ToString(), newLine, valid_month.ToString(), newLine, valid_year.ToString())); ;

        }
    }
    else
    {
        MessageBox.Show("TextBox is empty!");
    }
</code>```

you will need to add this using:

```<code>using System.Text.RegularExpressions;
</code>```

I didn't get a chance to create sample project to try it myself...

Body:
I have a string that contains 9 characters, for example LON052012 (from London 23.05.2012. - day.month.year.). I want to delete all records from table in Access where all cities start with first three letters from that string and have those months and year (05.2007.).

This is the function:

private void button2_Click(object sender, EventArgs e)
    {
        if (textBox1.Text != "")
        {
            try
            {
                string sTown, s1, s2;
                sTown = textBox1.Text.Substring(0, 3);
                s1 = textBox1.Text.Substring(3, 2);
                s2 = textBox1.Text.Substring(5);

                string sDelete = "DELETE * FROM Country WHERE Town LIKE @p1 and month(TownDate) = @p2 and year(TownDate) = @p3";
                OleDbCommand komDelete = new OleDbCommand(sDelete, connection);
                komDelete.Parameters.AddWithValue("@p1", sTown + "*");
                komDelete.Parameters.AddWithValue("@p2", s1);
                komDelete.Parameters.AddWithValue("@p3", s2);
                connection.Open();
                komDelete.ExecuteNonQuery();
                MessageBox.Show("Deleted");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
            finally
            {
                connection.Close();
            }
        }
        else
        {
            MessageBox.Show("TextBox is empty!");
        }
    }

This is how table Country looks like (CountryID, Town, TownDate):

It always says that the record is deleted even if it's not.

Body:
Try this:

        if (textBox1.Text != "")
    {
        //retrieve data
        string sTown, sMonth, sYear;
        sTown = textBox1.Text.Substring(0, 3);
        sMonth = textBox1.Text.Substring(3, 2);
        sYear = textBox1.Text.Substring(5);

        //validate input
        bool valid_town = new Regex(@"[a-z]", RegexOptions.IgnoreCase).IsMatch(sTown) && new Regex(@"[^0-9]").IsMatch(sTown) && sTown.Length ==3;
        bool valid_month = new Regex(@"[0][1-9]|[1][0-2]").IsMatch(sMonth) && new Regex(@"[^a-z]", RegexOptions.IgnoreCase).IsMatch(sMonth) && sMonth.Length ==2;

        int year = 0;
        bool isNum = int.TryParse(sYear,out year);
        bool valid_year = new Regex(@"[^a-z]", RegexOptions.IgnoreCase).IsMatch(sYear) && sYear.Length == 4 && (isNum ? year > 1980 && year < 2100 : false);

        string newLine = System.Environment.NewLine;

        //if input valid
        if (valid_town && valid_month && valid_year)
        {
            //create sql statements
            string sWhere = String.Format("WHERE Town LIKE {0} and month(TownDate) = {1] and year(TownDate) = {2}", sTown,sMonth,sYear);
            string sCount = String.Format("SELECT COUNT(*) FROM Country {0}", sWhere);
            string sDelete = String.Format("DELETE * FROM Country {0}",sWhere);

            //counts; to be deleted, actually deleted
            int initialCount = 0;
            int deletedCount = 0;

            try
            {
                //create connection//NOTE: Using 'Use' statement will handle opening and closing. I dont know where you created your initial 'connection' object but it could cause you problems by haven a connection that is being used in multiple methods.
                using (OleDbCommand connection = new OleDbCommand(ConnectionString))
                {
                    //get total rows to be affected
                    connection.CommandText = sCount;
                    initialCount = connection.ExecuteNonQuery();

                    //delete rows and get delete count
                    connection.CommandText = sDelete;
                    deletedCount = connection.ExecuteNonQuery();
                    //display message
                    MessageBox.Show(String.Format("Found {0} rows to delete. {1}Deleted {2} rows.", initialCount, newLine, deletedCount));

                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
            finally
            {
                connection.Close();
            }
        }
        {
            //else; input not valid
            MessageBox.Show(String.Format("Failed validation of TextBox:{0}Country:{1}{2}Month{3}{4}Year{5}.", newLine, valid_town.ToString(), newLine, valid_month.ToString(), newLine, valid_year.ToString())); ;

        }
    }
    else
    {
        MessageBox.Show("TextBox is empty!");
    }

you will need to add this using:

using System.Text.RegularExpressions;

I didn't get a chance to create sample project to try it myself...


问:
How is Date.prototype.getUTCFullYear() compliant with year-2000?
From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getUTCFullYear:

The value returned by getUTCFullYear() is an absolute number that is compliant with year-2000, for example, 1995.

What does it mean to be "compliant with year-2000"?

答:
The phrase "compliant with year-2000" is a bit misleading, and probably should be removed.

Initially, ECMAScript was implemented with a Java-like method called getYear which returned a 2 digit year that was the full year - 1900, so 1995 was returned as 95, 2017 as 117 and 1832 as -68. This method has now been moved to an appendix of ECMA-262 for web browsers only and is maintained for backward compatibility reasons, it should not be used in new code.

Although the getYear method seems a bit weird now, it was easily converted to a full year by adding 1900.

The "Y2K" issue is that 2 digit years became an issue after 1 Jan 2000 as a date like 1/1/00 would be interpreted as 1/1/1900 when 1/1/2000 was intended (and so on for any 2 digit year). This issue persists, since new Date(0,0,1) creates a date for 1/1/1900, not 1/1/0000.

That is the real year 2000 (Y2K) issue, not getting the year.

To create a date between -99 and +99, you need to set the full year, e.g. for 1 Jan 23 you need to do:

```<code>var d = new Date();
d.setFullYear(23,0,1);
</code>```

In regard to getFullYear (and getUTCFullYear), it returns the full year, which can be any year that is roughly ±285,616 from 1970. It doesn't, of itself, avoid the Y2K issue. But it will return the actual year:

var d = new Date();
d.setFullYear(23, 0, 1);
console.log(d.getYear());     // -1877
console.log(d.getFullYear()); // 23```

Body:
The phrase "compliant with year-2000" is a bit misleading, and probably should be removed.

Initially, ECMAScript was implemented with a Java-like method called getYear which returned a 2 digit year that was the full year - 1900, so 1995 was returned as 95, 2017 as 117 and 1832 as -68. This method has now been moved to an appendix of ECMA-262 for web browsers only and is maintained for backward compatibility reasons, it should not be used in new code.

Although the getYear method seems a bit weird now, it was easily converted to a full year by adding 1900.

The "Y2K" issue is that 2 digit years became an issue after 1 Jan 2000 as a date like 1/1/00 would be interpreted as 1/1/1900 when 1/1/2000 was intended (and so on for any 2 digit year). This issue persists, since new Date(0,0,1) creates a date for 1/1/1900, not 1/1/0000.

That is the real year 2000 (Y2K) issue, not getting the year.

To create a date between -99 and +99, you need to set the full year, e.g. for 1 Jan 23 you need to do:

var d = new Date();
d.setFullYear(23,0,1);

In regard to getFullYear (and getUTCFullYear), it returns the full year, which can be any year that is roughly ±285,616 from 1970. It doesn't, of itself, avoid the Y2K issue. But it will return the actual year:

var d = new Date();
d.setFullYear(23, 0, 1);
console.log(d.getYear());     // -1877
console.log(d.getFullYear()); // 23


问:
End user add values to a dropdownlist?
I'm populating a dropdownlist in c# asp.net-MVC from a SQL table using Linq2Sql.  I'd like for the user to be able to enter something that isn't in the list into the drop down and have it add to the table.  Is this possible?</p>

答: Why can't we use a lightweight Add-on like www.combodropdown.info for this purpose? You can even consider AutoComplete plugin from jQuery, if your app already references jQuery.</p>

ContentLicense: CC BY-SA 2.5

Title: End user add values to a dropdownlist?


问:
SQL error: 1170
I am getting the following error when running the below code...what is wrong with it?

Error Code:1170. BLOB/TEXT column 'message" used in key specification without a key length.

```<code>-- MySQL Script generated by MySQL Workbench
-- Sun Jun  4 21:25:42 2017
-- Model: New Model    Version: 1.0
-- MySQL Workbench Forward Engineering

    SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
    SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
    SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';

-- -----------------------------------------------------
-- Schema mydb
-- -----------------------------------------------------

-- -----------------------------------------------------
-- Schema mydb
-- -----------------------------------------------------
    CREATE SCHEMA IF NOT EXISTS `mydb` DEFAULT CHARACTER SET utf8 ;
    USE `mydb` ;

-- -----------------------------------------------------
-- Table `mydb`.`users`
-- -----------------------------------------------------
    CREATE TABLE IF NOT EXISTS `mydb`.`users` (
      `id` INT NOT NULL AUTO_INCREMENT,
      `first_name` VARCHAR(255) NOT NULL,
      `last_name` VARCHAR(255) NOT NULL,
      `email` VARCHAR(255) NOT NULL,
      `password` VARCHAR(255) NOT NULL,
      `created_at` DATETIME NOT NULL,
      `updates_at` DATETIME NOT NULL,
      PRIMARY KEY (`id`),
      UNIQUE INDEX `first_name_UNIQUE` (`first_name` ASC),
      UNIQUE INDEX `last_name_UNIQUE` (`last_name` ASC),
      UNIQUE INDEX `email_UNIQUE` (`email` ASC),
      UNIQUE INDEX `password_UNIQUE` (`password` ASC),
      UNIQUE INDEX `created_at_UNIQUE` (`created_at` ASC),
      UNIQUE INDEX `updates_at_UNIQUE` (`updates_at` ASC))
      ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `mydb`.`messages`
-- -----------------------------------------------------
    CREATE TABLE IF NOT EXISTS `mydb`.`messages` (
      `id` INT NOT NULL AUTO_INCREMENT,
      `users_id` INT NOT NULL,
      `message` TEXT NOT NULL,
      `created_at` DATETIME NOT NULL,
      `updated_at` DATETIME NOT NULL,
      PRIMARY KEY (`id`),
      INDEX `fk_messages_users_idx` (`users_id` ASC),
      UNIQUE INDEX `id_UNIQUE` (`id` ASC),
      UNIQUE INDEX `users_id_UNIQUE` (`users_id` ASC),
      UNIQUE INDEX `message_UNIQUE` (`message` ASC),
      UNIQUE INDEX `created_at_UNIQUE` (`created_at` ASC),
      UNIQUE INDEX `updated_at_UNIQUE` (`updated_at` ASC),
      CONSTRAINT `fk_messages_users`
        FOREIGN KEY (`users_id`)
        REFERENCES `mydb`.`users` (`id`)
        ON DELETE NO ACTION
        ON UPDATE NO ACTION)
      ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `mydb`.`comments`
-- -----------------------------------------------------
    CREATE TABLE IF NOT EXISTS `mydb`.`comments` (
      `id` INT NOT NULL AUTO_INCREMENT,
      `users_id` INT NOT NULL,
      `messages_id` INT NOT NULL,
      `comment` TEXT NOT NULL,
      `created_at` DATETIME NOT NULL,
      `updated_at` DATETIME NOT NULL,
      PRIMARY KEY (`id`),
      INDEX `fk_comments_users1_idx` (`users_id` ASC),
      INDEX `fk_comments_messages1_idx` (`messages_id` ASC),
      UNIQUE INDEX `id_UNIQUE` (`id` ASC),
      UNIQUE INDEX `users_id_UNIQUE` (`users_id` ASC),
      UNIQUE INDEX `messages_id_UNIQUE` (`messages_id` ASC),
      UNIQUE INDEX `comment_UNIQUE` (`comment` ASC),
      UNIQUE INDEX `created_at_UNIQUE` (`created_at` ASC),
      UNIQUE INDEX `updated_at_UNIQUE` (`updated_at` ASC),
      CONSTRAINT `fk_comments_users1`
        FOREIGN KEY (`users_id`)
        REFERENCES `mydb`.`users` (`id`)
        ON DELETE NO ACTION
        ON UPDATE NO ACTION,
      CONSTRAINT `fk_comments_messages1`
        FOREIGN KEY (`messages_id`)
        REFERENCES `mydb`.`messages` (`id`)
        ON DELETE NO ACTION
        ON UPDATE NO ACTION)
    ENGINE = InnoDB;

    SET SQL_MODE=@OLD_SQL_MODE;
    SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
    SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
</code>```

答:
It is rare for a table to have 6 unique keys.  Even 2 is rare; 1 (the PRIMARY KEY) is typical.

UNIQUE is two things... an index and a uniqueness constraint.  As Bill points out, a "prefix" index can achieve a form of indexing.  Uniqueness is more complex.  If you really need that, then we can discuss it.

A uniqueness constraint on a DATETIME or TIMESTAMP is risky because there (usually) could be two events happening in the same second.  It is also rare to need a uniqueness check on "continuous" values like that.  (Ditto for FLOAT.)

Title: SQL error: 1170

Body:
I am getting the following error when running the below code...what is wrong with it?

Error Code:1170. BLOB/TEXT column 'message" used in key specification without a key length.

-- MySQL Script generated by MySQL Workbench
-- Sun Jun  4 21:25:42 2017
-- Model: New Model    Version: 1.0
-- MySQL Workbench Forward Engineering

    SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
    SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
    SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';

-- -----------------------------------------------------
-- Schema mydb
-- -----------------------------------------------------

-- -----------------------------------------------------
-- Schema mydb
-- -----------------------------------------------------
    CREATE SCHEMA IF NOT EXISTS `mydb` DEFAULT CHARACTER SET utf8 ;
    USE `mydb` ;

-- -----------------------------------------------------
-- Table `mydb`.`users`
-- -----------------------------------------------------
    CREATE TABLE IF NOT EXISTS `mydb`.`users` (
      `id` INT NOT NULL AUTO_INCREMENT,
      `first_name` VARCHAR(255) NOT NULL,
      `last_name` VARCHAR(255) NOT NULL,
      `email` VARCHAR(255) NOT NULL,
      `password` VARCHAR(255) NOT NULL,
      `created_at` DATETIME NOT NULL,
      `updates_at` DATETIME NOT NULL,
      PRIMARY KEY (`id`),
      UNIQUE INDEX `first_name_UNIQUE` (`first_name` ASC),
      UNIQUE INDEX `last_name_UNIQUE` (`last_name` ASC),
      UNIQUE INDEX `email_UNIQUE` (`email` ASC),
      UNIQUE INDEX `password_UNIQUE` (`password` ASC),
      UNIQUE INDEX `created_at_UNIQUE` (`created_at` ASC),
      UNIQUE INDEX `updates_at_UNIQUE` (`updates_at` ASC))
      ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `mydb`.`messages`
-- -----------------------------------------------------
    CREATE TABLE IF NOT EXISTS `mydb`.`messages` (
      `id` INT NOT NULL AUTO_INCREMENT,
      `users_id` INT NOT NULL,
      `message` TEXT NOT NULL,
      `created_at` DATETIME NOT NULL,
      `updated_at` DATETIME NOT NULL,
      PRIMARY KEY (`id`),
      INDEX `fk_messages_users_idx` (`users_id` ASC),
      UNIQUE INDEX `id_UNIQUE` (`id` ASC),
      UNIQUE INDEX `users_id_UNIQUE` (`users_id` ASC),
      UNIQUE INDEX `message_UNIQUE` (`message` ASC),
      UNIQUE INDEX `created_at_UNIQUE` (`created_at` ASC),
      UNIQUE INDEX `updated_at_UNIQUE` (`updated_at` ASC),
      CONSTRAINT `fk_messages_users`
        FOREIGN KEY (`users_id`)
        REFERENCES `mydb`.`users` (`id`)
        ON DELETE NO ACTION
        ON UPDATE NO ACTION)
      ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `mydb`.`comments`
-- -----------------------------------------------------
    CREATE TABLE IF NOT EXISTS `mydb`.`comments` (
      `id` INT NOT NULL AUTO_INCREMENT,
      `users_id` INT NOT NULL,
      `messages_id` INT NOT NULL,
      `comment` TEXT NOT NULL,
      `created_at` DATETIME NOT NULL,
      `updated_at` DATETIME NOT NULL,
      PRIMARY KEY (`id`),
      INDEX `fk_comments_users1_idx` (`users_id` ASC),
      INDEX `fk_comments_messages1_idx` (`messages_id` ASC),
      UNIQUE INDEX `id_UNIQUE` (`id` ASC),
      UNIQUE INDEX `users_id_UNIQUE` (`users_id` ASC),
      UNIQUE INDEX `messages_id_UNIQUE` (`messages_id` ASC),
      UNIQUE INDEX `comment_UNIQUE` (`comment` ASC),
      UNIQUE INDEX `created_at_UNIQUE` (`created_at` ASC),
      UNIQUE INDEX `updated_at_UNIQUE` (`updated_at` ASC),
      CONSTRAINT `fk_comments_users1`
        FOREIGN KEY (`users_id`)
        REFERENCES `mydb`.`users` (`id`)
        ON DELETE NO ACTION
        ON UPDATE NO ACTION,
      CONSTRAINT `fk_comments_messages1`
        FOREIGN KEY (`messages_id`)
        REFERENCES `mydb`.`messages` (`id`)
        ON DELETE NO ACTION
        ON UPDATE NO ACTION)
    ENGINE = InnoDB;

    SET SQL_MODE=@OLD_SQL_MODE;
    SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
    SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;


答:
When an error occurs, the program

Prints a message to the console, but there is no console, so the message goes nowhere, then

Immediately quits so that even if there were a console, it disappear in a flash.

If you want to actually report an error from a GUI Windows program, you have to wait around long enough for the user to see the error.  With SDL, the SDL_ShowSimpleMessageBox is a good choice for doing that.

Title: Windows executable fails to start despite having correct DLLs in root directory

Body:
My ultra simple 2D game Caventure depends on sdl-2 and sdl-ttf.

When compiled, the directory looks like

Caventure.exe
libfreetype-6.dll
notomono-regular.ttf
SDL2.dll
SDL2_ttf.dll
zlib1.dll

I'm using Microsoft Visual Studio 2015. I've been following Lazy Foo's tutorials on building with Windows and even after following the steps, it doesn't work. Here's what I've done:

Linked the compiler to include and library directories in x64.

Linked the libraries.

Copied the libraries to C:\Windows\SysWOW64.

Included <Windows.h>.

Used compatibility mode.

Tested it in the Visual Studio IDE, including with the debugger.

When I open it, it immediately closes, it doesn't return any error.

Here's the main source file:

#include <stdio.h>
#include <stdexcept>
#include <Windows.h>
#include <SDL.h>
#include <SDL_ttf.h>

#include "TextMenu.h"
#include "TextBox.h"

#include "Graphics.h"
#include "Event.h"

// Screen dimensions, constants
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
// 600 for ground, 280 for output, 20 for input

Graphics Global;
Event Loop;

void Init(Graphics& Global)
{
    if (SDL_Init(SDL_INIT_VIDEO) > 0)
    {
        throw(::std::runtime_error("SDL failed to initialise! ERROR: "));
    }
    Global.Window = SDL_CreateWindow("Caventure",
        SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        SCREEN_WIDTH,
        SCREEN_HEIGHT,
        SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
    if (Global.Window == NULL)
    {
        throw(::std::runtime_error("Window failed to initialise! ERROR: "));
    }
    Global.ScreenSurface = SDL_GetWindowSurface(Global.Window);
    if (Global.ScreenSurface == NULL)
    {
        throw(::std::runtime_error("Surface failed to initialise! ERROR: "));
    }
    Global.Renderer = SDL_CreateRenderer(Global.Window, -1, 0);
    if (Global.Renderer == NULL)
    {
        throw(::std::runtime_error("Renderer could not be initialised! ERROR: "));
    }
    if (TTF_Init() > 0)
    {
        throw(::std::runtime_error("TTF could not be initialised! ERROR: "));
    }
}

void UpdateMedia(Graphics& Global)
{
    SDL_GetWindowSize(Global.Window, &Global.width, &Global.height);

    // Set geomtry dimensions, apart from rcTextInput.
    Global.rcGround = { 0, 0, Global.width, (Global.height / 3) * 2 };
    Global.rcTextOutput = { 0, (Global.height / 3) * 2, Global.width, Global.height - 40 };
    Global.rcTextOutputGrd = { 0, (Global.height / 3) * 2, Global.width, Global.height - 40 };

    Global.SpriteDefaultX = Global.width / 2;
    Global.SpriteDefaultY = Global.height / 2;
};

void LoadMedia(Graphics& Global)
{
    UpdateMedia(Global);

    Global.rcSprite = { Global.SpriteDefaultX, Global.SpriteDefaultY, 4, 4 };

    Global.Font = TTF_OpenFont("src/graphics/resources/notomono-regular.ttf", 14);
    if (Global.Font == NULL)
    {
        throw(::std::runtime_error("Font failed to load! ERROR: "));
    }

    SDL_SetTextInputRect(&Global.rcTextInput);
}

void InputLoop(Graphics& Global, Event& Loop)
{
    if (Loop.event.type == SDL_QUIT)
    {
        Loop.bQuit = true;
    }
    else if (Loop.event.type == SDL_KEYDOWN)
    {
        // Sprite movement
        switch (Loop.event.key.keysym.sym)
        {
        case SDLK_UP:
            Global.rcSprite.y -= 5;
            break;

        case SDLK_DOWN:
            Global.rcSprite.y += 5;
            break;

        case SDLK_LEFT:
            Global.rcSprite.x -= 5;
            break;

        case SDLK_RIGHT:
            Global.rcSprite.x += 5;
            break;
        }

        // Backspace handler
        if (Loop.event.key.keysym.sym == SDLK_BACKSPACE && Loop.InputText.length() > 0)
        {
            Loop.InputText.pop_back();
            if (Loop.InputText.length() == 0)
            {
                Loop.InputText = " ";
            }
        }

        // Creates new line of text
        else if (Loop.event.key.keysym.sym == SDLK_RETURN && Loop.InputText.length() != 0 && Loop.InputText != " ")
        {
            Global.Menu.NewBox(Loop.InputText);
            Loop.bRenderText = true;
            Loop.InputText = " ";
        }
    }
    else if (Loop.event.type == SDL_TEXTINPUT)
    {
        Loop.InputText += Loop.event.text.text;
    }
}

void RenderLoop(Graphics& Global, Event& Loop)
{
    UpdateMedia(Global);

    // Renders sprite movement
    if (Global.rcSprite.x < 0 || Global.rcSprite.y < 0 || Global.rcSprite.y > Global.rcGround.h || Global.rcSprite.x > Global.rcGround.w)
    {
        Global.rcSprite.x = Global.SpriteDefaultX;
        Global.rcSprite.y = Global.SpriteDefaultY;
    }

    // Sets background to black
    SDL_SetRenderDrawColor(Global.Renderer, 0x00, 0x00, 0x00, 0x00);
    SDL_RenderClear(Global.Renderer);

    // Renders background of sprite to black
    SDL_RenderFillRect(Global.Renderer, &Global.rcGround);
    SDL_BlitSurface(Global.CurrentSurface, NULL, Global.ScreenSurface, &Global.rcGround);

    // Renders background of text box to grey
    SDL_SetRenderDrawColor(Global.Renderer, 0x40, 0x40, 0x40, 0x40);
    SDL_RenderFillRect(Global.Renderer, &Global.rcTextOutputGrd);
    SDL_BlitSurface(Global.CurrentSurface, NULL, Global.ScreenSurface, &Global.rcTextOutputGrd);

    SDL_SetRenderDrawColor(Global.Renderer, 0x00, 0x00, 0x00, 0x00);
    // Renders text input
    Global.TextInput.Render(Global.Renderer, Global.Font, Loop.InputText.c_str(), Global.TextColor);
    Global.rcTextInput = { 0, Global.height - 20, Global.TextInput.GetWidth(), Global.TextInput.GetHeight() };
    SDL_RenderCopy(Global.Renderer, Global.TextInput.GetTexture(), NULL, &Global.rcTextInput);

    // Renders text output
    if (Loop.bRenderText)
    {
        Global.Menu.Update(Global.Renderer, Global.Font, Global.TextColor, Global.rcTextOutput);
    }
    SDL_RenderSetClipRect(Global.Renderer, NULL);

    // Renders text box background edges white
    SDL_SetRenderDrawColor(Global.Renderer, 0xFF, 0xFF, 0xFF, 0xFF);
    SDL_RenderDrawLine(Global.Renderer, 0, (Global.height / 3) * 2, Global.width, (Global.height / 3) * 2);
    SDL_RenderDrawLine(Global.Renderer, 0, Global.height - 20, Global.width, Global.height - 20);

    // Renders sprite
    SDL_RenderFillRect(Global.Renderer, &Global.rcSprite);
    SDL_BlitSurface(Global.CurrentSurface, NULL, Global.ScreenSurface, &Global.rcSprite);

    // Presents render
    SDL_RenderPresent(Global.Renderer);
}

void Quit(Graphics& Global)
{
    // Deallocate memory
    SDL_DestroyWindow(Global.Window);
    SDL_DestroyRenderer(Global.Renderer);
    TTF_CloseFont(Global.Font);
    Global.Window = NULL;
    Global.Renderer = NULL;
    Global.Font = NULL;

    // Quit SDL subsystems
    TTF_Quit();
    SDL_Quit();
}

int main(int argc, char *argv[])
{
    try
    {
        Init(Global);
        LoadMedia(Global);
        SDL_StartTextInput();
        while (!Loop.bQuit)
        {
            while (SDL_PollEvent(&Loop.event) != 0)
            {
                InputLoop(Global, Loop);
                RenderLoop(Global, Loop);
            }
        }
        SDL_StopTextInput();
    }
    catch (std::runtime_error const& msg)
    {
        printf("%s", msg.what());
        if (SDL_GetError() != NULL)
        {
            printf("%s", SDL_GetError());
        }
        else if (TTF_GetError() != NULL)
        {
            printf("%s", TTF_GetError());
        }
        else
        {
            printf("%s", "NULL");
        }
        Quit(Global);
        return EXIT_FAILURE;
    }
    Quit(Global);
    return EXIT_SUCCESS;
}


问:
Building your own Interpreter that can function as a compiler
It is possible  for me to build my own Interpreter that could then be transformed into a compiler? If yes, how do I go about building it?</p>

答:
Apart from Futaruma projections, another approach is meta-tracing jit. Meta-tracing jit doesn't directly trace or jit your programs, but indirectly, through the interpreter.
RPython is a cool meta-tracing framework. You write an interpreter in a restricted version of python, and RPython turns it into a jit compiler in C.</p>