问:
Extra bytes at the end of a DOS .COM file, compiled with GCC
I have the following C source file, with some asm blocks that implement a print and exit routine by calling DOS system calls.

```<code>__asm__(
    ".code16gcc;"
    "call dosmain;"
    "mov $0x4C, %AH;"
    "int $0x21;"
);

void print(char *str)
{
    __asm__(
        "mov $0x09, %%ah;"
        "int $0x21;"
        : // no output
        : "d"(str)
        : "ah"
    );
}

void dosmain()
{
    // DOS system call expects strings to be terminated by $.
    print("Hello world$");
}

</code>```

The linker script file and the build script file are as such,

```<code>OUTPUT_FORMAT(binary)
SECTIONS
{
    . = 0x0100;
    .text :
    {
        *(.text);
    }
    .data :
    {
        *(.data);
        *(.bss);
        *(.rodata);
    }
    _heap = ALIGN(4);
}
</code>```

```<code>gcc -fno-pie -Os -nostdlib -ffreestanding -m16 -march=i386 \
-Wl,--nmagic,--script=simple_dos.ld simple_dos.c -o simple_dos.com
</code>```

I am used to building .COM files in assembly, and I am aware of the structure of a dos file. However in case of the .COM file generated using GCC, I am getting some extra bytes at the end and I cannot figure out why. (The bytes that are inside the shaded area and the box below is what is expected everything else is unaccounted).

[]

My hunch is that these are some static storage used by GCC. I thought this could be due to the string in the program. I have thus commented the line print("Hello world$"); but the extra bytes still reside. It will be of great help if someone knows what is going on and tell how to prevent GCC inserting these bytes in the output.

Source code is available here: Github

PS: Object file also contains these extra bytes.

答:
Since you are using a native compiler and not an i686(or i386) cross compiler you can get a fair amount of extra information. It is rather dependent on the compiler configurations. I would recommend doing the following to remove unwanted code generation and sections:

Use GCC option -fno-asynchronous-unwind-tables to eliminate any .eh_frame sections. This is the cause of the unwanted data appended at the end of your DOS COM program in this case.

Use GCC option -static to build without relocations to avoid any form of dynamic linking.

Have GCC pass the --build-id=none option to the linker with -Wl to avoid unnecessarily generating any .note.gnu.build-id sections.

Modify the linker script to DISCARD any .comment sections.

Your build command could look like:

```<code>gcc -fno-pie -static -Os -nostdlib -fno-asynchronous-unwind-tables -ffreestanding \
-m16 -march=i386 -Wl,--build-id=none,--nmagic,--script=simple_dos.ld simple_dos.c \
-o simple_dos.com
</code>```

I would modify your linker script to look like:

```<code>OUTPUT_FORMAT(binary)
SECTIONS
{
    . = 0x0100;
    .text :
    {
        *(.text*);
    }
    .data :
    {
        *(.data);
        *(.rodata*);
        *(.bss);
        *(COMMON)
    }
    _heap = ALIGN(4);

    /DISCARD/ : { *(.comment); }
}
</code>```

Besides adding a /DISCARD/ directive to eliminate any .comment sections I also add *(COMMON) along side .bss. Both are BSS sections. I have also moved them after the data sections as they won't take up space in the .COM file if they appear after the other sections. I also changed *(.rodata); to *(.rodata*); and *(.text); to *(.text*); because GCC can generate section names that begin with .rodata and .text but have different suffixes on them.

Inline Assembly

Not related to the problem you asked about, but is important. In this inline assembly:

```<code>__asm__(
    "mov $0x09, %%ah;"
    "int $0x21;"
    : // no output
    : "d"(str)
    : "ah"
);
</code>```

Int 21h/AH=9h also clobbers AL. You should use ax as the clobber.

Since you are passing the address of an array through a register you will also want to add a memory clobber so that the compiler realizes the entire array into memory before your inline assembly is emitted. The constraint "d"(str) only tells the compiler that you will be using the pointer as input, not what the pointer points at.

Likely if you compiled with optimisations at -O3 you'd probably discover the following version of the program doesn't even have your string "Hello world$" in it because of this bug:

```<code>__asm__(
        ".code16gcc;"
        "call dosmain;"
        "mov $0x4C, %AH;"
        "int $0x21;"
);

void print(char *str)
{
        __asm__(
                "mov $0x09, %%ah;"
                "int $0x21;"
                : // no output
                : "d"(str)
                : "ax");
}

void dosmain()
{
        char hello[] = "Hello world$";
        print(hello);
}
</code>```

The generated code for dosmain allocated space on the stack for the string but never put the string on the stack before printing the string:

```<code>00000100 <print-0xc>:
 100:   66 e8 12 00 00 00       calll  118 <dosmain>
 106:   b4 4c                   mov    $0x4c,%ah
 108:   cd 21                   int    $0x21
 10a:   66 90                   xchg   %eax,%eax

0000010c <print>:
 10c:   67 66 8b 54 24 04       mov    0x4(%esp),%edx
 112:   b4 09                   mov    $0x9,%ah
 114:   cd 21                   int    $0x21
 116:   66 c3                   retl

00000118 <dosmain>:
 118:   66 83 ec 10             sub    $0x10,%esp
 11c:   67 66 8d 54 24 03       lea    0x3(%esp),%edx
 122:   b4 09                   mov    $0x9,%ah
 124:   cd 21                   int    $0x21
 126:   66 83 c4 10             add    $0x10,%esp
 12a:   66 c3                   retl
</code>```

If you change the inline assembly to include a "memory" clobber like this:

```<code>void print(char *str)
{
        __asm__(
                "mov $0x09, %%ah;"
                "int $0x21;"
                : // no output
                : "d"(str)
                : "ax", "memory");
}
</code>```

The generated code may look similar to this:

```<code>00000100 <print-0xc>:
 100:   66 e8 12 00 00 00       calll  118 <dosmain>
 106:   b4 4c                   mov    $0x4c,%ah
 108:   cd 21                   int    $0x21
 10a:   66 90                   xchg   %eax,%eax

0000010c <print>:
 10c:   67 66 8b 54 24 04       mov    0x4(%esp),%edx
 112:   b4 09                   mov    $0x9,%ah
 114:   cd 21                   int    $0x21
 116:   66 c3                   retl

00000118 <dosmain>:
 118:   66 57                   push   %edi
 11a:   66 56                   push   %esi
 11c:   66 83 ec 10             sub    $0x10,%esp
 120:   67 66 8d 7c 24 03       lea    0x3(%esp),%edi
 126:   66 be 48 01 00 00       mov    $0x148,%esi
 12c:   66 b9 0d 00 00 00       mov    $0xd,%ecx
 132:   f3 a4                   rep movsb %ds:(%si),%es:(%di)
 134:   67 66 8d 54 24 03       lea    0x3(%esp),%edx
 13a:   b4 09                   mov    $0x9,%ah
 13c:   cd 21                   int    $0x21
 13e:   66 83 c4 10             add    $0x10,%esp
 142:   66 5e                   pop    %esi
 144:   66 5f                   pop    %edi
 146:   66 c3                   retl

Disassembly of section .rodata.str1.1:

00000148 <_heap-0x10>:
 148:   48                      dec    %ax
 149:   65 6c                   gs insb (%dx),%es:(%di)
 14b:   6c                      insb   (%dx),%es:(%di)
 14c:   6f                      outsw  %ds:(%si),(%dx)
 14d:   20 77 6f                and    %dh,0x6f(%bx)
 150:   72 6c                   jb     1be <_heap+0x66>
 152:   64 24 00                fs and $0x0,%al
</code>```

An alternate version of the inline assembly that passes the sub function 9 via an a constraint using a variable and marks it as an input/output with + (since the return value of AX gets clobbered) could be done this way:

```<code>void print(char *str)
{
    unsigned short int write_fun = (0x09<<8) | 0x00;
    __asm__ __volatile__ (
        "int $0x21;"
        : "+a"(write_fun)
        : "d"(str)
        : "memory"
    );
}
</code>```

Recommendation: Don't use GCC for 16-bit code generation. The inline assembly is difficult to get right and you will probably be using a fair amount of it for low level routines. You could look at Smaller C, Bruce's C compiler, or Openwatcom C as alternatives. All of them can generate DOS COM programs.

Body:
I have the following C source file, with some asm blocks that implement a print and exit routine by calling DOS system calls.

__asm__(
    ".code16gcc;"
    "call dosmain;"
    "mov $0x4C, %AH;"
    "int $0x21;"
);

void print(char *str)
{
    __asm__(
        "mov $0x09, %%ah;"
        "int $0x21;"
        : // no output
        : "d"(str)
        : "ah"
    );
}

void dosmain()
{
    // DOS system call expects strings to be terminated by $.
    print("Hello world$");
}

The linker script file and the build script file are as such,

OUTPUT_FORMAT(binary)
SECTIONS
{
    . = 0x0100;
    .text :
    {
        *(.text);
    }
    .data :
    {
        *(.data);
        *(.bss);
        *(.rodata);
    }
    _heap = ALIGN(4);
}

gcc -fno-pie -Os -nostdlib -ffreestanding -m16 -march=i386 \
-Wl,--nmagic,--script=simple_dos.ld simple_dos.c -o simple_dos.com

I am used to building .COM files in assembly, and I am aware of the structure of a dos file. However in case of the .COM file generated using GCC, I am getting some extra bytes at the end and I cannot figure out why. (The bytes that are inside the shaded area and the box below is what is expected everything else is unaccounted).

[]

My hunch is that these are some static storage used by GCC. I thought this could be due to the string in the program. I have thus commented the line print("Hello world$"); but the extra bytes still reside. It will be of great help if someone knows what is going on and tell how to prevent GCC inserting these bytes in the output.

Source code is available here: Github

PS: Object file also contains these extra bytes.

Body:
Since you are using a native compiler and not an i686(or i386) cross compiler you can get a fair amount of extra information. It is rather dependent on the compiler configurations. I would recommend doing the following to remove unwanted code generation and sections:

Use GCC option -fno-asynchronous-unwind-tables to eliminate any .eh_frame sections. This is the cause of the unwanted data appended at the end of your DOS COM program in this case.

Use GCC option -static to build without relocations to avoid any form of dynamic linking.

Have GCC pass the --build-id=none option to the linker with -Wl to avoid unnecessarily generating any .note.gnu.build-id sections.

Modify the linker script to DISCARD any .comment sections.

Your build command could look like:

gcc -fno-pie -static -Os -nostdlib -fno-asynchronous-unwind-tables -ffreestanding \
-m16 -march=i386 -Wl,--build-id=none,--nmagic,--script=simple_dos.ld simple_dos.c \
-o simple_dos.com

I would modify your linker script to look like:

OUTPUT_FORMAT(binary)
SECTIONS
{
    . = 0x0100;
    .text :
    {
        *(.text*);
    }
    .data :
    {
        *(.data);
        *(.rodata*);
        *(.bss);
        *(COMMON)
    }
    _heap = ALIGN(4);

    /DISCARD/ : { *(.comment); }
}

Besides adding a /DISCARD/ directive to eliminate any .comment sections I also add *(COMMON) along side .bss. Both are BSS sections. I have also moved them after the data sections as they won't take up space in the .COM file if they appear after the other sections. I also changed *(.rodata); to *(.rodata*); and *(.text); to *(.text*); because GCC can generate section names that begin with .rodata and .text but have different suffixes on them.

Inline Assembly

Not related to the problem you asked about, but is important. In this inline assembly:

__asm__(
    "mov $0x09, %%ah;"
    "int $0x21;"
    : // no output
    : "d"(str)
    : "ah"
);

Int 21h/AH=9h also clobbers AL. You should use ax as the clobber.

Since you are passing the address of an array through a register you will also want to add a memory clobber so that the compiler realizes the entire array into memory before your inline assembly is emitted. The constraint "d"(str) only tells the compiler that you will be using the pointer as input, not what the pointer points at.

Likely if you compiled with optimisations at -O3 you'd probably discover the following version of the program doesn't even have your string "Hello world$" in it because of this bug:

__asm__(
        ".code16gcc;"
        "call dosmain;"
        "mov $0x4C, %AH;"
        "int $0x21;"
);

void print(char *str)
{
        __asm__(
                "mov $0x09, %%ah;"
                "int $0x21;"
                : // no output
                : "d"(str)
                : "ax");
}

void dosmain()
{
        char hello[] = "Hello world$";
        print(hello);
}

The generated code for dosmain allocated space on the stack for the string but never put the string on the stack before printing the string:

00000100 <print-0xc>:
 100:   66 e8 12 00 00 00       calll  118 <dosmain>
 106:   b4 4c                   mov    $0x4c,%ah
 108:   cd 21                   int    $0x21
 10a:   66 90                   xchg   %eax,%eax

0000010c <print>:
 10c:   67 66 8b 54 24 04       mov    0x4(%esp),%edx
 112:   b4 09                   mov    $0x9,%ah
 114:   cd 21                   int    $0x21
 116:   66 c3                   retl

00000118 <dosmain>:
 118:   66 83 ec 10             sub    $0x10,%esp
 11c:   67 66 8d 54 24 03       lea    0x3(%esp),%edx
 122:   b4 09                   mov    $0x9,%ah
 124:   cd 21                   int    $0x21
 126:   66 83 c4 10             add    $0x10,%esp
 12a:   66 c3                   retl

If you change the inline assembly to include a "memory" clobber like this:

void print(char *str)
{
        __asm__(
                "mov $0x09, %%ah;"
                "int $0x21;"
                : // no output
                : "d"(str)
                : "ax", "memory");
}

The generated code may look similar to this:

00000100 <print-0xc>:
 100:   66 e8 12 00 00 00       calll  118 <dosmain>
 106:   b4 4c                   mov    $0x4c,%ah
 108:   cd 21                   int    $0x21
 10a:   66 90                   xchg   %eax,%eax

0000010c <print>:
 10c:   67 66 8b 54 24 04       mov    0x4(%esp),%edx
 112:   b4 09                   mov    $0x9,%ah
 114:   cd 21                   int    $0x21
 116:   66 c3                   retl

00000118 <dosmain>:
 118:   66 57                   push   %edi
 11a:   66 56                   push   %esi
 11c:   66 83 ec 10             sub    $0x10,%esp
 120:   67 66 8d 7c 24 03       lea    0x3(%esp),%edi
 126:   66 be 48 01 00 00       mov    $0x148,%esi
 12c:   66 b9 0d 00 00 00       mov    $0xd,%ecx
 132:   f3 a4                   rep movsb %ds:(%si),%es:(%di)
 134:   67 66 8d 54 24 03       lea    0x3(%esp),%edx
 13a:   b4 09                   mov    $0x9,%ah
 13c:   cd 21                   int    $0x21
 13e:   66 83 c4 10             add    $0x10,%esp
 142:   66 5e                   pop    %esi
 144:   66 5f                   pop    %edi
 146:   66 c3                   retl

Disassembly of section .rodata.str1.1:

00000148 <_heap-0x10>:
 148:   48                      dec    %ax
 149:   65 6c                   gs insb (%dx),%es:(%di)
 14b:   6c                      insb   (%dx),%es:(%di)
 14c:   6f                      outsw  %ds:(%si),(%dx)
 14d:   20 77 6f                and    %dh,0x6f(%bx)
 150:   72 6c                   jb     1be <_heap+0x66>
 152:   64 24 00                fs and $0x0,%al

An alternate version of the inline assembly that passes the sub function 9 via an a constraint using a variable and marks it as an input/output with + (since the return value of AX gets clobbered) could be done this way:

void print(char *str)
{
    unsigned short int write_fun = (0x09<<8) | 0x00;
    __asm__ __volatile__ (
        "int $0x21;"
        : "+a"(write_fun)
        : "d"(str)
        : "memory"
    );
}

Recommendation: Don't use GCC for 16-bit code generation. The inline assembly is difficult to get right and you will probably be using a fair amount of it for low level routines. You could look at Smaller C, Bruce's C compiler, or Openwatcom C as alternatives. All of them can generate DOS COM programs.


来源: stackexchange

问:
Dart How to get the name of an enum as a String
Before enums were available in Dart I wrote some cumbersome and hard to maintain code to simulate enums and now want to simplify it.  I need to get the name of the enum as a string such as can be done with Java but cannot.

For instance little test code snippet returns 'day.MONDAY' in each case when what I want is 'MONDAY"

```<code>enum day {MONDAY, TUESDAY}
print( 'Today is $day.MONDAY');
print( 'Today is $day.MONDAY.toString()');
</code>```

Am I correct that to get just 'MONDAY' I will need to parse the string?

答:
I got so over this I made a package:

https://pub.dev/packages/enum_to_string

Also has a handy function that takes enum.ValueOne and parses it to "Value one"

Its a simple little library but its unit tested and I welcome any additions for edge cases.

ContentLicense: CC BY-SA 4.0

Body:
Before enums were available in Dart I wrote some cumbersome and hard to maintain code to simulate enums and now want to simplify it.  I need to get the name of the enum as a string such as can be done with Java but cannot.

For instance little test code snippet returns 'day.MONDAY' in each case when what I want is 'MONDAY"

enum day {MONDAY, TUESDAY}
print( 'Today is $day.MONDAY');
print( 'Today is $day.MONDAY.toString()');

Am I correct that to get just 'MONDAY' I will need to parse the string?


问:
How do I deal with fullscreen in a 2d game?
I'm making a game using Go with the rendering library "pixel".

I am trying to get fullscreen/resizing working, but I have an issue, and that's how to deal with stretching of images

I've seen and have used the solution of a "letterbox" effect for the game.

That is, drawing the game in the same aspect ratio, so stretching wouldn't be an issue, leaving the extra space as black bars.

My issue is, when trying to do this in this rendering library, I can only scale the matrix of the "Canvas" I'm drawing on.

I'm used to SFML with C++ where I can just define a fixed size for the "View" [what's being drawn on], not scaling it.

This is how I'm getting the current scaling for the matrix, it's incorrect, but it's what I have.

camZoom is 2.0, it's in there so the screen is bigger. If the camZoom is 1.0 [normal], the images are too small.

```<code>func letterBox(win *pixelgl.Window) {
windowRatio := winWidth / winHeight
viewRatio := win.Bounds().W() / win.Bounds().H()
sizeX := 1.
sizeY := 1.

horizontalSpacing := true
if windowRatio < viewRatio {
    horizontalSpacing = false
}

if horizontalSpacing {
    sizeX = viewRatio / windowRatio
} else {
    sizeY = windowRatio / viewRatio
}

viewMatrix = pixel.IM.
    Moved(pixel.V(win.Bounds().Center().X/camZoom, win.Bounds().Center().Y/camZoom)).
    ScaledXY(pixel.V(win.Bounds().Center().X/camZoom, win.Bounds().Center().Y/camZoom), pixel.V(sizeY, sizeX))
</code>```

}

Here's what it currently looks like:

Normal [no resizing done, 1024x768]:

Width of window increased [shrinks]
[]2

Height of window increased [stretches on X, hiding most of 'Canvas']
[]3

Fullscreen [just keeps it's original size, but the width of the 'canvas' is slightly shrunken]
[]4

I just can't really figure out the math to it.

If this is not the best way to solve the full-screen issue I have, then let me know and I can make another question, but I was told this is how you should do it.

答:
Ended up being super simple just a math error on my part.

```<code>func letterBox(win *pixelgl.Window) {
sizeX := 1.
sizeY := 1.

if win.Bounds().H()-winHeight > win.Bounds().W()-winWidth {
    sizeX = win.Bounds().W() / winWidth
    sizeY = win.Bounds().W() / winWidth
} else {
    sizeX = win.Bounds().H() / winHeight
    sizeY = win.Bounds().H() / winHeight
}

viewMatrix = pixel.IM.
    Moved(pixel.V(win.Bounds().Center().X/camZoom, win.Bounds().Center().Y/camZoom)).
    ScaledXY(pixel.V(win.Bounds().Center().X/camZoom, win.Bounds().Center().Y/camZoom), pixel.V(sizeX, sizeY))
</code>```

}

Just had to figure out if the width difference of the newly-sized window was greater, or the height, then apply the same ratio [new window width / width of old frame] to scale the matrix properly. Dumb answer to a dumb question.

Body:
I'm making a game using Go with the rendering library "pixel".

I am trying to get fullscreen/resizing working, but I have an issue, and that's how to deal with stretching of images

I've seen and have used the solution of a "letterbox" effect for the game.

That is, drawing the game in the same aspect ratio, so stretching wouldn't be an issue, leaving the extra space as black bars.

My issue is, when trying to do this in this rendering library, I can only scale the matrix of the "Canvas" I'm drawing on.

I'm used to SFML with C++ where I can just define a fixed size for the "View" [what's being drawn on], not scaling it.

This is how I'm getting the current scaling for the matrix, it's incorrect, but it's what I have.

camZoom is 2.0, it's in there so the screen is bigger. If the camZoom is 1.0 [normal], the images are too small.

func letterBox(win *pixelgl.Window) {
windowRatio := winWidth / winHeight
viewRatio := win.Bounds().W() / win.Bounds().H()
sizeX := 1.
sizeY := 1.

horizontalSpacing := true
if windowRatio < viewRatio {
    horizontalSpacing = false
}

if horizontalSpacing {
    sizeX = viewRatio / windowRatio
} else {
    sizeY = windowRatio / viewRatio
}

viewMatrix = pixel.IM.
    Moved(pixel.V(win.Bounds().Center().X/camZoom, win.Bounds().Center().Y/camZoom)).
    ScaledXY(pixel.V(win.Bounds().Center().X/camZoom, win.Bounds().Center().Y/camZoom), pixel.V(sizeY, sizeX))

}

Here's what it currently looks like:

Normal [no resizing done, 1024x768]:

Width of window increased [shrinks]
[]2

Height of window increased [stretches on X, hiding most of 'Canvas']
[]3

Fullscreen [just keeps it's original size, but the width of the 'canvas' is slightly shrunken]
[]4

I just can't really figure out the math to it.

If this is not the best way to solve the full-screen issue I have, then let me know and I can make another question, but I was told this is how you should do it.

Body:
Ended up being super simple just a math error on my part.

func letterBox(win *pixelgl.Window) {
sizeX := 1.
sizeY := 1.

if win.Bounds().H()-winHeight > win.Bounds().W()-winWidth {
    sizeX = win.Bounds().W() / winWidth
    sizeY = win.Bounds().W() / winWidth
} else {
    sizeX = win.Bounds().H() / winHeight
    sizeY = win.Bounds().H() / winHeight
}

viewMatrix = pixel.IM.
    Moved(pixel.V(win.Bounds().Center().X/camZoom, win.Bounds().Center().Y/camZoom)).
    ScaledXY(pixel.V(win.Bounds().Center().X/camZoom, win.Bounds().Center().Y/camZoom), pixel.V(sizeX, sizeY))

}

Just had to figure out if the width difference of the newly-sized window was greater, or the height, then apply the same ratio [new window width / width of old frame] to scale the matrix properly. Dumb answer to a dumb question.


问:
Spatial Indexing not working with ST_DISTANCE queries and '<'
Spatial indexing does not seem to be working on a collection which contains a document with GeoJson coordinates. I've tried using the default indexing policy which inherently provides spatial indexing on all fields.

I've tried creating a new Cosmos Db account, database, and collection from scratch without any success of getting the spatial indexing to work with ST_DISTANCE query.

I've setup a simple collection with the following indexing policy:

```<code>{
    "indexingMode": "consistent",
    "automatic": true,
    "includedPaths": [
        {
            "path": "/\"location\"/?",
            "indexes": [
                {
                    "kind": "Spatial",
                    "dataType": "Point"
                },
                {
                    "kind": "Range",
                    "dataType": "Number",
                    "precision": -1
                },
                {
                    "kind": "Range",
                    "dataType": "String",
                    "precision": -1
                }
            ]
        }
    ],
    "excludedPaths": [
        {
            "path": "/*",
        },
        {
            "path": "/\"_etag\"/?"
        }
    ]
}
</code>```

The document that I've inserted into the collection:

```<code>{
    "id": "document1",
    "type": "Type1",
    "location": {
        "type": "Point",
        "coordinates": [
            -50,
            50
        ]
    },
    "name": "TestObject"
}
</code>```

The query that should return the single document in the collection:

```<code>SELECT * FROM f WHERE f.type = "Type1" and ST_DISTANCE(f.location, {'type': 'Point', 'coordinates':[-50,50]}) < 200000
</code>```

Is not returning any results. If I explicitly query without using the spatial index like so:

```<code>SELECT * FROM f WHERE f.type = "Type1" and ST_DISTANCE({'type': 'Point', 'coordinates':[f.location.coordinates[0],f.location.coordinates[1]]}, {'type': 'Point', 'coordinates':[-50,50]}) < 200000
</code>```

It returns the document as it should, but doesn't take advantage of the indexing which I will need because I will be storing a lot of coordinates.

This seems to be the same issue referenced here. If I add a second document far away and change the '<' to '>' in the first query it works!

I should mention this is only occurring on Azure. When I use the Azure Cosmos Db Emulator it works perfectly! What is going on here?! Any tips or suggestions are much appreciated.

UPDATE: I found out the reason that the query works on the Emulator and not Azure - the database on the emulator doesn't have provisioned (shared) throughput among its collections, while I made the database in Azure with provisioned throughput to keep costs down (i.e. 4 collections sharing 400 RU/s). I created a non provisioned throughput database in Azure and the query works with spatial indexing!! I will log this issue with Microsoft to see if there is a reason why this is the case?

答:
Thanks for following up with additional details with regards to a fixed collection being the solution but, I did want to get some additional information.

The Cosmos DB Emulator now supports containers:

By default, you can create up to 25 fixed size containers (only supported using Azure Cosmos DB SDKs), or 5 unlimited containers using the Azure Cosmos Emulator. By modifying the PartitionCount value, you can create up to 250 fixed size containers or 50 unlimited containers, or any combination of the two that does not exceed 250 fixed size containers (where one unlimited container = 5 fixed size containers). However it's not recommended to set up the emulator to run with more than 200 fixed size containers. Because of the overhead that it adds to the disk IO operations, which result in unpredictable timeouts when using the endpoint APIs.

So, I want to see which version of the Emulator you were using. Current version is azure-cosmosdb-emulator-2.2.2.

Body:
Spatial indexing does not seem to be working on a collection which contains a document with GeoJson coordinates. I've tried using the default indexing policy which inherently provides spatial indexing on all fields.

I've tried creating a new Cosmos Db account, database, and collection from scratch without any success of getting the spatial indexing to work with ST_DISTANCE query.

I've setup a simple collection with the following indexing policy:

{
    "indexingMode": "consistent",
    "automatic": true,
    "includedPaths": [
        {
            "path": "/\"location\"/?",
            "indexes": [
                {
                    "kind": "Spatial",
                    "dataType": "Point"
                },
                {
                    "kind": "Range",
                    "dataType": "Number",
                    "precision": -1
                },
                {
                    "kind": "Range",
                    "dataType": "String",
                    "precision": -1
                }
            ]
        }
    ],
    "excludedPaths": [
        {
            "path": "/*",
        },
        {
            "path": "/\"_etag\"/?"
        }
    ]
}

The document that I've inserted into the collection:

{
    "id": "document1",
    "type": "Type1",
    "location": {
        "type": "Point",
        "coordinates": [
            -50,
            50
        ]
    },
    "name": "TestObject"
}

The query that should return the single document in the collection:

SELECT * FROM f WHERE f.type = "Type1" and ST_DISTANCE(f.location, {'type': 'Point', 'coordinates':[-50,50]}) < 200000

Is not returning any results. If I explicitly query without using the spatial index like so:

SELECT * FROM f WHERE f.type = "Type1" and ST_DISTANCE({'type': 'Point', 'coordinates':[f.location.coordinates[0],f.location.coordinates[1]]}, {'type': 'Point', 'coordinates':[-50,50]}) < 200000

It returns the document as it should, but doesn't take advantage of the indexing which I will need because I will be storing a lot of coordinates.

This seems to be the same issue referenced here. If I add a second document far away and change the '<' to '>' in the first query it works!

I should mention this is only occurring on Azure. When I use the Azure Cosmos Db Emulator it works perfectly! What is going on here?! Any tips or suggestions are much appreciated.

UPDATE: I found out the reason that the query works on the Emulator and not Azure - the database on the emulator doesn't have provisioned (shared) throughput among its collections, while I made the database in Azure with provisioned throughput to keep costs down (i.e. 4 collections sharing 400 RU/s). I created a non provisioned throughput database in Azure and the query works with spatial indexing!! I will log this issue with Microsoft to see if there is a reason why this is the case?


问:
How to use APEX$ROW_SELECTOR with Dynamic Actions within an Interactive Grid
Environment: Oracle APEX 5.1.2 / Oracle 12c

I'm currently using an Interactive Grid (IG) with the APEX$ROW_SELECTOR set to single record selection (i.e. radio group). What I am attempting to do, is use a Dynamic Action "Click" event off this APEX$ROW_SELECTOR, but unfortunately it's not firing when I click on the radio group selector.

I have the following questions based on the above:

How to add a Dynamic Action on row selection (APEX$ROW_SELECTOR) to fire when clicked?

When clicked, how to set a column value in session state to be used within a classic report?

Assuming the above is NOT possible with a Dynamic Action as part of an IG, how else can I perform something similar when a user selects a row with my IG?

答:
You can search the class in the dom

.u-selector

Create a dynamic action using this class

And the result is


问:
Cannot upload image with size more than 2mb+
I want to show a large image in my Crud Layout. I success upload image with size 1mb+ but can't upload image more than 2mb.
any solution? maybe reduce an Image file size before uploading to SQLite server?
here's my code

I will really appreciate if you help me

CRUDActivity

```<code>package foodsqlitedemo.quocnguyen.com.foodsqlitedemo;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;

import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;

public class CrudActivity extends AppCompatActivity {

    EditText edtName, edtPrice;
    Button btnChoose, btnAdd, btnList;
    ImageView imageView;

    final int REQUEST_CODE_GALLERY = 999;

    public static SQLiteHelper sqLiteHelper;

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

        init();

        sqLiteHelper = new SQLiteHelper(this, "FoodDB.sqlite", null, 1);

        sqLiteHelper.queryData("CREATE TABLE IF NOT EXISTS FOOD(Id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR, price VARCHAR, image BLOB)");

        btnChoose.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ActivityCompat.requestPermissions(
                        CrudActivity.this,
                        new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                        REQUEST_CODE_GALLERY
                );
            }
        });

        btnAdd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try{
                    sqLiteHelper.insertData(
                            edtName.getText().toString().trim(),
                            edtPrice.getText().toString().trim(),
                            imageViewToByte(imageView)
                    );
                    Toast.makeText(getApplicationContext(), "Added successfully!", Toast.LENGTH_SHORT).show();
                    edtName.setText("");
                    edtPrice.setText("");
                    imageView.setImageResource(R.mipmap.ic_launcher);
                }
                catch (Exception e){
                    e.printStackTrace();
                }
            }
        });

        btnList.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(CrudActivity.this, GudangList.class);
                startActivity(intent);
            }
        });
    }

    public static byte[] imageViewToByte(ImageView image) {
        Bitmap bitmap = ((BitmapDrawable)image.getDrawable()).getBitmap();
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
        byte[] byteArray = stream.toByteArray();
        return byteArray;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

        if(requestCode == REQUEST_CODE_GALLERY){
            if(grantResults.length >0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
              Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
                intent.setType("image/*");
                startActivityForResult(intent, REQUEST_CODE_GALLERY);
            }
            else {
                Toast.makeText(getApplicationContext(), "You don't have permission to access file location!", Toast.LENGTH_SHORT).show();
            }
            return;
        }

        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        if(requestCode == REQUEST_CODE_GALLERY && resultCode == RESULT_OK && data != null){
            Uri uri = data.getData();

            try {
                InputStream inputStream = getContentResolver().openInputStream(uri);

                Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                imageView.setImageBitmap(bitmap);

            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }

        super.onActivityResult(requestCode, resultCode, data);
    }

    private void init(){
        edtName = (EditText) findViewById(R.id.edtName);
        edtPrice = (EditText) findViewById(R.id.edtPrice);
        btnChoose = (Button) findViewById(R.id.btnChoose);
        btnAdd = (Button) findViewById(R.id.btnAdd);
        btnList = (Button) findViewById(R.id.btnList);
        imageView = (ImageView) findViewById(R.id.imageView);
    }

}
</code>```

Gudang.java

```<code>package foodsqlitedemo.quocnguyen.com.foodsqlitedemo;

/**
 * Created by Quoc Nguyen on 13-Dec-16.
 */

public class Gudang {
    private int id;
    private String name;
    private String price;
    private byte[] image;

    public Gudang(String name, String price, byte[] image, int id) {
        this.name = name;
        this.price = price;
        this.image = image;
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPrice() {
        return price;
    }

    public void setPrice(String price) {
        this.price = price;
    }

    public byte[] getImage() {
        return image;
    }

    public void setImage(byte[] image) {
        this.image = image;
    }
}
</code>```

GudangList.java

```<code>package foodsqlitedemo.quocnguyen.com.foodsqlitedemo;

import android.Manifest;
import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.Toast;

import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;

/**
 * Created by Quoc Nguyen on 13-Dec-16.
 */

public class GudangList extends AppCompatActivity {

    GridView gridView;
    ArrayList<Gudang> list;
    GudangListAdapter adapter = null;

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

        gridView = (GridView) findViewById(R.id.gridView);
        list = new ArrayList<>();
        adapter = new GudangListAdapter(this, R.layout.gudang_items, list);
        gridView.setAdapter(adapter);

        // get all data from sqlite
        Cursor cursor = CrudActivity.sqLiteHelper.getData("SELECT * FROM FOOD");
        list.clear();
        while (cursor.moveToNext()) {
            int id = cursor.getInt(0);
            String name = cursor.getString(1);
            String price = cursor.getString(2);
            byte[] image = cursor.getBlob(3);

            list.add(new Gudang(name, price, image, id));
        }
        adapter.notifyDataSetChanged();

        gridView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, final int position, long id) {

                CharSequence[] items = {"Update", "Delete"};
                AlertDialog.Builder dialog = new AlertDialog.Builder(GudangList.this);

                dialog.setTitle("Choose an action");
                dialog.setItems(items, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int item) {
                        if (item == 0) {
                            // update
                            Cursor c = CrudActivity.sqLiteHelper.getData("SELECT id FROM FOOD");
                            ArrayList<Integer> arrID = new ArrayList<Integer>();
                            while (c.moveToNext()){
                                arrID.add(c.getInt(0));
                            }
                            // show dialog update at here
                            showDialogUpdate(GudangList.this, arrID.get(position));

                        } else {
                            // delete
                            Cursor c = CrudActivity.sqLiteHelper.getData("SELECT id FROM FOOD");
                            ArrayList<Integer> arrID = new ArrayList<Integer>();
                            while (c.moveToNext()){
                                arrID.add(c.getInt(0));
                            }
                            showDialogDelete(arrID.get(position));
                        }
                    }
                });
                dialog.show();
                return true;
            }
        });
    }

    ImageView imageViewFood;
    private void showDialogUpdate(Activity activity, final int position){

        final Dialog dialog = new Dialog(activity);
        dialog.setContentView(R.layout.update_gudang_activity);
        dialog.setTitle("Update");

        imageViewFood = (ImageView) dialog.findViewById(R.id.imageViewFood);
        final EditText edtName = (EditText) dialog.findViewById(R.id.edtName);
        final EditText edtPrice = (EditText) dialog.findViewById(R.id.edtPrice);
        Button btnUpdate = (Button) dialog.findViewById(R.id.btnUpdate);

        // set width for dialog
        int width = (int) (activity.getResources().getDisplayMetrics().widthPixels * 0.95);
        // set height for dialog
        int height = (int) (activity.getResources().getDisplayMetrics().heightPixels * 0.7);
        dialog.getWindow().setLayout(width, height);
        dialog.show();

        imageViewFood.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // request photo library
                ActivityCompat.requestPermissions(
                        GudangList.this,
                        new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                        888
                );
            }
        });

        btnUpdate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    CrudActivity.sqLiteHelper.updateData(
                            edtName.getText().toString().trim(),
                            edtPrice.getText().toString().trim(),
                            CrudActivity.imageViewToByte(imageViewFood),
                            position
                    );
                    dialog.dismiss();
                    Toast.makeText(getApplicationContext(), "Update successfully!!!",Toast.LENGTH_SHORT).show();
                }
                catch (Exception error) {
                    Log.e("Update error", error.getMessage());
                }
                updateFoodList();
            }
        });
    }

    private void showDialogDelete(final int idFood){
        final AlertDialog.Builder dialogDelete = new AlertDialog.Builder(GudangList.this);

        dialogDelete.setTitle("Warning!!");
        dialogDelete.setMessage("Are you sure you want to this delete?");
        dialogDelete.setPositiveButton("OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                try {
                    CrudActivity.sqLiteHelper.deleteData(idFood);
                    Toast.makeText(getApplicationContext(), "Delete successfully!!!",Toast.LENGTH_SHORT).show();
                } catch (Exception e){
                    Log.e("error", e.getMessage());
                }
                updateFoodList();
            }
        });

        dialogDelete.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });
        dialogDelete.show();
    }

    private void updateFoodList(){
        // get all data from sqlite
        Cursor cursor = CrudActivity.sqLiteHelper.getData("SELECT * FROM FOOD");
        list.clear();
        while (cursor.moveToNext()) {
            int id = cursor.getInt(0);
            String name = cursor.getString(1);
            String price = cursor.getString(2);
            byte[] image = cursor.getBlob(3);

            list.add(new Gudang(name, price, image, id));
        }
        adapter.notifyDataSetChanged();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

        if(requestCode == 888){
            if(grantResults.length >0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
                 Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
                intent.setType("image/*");
                startActivityForResult(intent, 888);
            }
            else {
                Toast.makeText(getApplicationContext(), "You don't have permission to access file location!", Toast.LENGTH_SHORT).show();
            }
            return;
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        if(requestCode == 888 && resultCode == RESULT_OK && data != null){
            Uri uri = data.getData();
            try {
                InputStream inputStream = getContentResolver().openInputStream(uri);
                Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                imageViewFood.setImageBitmap(bitmap);

            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }

        super.onActivityResult(requestCode, resultCode, data);
    }
}
</code>```

GudangListAdapter.java

```<code>package foodsqlitedemo.quocnguyen.com.foodsqlitedemo;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;

/**
 * Created by Quoc Nguyen on 13-Dec-16.
 */

public class GudangListAdapter extends BaseAdapter {

    private Context context;
    private  int layout;
    private ArrayList<Gudang> foodsList;

    public GudangListAdapter(Context context, int layout, ArrayList<Gudang> foodsList) {
        this.context = context;
        this.layout = layout;
        this.foodsList = foodsList;
    }

    @Override
    public int getCount() {
        return foodsList.size();
    }

    @Override
    public Object getItem(int position) {
        return foodsList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    private class ViewHolder{
        ImageView imageView;
        TextView txtName, txtPrice;
    }

    @Override
    public View getView(int position, View view, ViewGroup viewGroup) {

        View row = view;
        ViewHolder holder = new ViewHolder();

        if(row == null){
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row = inflater.inflate(layout, null);

            holder.txtName = (TextView) row.findViewById(R.id.txtName);
            holder.txtPrice = (TextView) row.findViewById(R.id.txtPrice);
            holder.imageView = (ImageView) row.findViewById(R.id.imgFood);
            row.setTag(holder);
        }
        else {
            holder = (ViewHolder) row.getTag();
        }

        Gudang gudang = foodsList.get(position);

        holder.txtName.setText(gudang.getName());
        holder.txtPrice.setText(gudang.getPrice());

        byte[] foodImage = gudang.getImage();
        Bitmap bitmap = BitmapFactory.decodeByteArray(foodImage, 0, foodImage.length);
        holder.imageView.setImageBitmap(bitmap);

        return row;
    }
}
</code>```

SQLiteHelper

```<code>package foodsqlitedemo.quocnguyen.com.foodsqlitedemo;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteStatement;

/**
 * Created by Quoc Nguyen on 13-Dec-16.
 */

public class SQLiteHelper extends SQLiteOpenHelper {

    public SQLiteHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    public void queryData(String sql){
        SQLiteDatabase database = getWritableDatabase();
        database.execSQL(sql);
    }

    public void insertData(String name, String price, byte[] image){
        SQLiteDatabase database = getWritableDatabase();
        String sql = "INSERT INTO FOOD VALUES (NULL, ?, ?, ?)";

        SQLiteStatement statement = database.compileStatement(sql);
        statement.clearBindings();

        statement.bindString(1, name);
        statement.bindString(2, price);
        statement.bindBlob(3, image);

        statement.executeInsert();
    }

    public void updateData(String name, String price, byte[] image, int id) {
        SQLiteDatabase database = getWritableDatabase();

        String sql = "UPDATE FOOD SET name = ?, price = ?, image = ? WHERE id = ?";
        SQLiteStatement statement = database.compileStatement(sql);

        statement.bindString(1, name);
        statement.bindString(2, price);
        statement.bindBlob(3, image);
        statement.bindDouble(4, (double)id);

        statement.execute();
        database.close();
    }

    public  void deleteData(int id) {
        SQLiteDatabase database = getWritableDatabase();

        String sql = "DELETE FROM FOOD WHERE id = ?";
        SQLiteStatement statement = database.compileStatement(sql);
        statement.clearBindings();
        statement.bindDouble(1, (double)id);

        statement.execute();
        database.close();
    }

    public Cursor getData(String sql){
        SQLiteDatabase database = getReadableDatabase();
        return database.rawQuery(sql, null);
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {

    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

    }
}
enter code here
</code>```

答:
It is not advisable to store large BLOBS or similar data in the SQLite database. You should use the file system and only store a reference to the data in you database

Generally you should avoid blobs in SQLite as they perform poorly; instead save the blob data as a file and store the location of the file in your DB.

There's a limit of 1MB on internal assets due to dynamic decompression; the 1MB limit also seems to apply to Cursor blobs but this doesn't seem to be documented anywhere.

so you store your image in internal directory and its path is insert in SQLite DB so its easy for you

Body:
I want to show a large image in my Crud Layout. I success upload image with size 1mb+ but can't upload image more than 2mb.
any solution? maybe reduce an Image file size before uploading to SQLite server?
here's my code

I will really appreciate if you help me

CRUDActivity

package foodsqlitedemo.quocnguyen.com.foodsqlitedemo;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;

import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;

public class CrudActivity extends AppCompatActivity {

    EditText edtName, edtPrice;
    Button btnChoose, btnAdd, btnList;
    ImageView imageView;

    final int REQUEST_CODE_GALLERY = 999;

    public static SQLiteHelper sqLiteHelper;

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

        init();

        sqLiteHelper = new SQLiteHelper(this, "FoodDB.sqlite", null, 1);

        sqLiteHelper.queryData("CREATE TABLE IF NOT EXISTS FOOD(Id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR, price VARCHAR, image BLOB)");

        btnChoose.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ActivityCompat.requestPermissions(
                        CrudActivity.this,
                        new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                        REQUEST_CODE_GALLERY
                );
            }
        });

        btnAdd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try{
                    sqLiteHelper.insertData(
                            edtName.getText().toString().trim(),
                            edtPrice.getText().toString().trim(),
                            imageViewToByte(imageView)
                    );
                    Toast.makeText(getApplicationContext(), "Added successfully!", Toast.LENGTH_SHORT).show();
                    edtName.setText("");
                    edtPrice.setText("");
                    imageView.setImageResource(R.mipmap.ic_launcher);
                }
                catch (Exception e){
                    e.printStackTrace();
                }
            }
        });

        btnList.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(CrudActivity.this, GudangList.class);
                startActivity(intent);
            }
        });
    }

    public static byte[] imageViewToByte(ImageView image) {
        Bitmap bitmap = ((BitmapDrawable)image.getDrawable()).getBitmap();
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
        byte[] byteArray = stream.toByteArray();
        return byteArray;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

        if(requestCode == REQUEST_CODE_GALLERY){
            if(grantResults.length >0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
              Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
                intent.setType("image/*");
                startActivityForResult(intent, REQUEST_CODE_GALLERY);
            }
            else {
                Toast.makeText(getApplicationContext(), "You don't have permission to access file location!", Toast.LENGTH_SHORT).show();
            }
            return;
        }

        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        if(requestCode == REQUEST_CODE_GALLERY && resultCode == RESULT_OK && data != null){
            Uri uri = data.getData();

            try {
                InputStream inputStream = getContentResolver().openInputStream(uri);

                Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                imageView.setImageBitmap(bitmap);

            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }

        super.onActivityResult(requestCode, resultCode, data);
    }

    private void init(){
        edtName = (EditText) findViewById(R.id.edtName);
        edtPrice = (EditText) findViewById(R.id.edtPrice);
        btnChoose = (Button) findViewById(R.id.btnChoose);
        btnAdd = (Button) findViewById(R.id.btnAdd);
        btnList = (Button) findViewById(R.id.btnList);
        imageView = (ImageView) findViewById(R.id.imageView);
    }

}

Gudang.java

package foodsqlitedemo.quocnguyen.com.foodsqlitedemo;

/**
 * Created by Quoc Nguyen on 13-Dec-16.
 */

public class Gudang {
    private int id;
    private String name;
    private String price;
    private byte[] image;

    public Gudang(String name, String price, byte[] image, int id) {
        this.name = name;
        this.price = price;
        this.image = image;
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPrice() {
        return price;
    }

    public void setPrice(String price) {
        this.price = price;
    }

    public byte[] getImage() {
        return image;
    }

    public void setImage(byte[] image) {
        this.image = image;
    }
}

GudangList.java

package foodsqlitedemo.quocnguyen.com.foodsqlitedemo;

import android.Manifest;
import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.Toast;

import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;

/**
 * Created by Quoc Nguyen on 13-Dec-16.
 */

public class GudangList extends AppCompatActivity {

    GridView gridView;
    ArrayList<Gudang> list;
    GudangListAdapter adapter = null;

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

        gridView = (GridView) findViewById(R.id.gridView);
        list = new ArrayList<>();
        adapter = new GudangListAdapter(this, R.layout.gudang_items, list);
        gridView.setAdapter(adapter);

        // get all data from sqlite
        Cursor cursor = CrudActivity.sqLiteHelper.getData("SELECT * FROM FOOD");
        list.clear();
        while (cursor.moveToNext()) {
            int id = cursor.getInt(0);
            String name = cursor.getString(1);
            String price = cursor.getString(2);
            byte[] image = cursor.getBlob(3);

            list.add(new Gudang(name, price, image, id));
        }
        adapter.notifyDataSetChanged();

        gridView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, final int position, long id) {

                CharSequence[] items = {"Update", "Delete"};
                AlertDialog.Builder dialog = new AlertDialog.Builder(GudangList.this);

                dialog.setTitle("Choose an action");
                dialog.setItems(items, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int item) {
                        if (item == 0) {
                            // update
                            Cursor c = CrudActivity.sqLiteHelper.getData("SELECT id FROM FOOD");
                            ArrayList<Integer> arrID = new ArrayList<Integer>();
                            while (c.moveToNext()){
                                arrID.add(c.getInt(0));
                            }
                            // show dialog update at here
                            showDialogUpdate(GudangList.this, arrID.get(position));

                        } else {
                            // delete
                            Cursor c = CrudActivity.sqLiteHelper.getData("SELECT id FROM FOOD");
                            ArrayList<Integer> arrID = new ArrayList<Integer>();
                            while (c.moveToNext()){
                                arrID.add(c.getInt(0));
                            }
                            showDialogDelete(arrID.get(position));
                        }
                    }
                });
                dialog.show();
                return true;
            }
        });
    }

    ImageView imageViewFood;
    private void showDialogUpdate(Activity activity, final int position){

        final Dialog dialog = new Dialog(activity);
        dialog.setContentView(R.layout.update_gudang_activity);
        dialog.setTitle("Update");

        imageViewFood = (ImageView) dialog.findViewById(R.id.imageViewFood);
        final EditText edtName = (EditText) dialog.findViewById(R.id.edtName);
        final EditText edtPrice = (EditText) dialog.findViewById(R.id.edtPrice);
        Button btnUpdate = (Button) dialog.findViewById(R.id.btnUpdate);

        // set width for dialog
        int width = (int) (activity.getResources().getDisplayMetrics().widthPixels * 0.95);
        // set height for dialog
        int height = (int) (activity.getResources().getDisplayMetrics().heightPixels * 0.7);
        dialog.getWindow().setLayout(width, height);
        dialog.show();

        imageViewFood.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // request photo library
                ActivityCompat.requestPermissions(
                        GudangList.this,
                        new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                        888
                );
            }
        });

        btnUpdate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    CrudActivity.sqLiteHelper.updateData(
                            edtName.getText().toString().trim(),
                            edtPrice.getText().toString().trim(),
                            CrudActivity.imageViewToByte(imageViewFood),
                            position
                    );
                    dialog.dismiss();
                    Toast.makeText(getApplicationContext(), "Update successfully!!!",Toast.LENGTH_SHORT).show();
                }
                catch (Exception error) {
                    Log.e("Update error", error.getMessage());
                }
                updateFoodList();
            }
        });
    }

    private void showDialogDelete(final int idFood){
        final AlertDialog.Builder dialogDelete = new AlertDialog.Builder(GudangList.this);

        dialogDelete.setTitle("Warning!!");
        dialogDelete.setMessage("Are you sure you want to this delete?");
        dialogDelete.setPositiveButton("OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                try {
                    CrudActivity.sqLiteHelper.deleteData(idFood);
                    Toast.makeText(getApplicationContext(), "Delete successfully!!!",Toast.LENGTH_SHORT).show();
                } catch (Exception e){
                    Log.e("error", e.getMessage());
                }
                updateFoodList();
            }
        });

        dialogDelete.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });
        dialogDelete.show();
    }

    private void updateFoodList(){
        // get all data from sqlite
        Cursor cursor = CrudActivity.sqLiteHelper.getData("SELECT * FROM FOOD");
        list.clear();
        while (cursor.moveToNext()) {
            int id = cursor.getInt(0);
            String name = cursor.getString(1);
            String price = cursor.getString(2);
            byte[] image = cursor.getBlob(3);

            list.add(new Gudang(name, price, image, id));
        }
        adapter.notifyDataSetChanged();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

        if(requestCode == 888){
            if(grantResults.length >0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
                 Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
                intent.setType("image/*");
                startActivityForResult(intent, 888);
            }
            else {
                Toast.makeText(getApplicationContext(), "You don't have permission to access file location!", Toast.LENGTH_SHORT).show();
            }
            return;
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        if(requestCode == 888 && resultCode == RESULT_OK && data != null){
            Uri uri = data.getData();
            try {
                InputStream inputStream = getContentResolver().openInputStream(uri);
                Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                imageViewFood.setImageBitmap(bitmap);

            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }

        super.onActivityResult(requestCode, resultCode, data);
    }
}

GudangListAdapter.java

package foodsqlitedemo.quocnguyen.com.foodsqlitedemo;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;

/**
 * Created by Quoc Nguyen on 13-Dec-16.
 */

public class GudangListAdapter extends BaseAdapter {

    private Context context;
    private  int layout;
    private ArrayList<Gudang> foodsList;

    public GudangListAdapter(Context context, int layout, ArrayList<Gudang> foodsList) {
        this.context = context;
        this.layout = layout;
        this.foodsList = foodsList;
    }

    @Override
    public int getCount() {
        return foodsList.size();
    }

    @Override
    public Object getItem(int position) {
        return foodsList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    private class ViewHolder{
        ImageView imageView;
        TextView txtName, txtPrice;
    }

    @Override
    public View getView(int position, View view, ViewGroup viewGroup) {

        View row = view;
        ViewHolder holder = new ViewHolder();

        if(row == null){
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row = inflater.inflate(layout, null);

            holder.txtName = (TextView) row.findViewById(R.id.txtName);
            holder.txtPrice = (TextView) row.findViewById(R.id.txtPrice);
            holder.imageView = (ImageView) row.findViewById(R.id.imgFood);
            row.setTag(holder);
        }
        else {
            holder = (ViewHolder) row.getTag();
        }

        Gudang gudang = foodsList.get(position);

        holder.txtName.setText(gudang.getName());
        holder.txtPrice.setText(gudang.getPrice());

        byte[] foodImage = gudang.getImage();
        Bitmap bitmap = BitmapFactory.decodeByteArray(foodImage, 0, foodImage.length);
        holder.imageView.setImageBitmap(bitmap);

        return row;
    }
}

SQLiteHelper

package foodsqlitedemo.quocnguyen.com.foodsqlitedemo;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteStatement;

/**
 * Created by Quoc Nguyen on 13-Dec-16.
 */

public class SQLiteHelper extends SQLiteOpenHelper {

    public SQLiteHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    public void queryData(String sql){
        SQLiteDatabase database = getWritableDatabase();
        database.execSQL(sql);
    }

    public void insertData(String name, String price, byte[] image){
        SQLiteDatabase database = getWritableDatabase();
        String sql = "INSERT INTO FOOD VALUES (NULL, ?, ?, ?)";

        SQLiteStatement statement = database.compileStatement(sql);
        statement.clearBindings();

        statement.bindString(1, name);
        statement.bindString(2, price);
        statement.bindBlob(3, image);

        statement.executeInsert();
    }

    public void updateData(String name, String price, byte[] image, int id) {
        SQLiteDatabase database = getWritableDatabase();

        String sql = "UPDATE FOOD SET name = ?, price = ?, image = ? WHERE id = ?";
        SQLiteStatement statement = database.compileStatement(sql);

        statement.bindString(1, name);
        statement.bindString(2, price);
        statement.bindBlob(3, image);
        statement.bindDouble(4, (double)id);

        statement.execute();
        database.close();
    }

    public  void deleteData(int id) {
        SQLiteDatabase database = getWritableDatabase();

        String sql = "DELETE FROM FOOD WHERE id = ?";
        SQLiteStatement statement = database.compileStatement(sql);
        statement.clearBindings();
        statement.bindDouble(1, (double)id);

        statement.execute();
        database.close();
    }

    public Cursor getData(String sql){
        SQLiteDatabase database = getReadableDatabase();
        return database.rawQuery(sql, null);
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {

    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

    }
}
enter code here


问:
Using "umlauts" in C++ code

Possible Duplicate:

  C++ source in unicode

I just discovered this line of code in a project:

```<code>string überwachung;
</code>```

I was surprised, because actually I thought you are not allowed to use umlauts like 'äöü' in C++ code other than in strings and so on, and it would result in a compiler error. But this compiles just fine with visual studio 2008.

Is this a special microsoft feature, or are umlauts allowed with other compilers too?

Are there any potential problems with that (portability,system language settings..)?

I can clearly remember this was not allowed. When did it change?

Kind regards for any clarification

P.S.: the tool cppcheck will even mark this usage as an error, even though it compiles

答:
The compiler is free to support any characters in identifiers it desires. Your compiler apparently supports umlauts. However, it is not guaranteed by the language standard. You can't use umlauts if you expect your program to be standard-compliant.

For another example, some compilers allow using $ character in identifiers, while the language specification does not support it.

ContentLicense: CC BY-SA 3.0

Title: Using "umlauts" in C++ code

Body:
Possible Duplicate:

  C++ source in unicode

I just discovered this line of code in a project:

string überwachung;

I was surprised, because actually I thought you are not allowed to use umlauts like 'äöü' in C++ code other than in strings and so on, and it would result in a compiler error. But this compiles just fine with visual studio 2008.

Is this a special microsoft feature, or are umlauts allowed with other compilers too?

Are there any potential problems with that (portability,system language settings..)?

I can clearly remember this was not allowed. When did it change?

Kind regards for any clarification

P.S.: the tool cppcheck will even mark this usage as an error, even though it compiles


问:
How to tell if authenticated
I'm using the ng-oidc-client package and in the navbar i am trying to use a ngIf statement. The problem i am having is determining if the user is authenicated.</p>

```<code>// -------------------- navbar.component.ts ---------------
// Imports for the library
import { OidcFacade } from 'ng-oidc-client';
import { User } from 'oidc-client';

// Constructor
constructor(private oidcFacade: OidcFacade) {}

// Method
isAuthenticated() {
    let isLoggedIn = this.oidcFacade.loggedIn$;
    if (!isLoggedIn) return false;
    return isLoggedIn;
}

// navbar.component.html
<li class="nav-item" [routerLinkActive]='["link-active"]' *ngIf="isAuthenticated() == true">
   <a class="nav-link" (click)='signOutRedirect()'>Sign Out</a>
</li>
</code>```

答:
Assuming that the library creator followed the naming convention for observable, this.oidcFacade.loggedIn$ is a type of boolean observable.

All you need to do is use the async pipe. *ngIf="oidcFacade.loggedIn$ | async"

Title: How to tell if authenticated

Body:
I'm using the ng-oidc-client package and in the navbar i am trying to use a ngIf statement. The problem i am having is determining if the user is authenicated.

// -------------------- navbar.component.ts ---------------
// Imports for the library
import { OidcFacade } from 'ng-oidc-client';
import { User } from 'oidc-client';

// Constructor
constructor(private oidcFacade: OidcFacade) {}

// Method
isAuthenticated() {
    let isLoggedIn = this.oidcFacade.loggedIn$;
    if (!isLoggedIn) return false;
    return isLoggedIn;
}

// navbar.component.html

   Sign Out


问:
TS: how to transform Object.assign in ts file?
I have some Object.assign usage in my ts files, and I am using ts-loader to handle ts files, however, I still find there are Object.assign in output js files. I have added transform-object-assign in my .babelrc file, and I find normal js files are all transformed, only ts files not. So is there any method to transform it in ts files ?

答:
I find normal js files are all transformed, only ts files not.

Make sure the generate .js from TypeScript is being passed to Babel i.e. ts-loader then babel-loader

```<code>{
      test: /\.ts(x?)$/,
      exclude: /node_modules/,
      use: [
        {
          loader: 'ts-loader'
        },
        {
          loader: 'babel-loader',
          options: babelOptions
        },
      ]
    }
</code>```

More

https://github.com/TypeStrong/ts-loader#babel

Body:
I find normal js files are all transformed, only ts files not.

Make sure the generate .js from TypeScript is being passed to Babel i.e. ts-loader then babel-loader

{
      test: /\.ts(x?)$/,
      exclude: /node_modules/,
      use: [
        {
          loader: 'ts-loader'
        },
        {
          loader: 'babel-loader',
          options: babelOptions
        },
      ]
    }

More

https://github.com/TypeStrong/ts-loader#babel


问:
replace a string with special " ' "
I want to find and replace string with special symbol " ' " using gsub of awk.

I tried escape the symbol with \ and even \\ but my code returns > .

```<code>awk '{ gsub("%27","'",$1); print $1 }' file.txt
</code>```

file.txt:

```<code>%27SWAY%27
</code>```

I want above to be replaced to 'SWAY'

答:
This might work for you (GNU sed):

```<code>sed 's/%27/'\''/g' file
</code>```

Poke a hole through to the underlying shell and use a quoted single quote.

Title: replace a string with special " ' "

Body:
I want to find and replace string with special symbol " ' " using gsub of awk.

I tried escape the symbol with \ and even \\ but my code returns > .

awk '{ gsub("%27","'",$1); print $1 }' file.txt

file.txt:

%27SWAY%27

I want above to be replaced to 'SWAY'

Body:
This might work for you (GNU sed):

sed 's/%27/'\''/g' file

Poke a hole through to the underlying shell and use a quoted single quote.


问:
A git submodule is stuck at wrong commit ('submodule update' doesn't work)
I have a parent project with a submodule (no nested submodules). The submodule has a new commit (let's call it new-sha), and the parent refers to that commit in remote repo (I can see submodule @ new-sha when viewing the repo in web browser).
I have pulled the parent project, and it also refers to the right commit in the working directory, as seen in git show output:

```<code>--- a/submodule
--- b/submodule
@@ -1 +1 @@
-Subproject commit old-sha
+Subproject commit new-sha
</code>```

I.e. the latest commit in parent project has changed the submodule to new-sha. However, neither git submodule update nor git pull --recurse-submodules update to new-sha in the submodule, they always check out old-sha.

Why, and how to fix it?

git version 2.21.0.windows.1

Some additional information: the submodule has sha-new locally, but its HEAD is stuck at sha-old.

sha-new is immediately derived from sha-old, and here are the last 3 commits, maybe this can give a clue:

```<code>sha-new  == the top of submodule's branch used by parent project
sha-old  == HEAD
sha-xyz  == origin/HEAD
</code>```

The origin/HEAD line worries me. Even after manually pulling the submodule (cd submodule; git pull origin branch-name:branch-name) origin/HEAD stayed at third commit from top.

答:
You need to make sure the new commit was pushed to the submodule remote repository. (the one listed in the .gitmodules URL line)

Then you need to do a git status within your main parent repo local clone, to check it is at the latest of the master branch and that git ls-tree does show the right submodule root tree commit.

The OP me76 adds in the comments:

I "solved" it differently.

I had to do some changes in the submodule, so I manually switched to the right commit, did and committed the changes in submodule, and committed the submodule in the parent project.

This finally updated the reference to submodule.

That is because doing so forces the main repository to update the gitlink (special entry in the index) to reference the new commit of the submodule main folder tree.

Pushing that will publish that new gitlink commit.

The OP also refers to this thread:

The person had (apparently conflicting) version of submodule in the index (git ls-files --stage | grep 160000).

After removing it from index (git rm --cached) and re-adding it with git submodule add, I was finally able to update the submodule from the parent project.

Note: the git rm --cached asubmoduleFolder must not ends with '/': you are removing a gitlink (the '160000' special entry in the index). Not a folder.

Body:
I have a parent project with a submodule (no nested submodules). The submodule has a new commit (let's call it new-sha), and the parent refers to that commit in remote repo (I can see submodule @ new-sha when viewing the repo in web browser).
I have pulled the parent project, and it also refers to the right commit in the working directory, as seen in git show output:

--- a/submodule
--- b/submodule
@@ -1 +1 @@
-Subproject commit old-sha
+Subproject commit new-sha

I.e. the latest commit in parent project has changed the submodule to new-sha. However, neither git submodule update nor git pull --recurse-submodules update to new-sha in the submodule, they always check out old-sha.

Why, and how to fix it?

git version 2.21.0.windows.1

Some additional information: the submodule has sha-new locally, but its HEAD is stuck at sha-old.

sha-new is immediately derived from sha-old, and here are the last 3 commits, maybe this can give a clue:

sha-new  == the top of submodule's branch used by parent project
sha-old  == HEAD
sha-xyz  == origin/HEAD

The origin/HEAD line worries me. Even after manually pulling the submodule (cd submodule; git pull origin branch-name:branch-name) origin/HEAD stayed at third commit from top.


问:
Laravel Routes not working like they're supposed to
I am creating an API to save and send events, nothing special about it... I've done it before but for some reason that I can't understand I'm getting this response from a normal route

I need to return an array of collections, nothing wrong about it, in tinker seems to work fine. But my problem doesn't involve data.

I want to do this:

(in routes/api.php)

Route::get('activity/events', function() {
    return 'hi there';
});
```

<p>But I got a 204 code in Postman with <code>my-site.test/api/activity/events</code>
The funny thing is, if I do this:</p>

<p><strong>(in routes/api.php)</strong></p>

<pre class="lang-php prettyprint-override"><code>Route::get('activity/events/{foo}', function() {
    return 'hi there';
});
</code>```

I receive the message with no problem with my-site.test/api/activity/events/bar

Am I doing something wrong? I really don't know where to look for an answer

Thanks, everyone!

EDIT: I'm using the most up-to-date versions of everything

Update: The problem I experienced is related to the answer below. I had:

Route::resource('/activity', 'ActivityController');

before: Route::prefix('activity') ...

For anyone reading this, please don't make the same mistake!

答:
Status 204 means that there is no additional content to send in the response payload body.

So try returning some JSON values like

```<code>Route::get('activity/events/{foo}', function() {
    return Response()->json(['success' => true], 200);
});
</code>```

or try Route::prefix

```<code>Route::prefix('activity')->group(function () {
  Route::get('events', function() {
        return Response()->json(['success' => true], 200);
    });
});
</code>```

Body:
I am creating an API to save and send events, nothing special about it... I've done it before but for some reason that I can't understand I'm getting this response from a normal route

I need to return an array of collections, nothing wrong about it, in tinker seems to work fine. But my problem doesn't involve data.

I want to do this:

(in routes/api.php)

Route::get('activity/events', function() {
    return 'hi there';
});

But I got a 204 code in Postman with my-site.test/api/activity/events
The funny thing is, if I do this:

(in routes/api.php)

Route::get('activity/events/{foo}', function() {
    return 'hi there';
});

I receive the message with no problem with my-site.test/api/activity/events/bar

Am I doing something wrong? I really don't know where to look for an answer

Thanks, everyone!

EDIT: I'm using the most up-to-date versions of everything

Update: The problem I experienced is related to the answer below. I had:

Route::resource('/activity', 'ActivityController');

before: Route::prefix('activity') ...

For anyone reading this, please don't make the same mistake!

Body:
Status 204 means that there is no additional content to send in the response payload body.

So try returning some JSON values like

Route::get('activity/events/{foo}', function() {
    return Response()->json(['success' => true], 200);
});

or try Route::prefix

Route::prefix('activity')->group(function () {
  Route::get('events', function() {
        return Response()->json(['success' => true], 200);
    });
});


问:
Sorting a Priority Queue with Objects made from a Map (values)
I have a problem with my Priority Queue not sorting my object values properly.

My code takes a String of text and gets the number of unique characters with also counting the frequency of each unique character. It is then put into a map of type Character and Integer with the Key and Value being assigned respectively.

It then takes each entry of the map and puts it into a PQNode object, also of type Character, Integer, then offers it to the Priority Queue.

The priority queue is to sort the PQNodes by the frequency (value) from lowest to highest via the compareTo method in PQNode.java

I have tried searching around on the web and trying to put in into a list to sort it but no luck.

```<code>public class Counting {
public Counting(String text) {
    text = "mississippi river";
    Queue<PQNode> fringe = new PriorityQueue<>();
    char[] letters = text.toCharArray();
    Map<Character, Integer> frequency = new HashMap<>();

    for(char letter : letters) {
        if(frequency.containsKey(letter)) {
            frequency.put(letter, frequency.get(letter) + 1);
        }
        else {frequency.put(letter, 1);}
        }

    for(Map.Entry<Character, Integer> element : frequency.entrySet()) {
        PQNode pqN = new PQNode(element.getKey(), element.getValue());
        fringe.offer(pqN);
    }
    System.out.println(fringe);
    }
}
</code>```

```<code>public class PQNode implements Comparable<PQNode>{
    Character c;
    int freq;

    public PQNode(Character c, int freq) {
        this.c = c;
        this.freq = freq;
    }

    public String toString() {
        return "[c=" + c + ", freq=" + freq + "]";
    }

    public int compareTo(PQNode otherFreq) {
        return Integer.compare(this.freq, otherFreq.freq);
    }
}
</code>```

The expected output is:
[[c= , freq=1], [c=e, freq=1], [c=v, freq=1], [c=m, freq=1], [c=p, freq=2], [c=r, freq=2], [c=s, freq=4], [c=i, freq=5]]

But the actual output is:
[[c= , freq=1], [c=e, freq=1], [c=v, freq=1], [c=m, freq=1], [c=p, freq=2], [c=r, freq=2], [c=i, freq=5], [c=s, freq=4]]

Where frequency is equal to 1, the order doesn't really matter but the last two elements are in the wrong order. Any ideas?

答:
PriorityQueue doesn't guarantee it will be sorted. PriorityQueue guarantees that the next item received from poll and peek will be the least. If you want your items in order, you have to poll them out one by one, not print the PriorityQueue as is.

If you are looking for a structure that will be sorted, a TreeSet might be better, or maybe a plain old ArrayList that you explicitly sort after you insert all the elements.

Body:
I have a problem with my Priority Queue not sorting my object values properly.

My code takes a String of text and gets the number of unique characters with also counting the frequency of each unique character. It is then put into a map of type Character and Integer with the Key and Value being assigned respectively.

It then takes each entry of the map and puts it into a PQNode object, also of type Character, Integer, then offers it to the Priority Queue.

The priority queue is to sort the PQNodes by the frequency (value) from lowest to highest via the compareTo method in PQNode.java

I have tried searching around on the web and trying to put in into a list to sort it but no luck.

public class Counting {
public Counting(String text) {
    text = "mississippi river";
    Queue<PQNode> fringe = new PriorityQueue<>();
    char[] letters = text.toCharArray();
    Map<Character, Integer> frequency = new HashMap<>();

    for(char letter : letters) {
        if(frequency.containsKey(letter)) {
            frequency.put(letter, frequency.get(letter) + 1);
        }
        else {frequency.put(letter, 1);}
        }

    for(Map.Entry<Character, Integer> element : frequency.entrySet()) {
        PQNode pqN = new PQNode(element.getKey(), element.getValue());
        fringe.offer(pqN);
    }
    System.out.println(fringe);
    }
}

public class PQNode implements Comparable<PQNode>{
    Character c;
    int freq;

    public PQNode(Character c, int freq) {
        this.c = c;
        this.freq = freq;
    }

    public String toString() {
        return "[c=" + c + ", freq=" + freq + "]";
    }

    public int compareTo(PQNode otherFreq) {
        return Integer.compare(this.freq, otherFreq.freq);
    }
}

The expected output is:
[[c= , freq=1], [c=e, freq=1], [c=v, freq=1], [c=m, freq=1], [c=p, freq=2], [c=r, freq=2], [c=s, freq=4], [c=i, freq=5]]

But the actual output is:
[[c= , freq=1], [c=e, freq=1], [c=v, freq=1], [c=m, freq=1], [c=p, freq=2], [c=r, freq=2], [c=i, freq=5], [c=s, freq=4]]

Where frequency is equal to 1, the order doesn't really matter but the last two elements are in the wrong order. Any ideas?


问:
Where does one create a new organization on "Google Cloud Platform"?
I want to use Google Cloud Platform

I go to https://console.cloud.google.com/, then go to Identity and Organization.

It says "To view this page, select an organization."

I did not yet create an organization, so I am expecting a button "create new organization" to appear on this page, but there is only "select", and when I click on "select", nothing happens.

An organization seems to be required for many tasks (for example, creating a new projects requires me to put it in an organization), but how can one create a new organization using Google Cloud Platform?

答: You need to have either a Gsuite or Cloud Identity account before you can create an Org. If you're on free trial then you don't need an Org to create a project.</p>


问:
How to Set a MaxDate for DateTimePicker in .NET MVC?
I've been trying to set a MaxDate value for my DateTimePicker but I couldn't find any useful way to do so. I have tried

```<code>$("#datepicker").datepicker({maxDate: '0'});
</code>```

And

```<code>$(function () {
    $('#datetimepicker6').datetimepicker();
    $('#datetimepicker7').datetimepicker({
        useCurrent: false //Important! See issue #1075
    });
    $("#datetimepicker6").on("dp.change", function (e) {
        $('#datetimepicker7').data("DateTimePicker").minDate(e.date);
    });
    $("#datetimepicker7").on("dp.change", function (e) {
        $('#datetimepicker6').data("DateTimePicker").maxDate(e.date);
    });
});
</code>```

But none solved my problem. In my razor file I have these two datetimepickers:

```<code><div class="form-group" style="width: 15%;">
<label for="example-search-input" class="col-form-label">Start:</label>
@Html.TextBoxFor(u => u.reportFrom, new { @class = "form-control", type = "date", @id = "datetimepicker6" })
</code>```

```<code><div class="form-group" style="width: 15%;">
    <label for="example-search-input" class="col-form-label">End:</label>
    @Html.TextBoxFor(u => u.reportTo, new { @class = "form-control", type = "date", @id = "datetimepicker7" })
</div>
</code>```

And I have this script right under this page;

```<code><script type="text/javascript">
    $(function () {
        $("#tarihsecici").datepicker({ maxDate: '0' });
    });
</script>
</code>```

Can someone help please, it is critically important for my project and I have tried to solve it many times but none worked.

Thanks in advance.

答:
Here you can try this code for datepicker. </p>

```<code>$("#datetimepicker6").datepicker({
      format: 'dd-mm-yyyy',
      autoclose: true,
  }).on('changeDate', function (selected) {
    var startDate = new Date(selected.date.valueOf());
      $('#datetimepicker7').datepicker('setStartDate', startDate);
  }).on('clearDate', function (selected) {
      $('#datetimepicker7').datepicker('setStartDate', null);
  });

  $("#datetimepicker7").datepicker({
      format: 'dd-mm-yyyy',
      autoclose: true,
  }).on('changeDate', function (selected) {
      var endDate = new Date(selected.date.valueOf());
      $('#datetimepicker6').datepicker('setEndDate', endDate);
  }).on('clearDate', function (selected) {
      $('#datetimepicker6').datepicker('setEndDate', null);
  });
</code>```

Body:
I've been trying to set a MaxDate value for my DateTimePicker but I couldn't find any useful way to do so. I have tried

$("#datepicker").datepicker({maxDate: '0'});

And

$(function () {
    $('#datetimepicker6').datetimepicker();
    $('#datetimepicker7').datetimepicker({
        useCurrent: false //Important! See issue #1075
    });
    $("#datetimepicker6").on("dp.change", function (e) {
        $('#datetimepicker7').data("DateTimePicker").minDate(e.date);
    });
    $("#datetimepicker7").on("dp.change", function (e) {
        $('#datetimepicker6').data("DateTimePicker").maxDate(e.date);
    });
});

But none solved my problem. In my razor file I have these two datetimepickers:

Start:
@Html.TextBoxFor(u => u.reportFrom, new { @class = "form-control", type = "date", @id = "datetimepicker6" })

    End:
    @Html.TextBoxFor(u => u.reportTo, new { @class = "form-control", type = "date", @id = "datetimepicker7" })

And I have this script right under this page;

Can someone help please, it is critically important for my project and I have tried to solve it many times but none worked.

Thanks in advance.

Body:
Here you can try this code for datepicker.

$("#datetimepicker6").datepicker({
      format: 'dd-mm-yyyy',
      autoclose: true,
  }).on('changeDate', function (selected) {
    var startDate = new Date(selected.date.valueOf());
      $('#datetimepicker7').datepicker('setStartDate', startDate);
  }).on('clearDate', function (selected) {
      $('#datetimepicker7').datepicker('setStartDate', null);
  });

  $("#datetimepicker7").datepicker({
      format: 'dd-mm-yyyy',
      autoclose: true,
  }).on('changeDate', function (selected) {
      var endDate = new Date(selected.date.valueOf());
      $('#datetimepicker6').datepicker('setEndDate', endDate);
  }).on('clearDate', function (selected) {
      $('#datetimepicker6').datepicker('setEndDate', null);
  });