问:
How to replace text with an image/icon when scaling to mobile?
I am newbie to this and can't find many specific answers. I am looking for a way to change text labels into images when the viewport is scaled down to mobile sizes. I have additional issues because I am doing so with Leaflet, a java script library for Open Street Maps. They organize things a little different and I have to inject my styling.

Here is my live page with icons: https://leksplay.com/playgroundmap (still working on my SSL cert).

My full inline styles are at the bottom. I have a couple of  things going on here.

I am styling the input directly because Leaflet inserts a div between label and input not allowing me to trigger animation on the label based on "checked" input states.

I am injecting a class into my labels through javascript. Leaflet allows this, example:

```<code>var overlayMaps = {
       "All Playgrounds": dummy[0],
       "<img class='icons' src='https://static.tildacdn.com/tild6162-6637-4663-b262-356661343562/IconsMedium_WC.png' alt='Restrooms'>": dummy[1],
       "<img class='icons' src='https://static.tildacdn.com/tild6238-6432-4162-a161-333539326537/IconsMedium_Grill.png' alt='Public grills'>": dummy[2],
       "<img class='icons' src='https://static.tildacdn.com/tild3939-3338-4237-b732-346131313435/IconsMedium_Access.png' alt='Accessible equipment'>": dummy[3],
       "<img class='icons' src='https://static.tildacdn.com/tild3634-3833-4338-b834-626437613735/IconsMedium_Indoor.png' alt='Indoor area'>": dummy[4],
       "<img class='icons' src='https://static.tildacdn.com/tild3331-3632-4239-a333-343137356133/IconsMedium_Full_Fen.png' alt='Fully fenced'>": dummy[5],
       "<img class='icons' src='https://static.tildacdn.com/tild3339-3038-4032-a638-626137393039/IconsMedium_Partial_.png' alt='Partially fenced'>": dummy[6],
       "<img class='icons' src='https://static.tildacdn.com/tild3336-3333-4137-a562-346663633031/IconsMedium_Horse.png' alt='Animals'>": dummy[7],
       "<img class='icons' src='https://static.tildacdn.com/tild3332-6230-4731-a138-373630383130/IconsMedium_Water.png' alt='Pool or beach'>": dummy[8],
       "<img class='icons' src='https://static.tildacdn.com/tild3761-3935-4338-b861-336231626433/IconsMedium_Toddler.png' alt='Toddler Area'>": dummy[9]
  };
</code>```

I am also having some issues with my flex container on smaller screens because of margins I can't manage to fix. On mobile there is too much space on the left and right side causing the container to only have two columns when clearly there is space for 3 or 4. Example:
photo of current mobile view

I am sure there is a way, maybe with jQuery (which I dont know), to either fix the flex container on mobile or simply transition from text only on desktop to icons when on a smaller screen. Here is a live example of the text only version: https://leksplay.com/test-and
My end goal is to find a way that can display my control box (filters) on mobile without the browser creating an overflow scroll box or making the user scroll needlessly far to get to the actual map.

Any help is appreciated.

```<code><div class="flexcontainer">
    <div id="new-parent">
    </div>
    </div>

<script>// Create the control and add it to the map;

var control = L.control.layers(null, overlayMaps,{collapsed:false});
control.addTo(map);

// Call the getContainer routine.
var htmlObject = control.getContainer();
// Get the desired parent node.
var a = document.getElementById('new-parent');

// Finally append that node to the new parent.
function setParent(el, newParent)
{
    newParent.appendChild(el);
}
setParent(htmlObject, a);

</script>

<style>
*, *::before, *::after {
  box-sizing: border-box;
  vertical-align: middle;
}

body {
    color: #435757;
    background: radial-gradient(#fff, #dac4cd);
    font: min(3vw, 16px) 'Montserrat';
    justify-content: center;
    align-items: center;
    flex-direction: column;
}
label:first-of-type {
    border: 3px solid #689c93;
    margin: min(1vw,10px) 75%;
    flex: 0 0 30%;
    border-radius: 100px;
}
label {
    display: block;
    position: relative;
    padding: min(.5vw, 5px) min(3vw, 15px) min(.5vw, 5px) min(.5vw, 5px);
    color: #000;
    background-color: transparent;
    white-space: nowrap;
    cursor: pointer;
    user-select: none;
    transition: background-color .2s, box-shadow .2s;
    flex: 0 0 20%;
    border-radius: 100px;

}

.flexcontainer {
    display: flex !important;
    flex-wrap: wrap;
}

.icons {
    width: 70px;
}

#new-parent {
    position: relative;
}

</style>

<style>
.leaflet-control-layers-selector {
     --primary: #679C92;
     --secondary: #E0E0E0;
     --duration: 0.5s;
     -webkit-appearance: none;
     -moz-appearance: none;
     -webkit-tap-highlight-color: transparent;
     -webkit-mask-image: -webkit-radial-gradient(white, black);
     outline: none;
     cursor: pointer;
     position: relative;
     overflow: hidden;
     transform-style: preserve-3d;
     perspective: 240px;
     border-radius: 50%;
     width: min(3.5vw, 25px);
     height: min(3.5vw, 25px);
     background-size: 300% 300%;
     transition: transform 0.3s;
     transform: translate(0vw, 0vw);
     transform-origin: center center;
     animation: var(--name, unchecked) var(--duration) ease forwards;
}
.leaflet-control-layers-selector:before, .leaflet-control-layers-selector:after {
     content: '';
     position: absolute;
     height: var(--height, 13px);
     left: 3px;
     top: var(--top, 3px);
     background: var(--background, var(--primary));
     animation: var(--name-icon-b, var(--name-icon, unchecked-icon)) var(--duration) ease forwards;
}
.leaflet-control-layers-selector:before {
     clip-path: polygon(0 0%);
}

.leaflet-control-layers-selector:active {
     --scale: 0.95;
}
.leaflet-control-layers-selector:checked {
     --name: checked;
     --name-icon-b: checked-icon;
     --name-icon-a: unchecked-icon;
}
 @keyframes checked-icon {
     from {
         transform: translateZ(12px);
    }
     to {
         transform: translateX(16px) rotateY(90deg) translateZ(12px);
    }
}
 @keyframes unchecked-icon {
     from {
         transform: translateX(-16px) rotateY(-90deg) translateZ(12px);
    }
     to {
         transform: translateZ(12px);
    }
}
 @keyframes checked {
     from {
         background-image: radial-gradient(ellipse at center, var(--primary) 0%, var(--primary) 25%, var(--secondary) 25.1%, var(--secondary) 100%);
         background-position: 100% 50%;
    }
     to {
         background-image: radial-gradient(ellipse at center, var(--primary) 0%, var(--primary) 25%, var(--secondary) 25.1%, var(--secondary) 100%);
         background-position: 50% 50%;
    }
}
 @keyframes unchecked {
     from {
         background-image: radial-gradient(ellipse at center, var(--secondary) 0%, var(--secondary) 25%, var(--primary) 25.1%, var(--primary) 100%);
         background-position: 100% 50%;
    }
     to {
         background-image: radial-gradient(ellipse at center, var(--secondary) 0%, var(--secondary) 25%, var(--primary) 25.1%, var(--primary) 100%);
         background-position: 50% 50%;
    }
}
 html {
     box-sizing: border-box;
     -webkit-font-smoothing: antialiased;
}
 * {
     box-sizing: inherit;
}
 *:before, *:after {
     box-sizing: inherit;
}

</style>

<style>
.leaflet-control-layers-expanded {
    padding: 0px 0px 0px 0px !important;
    background: transparent !important;
    }

.leaflet-control-layers {
    box-shadow: 0 0px 0px rgba(0,0,0,00) !important;
    background: transparent !important;
    border-radius: 0px !important;
}
.leaflet-control-layers-overlays {
    display: flex !important;
    position:unset;
    justify-content: center;
    flex-wrap: wrap;
    flex-basis: unset;
    align-items: center;
    width: 75%;
    margin: 0px 12.5% 0px 12.5%;
    align: center;
}

</style>
</code>```

答:
Here is the solution:

Step 1: hide the text when the browser size is less than 991px or in mobile screens which have size less than 991px;

Step 2: set a background image.

@media all and (max-width:991px){

  #tst1{
      background-image:url('https://static.tildacdn.com/tild6162-6637-4663-b262-356661343562/IconsMedium_WC.png');
       transition:all 0.3s;
       color:transparent;
       background-size:50px 25px;
       background-repeat:no-repeat;
       background-position:center;

  }
  #tst2{
      background-image:url('https://static.tildacdn.com/tild6238-6432-4162-a161-333539326537/IconsMedium_Grill.png');
       transition:all 0.3s;
       color:transparent;
       background-size:50px 25px;
       background-repeat:no-repeat;
       background-position:center;

  }
  #tst3{
      background-image:url('https://static.tildacdn.com/tild3939-3338-4237-b732-346131313435/IconsMedium_Access.png');
       transition:all 0.3s;
       color:transparent;
       background-size:50px 25px;
       background-repeat:no-repeat;
       background-position:center;

  }
  #tst4{
      background-image:url('https://static.tildacdn.com/tild3634-3833-4338-b834-626437613735/IconsMedium_Indoor.png');
       transition:all 0.3s;
       color:transparent;
       background-size:50px 25px;
       background-repeat:no-repeat;
       background-position:center;

  }
  #tst5{
      background-image:url('https://static.tildacdn.com/tild3331-3632-4239-a333-343137356133/IconsMedium_Full_Fen.png');
       transition:all 0.3s;
       color:transparent;
       background-size:50px 25px;
       background-repeat:no-repeat;
       background-position:center;

  }
  #tst6{
      background-image:url('https://static.tildacdn.com/tild3339-3038-4032-a638-626137393039/IconsMedium_Partial_.png');
       transition:all 0.3s;
       color:transparent;
       background-size:50px 25px;
       background-repeat:no-repeat;
       background-position:center;

  }
  #tst7{
      background-image:url('https://static.tildacdn.com/tild3336-3333-4137-a562-346663633031/IconsMedium_Horse.png');
       transition:all 0.3s;
       color:transparent;
       background-size:50px 25px;
       background-repeat:no-repeat;
       background-position:center;

  }
  #tst8{
      background-image:url('https://static.tildacdn.com/tild3332-6230-4731-a138-373630383130/IconsMedium_Water.png');
       transition:all 0.3s;
       color:transparent;
       background-size:50px 25px;
       background-repeat:no-repeat;
       background-position:center;

  }
  #tst9{
      background-image:url('https://static.tildacdn.com/tild3761-3935-4338-b861-336231626433/IconsMedium_Toddler.png');
       transition:all 0.3s;
       color:transparent;
       background-size:50px 25px;
       background-repeat:no-repeat;
       background-position:center;

  }

 }```
<pre class="snippet-code-html lang-html prettyprint-override"><code><span id="tst1">Restrooms</span>

<span id="tst2">Public grills</span>

<span id="tst3">Accessible equipment</span>

<span id="tst4">Indoor area</span>

<span id="tst5">Fully fenced</span>

<span id="tst6">Partially fenced</span>

<span id="tst7">Animals</span>

<span id="tst8">Pool or beach</span>

<span id="tst9">Toddler Area</span></code>```

I have done little modification to your code to make things working.Please run it full screen and reduce the browser's size to see the changes.

Also, replace the areas of your code with this code and apply css.I have taken 991px as breakpoint, but you can take breakpoint of your choice.

Body:
I am newbie to this and can't find many specific answers. I am looking for a way to change text labels into images when the viewport is scaled down to mobile sizes. I have additional issues because I am doing so with Leaflet, a java script library for Open Street Maps. They organize things a little different and I have to inject my styling.

Here is my live page with icons: https://leksplay.com/playgroundmap (still working on my SSL cert).

My full inline styles are at the bottom. I have a couple of  things going on here.

I am styling the input directly because Leaflet inserts a div between label and input not allowing me to trigger animation on the label based on "checked" input states.

I am injecting a class into my labels through javascript. Leaflet allows this, example:

var overlayMaps = {
       "All Playgrounds": dummy[0],
       "": dummy[1],
       "": dummy[2],
       "": dummy[3],
       "": dummy[4],
       "": dummy[5],
       "": dummy[6],
       "": dummy[7],
       "": dummy[8],
       "": dummy[9]
  };

I am also having some issues with my flex container on smaller screens because of margins I can't manage to fix. On mobile there is too much space on the left and right side causing the container to only have two columns when clearly there is space for 3 or 4. Example:
photo of current mobile view

I am sure there is a way, maybe with jQuery (which I dont know), to either fix the flex container on mobile or simply transition from text only on desktop to icons when on a smaller screen. Here is a live example of the text only version: https://leksplay.com/test-and
My end goal is to find a way that can display my control box (filters) on mobile without the browser creating an overflow scroll box or making the user scroll needlessly far to get to the actual map.

Any help is appreciated.

Body:
Here is the solution:

Step 1: hide the text when the browser size is less than 991px or in mobile screens which have size less than 991px;

Step 2: set a background image.

@media all and (max-width:991px){

  #tst1{
      background-image:url('https://static.tildacdn.com/tild6162-6637-4663-b262-356661343562/IconsMedium_WC.png');
       transition:all 0.3s;
       color:transparent;
       background-size:50px 25px;
       background-repeat:no-repeat;
       background-position:center;

  }
  #tst2{
      background-image:url('https://static.tildacdn.com/tild6238-6432-4162-a161-333539326537/IconsMedium_Grill.png');
       transition:all 0.3s;
       color:transparent;
       background-size:50px 25px;
       background-repeat:no-repeat;
       background-position:center;

  }
  #tst3{
      background-image:url('https://static.tildacdn.com/tild3939-3338-4237-b732-346131313435/IconsMedium_Access.png');
       transition:all 0.3s;
       color:transparent;
       background-size:50px 25px;
       background-repeat:no-repeat;
       background-position:center;

  }
  #tst4{
      background-image:url('https://static.tildacdn.com/tild3634-3833-4338-b834-626437613735/IconsMedium_Indoor.png');
       transition:all 0.3s;
       color:transparent;
       background-size:50px 25px;
       background-repeat:no-repeat;
       background-position:center;

  }
  #tst5{
      background-image:url('https://static.tildacdn.com/tild3331-3632-4239-a333-343137356133/IconsMedium_Full_Fen.png');
       transition:all 0.3s;
       color:transparent;
       background-size:50px 25px;
       background-repeat:no-repeat;
       background-position:center;

  }
  #tst6{
      background-image:url('https://static.tildacdn.com/tild3339-3038-4032-a638-626137393039/IconsMedium_Partial_.png');
       transition:all 0.3s;
       color:transparent;
       background-size:50px 25px;
       background-repeat:no-repeat;
       background-position:center;

  }
  #tst7{
      background-image:url('https://static.tildacdn.com/tild3336-3333-4137-a562-346663633031/IconsMedium_Horse.png');
       transition:all 0.3s;
       color:transparent;
       background-size:50px 25px;
       background-repeat:no-repeat;
       background-position:center;

  }
  #tst8{
      background-image:url('https://static.tildacdn.com/tild3332-6230-4731-a138-373630383130/IconsMedium_Water.png');
       transition:all 0.3s;
       color:transparent;
       background-size:50px 25px;
       background-repeat:no-repeat;
       background-position:center;

  }
  #tst9{
      background-image:url('https://static.tildacdn.com/tild3761-3935-4338-b861-336231626433/IconsMedium_Toddler.png');
       transition:all 0.3s;
       color:transparent;
       background-size:50px 25px;
       background-repeat:no-repeat;
       background-position:center;

  }

 }

<span id="tst1">Restrooms</span>

<span id="tst2">Public grills</span>

<span id="tst3">Accessible equipment</span>

<span id="tst4">Indoor area</span>

<span id="tst5">Fully fenced</span>

<span id="tst6">Partially fenced</span>

<span id="tst7">Animals</span>

<span id="tst8">Pool or beach</span>

<span id="tst9">Toddler Area</span>

I have done little modification to your code to make things working.Please run it full screen and reduce the browser's size to see the changes.

Also, replace the areas of your code with this code and apply css.I have taken 991px as breakpoint, but you can take breakpoint of your choice.


来源: stackexchange

问:
How to terminate a dockerfile?
I use # to comment out the commands that I don't need in a Dockerfile. Does anybody know if there is a command (something like exit) to terminate a Dockfile so that all the lines below it won't be run? Thanks.

答:
Technically I see coupe of options:

Comments # are the way to go.

Create two separate docker files. Like Dockerfile.dev or Dockerfile.prod and specify them via build (which I personally do not like and do not practice)

Pls describe your initial intent (why do you need it) and maybe we will figure out an appropriate solution.

ContentLicense: CC BY-SA 4.0

Title: How to terminate a dockerfile?


问:
Animation goes into background view instead of foreground
I have the following:

```<code>struct SettingsView: View {
    @State private var showSuccessSave: Bool = false

    var body: some View {
        NavigationView {
            ScrollView {
                VStack {
                    SuccessNotificationView()
                    .offset(y: self.showSuccessSave ? -UIScreen.main.bounds.height/9 : -UIScreen.main.bounds.height)
                        .animation(
                            .interactiveSpring(
                                response: 0.8,
                                dampingFraction: 0.8,
                                blendDuration: 1
                            )
                    )
                    .onTapGesture {
                        self.showSuccessSave = false
                    }

                    Button(action: {
                        self.showSuccessSave.toggle()

                    }) {
                        Text("Save")
                    }
                }
            }
            .navigationBarTitle("Settings")
        }
    }
}
</code>```

And the function I call:

```<code>struct SuccessNotificationView: View {
    var body: some View {
        Text("Success")
            .padding()
            .foregroundColor(Color.white)
            .frame(width: UIScreen.main.bounds.width, height: 100)
            .background(Color.green)
            .cornerRadius(20)
    }
}
</code>```

When it pops up, look at the settings text:

How do I make that notification be on the foreground covering the Settings text? Right now it displays everything in that view on top of it.

答:
Here is possible approach. Tested with Xcode 11.4 / iOS 13.4

```<code>struct SettingsView: View {
    @State private var showSuccessSave: Bool = false

    var body: some View {
        ZStack(alignment: .top) {
            NavigationView {
                ScrollView {
                    VStack {
                        Button(action: {
                            self.showSuccessSave.toggle()

                        }) {
                            Text("Save")
                        }
                    }
                }
                .navigationBarTitle("Settings")
            }

            SuccessNotificationView()
            .offset(y: self.showSuccessSave ? 0 : -UIScreen.main.bounds.height)
                .animation(
                    .interactiveSpring(
                        response: 0.8,
                        dampingFraction: 0.8,
                        blendDuration: 1
                    )
            )
            .onTapGesture {
                self.showSuccessSave = false
            }
        }
    }
}
</code>```

Body:
I have the following:

struct SettingsView: View {
    @State private var showSuccessSave: Bool = false

    var body: some View {
        NavigationView {
            ScrollView {
                VStack {
                    SuccessNotificationView()
                    .offset(y: self.showSuccessSave ? -UIScreen.main.bounds.height/9 : -UIScreen.main.bounds.height)
                        .animation(
                            .interactiveSpring(
                                response: 0.8,
                                dampingFraction: 0.8,
                                blendDuration: 1
                            )
                    )
                    .onTapGesture {
                        self.showSuccessSave = false
                    }

                    Button(action: {
                        self.showSuccessSave.toggle()

                    }) {
                        Text("Save")
                    }
                }
            }
            .navigationBarTitle("Settings")
        }
    }
}

And the function I call:

struct SuccessNotificationView: View {
    var body: some View {
        Text("Success")
            .padding()
            .foregroundColor(Color.white)
            .frame(width: UIScreen.main.bounds.width, height: 100)
            .background(Color.green)
            .cornerRadius(20)
    }
}

When it pops up, look at the settings text:

How do I make that notification be on the foreground covering the Settings text? Right now it displays everything in that view on top of it.

Body:
Here is possible approach. Tested with Xcode 11.4 / iOS 13.4

struct SettingsView: View {
    @State private var showSuccessSave: Bool = false

    var body: some View {
        ZStack(alignment: .top) {
            NavigationView {
                ScrollView {
                    VStack {
                        Button(action: {
                            self.showSuccessSave.toggle()

                        }) {
                            Text("Save")
                        }
                    }
                }
                .navigationBarTitle("Settings")
            }

            SuccessNotificationView()
            .offset(y: self.showSuccessSave ? 0 : -UIScreen.main.bounds.height)
                .animation(
                    .interactiveSpring(
                        response: 0.8,
                        dampingFraction: 0.8,
                        blendDuration: 1
                    )
            )
            .onTapGesture {
                self.showSuccessSave = false
            }
        }
    }
}


问:
After upgrading Gulp, javascript is throwing an syntax-error "import declarations may only appear at top level of a module"
I have a gulpfile.js that watch file changes in a folder. Everything was working fine until I upgraded from Gulp 3.9.1 to 4.0.2. When upgrading the Gulp, I also upgraded my node.js to the latest v12.17.0

Here is my gulp task that bundles the js files

```<code>var gulp = require("gulp"),
    concat = require("gulp-concat"),
    filter = require('gulp-filter'),
    merge = require("merge-stream");

gulp.task("min:js", function () {
    var tasks = [];

    var task = gulp.src(['path_1/**/*.js', 'path_2/**/*.js'], { base: "." })
            .pipe(filter('**/*.js'))
            .pipe(concat('output.js'))
            .pipe(gulp.dest("."));

    tasks.push(task);

    return merge(tasks);
});
</code>```

The task generates the following code

```<code>// More Js code...
import { setTimeout } from "timers";

'use strict';
// more js code.....
</code>```

But the line import { setTimeout } from "timers"; is throwing the following error

SyntaxError: import declarations may only appear at the level of a
  module

How can I fix this error?

答:
The above problem might be caused due to the attempt to import setTimeout as a module.

setTimeout is a standard javascript function and it need not be imported explicitly. Therefore, removing the import statement may solve the issue.

If the above step does not fix the issue, then the following may be tried:

Add type="module" attribute to the HTML script tag that includes the module.

```<code><script type="module" src="my-module.js"></script>
</code>```

Body:
I have a gulpfile.js that watch file changes in a folder. Everything was working fine until I upgraded from Gulp 3.9.1 to 4.0.2. When upgrading the Gulp, I also upgraded my node.js to the latest v12.17.0

Here is my gulp task that bundles the js files

var gulp = require("gulp"),
    concat = require("gulp-concat"),
    filter = require('gulp-filter'),
    merge = require("merge-stream");

gulp.task("min:js", function () {
    var tasks = [];

    var task = gulp.src(['path_1/**/*.js', 'path_2/**/*.js'], { base: "." })
            .pipe(filter('**/*.js'))
            .pipe(concat('output.js'))
            .pipe(gulp.dest("."));

    tasks.push(task);

    return merge(tasks);
});

The task generates the following code

// More Js code...
import { setTimeout } from "timers";

'use strict';
// more js code.....

But the line import { setTimeout } from "timers"; is throwing the following error

SyntaxError: import declarations may only appear at the level of a
  module

How can I fix this error?

Body:
The above problem might be caused due to the attempt to import setTimeout as a module.

setTimeout is a standard javascript function and it need not be imported explicitly. Therefore, removing the import statement may solve the issue.

If the above step does not fix the issue, then the following may be tried:

Add type="module" attribute to the HTML script tag that includes the module.

<script type="module" src="my-module.js"></script>


问:
Django view and separate processes
I would like to do something similar:

f(n) calculates n! , this obviously takes a long time to do, so the calculations need to run in a separate process from the django view. Additionally I would like the view to return a response immediately (ex.  progress 0% ) and subsequent polling needs to update progress, so the view needs to communicate with the above process.

What would be the best way to achieve this?

答: Try django-celery</p>

ContentLicense: CC BY-SA 3.0

Title: Django view and separate processes

Body: Try django-celery


问:
Make methods available everywhere
I am trying to write a recursive descent parser in C and have the following problem with the availability of my methods, since C uses a top down compiler:

```<code>void a(){
    b();
}
void b(){
    c();
}
void c(){
    a();
}
</code>```

How can I work around this problem so I can call all methods where I need them? I could not come up with an elegant solution, since I am rather new to C.

答:
This is normally solved with function prototypes:

```<code>void a(void);
void b(void);
void c(void);
//^function prototypes

void a(void){
    b();
}
void b(void){
    c();
}
void c(void){
    a();
}
</code>```

You could also use old-style declarations (without the void in the parens)
which would declare the functions as taking an unspecified number of promoted arguments, but those are deprecated and they result in weak typechecking and slightly worse codegen, so better put the void in there if the function takes no arguments.

Title: Make methods available everywhere

Body:
I am trying to write a recursive descent parser in C and have the following problem with the availability of my methods, since C uses a top down compiler:

void a(){
    b();
}
void b(){
    c();
}
void c(){
    a();
}

How can I work around this problem so I can call all methods where I need them? I could not come up with an elegant solution, since I am rather new to C.

Body:
This is normally solved with function prototypes:

void a(void);
void b(void);
void c(void);
//^function prototypes

void a(void){
    b();
}
void b(void){
    c();
}
void c(void){
    a();
}

You could also use old-style declarations (without the void in the parens)
which would declare the functions as taking an unspecified number of promoted arguments, but those are deprecated and they result in weak typechecking and slightly worse codegen, so better put the void in there if the function takes no arguments.


问:
WebJobs SDK 3 Braking on Function Exception
I have an Azure WebJob (.NET Core - SDK 3) that is braking when an execution of queue triggered function fails. I would like this WebJob to behave like others WebJobs (SDK 2 - .NET Framework) I have running on Windows WebApps.

When execution of queue triggered functions fail on WebJobs SDK 2 (Windows WebApp) the message is sent back to queue with DequeueCount incremented and after X times (default is 5) message is sent to poison queue. And the WebJob always keeps running.

Is it possible to have same behavior with WebJobs SDK 3? This is an example of described bahavior (webjobs.ricardogaefke.com). In this case I needed to use a try/catch and manually send the message to poison queue and it is a waste of the power of webjobs (retry is lost this way).

Thank you very much.

答:
I found the solution using FunctionExceptionFilterAttribute. Functions' filters are similar to ASP.NET MVC filters and in my case I can handle error in My WebJob's functions and return a completed Task even on error, so the message is sent back to queue with DequeueCount++ (till the limit of dequeues - default is 5).

The final solution can be found at webjobs.ricardogaefke.com and there is a How it works page with links to GitHub repo, public Azure Pipelines and public Docker registry.


问:
Websocket request succeeds in writing to DynamoDB but returns Internal Server Error
I created an AWS API Gateway route for Websocket connections.  I started with the AWS provided Simple Web Chat templates but have modified it to fit my needs.  The API Gateway calls a Lambda function that writes to a DynamoDB table.

I am able to make a websocket connection but when I make my next request to insert some data the data appears successfully in my DynamoDB table but the response I get back is Internal Server Error.

I don't understand what is causing the Internal Server Error.  When I look in the CloudWatch logs I just see normal traffic with no errors.

I could use some help understanding what is going wrong or how I can troubleshoot this better.

Here is the Lamba function that is being called:

```<code>const AWS = require("aws-sdk");
const customId = require("custom-id");

const ddb = new AWS.DynamoDB.DocumentClient({
  apiVersion: "2012-08-10",
  region: process.env.AWS_REGION,
});

exports.handler = async (event) => {
  const uniqueId = customId({
    randomLength: 1,
  });

  const data = {
    uniqueId: uniqueId,
    members: [
      {
        connectionId: event.requestContext.connectionId,
      },
    ],
    events: [],
    parameters: [],
  };

  const putParams = {
    TableName: process.env.EVENT_TABLE_NAME,
    Item: data,
  };

  try {
    await ddb.put(putParams).promise();
  } catch (err) {
    return {
      statusCode: 400,
      body: "Failed to create: " + JSON.stringify(err),
    };
  }

  return { statusCode: 200, body: putParams };
};
</code>```

Image of AWS CloudWatch Logs

The error returned by wcat looks like this:
{"message": "Internal server error", "connectionId":"NZxV_ddNIAMCJrw=", "requestId":"NZxafGiyoAMFoAA="}

答:
I see it now.  It was the last line.  I changed it and now it works fine.</p>

```<code>return { statusCode: 200, body: JSON.stringify(putParams) };
</code>```

Body:
I created an AWS API Gateway route for Websocket connections.  I started with the AWS provided Simple Web Chat templates but have modified it to fit my needs.  The API Gateway calls a Lambda function that writes to a DynamoDB table.

I am able to make a websocket connection but when I make my next request to insert some data the data appears successfully in my DynamoDB table but the response I get back is Internal Server Error.

I don't understand what is causing the Internal Server Error.  When I look in the CloudWatch logs I just see normal traffic with no errors.

I could use some help understanding what is going wrong or how I can troubleshoot this better.

Here is the Lamba function that is being called:

const AWS = require("aws-sdk");
const customId = require("custom-id");

const ddb = new AWS.DynamoDB.DocumentClient({
  apiVersion: "2012-08-10",
  region: process.env.AWS_REGION,
});

exports.handler = async (event) => {
  const uniqueId = customId({
    randomLength: 1,
  });

  const data = {
    uniqueId: uniqueId,
    members: [
      {
        connectionId: event.requestContext.connectionId,
      },
    ],
    events: [],
    parameters: [],
  };

  const putParams = {
    TableName: process.env.EVENT_TABLE_NAME,
    Item: data,
  };

  try {
    await ddb.put(putParams).promise();
  } catch (err) {
    return {
      statusCode: 400,
      body: "Failed to create: " + JSON.stringify(err),
    };
  }

  return { statusCode: 200, body: putParams };
};

Image of AWS CloudWatch Logs

The error returned by wcat looks like this:
{"message": "Internal server error", "connectionId":"NZxV_ddNIAMCJrw=", "requestId":"NZxafGiyoAMFoAA="}

Body:
I see it now.  It was the last line.  I changed it and now it works fine.

return { statusCode: 200, body: JSON.stringify(putParams) };


问:
Bullet-proof groovy script embedding
I'm working on a server app that may be extended by user-supplied Groovy scripts. It's evident that I want to make sure these scripts run in a very tight sandbox where they cannot disrupt the core application code or consume too much resources to overload the server.

I have studied various possibilities and the final solution may be a combination of these:

Run the script within a very restricted security manager. The script is run within a no permission SecurityManager. Additional permissions have to be declared (like Android).

Launch a new JVM. Create a ScriptProcess wrapper around Runtime.exec and spawning a new JVM with a security manager, limited heap, etc. Because we launch a full-blown process, we might get more control on monitor bad behaving ones? The cost in resource would be dire though... An alternative would be to use Ant here, but would it be scalable?

Java Monitor API In Java 6 there is a package with monitoring capacity. We could monitor threads and maybe detect infinite loops and memory consumption. Anyone used this?

These are what I have in mind today. What would be the best way to make sure these scripts behave correctly and still keep a certain scalability and performance?

答:
An additional possibility is using Groovy 1.8 compilation customizers on the GroovyShell that runs the embedded scripts. You can pre-import classes and methods, restrict use of the Groovy AST, and pre-apply an AST transformation, such as @ThreadInterrupt, @TimedInterrupt, or @ConditionalInterrupt. Details at:

http://www.jroller.com/melix/entry/customizing_groovy_compilation_process

Title: Bullet-proof groovy script embedding


问:
Firestore Read - Rule for Webapp
I'm using Firestore for the data of my webapp. Therefore read needs to be possible for everyone visiting my webapp.

Preferably I want to restrict read to the domain but I guess this is not possible. Therefore I just let it open for everyone. However Google reminds me every day that my firebase roles are insecure.

What is best practice to do that? do I need to use cloud functions as a middle layer?

This is my rule:

```<code>service cloud.firestore {
  match /databases/{database}/documents {
   match /{document=**} {
    allow read;
    allow write: if request.auth != null;
   }
 }
}
</code>```

答:
What you have now is using a global wildcard to match all documents the entire database.  The best practice is to call out each collection you want to provide access to.  The global wildcard is risky because it's too easy to use it to accidentally allow access to everything unintentionally.

The first think you should do is remove the global wildcard completely.  The next thing is to write specific rules for each collection where clients should have access.  For example to give read-only access to "collection1":

```<code>   match /collection1/{id} {
    allow read;
   }
</code>```

And to give read and write access only to signed in users:

```<code>   match /collection1/{id} {
    allow read, write: if request.auth != null;
   }
</code>```

These rules are not necessarily going to make your app "secure".  They are just starting points.  You should assess the security requirements for your app and write specific rules that implement those requirements.  Only you know your specific requirements.  There are not really universal rules that can make any app secure.

Title: Firestore Read - Rule for Webapp

Body:
I'm using Firestore for the data of my webapp. Therefore read needs to be possible for everyone visiting my webapp.

Preferably I want to restrict read to the domain but I guess this is not possible. Therefore I just let it open for everyone. However Google reminds me every day that my firebase roles are insecure.

What is best practice to do that? do I need to use cloud functions as a middle layer?

This is my rule:

service cloud.firestore {
  match /databases/{database}/documents {
   match /{document=**} {
    allow read;
    allow write: if request.auth != null;
   }
 }
}

Body:
What you have now is using a global wildcard to match all documents the entire database.  The best practice is to call out each collection you want to provide access to.  The global wildcard is risky because it's too easy to use it to accidentally allow access to everything unintentionally.

The first think you should do is remove the global wildcard completely.  The next thing is to write specific rules for each collection where clients should have access.  For example to give read-only access to "collection1":

   match /collection1/{id} {
    allow read;
   }

And to give read and write access only to signed in users:

   match /collection1/{id} {
    allow read, write: if request.auth != null;
   }

These rules are not necessarily going to make your app "secure".  They are just starting points.  You should assess the security requirements for your app and write specific rules that implement those requirements.  Only you know your specific requirements.  There are not really universal rules that can make any app secure.


问:
What is the best practice for associations and view restrictions?
I'm working on a rails app to teach myself associations. Its an app with Tutors and Students where Tutors create Students as Users and can then Tutors create "posts" for what was taught in that lesson to the specific Students page to show their progress. When the Student logs in they can only see their assigned progress and do nothing else.

I figured an option is having Students as "categories" so the Students can be filtered but what is the best practice?

It seems simple but I keep overthinking it

答:
Generally you want to create the associations as you need them in your code later. So if a tutor has many students and many posts and a student has many posts and belongs to a tutor and so on.

In order to restrict it in the view, you can restrict that in the controller. So this is where you can filter the posts by the students then. So you could do student.posts (Beware, I am not super sure what your db structure/schema looks like).

And there are gems that handle authorization. Look at pundit (my favorite) or cancancan. With those you can specifiy for each controller action, who can see/do certain things.

Now judging from the little information you gave, you might also want to look into namespaced controllers because you probably have a posts#index for tutors and another one for students. Here you can get another layer of organisation by adding a so called namespace meaning you can have one posts controller under tutors and one under students. You can find more info here: https://guides.rubyonrails.org/routing.html#controller-namespaces-and-routing

Let me know if anything is unclear!


问:
How can I combine jquery selectors?
I have a jquery object that is an array of different tab links: var $links = $('.tab-link');

I can use this with .click like so: $links.click().

How can I combine this with another selector, like $('.btn-next')?

$('.btn-next '+ $links).click() and $('.btn-next', $links).click() both result in:

Uncaught Error: Syntax error, unrecognized expression: .btn-next [object Object]

答:
You can try it with filter() to attach the click() event to all elements that have the classes tab-link and btn-next:

```<code> $links.filter(".btn-next").click(function(){});
</code>```

And in case you want to attach the click() event to separate elements with the class tab-links or btn-next, it's

```<code> $($links, ".btn-next").click(function(){});
</code>```

Title: How can I combine jquery selectors?

Body:
You can try it with filter() to attach the click() event to all elements that have the classes tab-link and btn-next:

 $links.filter(".btn-next").click(function(){});

And in case you want to attach the click() event to separate elements with the class tab-links or btn-next, it's

 $($links, ".btn-next").click(function(){});


问:
performance issue on left join with subquery to find out the latest date
```<code>SELECT m.*, pc.call_date
                    FROM messages m
                    LEFT JOIN customers c ON m.device_user_id = c.device_user_id
                    LEFT JOIN phone_call pc ON pc.id = (
                        SELECT MAX(pc2.id)
                        FROM phone_call pc2
                        WHERE pc2.device_user_id = c.device_user_id OR pc2.customer_id = c.customer_id
                    )
</code>```

The issue with the above is the left join phone_call table to find out the latest phone call made for each record. phone_call table has GBs of data. With left join phone_call, it takes more than 30 secs to return data. without it less than a sec. so that table is the issue. is there a better way to achieve the same result as the above query?

答:
The way you phrased the query looks good to me for MySQL 5.7. But the OR in the subquery is a performance killer.

I would recommend the following index, so the correlated subquery executed quickly:

```<code>phone_call(device_user_id, customer_id, id)
</code>```

You might try and switch the first two columns in the index to see if one version or another has better effect.

Another thing you could try is change the subquery to use a sort and a row limiting clause rather than aggregation (with the same above index in place). There is guarantee it will improve things, but it is worth trying:

```<code>LEFT JOIN phone_call pc ON pc.id = (
    SELECT pc2.id
    FROM phone_call pc2
    WHERE
        pc2.device_user_id = c.device_user_id
        OR pc2.customer_id = c.customer_id
    ORDER BY pc2.id
    LIMIT 1
)
</code>```

Finally, another idea is to split the subquery into two to  avoid the OR:

```<code>LEFT JOIN phone_call pc ON pc.id = (
    SELECT MAX(id)
    FROM (
        SELECT MAX(pc2.id)
        FROM phone_call pc2
        WHERE pc2.device_user_id = c.device_user_id
        UNION ALL
        SELECT MAX(pc3.id)
        FROM phone_call pc3
        WHERE pc3.customer_id = c.customer_id
    ) t
)
</code>```

Or without intermediate aggregation:

```<code>LEFT JOIN phone_call pc ON pc.id = (
    SELECT MAX(id)
    FROM (
        SELECT pc2.id
        FROM phone_call pc2
        WHERE pc2.device_user_id = c.device_user_id
        UNION ALL
        SELECT pc3.id
        FROM phone_call pc3
        WHERE pc3.customer_id = c.customer_id
    ) t
)
</code>```

For the last two queries, you would need two indexes:

```<code>phone_call(device_user_id, id)
phone_call(customer_id, id)
</code>```

EDIT

The above solutions using union all require MySQL 8.0 - in earlier versions, they fail because the subqueries are too deeply nested to reference columns from the outer query. So, another alternative is IN:

```<code>LEFT JOIN phone_call pc ON pc.id IN (
    SELECT pc2.id
    FROM phone_call pc2
    WHERE pc2.device_user_id = c.device_user_id
    UNION ALL
    SELECT pc3.id
    FROM phone_call pc3
    WHERE pc3.customer_id = c.customer_id
)
</code>```

This can also be phase with EXISTS - which I like better, because the predicates explicitly match the indexes definition, so it should be an easy decision for MySQL to use them:

```<code>LEFT JOIN phone_call pc ON EXISTS (
    SELECT 1
    FROM phone_call pc2
    WHERE pc2.device_user_id = c.device_user_id AND pc2.id = pc.id
    UNION ALL
    SELECT 1
    FROM phone_call pc3
    WHERE pc3.customer_id = c.customer_id AND pc3.id = pc.id
)
</code>```

Again, this works under the assumption that you have the two following, multicolumn indexes:

```<code>phone_call(device_user_id, id)
phone_call(customer_id, id)
</code>```

You can create the indexes as follow:

```<code>create index idx_phone_call_device_user on phone_call(device_user_id, id);
create index idx_phone_call_customer    on phone_call(customer_id, id);
</code>```

Body:
SELECT m.*, pc.call_date
                    FROM messages m
                    LEFT JOIN customers c ON m.device_user_id = c.device_user_id
                    LEFT JOIN phone_call pc ON pc.id = (
                        SELECT MAX(pc2.id)
                        FROM phone_call pc2
                        WHERE pc2.device_user_id = c.device_user_id OR pc2.customer_id = c.customer_id
                    )

The issue with the above is the left join phone_call table to find out the latest phone call made for each record. phone_call table has GBs of data. With left join phone_call, it takes more than 30 secs to return data. without it less than a sec. so that table is the issue. is there a better way to achieve the same result as the above query?

Body:
The way you phrased the query looks good to me for MySQL 5.7. But the OR in the subquery is a performance killer.

I would recommend the following index, so the correlated subquery executed quickly:

phone_call(device_user_id, customer_id, id)

You might try and switch the first two columns in the index to see if one version or another has better effect.

Another thing you could try is change the subquery to use a sort and a row limiting clause rather than aggregation (with the same above index in place). There is guarantee it will improve things, but it is worth trying:

LEFT JOIN phone_call pc ON pc.id = (
    SELECT pc2.id
    FROM phone_call pc2
    WHERE
        pc2.device_user_id = c.device_user_id
        OR pc2.customer_id = c.customer_id
    ORDER BY pc2.id
    LIMIT 1
)

Finally, another idea is to split the subquery into two to  avoid the OR:

LEFT JOIN phone_call pc ON pc.id = (
    SELECT MAX(id)
    FROM (
        SELECT MAX(pc2.id)
        FROM phone_call pc2
        WHERE pc2.device_user_id = c.device_user_id
        UNION ALL
        SELECT MAX(pc3.id)
        FROM phone_call pc3
        WHERE pc3.customer_id = c.customer_id
    ) t
)

Or without intermediate aggregation:

LEFT JOIN phone_call pc ON pc.id = (
    SELECT MAX(id)
    FROM (
        SELECT pc2.id
        FROM phone_call pc2
        WHERE pc2.device_user_id = c.device_user_id
        UNION ALL
        SELECT pc3.id
        FROM phone_call pc3
        WHERE pc3.customer_id = c.customer_id
    ) t
)

For the last two queries, you would need two indexes:

phone_call(device_user_id, id)
phone_call(customer_id, id)

EDIT

The above solutions using union all require MySQL 8.0 - in earlier versions, they fail because the subqueries are too deeply nested to reference columns from the outer query. So, another alternative is IN:

LEFT JOIN phone_call pc ON pc.id IN (
    SELECT pc2.id
    FROM phone_call pc2
    WHERE pc2.device_user_id = c.device_user_id
    UNION ALL
    SELECT pc3.id
    FROM phone_call pc3
    WHERE pc3.customer_id = c.customer_id
)

This can also be phase with EXISTS - which I like better, because the predicates explicitly match the indexes definition, so it should be an easy decision for MySQL to use them:

LEFT JOIN phone_call pc ON EXISTS (
    SELECT 1
    FROM phone_call pc2
    WHERE pc2.device_user_id = c.device_user_id AND pc2.id = pc.id
    UNION ALL
    SELECT 1
    FROM phone_call pc3
    WHERE pc3.customer_id = c.customer_id AND pc3.id = pc.id
)

Again, this works under the assumption that you have the two following, multicolumn indexes:

phone_call(device_user_id, id)
phone_call(customer_id, id)

You can create the indexes as follow:

create index idx_phone_call_device_user on phone_call(device_user_id, id);
create index idx_phone_call_customer    on phone_call(customer_id, id);


问:
Is there a way to dynamically create XSL file based on XSD file
I have a project where I need to convert a XML file to CSV file and vice versa. I can't use a single XSL file because, there are different XML and CSV formats. So, I am just wondering if there is any way (any tool or editors or any APIs) to create XSL file based on XSD file.

I am also open to any other suggestions too (I believe I can't avoid XSL because in the future I might be asked to convert to different formats such as pdf, html etc)

答: Answer is - YES. It can be done. If you look at Eclipse there is a function which generates sample XML based on XSD. So it will be possible to make own XSTL transformation for XSD to obtain another XSLT - but this time based on source XSD. I won't be easy but it is achievable.</p>


问:
React Native: is it possible to stop PanResponder event inside onPanResponderMove?
I want to add limitations on how far by Y axis can View be dragged inside other View.
My onPanResponderMove looks something like this:

onPanResponderMove: (evt: any, gestureEvent: any) => {
  if (y >= 0 && y <= backgroundHeight - 40) {
    Animated.event([null, { dx: pan.x, dy: pan.y }], { useNativeDriver: false })(evt, gestureEvent);
  } else if (y < 0) {
    pan.setValue({ x: pan.x._value, y: 0 });
  } else {
    pan.setValue({ x: pan.x._value, y: backgroundHeight - 40 });
  }
}
```

So now inner View still draggs when its scrolled further limitations and goes back (looks like it's shaking). And I want drag stop on hitting these limitations and don't know how.

If there is another better solution, that can be implemented, I'd much appreciate your help :)

答:
Did you manage to get it working the way you want ?
I came across your question to achieve the same, and managed to do so just with :

onPanResponderMove: (e, gs) => {
        if (gs.moveY < yOffset) {
          Animated.event([null, {dx: 0, dy: pan.y}], {
            useNativeDriver: false,
          })(e, gs);
        }
      },
```

So no else after and my image stays while finger is outbound (2D for me, but looks like it's the same ?).
Otherwise you are still setting pan values, so View is still asking to move isn't it ?

Body:
I want to add limitations on how far by Y axis can View be dragged inside other View.
My onPanResponderMove looks something like this:

onPanResponderMove: (evt: any, gestureEvent: any) => {
  if (y >= 0 && y <= backgroundHeight - 40) {
    Animated.event([null, { dx: pan.x, dy: pan.y }], { useNativeDriver: false })(evt, gestureEvent);
  } else if (y < 0) {
    pan.setValue({ x: pan.x._value, y: 0 });
  } else {
    pan.setValue({ x: pan.x._value, y: backgroundHeight - 40 });
  }
}

So now inner View still draggs when its scrolled further limitations and goes back (looks like it's shaking). And I want drag stop on hitting these limitations and don't know how.

If there is another better solution, that can be implemented, I'd much appreciate your help :)

Body:
Did you manage to get it working the way you want ?
I came across your question to achieve the same, and managed to do so just with :

onPanResponderMove: (e, gs) => {
        if (gs.moveY < yOffset) {
          Animated.event([null, {dx: 0, dy: pan.y}], {
            useNativeDriver: false,
          })(e, gs);
        }
      },

So no else after and my image stays while finger is outbound (2D for me, but looks like it's the same ?).
Otherwise you are still setting pan values, so View is still asking to move isn't it ?


问:
How do I make a function work in a derived class?
So this is my code. It has an abstact class named PC and 3 derived classes named HomePC, GamingPC and WorkStationPC. It has to do 4 things: 1)Create new pc of whatever type, 2)Upgrade a pc that already exists, 3)Delete a pc that already exists and 4)Print all pcs of a certain type. I managed to make the "new" and "print" functions work. I can't figure out how to make the "upgrade" and "delete" functions work. I suppose they will be similar. If someone has an idea of how I can do it please let me know.

Thank you!

```<code>#include <iostream>
#include <string>
#include <vector>

using namespace std;

class PC{
protected:
    string operatingSystem;
    int ramSlots;
    int pcieSlots;
    int cpu;
    int totalRamSlots;
    int gbPerRam;
    int ssd;
    int cost;
public:
    virtual void Print() = 0;
    virtual void Upgrade(string opt) = 0;

    PC(string OS, int moboRam, int moboPcie, int numOfCores, int ramSlots, int ramGB, int ssdGB, int pcCost){
        operatingSystem = OS;
        ramSlots = moboRam;
        pcieSlots = moboPcie;
        cpu = numOfCores;
        totalRamSlots = ramSlots;
        gbPerRam = ramGB;
        ssd = ssdGB;
        cost = pcCost;
    }
};

class HomePC: public PC{
private:
    string model;
public:
    HomePC(string OS, int moboRam, int moboPcie, int numOfCores, int ramSlot, int ramGB, int ssdGB, int pcCost, string mdl):PC(OS, moboRam, moboPcie, numOfCores, ramSlot, ramGB, ssdGB, pcCost){
        model = mdl;
    }

    void set_totalRamSlots(int ramSlots){totalRamSlots = ramSlots;}
    void set_gbPerRam(int ramGB){gbPerRam = ramGB;}
    void set_cpu(int numOfCores){cpu = numOfCores;}

    //delete spaces

    void Print(){ cout << "Μodel: " << model << endl << "Operating System: MacOS" <<endl << "Motherboard: 2 RAM slot(s), 0 GPU slot(s)" << endl << "CPU: " << cpu << endl << "RAM: " << totalRamSlots << " stick(s), " << gbPerRam << " GigaBytes" << endl << "SSD: 256" << endl << "Cost: 800EUR" << endl;}
    void Upgrade(string opt){ cout << opt << endl;}

    //delete spaces

    string get_model() const {return model;}
};

class GamingPC: public PC{
private:
    string model;
    int gpu;
public:
    GamingPC(string OS, int moboRam, int moboPcie, int numOfCores, int ramSlot, int ramGB, int ssdGB, int pcCost, int numOfGpus, string mdl):PC(OS, moboRam, moboPcie, numOfCores, ramSlot, ramGB, ssdGB, pcCost){
        model = mdl;
        gpu = numOfGpus;
    }

    //delete spaces

    void set_totalRamSlots(int ramSlots){totalRamSlots = ramSlots;}
    void set_gbPerRam(int ramGB){gbPerRam = ramGB;}
    void set_cpu(int numOfCores){cpu = numOfCores;}
    void set_gpu(int numOfGpus){gpu = numOfGpus;}

    //delete spaces

    void Print(){ cout << "Μodel: " << model << endl << "Operating System: MacOS" << endl << "Motherboard: 4 RAM slot(s), 2 GPU slot(s)" << endl << "CPU: " << cpu << endl << "RAM: "<< totalRamSlots << " stick(s), " << gbPerRam << " GigaBytes" << endl << "SSD: 256" << endl << "GPU: " << gpu << endl << "Cost: 1300EUR" << endl;}
    void Upgrade(string opt){ cout << opt << endl;}

    //delete spaces

    string get_model() const {return model;}
};

class WorkStationPC: public PC{
private:
    string model;
    int gpu;
    bool afterburner;
public:
    WorkStationPC(string OS, int moboRam, int moboPcie, int numOfCores, int ramSlot, int ramGB, int ssdGB, int pcCost, int numOfGpus, bool aburner, string mdl):PC(OS, moboRam, moboPcie, numOfCores, ramSlot, ramGB, ssdGB, pcCost){
        model = mdl;
        gpu = numOfGpus;
        afterburner = aburner;
    }

    //delete spaces

    void set_totalRamSlots(int ramSlots){totalRamSlots = ramSlots;}
    void set_gbPerRam(int ramGB){gbPerRam = ramGB;}
    void set_cpu(int numOfCores){cpu = numOfCores;}
    void set_gpu(int numOfGpus){gpu = numOfGpus;}
    void set_afterburner(int aburner){afterburner = aburner;}

    //delete spaces

    void Print(){ cout << "Μodel: " << model << endl << "Operating System: MacOS" << endl << "Motherboard: 8 RAM slot(s), 1 GPU slot(s)" << endl << "CPU: " << cpu << endl << "RAM: " << totalRamSlots << " stick(s), " << gbPerRam << " GigaBytes" << endl << "SSD: 256" << endl << "GPU: " << gpu << endl << "Afterburner: " << afterburner << endl << "Cost: 1600EUR" << endl;}
    void Upgrade(string opt){ cout << opt << endl;}

    //delete spaces

    string get_model() const {return model;}
};

int main(){
    vector<int> count_homepc;
    vector<int> count_gamingpc;
    vector<int> count_workstationpc;
    int i, k = 0;
    string input, opCode, key=" ", pcType, pcModel, data[5];
    size_t pos = 0;
    vector<PC*> pcList;
    do{
        cout << "---Enter an operation:" << endl;
        getline(cin,input);
        pos=input.find(key);
        opCode=input.substr(0,pos);
        input.erase(0,pos + 1);
        if(opCode=="new"){
            pos=input.find(key);
            pcType=input.substr(0,pos);
            input.erase(0,pos + 1);
            pcModel=input;
            if(pcType=="homepc"){
                HomePC* myPC = new HomePC("MacOS", 2, 0, 2, 1, 4, 256, 800, pcModel);
                pcList.push_back(myPC);
                count_homepc.push_back(k);
            }else if(pcType=="gamingpc"){
                GamingPC* myPC = new GamingPC("Windows", 4, 2, 6, 2, 8, 1024, 1300, 1, pcModel);
                pcList.push_back(myPC);
                count_gamingpc.push_back(k);
            }else if(pcType=="workstationpc"){
                WorkStationPC* myPC = new WorkStationPC("Linux", 8, 1, 6, 4, 16, 2048, 1600, 0, 0, pcModel);
                pcList.push_back(myPC);
                count_workstationpc.push_back(k);
            }else cout << "Wrong PC type, try again." << endl;
        }else if(opCode=="upgrade"){
            pos=input.find(key);
            pcModel=input.substr(0,pos);
            input.erase(0,pos + 1);
            cout << input << endl;
        }else if(opCode=="delete"){
            cout << "WIP" << endl;
        }else if(opCode=="print"){
            cout << endl;
            int point;
            if(input=="homepc"){
                for(i=0;i<count_homepc.size();i++){
                    point = count_homepc[i];
                    pcList[point]->Print();
                    cout << endl;
                }
            }else if(input=="gamingpc"){
                for(i=0;i<count_gamingpc.size();i++){
                    point = count_gamingpc[i];
                    pcList[point]->Print();
                    cout << endl;
                }
            }else if(input=="workstationpc"){
                for(i=0;i<count_workstationpc.size();i++){
                    point = count_workstationpc[i];
                    pcList[point]->Print();
                    cout << endl;
                }
            }
        }else if(opCode!="q") cout << "Wrong operation, try again." << endl;
        k++;
    }while(opCode!="q"); //when someone inputs the string "q" the loop ends
    return 0;
}
</code>```

答:
Delete

Seems like u keep the name of the pc in a member called model. First thing to do is to remove it from all the 3 derived classes and put it in the base PC class. This is where it belongs. Every pc must have a name. U have 4 things to do:

read PC name

search for it in vector

actually delete the PC

erase the PC pointer from the vector

// "name" is the name of target "PC"
for(auto i = 0; i < pcList.size(); i++)
    if(pcList[i]->model == name) {
        delete pcList[i];
        pcList.erase(pcList.begin() + i);
        break;
    }
```

<p>U could set up a <code>auto found = false</code> and set it to true when the <code>PC</code> was found, so u know if there was actually a <code>PC</code> with that name</p>

<h1>Upgrade</h1>

<p>This one is a bit more complex as u have to pass multiple stuff. One way to achieve this is just to take one part at a time by setting a loop. Everytime u're in the loop u can select which part u wanna upgrade, or to exit. This would look like:</p>

<pre class="lang-cpp prettyprint-override"><code>std::cin >> pc; // Pos in vector
while(true) {
    // 1: upgrade cpu
    // 2: upgrade ram
    // ...
    // 0: finish
    int option;
    std::cin >> option;
    if(option == cpu) { // "cpu" should be a constant. In this case is integer "1"
        int cpu; // The new cpu goes here
        std::cin >> cpu;
        pcList[pc]->cpu = cpu;
        // pcList[pc]->upgradeCpu(cpu); // If u wanna do it OOP. Same as the line before
        // I see u have "set_cpu()" and more fcts for that. Use them
    }
    // Repeat here for every upgradable part of a pc
    else if(option == exit)
        break;
}
</code>```

Body:
So this is my code. It has an abstact class named PC and 3 derived classes named HomePC, GamingPC and WorkStationPC. It has to do 4 things: 1)Create new pc of whatever type, 2)Upgrade a pc that already exists, 3)Delete a pc that already exists and 4)Print all pcs of a certain type. I managed to make the "new" and "print" functions work. I can't figure out how to make the "upgrade" and "delete" functions work. I suppose they will be similar. If someone has an idea of how I can do it please let me know.

Thank you!

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class PC{
protected:
    string operatingSystem;
    int ramSlots;
    int pcieSlots;
    int cpu;
    int totalRamSlots;
    int gbPerRam;
    int ssd;
    int cost;
public:
    virtual void Print() = 0;
    virtual void Upgrade(string opt) = 0;

    PC(string OS, int moboRam, int moboPcie, int numOfCores, int ramSlots, int ramGB, int ssdGB, int pcCost){
        operatingSystem = OS;
        ramSlots = moboRam;
        pcieSlots = moboPcie;
        cpu = numOfCores;
        totalRamSlots = ramSlots;
        gbPerRam = ramGB;
        ssd = ssdGB;
        cost = pcCost;
    }
};

class HomePC: public PC{
private:
    string model;
public:
    HomePC(string OS, int moboRam, int moboPcie, int numOfCores, int ramSlot, int ramGB, int ssdGB, int pcCost, string mdl):PC(OS, moboRam, moboPcie, numOfCores, ramSlot, ramGB, ssdGB, pcCost){
        model = mdl;
    }

    void set_totalRamSlots(int ramSlots){totalRamSlots = ramSlots;}
    void set_gbPerRam(int ramGB){gbPerRam = ramGB;}
    void set_cpu(int numOfCores){cpu = numOfCores;}

    //delete spaces

    void Print(){ cout << "Μodel: " << model << endl << "Operating System: MacOS" <<endl << "Motherboard: 2 RAM slot(s), 0 GPU slot(s)" << endl << "CPU: " << cpu << endl << "RAM: " << totalRamSlots << " stick(s), " << gbPerRam << " GigaBytes" << endl << "SSD: 256" << endl << "Cost: 800EUR" << endl;}
    void Upgrade(string opt){ cout << opt << endl;}

    //delete spaces

    string get_model() const {return model;}
};

class GamingPC: public PC{
private:
    string model;
    int gpu;
public:
    GamingPC(string OS, int moboRam, int moboPcie, int numOfCores, int ramSlot, int ramGB, int ssdGB, int pcCost, int numOfGpus, string mdl):PC(OS, moboRam, moboPcie, numOfCores, ramSlot, ramGB, ssdGB, pcCost){
        model = mdl;
        gpu = numOfGpus;
    }

    //delete spaces

    void set_totalRamSlots(int ramSlots){totalRamSlots = ramSlots;}
    void set_gbPerRam(int ramGB){gbPerRam = ramGB;}
    void set_cpu(int numOfCores){cpu = numOfCores;}
    void set_gpu(int numOfGpus){gpu = numOfGpus;}

    //delete spaces

    void Print(){ cout << "Μodel: " << model << endl << "Operating System: MacOS" << endl << "Motherboard: 4 RAM slot(s), 2 GPU slot(s)" << endl << "CPU: " << cpu << endl << "RAM: "<< totalRamSlots << " stick(s), " << gbPerRam << " GigaBytes" << endl << "SSD: 256" << endl << "GPU: " << gpu << endl << "Cost: 1300EUR" << endl;}
    void Upgrade(string opt){ cout << opt << endl;}

    //delete spaces

    string get_model() const {return model;}
};

class WorkStationPC: public PC{
private:
    string model;
    int gpu;
    bool afterburner;
public:
    WorkStationPC(string OS, int moboRam, int moboPcie, int numOfCores, int ramSlot, int ramGB, int ssdGB, int pcCost, int numOfGpus, bool aburner, string mdl):PC(OS, moboRam, moboPcie, numOfCores, ramSlot, ramGB, ssdGB, pcCost){
        model = mdl;
        gpu = numOfGpus;
        afterburner = aburner;
    }

    //delete spaces

    void set_totalRamSlots(int ramSlots){totalRamSlots = ramSlots;}
    void set_gbPerRam(int ramGB){gbPerRam = ramGB;}
    void set_cpu(int numOfCores){cpu = numOfCores;}
    void set_gpu(int numOfGpus){gpu = numOfGpus;}
    void set_afterburner(int aburner){afterburner = aburner;}

    //delete spaces

    void Print(){ cout << "Μodel: " << model << endl << "Operating System: MacOS" << endl << "Motherboard: 8 RAM slot(s), 1 GPU slot(s)" << endl << "CPU: " << cpu << endl << "RAM: " << totalRamSlots << " stick(s), " << gbPerRam << " GigaBytes" << endl << "SSD: 256" << endl << "GPU: " << gpu << endl << "Afterburner: " << afterburner << endl << "Cost: 1600EUR" << endl;}
    void Upgrade(string opt){ cout << opt << endl;}

    //delete spaces

    string get_model() const {return model;}
};

int main(){
    vector<int> count_homepc;
    vector<int> count_gamingpc;
    vector<int> count_workstationpc;
    int i, k = 0;
    string input, opCode, key=" ", pcType, pcModel, data[5];
    size_t pos = 0;
    vector<PC*> pcList;
    do{
        cout << "---Enter an operation:" << endl;
        getline(cin,input);
        pos=input.find(key);
        opCode=input.substr(0,pos);
        input.erase(0,pos + 1);
        if(opCode=="new"){
            pos=input.find(key);
            pcType=input.substr(0,pos);
            input.erase(0,pos + 1);
            pcModel=input;
            if(pcType=="homepc"){
                HomePC* myPC = new HomePC("MacOS", 2, 0, 2, 1, 4, 256, 800, pcModel);
                pcList.push_back(myPC);
                count_homepc.push_back(k);
            }else if(pcType=="gamingpc"){
                GamingPC* myPC = new GamingPC("Windows", 4, 2, 6, 2, 8, 1024, 1300, 1, pcModel);
                pcList.push_back(myPC);
                count_gamingpc.push_back(k);
            }else if(pcType=="workstationpc"){
                WorkStationPC* myPC = new WorkStationPC("Linux", 8, 1, 6, 4, 16, 2048, 1600, 0, 0, pcModel);
                pcList.push_back(myPC);
                count_workstationpc.push_back(k);
            }else cout << "Wrong PC type, try again." << endl;
        }else if(opCode=="upgrade"){
            pos=input.find(key);
            pcModel=input.substr(0,pos);
            input.erase(0,pos + 1);
            cout << input << endl;
        }else if(opCode=="delete"){
            cout << "WIP" << endl;
        }else if(opCode=="print"){
            cout << endl;
            int point;
            if(input=="homepc"){
                for(i=0;i<count_homepc.size();i++){
                    point = count_homepc[i];
                    pcList[point]->Print();
                    cout << endl;
                }
            }else if(input=="gamingpc"){
                for(i=0;i<count_gamingpc.size();i++){
                    point = count_gamingpc[i];
                    pcList[point]->Print();
                    cout << endl;
                }
            }else if(input=="workstationpc"){
                for(i=0;i<count_workstationpc.size();i++){
                    point = count_workstationpc[i];
                    pcList[point]->Print();
                    cout << endl;
                }
            }
        }else if(opCode!="q") cout << "Wrong operation, try again." << endl;
        k++;
    }while(opCode!="q"); //when someone inputs the string "q" the loop ends
    return 0;
}

Body:
Delete

Seems like u keep the name of the pc in a member called model. First thing to do is to remove it from all the 3 derived classes and put it in the base PC class. This is where it belongs. Every pc must have a name. U have 4 things to do:

read PC name

search for it in vector

actually delete the PC

erase the PC pointer from the vector

// "name" is the name of target "PC"
for(auto i = 0; i < pcList.size(); i++)
    if(pcList[i]->model == name) {
        delete pcList[i];
        pcList.erase(pcList.begin() + i);
        break;
    }

U could set up a auto found = false and set it to true when the PC was found, so u know if there was actually a PC with that name

Upgrade

This one is a bit more complex as u have to pass multiple stuff. One way to achieve this is just to take one part at a time by setting a loop. Everytime u're in the loop u can select which part u wanna upgrade, or to exit. This would look like:

std::cin >> pc; // Pos in vector
while(true) {
    // 1: upgrade cpu
    // 2: upgrade ram
    // ...
    // 0: finish
    int option;
    std::cin >> option;
    if(option == cpu) { // "cpu" should be a constant. In this case is integer "1"
        int cpu; // The new cpu goes here
        std::cin >> cpu;
        pcList[pc]->cpu = cpu;
        // pcList[pc]->upgradeCpu(cpu); // If u wanna do it OOP. Same as the line before
        // I see u have "set_cpu()" and more fcts for that. Use them
    }
    // Repeat here for every upgradable part of a pc
    else if(option == exit)
        break;
}


问:
Auto redirect in old paypal integration
I have an old integration where payment values are posted to https://www.paypal.com/cgi-bin/webscr
I want to change paypal account to a new one, so I changed "old email" to new one in <input type="hidden" name="business" value="old email" />
Payment works, but it's not redirected to page in my server after payment.

Can I specify a redirect url in post values? Adding <input type="hidden" name="return" value="my redirect url" /> only showed "Return to Merchant" button after payment, didn't automatically redirect to "my redirect url"

Where can I find the new identity token in my new paypal account? identity token is used in call back page,

```<code>    function get_call_back_vars($tx_token, $identity_token, $sand_box = false)
    { }
</code>```

In the documentation of the above PHP function it says,
$identity_token - Identity token generated for you from Paypal (can be found at Web Reference Profile page) but couldn't find "Web Reference Profile"  page

Thanks

答:
The return will not and cannot be automatic. In most jurisdictions a receipt has to be displayed. Changing accounts did not change this behavior; unregistered buyers must click to return.

The website payment preferences page is in your account settings. Here is a direct link to it: https://www.paypal.com/businessmanage/preferences/website

PDT is the second section.

Title: Auto redirect in old paypal integration

Body:
I have an old integration where payment values are posted to https://www.paypal.com/cgi-bin/webscr
I want to change paypal account to a new one, so I changed "old email" to new one in <input type="hidden" name="business" value="old email" />
Payment works, but it's not redirected to page in my server after payment.

Can I specify a redirect url in post values? Adding <input type="hidden" name="return" value="my redirect url" /> only showed "Return to Merchant" button after payment, didn't automatically redirect to "my redirect url"

Where can I find the new identity token in my new paypal account? identity token is used in call back page,

    function get_call_back_vars($tx_token, $identity_token, $sand_box = false)
    { }

In the documentation of the above PHP function it says,
$identity_token - Identity token generated for you from Paypal (can be found at Web Reference Profile page) but couldn't find "Web Reference Profile"  page

Thanks


问:
Wrong Route in RouteGroup Laravel 7
I defined some RoteGroup in api.php

```<code>Route::group(['prefix' => 'galleries'], function () {
    Route::get('/', 'GalleriesController@index');
    Route::get('/{id}', 'GalleriesController@show');
    Route::post('/', 'GalleriesController@store');
    Route::post('/{id}', 'GalleriesController@update');
    Route::delete('/{id}', 'GalleriesController@delete');
});

Route::group(['prefex'=>'files'],function(){
    Route::get('/', 'FilesController@index');
    Route::get('/{id}', 'FilesController@show');
    Route::post('/', 'FilesController@store');
    Route::delete('/{id}', 'FilesController@delete');
});

Route::group(['prefix' => 'brands'], function () {
    Route::get('/', 'BrandsController@index');
    Route::get('/{id}', 'BrandsController@show');
    Route::post('/', 'BrandsController@store');
    Route::post('/{id}', 'BrandsController@update');
    Route::delete('/{id}', 'BrandsController@delete');
});
</code>```

when I call /api/brands Laravel itself calls /api/files/{id} and passes brands as id parameter. I cleared route cache and application cache but it doesn't works.

my route:list command is as follow:

```<code>    +--------+----------+--------------------+-----------------------------+-------------------------------------------------+------------+
| Domain | Method   | URI                | Name                        | Action                                          | Middleware |
+--------+----------+--------------------+-----------------------------+-------------------------------------------------+------------+
|        | GET|HEAD | api                | generated::t71BZCrrwrUEipSw | App\Http\Controllers\FilesController@index      | api        |
|        | POST     | api                | generated::aShgozBu0aAJb5Oh | App\Http\Controllers\FilesController@store      | api        |
|        | GET|HEAD | api/brands         | generated::3aUm0HLF9QQRczyA | App\Http\Controllers\BrandsController@index     | api        |
|        | POST     | api/brands         | generated::V58YTIOhzv62STxe | App\Http\Controllers\BrandsController@store     | api        |
|        | GET|HEAD | api/brands/{id}    | generated::SuOaq2tKeDBAWcKH | App\Http\Controllers\BrandsController@show      | api        |
|        | POST     | api/brands/{id}    | generated::Ij9a3h9rjPTJtrl6 | App\Http\Controllers\BrandsController@update    | api        |
|        | DELETE   | api/brands/{id}    | generated::h9fZYI1jripojkLm | App\Http\Controllers\BrandsController@delete    | api        |
|        | GET|HEAD | api/galleries      | generated::UGeFE22cHyQVcjCS | App\Http\Controllers\GalleriesController@index  | api        |
|        | POST     | api/galleries      | generated::oKqS94qAO9isKmCs | App\Http\Controllers\GalleriesController@store  | api        |
|        | GET|HEAD | api/galleries/{id} | generated::mtUddNdRZr9olMHb | App\Http\Controllers\GalleriesController@show   | api        |
|        | POST     | api/galleries/{id} | generated::DD3hLUdSswKYlXse | App\Http\Controllers\GalleriesController@update | api        |
|        | DELETE   | api/galleries/{id} | generated::QTxRv04TlN24QgWO | App\Http\Controllers\GalleriesController@delete | api        |
|        | GET|HEAD | api/{id}           | generated::kt66p66Ao0pBlENo | App\Http\Controllers\FilesController@show       | api        |
|        | DELETE   | api/{id}           | generated::9C7SNWSa1JbTtS1p | App\Http\Controllers\FilesController@delete     | api        |
+--------+----------+--------------------+-----------------------------+-------------------------------------------------+------------+
</code>```

How can I fix that?

答:
There is a typo in your route definitions. Here:

```<code>Route::group(['prefex'=>'files'],function(){
 [...]
});
</code>```

Change it from 'prefex' to 'prefix':

```<code>Route::group(['prefix'=>'files'],function(){
 [...]
});
</code>```

Title: Wrong Route in RouteGroup Laravel 7

Body:
I defined some RoteGroup in api.php

Route::group(['prefix' => 'galleries'], function () {
    Route::get('/', 'GalleriesController@index');
    Route::get('/{id}', 'GalleriesController@show');
    Route::post('/', 'GalleriesController@store');
    Route::post('/{id}', 'GalleriesController@update');
    Route::delete('/{id}', 'GalleriesController@delete');
});

Route::group(['prefex'=>'files'],function(){
    Route::get('/', 'FilesController@index');
    Route::get('/{id}', 'FilesController@show');
    Route::post('/', 'FilesController@store');
    Route::delete('/{id}', 'FilesController@delete');
});

Route::group(['prefix' => 'brands'], function () {
    Route::get('/', 'BrandsController@index');
    Route::get('/{id}', 'BrandsController@show');
    Route::post('/', 'BrandsController@store');
    Route::post('/{id}', 'BrandsController@update');
    Route::delete('/{id}', 'BrandsController@delete');
});

when I call /api/brands Laravel itself calls /api/files/{id} and passes brands as id parameter. I cleared route cache and application cache but it doesn't works.

my route:list command is as follow:

    +--------+----------+--------------------+-----------------------------+-------------------------------------------------+------------+
| Domain | Method   | URI                | Name                        | Action                                          | Middleware |
+--------+----------+--------------------+-----------------------------+-------------------------------------------------+------------+
|        | GET|HEAD | api                | generated::t71BZCrrwrUEipSw | App\Http\Controllers\FilesController@index      | api        |
|        | POST     | api                | generated::aShgozBu0aAJb5Oh | App\Http\Controllers\FilesController@store      | api        |
|        | GET|HEAD | api/brands         | generated::3aUm0HLF9QQRczyA | App\Http\Controllers\BrandsController@index     | api        |
|        | POST     | api/brands         | generated::V58YTIOhzv62STxe | App\Http\Controllers\BrandsController@store     | api        |
|        | GET|HEAD | api/brands/{id}    | generated::SuOaq2tKeDBAWcKH | App\Http\Controllers\BrandsController@show      | api        |
|        | POST     | api/brands/{id}    | generated::Ij9a3h9rjPTJtrl6 | App\Http\Controllers\BrandsController@update    | api        |
|        | DELETE   | api/brands/{id}    | generated::h9fZYI1jripojkLm | App\Http\Controllers\BrandsController@delete    | api        |
|        | GET|HEAD | api/galleries      | generated::UGeFE22cHyQVcjCS | App\Http\Controllers\GalleriesController@index  | api        |
|        | POST     | api/galleries      | generated::oKqS94qAO9isKmCs | App\Http\Controllers\GalleriesController@store  | api        |
|        | GET|HEAD | api/galleries/{id} | generated::mtUddNdRZr9olMHb | App\Http\Controllers\GalleriesController@show   | api        |
|        | POST     | api/galleries/{id} | generated::DD3hLUdSswKYlXse | App\Http\Controllers\GalleriesController@update | api        |
|        | DELETE   | api/galleries/{id} | generated::QTxRv04TlN24QgWO | App\Http\Controllers\GalleriesController@delete | api        |
|        | GET|HEAD | api/{id}           | generated::kt66p66Ao0pBlENo | App\Http\Controllers\FilesController@show       | api        |
|        | DELETE   | api/{id}           | generated::9C7SNWSa1JbTtS1p | App\Http\Controllers\FilesController@delete     | api        |
+--------+----------+--------------------+-----------------------------+-------------------------------------------------+------------+

How can I fix that?

Body:
There is a typo in your route definitions. Here:

Route::group(['prefex'=>'files'],function(){
 [...]
});

Change it from 'prefex' to 'prefix':

Route::group(['prefix'=>'files'],function(){
 [...]
});


问:
Accessing a MySQL database from python
I have been trying for the past several hours to find a working method of accessing a mysql database in python. The only thing that I've managed to get to compile and install is pyodbc but the necessary driver is not available for ppc leopard.

I already know about this.

UPDATE:

I've gotten setuptools to install, but now MySQL-python won't build.

UPDATE:
Now I've gotten sqlalchemy to install but while it will show up when called by the command line it won't import when used in my cgi script.

答: Install fink. It includes the MySQLdb package.</p>

OwnerDisplayName: GameFreak

ContentLicense: CC BY-SA 2.5

Title: Accessing a MySQL database from python

LastEditorDisplayName: GameFreak

OwnerDisplayName: joeforker


问:
Getter returning null when testing get methods
I am trying to get data from my database to show on a listview. The problem I am having is it seems the getters are not working properly. When I test what they are returning, it comes back null.

Any insight would be appreciated as I am lost here. Thanks in advance.

Here is where I initialise the class:

```<code>    public ArrayList<GameStats> getAllData() {
    ArrayList<GameStats> arrayList = new ArrayList<>();
    SQLiteDatabase db = this.getReadableDatabase();

    Cursor cursor = db.rawQuery("SELECT * FROM savedGamesTable", null);

    while(cursor.moveToNext()){
        int id = cursor.getInt(0);
        String lName = cursor.getString(1);
        int lScore = cursor.getInt(2);
        String rName = cursor.getString(3);
        int rScore = cursor.getInt(4);
        String notes = cursor.getString(5);

        GameStats gameStats = new GameStats(id, lName, lScore, rName, rScore, notes);
        arrayList.add(gameStats);

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

Here is where I am trying to use the getters:

```<code>    public View getView(int position, View convertView, ViewGroup parent) {

        LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inflater.inflate(R.layout.activity_saved_games, null);
        TextView lName = convertView.findViewById(R.id.lName);
        TextView lScore = convertView.findViewById(R.id.lScore);
        TextView rName = convertView.findViewById(R.id.rName);
        TextView rScore = convertView.findViewById(R.id.rScore);
        TextView notes = convertView.findViewById(R.id.notes);

    GameStats gameStats = arrayList.get(position);
    testVar = gameStats.getlName();
    Log.d("MyAdaptor","gameStats = " + var);
    lName.setText(gameStats.getlName());
    lScore.setText(String.valueOf(gameStats.getlScore()));
    rName.setText(gameStats.getrName());
    rScore.setText(String.valueOf(gameStats.getrScore()));
    notes.setText(gameStats.getNotes());
    return convertView;
}
</code>```

Here is the model class:

```<code>public class GameStats {
int id, lScore, rScore;
String lName, rName, notes;

public GameStats(int id, String lName, int lScore, String rName, int rScore, String notes) {

}

public int getId() {
    return id;
}

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

public int getlScore() {
    return lScore;
}

public void setlScore(int lScore) {
    this.lScore = lScore;
}

public int getrScore() {
    return rScore;
}

public void setrScore(int rScore) {
    this.rScore = rScore;
}

public String getlName() {
    return lName;
}

public void setlName(String lName) {
    this.lName = lName;
}

public String getrName() {
    return rName;
}

public void setrName(String rName) {
    this.rName = rName;
}

public String getNotes() {
    return notes;
}

public void setNotes(String notes) {
    this.notes = notes;
}
</code>```

}

and here is where I am calling the methods:

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

ListView lv1;
ArrayList<GameStats> arrayList;
MyAdaptor myAdaptor;
DatabaseHelper databaseHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_saved_game_screen);
    lv1 = findViewById(R.id.lv1);
    databaseHelper = new DatabaseHelper(this);
    arrayList = new ArrayList<>();
    loadData();
}

private void loadData() {
    arrayList = databaseHelper.getAllData();
    myAdaptor = new MyAdaptor(this, arrayList);
    lv1.setAdapter(myAdaptor);
    myAdaptor.notifyDataSetChanged();
}
</code>```

}

答: In your model class initialize the variables using constrtuctor. I guess that is the problem. Since you are not initializing the model class properties, it the getters will return "null" or any garbage value</p>

Body:
I am trying to get data from my database to show on a listview. The problem I am having is it seems the getters are not working properly. When I test what they are returning, it comes back null.

Any insight would be appreciated as I am lost here. Thanks in advance.

Here is where I initialise the class:

    public ArrayList<GameStats> getAllData() {
    ArrayList<GameStats> arrayList = new ArrayList<>();
    SQLiteDatabase db = this.getReadableDatabase();

    Cursor cursor = db.rawQuery("SELECT * FROM savedGamesTable", null);

    while(cursor.moveToNext()){
        int id = cursor.getInt(0);
        String lName = cursor.getString(1);
        int lScore = cursor.getInt(2);
        String rName = cursor.getString(3);
        int rScore = cursor.getInt(4);
        String notes = cursor.getString(5);

        GameStats gameStats = new GameStats(id, lName, lScore, rName, rScore, notes);
        arrayList.add(gameStats);

    }
    return arrayList;
}

Here is where I am trying to use the getters:

    public View getView(int position, View convertView, ViewGroup parent) {

        LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inflater.inflate(R.layout.activity_saved_games, null);
        TextView lName = convertView.findViewById(R.id.lName);
        TextView lScore = convertView.findViewById(R.id.lScore);
        TextView rName = convertView.findViewById(R.id.rName);
        TextView rScore = convertView.findViewById(R.id.rScore);
        TextView notes = convertView.findViewById(R.id.notes);

    GameStats gameStats = arrayList.get(position);
    testVar = gameStats.getlName();
    Log.d("MyAdaptor","gameStats = " + var);
    lName.setText(gameStats.getlName());
    lScore.setText(String.valueOf(gameStats.getlScore()));
    rName.setText(gameStats.getrName());
    rScore.setText(String.valueOf(gameStats.getrScore()));
    notes.setText(gameStats.getNotes());
    return convertView;
}

Here is the model class:

public class GameStats {
int id, lScore, rScore;
String lName, rName, notes;

public GameStats(int id, String lName, int lScore, String rName, int rScore, String notes) {

}

public int getId() {
    return id;
}

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

public int getlScore() {
    return lScore;
}

public void setlScore(int lScore) {
    this.lScore = lScore;
}

public int getrScore() {
    return rScore;
}

public void setrScore(int rScore) {
    this.rScore = rScore;
}

public String getlName() {
    return lName;
}

public void setlName(String lName) {
    this.lName = lName;
}

public String getrName() {
    return rName;
}

public void setrName(String rName) {
    this.rName = rName;
}

public String getNotes() {
    return notes;
}

public void setNotes(String notes) {
    this.notes = notes;
}

}

and here is where I am calling the methods:

public class SavedGameScreen extends AppCompatActivity {

ListView lv1;
ArrayList<GameStats> arrayList;
MyAdaptor myAdaptor;
DatabaseHelper databaseHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_saved_game_screen);
    lv1 = findViewById(R.id.lv1);
    databaseHelper = new DatabaseHelper(this);
    arrayList = new ArrayList<>();
    loadData();
}

private void loadData() {
    arrayList = databaseHelper.getAllData();
    myAdaptor = new MyAdaptor(this, arrayList);
    lv1.setAdapter(myAdaptor);
    myAdaptor.notifyDataSetChanged();
}

}


问:
How to get the column names with value more than ZERO as the multilabels for each row
I have a case where I have label names as columns of a DataFrame with value 0 or more like below.

```<code>.net    2007    actionscript-3  activerecord    air ajax
0   0   0   0   1   1   1
1   0   0   0   1   1   1
2   0   0   0   1   1   1
3   2   2   2   2   0   0
4   2   2   2   2   0   0
5   2   2   2   2   0   0
</code>```

My requirement is to put those column names whose value is more than zero, in a single column seperated by space for each row like below :

```<code>0   activerecord air ajax
1   activerecord air ajax
2   activerecord air ajax
3   .net 2007 actionscript-3 activerecord
4   .net 2007 actionscript-3 activerecord
5   .net 2007 actionscript-3 activerecord
</code>```

Example : values in columns activerecord, air, ajax has value of 1 in first row so these 3 should appear in one column of the dataframe separated by space.

This is an example of multi-label classification.

答:
You can try this using df.apply

```<code>df.apply(lambda x:' '.join(x.index[x!=0]) , axis=1)
</code>```

Or
df.T is short hand for df.transpose

```<code>df.T.apply(lambda x: ' '.join(x.index[x!=0]))
</code>```

Here's another hack: Using df.stack df.where to find values not equal to 0 and drop NaN using df.dropna and df.groupby

```<code>df = df.stack()
(df.where(df!=0).dropna().reset_index().
    groupby('level_0')['level_1'].apply(','.join))

level_0
0                    activerecord,air,ajax
1                    activerecord,air,ajax
2                    activerecord,air,ajax
3    .net,2007,actionscript-3,activerecord
4    .net,2007,actionscript-3,activerecord
5    .net,2007,actionscript-3,activerecord
Name: level_1, dtype: object
</code>```

Or
df.groupby allows to group by level and use pd.MultiIndex.get_level_values to get level1 index values.

```<code>df = df.stack()
(df.where(df!=0).dropna().groupby(level=0).
    apply(lambda x:','.join(x.index.get_level_values(1))))

0                    activerecord,air,ajax
1                    activerecord,air,ajax
2                    activerecord,air,ajax
3    .net,2007,actionscript-3,activerecord
4    .net,2007,actionscript-3,activerecord
5    .net,2007,actionscript-3,activerecord
dtype: object
</code>```

Body:
I have a case where I have label names as columns of a DataFrame with value 0 or more like below.

.net    2007    actionscript-3  activerecord    air ajax
0   0   0   0   1   1   1
1   0   0   0   1   1   1
2   0   0   0   1   1   1
3   2   2   2   2   0   0
4   2   2   2   2   0   0
5   2   2   2   2   0   0

My requirement is to put those column names whose value is more than zero, in a single column seperated by space for each row like below :

0   activerecord air ajax
1   activerecord air ajax
2   activerecord air ajax
3   .net 2007 actionscript-3 activerecord
4   .net 2007 actionscript-3 activerecord
5   .net 2007 actionscript-3 activerecord

Example : values in columns activerecord, air, ajax has value of 1 in first row so these 3 should appear in one column of the dataframe separated by space.

This is an example of multi-label classification.

Body:
You can try this using df.apply

df.apply(lambda x:' '.join(x.index[x!=0]) , axis=1)

Or
df.T is short hand for df.transpose

df.T.apply(lambda x: ' '.join(x.index[x!=0]))

Here's another hack: Using df.stack df.where to find values not equal to 0 and drop NaN using df.dropna and df.groupby

df = df.stack()
(df.where(df!=0).dropna().reset_index().
    groupby('level_0')['level_1'].apply(','.join))

level_0
0                    activerecord,air,ajax
1                    activerecord,air,ajax
2                    activerecord,air,ajax
3    .net,2007,actionscript-3,activerecord
4    .net,2007,actionscript-3,activerecord
5    .net,2007,actionscript-3,activerecord
Name: level_1, dtype: object

Or
df.groupby allows to group by level and use pd.MultiIndex.get_level_values to get level1 index values.

df = df.stack()
(df.where(df!=0).dropna().groupby(level=0).
    apply(lambda x:','.join(x.index.get_level_values(1))))

0                    activerecord,air,ajax
1                    activerecord,air,ajax
2                    activerecord,air,ajax
3    .net,2007,actionscript-3,activerecord
4    .net,2007,actionscript-3,activerecord
5    .net,2007,actionscript-3,activerecord
dtype: object


问:
How to fix "Trailing Whitespace Violation" warnings caused by swiftlint in Xcode?
How can we fix the "Trailing Whitespace Violation" warnings caused by swiftlint in my iOS project all in one go? I don't want to manually correct each one of them. Moreover, I don't want to disable these warnings so you can skip that suggestion.

I have been trying Find And Replace option but I am not getting a correct keyword to sort this out.

Image :

答: to fix existing (remove trailing whitespace from) whitespace-only lines, after turning on the preference include-whitespace-only-lines as rmaddy suggests, one can select all, copy the entire file, and then paste, replacing all text with the same text.  Xcode will apply the preference on the pasted code.


问:
How to cancel button tap if UIGestureRecognizer fires?
Update: The problem seems to be the dependency on another GestureRecognizer to fail. See comments and test project below this question!

In my iPhone app I have a view with multiple UIButtons as subviews. The view also has a UITapGestureRecognizer which is listening for taps with two fingers.

When a two-finger-tap occurs on the view I don't want the buttons to react to the tap, even if one of the fingers was inside the button. I thought this is what "cancelsTouchesInView" is for, but that doesn't work.

My question now is: How to tell my buttons to ignore taps when a gesture is recognized?

Edit: This is my gesture recognizer.

```<code>UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTapped:)];
[doubleTap setNumberOfTouchesRequired:2];
[doubleTap setNumberOfTapsRequired:1];
[doubleTap setCancelsTouchesInView:YES];
[doubleTap setDelaysTouchesBegan:YES];
[doubleTap setDelaysTouchesEnded:YES];
[self.view addGestureRecognizer:doubleTap];
[doubleTap release];
</code>```

答:
According to an Apple dev this is a bug. I filed a bug report with Apple.
Thanks a lot for your hints, Deepak and gcamp!

Bug report:

Summary:
  When adding two UITapGestureRecognizers to a view where one requires the other to fail (requiresGestureRecognizerToFail:) the cancelsTouchesInView property of the first gesture recognizer is ignored.

Steps to Reproduce:
  1. Create two UITapGestureRecognizers (r1 and r2)
  2. Configure r1 to require two touches and one tap and to delay touchesBegan
  3. Configure r2 to require two touches and two taps and to delay touchesBegan
  4. Configure r1 to require r2 to fail [r1 requiresGestureRecognizerToFail:r2]
  5. Add r1 and r2 to a view
  6. Place a UIButton in the view
  7. Tap with two fingers on the view, one should hit the button.

Expected Results:
  r1 should be recognized and the button tap should be canceled (cancelsTouchesInView defaults to YES for UITapGestureRecognizers).

Actual Results:
  r1 is recognized but the button touchedUpInside event is fired, too.

Regression:
  cancelTouchesInView works fine for r1 once you remove the dependency on r2 (step 4).

Body:
Update: The problem seems to be the dependency on another GestureRecognizer to fail. See comments and test project below this question!

In my iPhone app I have a view with multiple UIButtons as subviews. The view also has a UITapGestureRecognizer which is listening for taps with two fingers.

When a two-finger-tap occurs on the view I don't want the buttons to react to the tap, even if one of the fingers was inside the button. I thought this is what "cancelsTouchesInView" is for, but that doesn't work.

My question now is: How to tell my buttons to ignore taps when a gesture is recognized?

Edit: This is my gesture recognizer.

UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTapped:)];
[doubleTap setNumberOfTouchesRequired:2];
[doubleTap setNumberOfTapsRequired:1];
[doubleTap setCancelsTouchesInView:YES];
[doubleTap setDelaysTouchesBegan:YES];
[doubleTap setDelaysTouchesEnded:YES];
[self.view addGestureRecognizer:doubleTap];
[doubleTap release];