问:
Is there a quicker method to get and output all filenames in a directory tree?
```<code>For /r %%a in (*.mp4) do (
echo %%~nxa >> FilenameList.txt
)

sort FilenameList.txt > FilenameList_sorted.txt
</code>```

The above will output only filenames with their extensions (mp4 files) from the directory, and sub-directories included, from where the script is ran. The next part will sort the completed file by sorting each line alphabetically and outputting that to a new file. But the loop is very slow.

Two questions

How can this script run faster by perhaps changing the methodology in
which this works?

Can the (*.mp4) part be changed to an array so that multiple
specific file types can be listed in the output instead if just one file type; if so, how?

Thank you

答:
Your code

```<code>For /r %%a in (*.mp4) do (
echo %%~nxa >> FilenameList.txt
)
</code>```

is generally the same the following code. However, the former one outputs each new file one by one, while the latter one outputs all the file at once. The difference is significant when processing large amount of files.

```<code>for /r %%a in (*.mp4) do (
    echo %%~nxa
) >> FilenameList.txt
</code>```

I also noticed that in the () clause, multiple file extension can be used.

```<code>for /r %%a in (*.mp4 *.avi) do (
    echo %%~nxa
) >> FilenameList.txt
</code>```

Body:
For /r %%a in (*.mp4) do (
echo %%~nxa >> FilenameList.txt
)

sort FilenameList.txt > FilenameList_sorted.txt

The above will output only filenames with their extensions (mp4 files) from the directory, and sub-directories included, from where the script is ran. The next part will sort the completed file by sorting each line alphabetically and outputting that to a new file. But the loop is very slow.

Two questions

How can this script run faster by perhaps changing the methodology in
which this works?

Can the (*.mp4) part be changed to an array so that multiple
specific file types can be listed in the output instead if just one file type; if so, how?

Thank you

Body:
Your code

For /r %%a in (*.mp4) do (
echo %%~nxa >> FilenameList.txt
)

is generally the same the following code. However, the former one outputs each new file one by one, while the latter one outputs all the file at once. The difference is significant when processing large amount of files.

for /r %%a in (*.mp4) do (
    echo %%~nxa
) >> FilenameList.txt

I also noticed that in the () clause, multiple file extension can be used.

for /r %%a in (*.mp4 *.avi) do (
    echo %%~nxa
) >> FilenameList.txt


来源: stackexchange

问:
Connect 4 algorithm in javascript
What is the best way to check 4 in a row in connect 4?

I won't copy the code for the array but it is basically an array of length 42. Each array element holds the X, Y position for drawing and the color

```<code>var board_array = [{x:60, y:55, c:"Red"}, // ... and so on
</code>```

and looks like this:

Initially I took this approach. Here are all the different possible ways someone can win the game. It's not all the possible 4 in a row positions but all the different ways someone can win vertically, horizontally and vertically - you still need to check using some sort of nested for loop

```<code>// Winning vertically
wins[0]  = new Array(0, 7,  14, 21, 28, 35);
wins[1]  = new Array(1, 8,  15, 22, 29, 36);
wins[2]  = new Array(2, 9,  16, 23, 30, 37);
wins[3]  = new Array(3, 10, 17, 24, 31, 38);
wins[4]  = new Array(4, 11, 18, 25, 32, 39);
wins[5]  = new Array(5, 12, 19, 26, 33, 40);
wins[6]  = new Array(6, 13, 20, 27, 34, 41);
// Winning horizontally
wins[7]  = new Array(0,   1,  2,  3,  4,  5,  6);
wins[8]  = new Array(7,   8,  9, 10, 11, 12, 13);
wins[9]  = new Array(14, 15, 16, 17, 18, 19, 20);
wins[10] = new Array(21, 22, 23, 24, 25, 26, 27);
wins[11] = new Array(28, 29, 30, 31, 32, 33, 34);
wins[12] = new Array(35, 36, 37, 38, 39, 40, 41);
// Winning diagonally, left to right
wins[13] = new Array(14, 22, 30, 38);
wins[14] = new Array(7, 15, 23, 31, 39);
wins[15] = new Array(0, 8, 16, 24, 32, 40);
wins[16] = new Array(1, 9, 17, 25, 33, 41);
wins[17] = new Array(2, 10, 18, 26, 34);
wins[18] = new Array(3, 11, 19, 27);
//Winning diagonally, right to left
wins[19] = new Array(20, 26, 32, 38);
wins[20] = new Array(13, 19, 25, 31, 37);
wins[21] = new Array(6,  12, 18, 24, 30, 36);
wins[22] = new Array(5,  11, 17, 23, 29, 35);
wins[23] = new Array(4,  10, 16, 22, 28);
wins[24] = new Array(3,   9, 15, 21);
</code>```

If you think of the board_array as this:

```<code>//0  1  2  3  4  5  6
//7  8  9  10 11 12 13
//14 15 16 17 18 19 20
//21 22 23 24 25 26 27
//28 29 30 31 32 33 34
//35 36 37 38 39 40 41
</code>```

I used a 3-layer for loop and a counter to check wins array against board_array but to no avail. I just wondered if there is a simpler way.

答:
"What is the best way to check 4 in a row in connect 4?"

I wouldn't claim that this is "the best way", but it is a way.

Mostly ignoring the UI gubbins, the process is (somewhat) simply to read the grid each time a counter is dropped in a dynamically created search pattern of strips which could contain a connection of four.

Each row, column and forward and backward leaning diagonal strip is a string concatenated from the values of the color found at each point along it.

The strips are tested against a simple RegEx to see if the same four counter colors (red or yellow) are mentioned consecutively.

Although it's quite loopy, the objects are trivially short, and the first nested loop(s) in check4Winner() (which reads the grid) collates all the data needed to finish checking whilst simultaneously checking the rows for winning connections.

The following loop of loops checks the columnal and diagonal strips only if a winner hasn't been found.

An optimization not included (hardly worth the extra code to be honest) could be to remove twelve diagonal strips (three in each corner) it is unnecessary to check, as they're too short.

If it were desired to export or import game data, the temporary object of arrays of strings (being console.logged for demo) could be easily utilized.

The UI gubbins, although not strictly important regarding the algorithm to find a winner, was designed with the algorithm in mind, and as such the state of the DOM is the source of the data being read.

I purposefully turned off the console output in the snippet, but you can see in your browser's console the data generated by reading the DOM (in this specific way).

var player = "red";
const players = { "red": "yellow", "yellow": "red" },
  output = document.querySelector( "output" ),
  tbody = document.querySelector( "tbody" ),
  rows = tbody.querySelectorAll( "tr" ),
  prepArray = ( n ) => {
    return Array( n ).fill( "" );
  },
  connect4 = ( strip ) => {
    const rslt = /(?:(red){4}|(yellow){4})/.exec( strip );
    if ( !!rslt ) {
      output.classList.add( rslt[ 1 ] || rslt[ 2 ] );
      return true;
    }
    return false;
  },
  check4Winner = () => {
    var strips = {
          h: [],
          v: prepArray( 7 ),
          f: prepArray( 12 ),
          b: prepArray( 12 )
        },
        strip, color, winner, dir;
    rows.forEach( ( row, ri ) => {
      strip = "";
      row.querySelectorAll( "td" ).forEach( ( cell, ci ) => {
        color = cell.getAttribute( "class" ) || " ";
        strips.b[ ci - ri + rows.length - 1 ] += color;
        strips.f[ ci + ri ] += color;
        strips.v[ ci ] += color;
        strip += color;
      } );
      strips.h.push( strip );
      winner = winner || connect4( strip );
    } );

    console.log( strips ); // game data object

    for ( dir in strips ) {
      if ( !winner && strips.hasOwnProperty( dir ) ) {
        strips[ dir ].forEach( ( s ) => {
          winner = winner || connect4( s );
        } );
      }
    }
  },
  dropCounter = ( ci ) => {
    var cell, pc;
    rows.forEach( ( row ) => {
      if ( !( pc = row.childNodes[ ci ] ).getAttribute( "class" ) ) {
        cell = pc;
      }
    } );
    if ( cell ) {
      cell.classList.add( player = players[ player ] );
      check4Winner();
    }
  };
output.addEventListener( "click", () => {
  output.removeAttribute( "class" );
  tbody.querySelectorAll( "td" ).forEach( ( c ) => {
    c.removeAttribute( "class" );
  } );
}, false );
tbody.addEventListener( "click", ( evt ) => {
  const trg = evt.target;
  if ( !output.getAttribute( "class" ) && trg.tagName.toLowerCase() === "td" ) {
    dropCounter( trg.cellIndex );
  }
}, false );```
<pre class="snippet-code-css lang-css prettyprint-override"><code>table,
output {
  box-shadow: .5vh .5vh 2vh .5vh rgba( 0, 0, 0, .5 );
}
table {
  width: 90vh;
  border-collapse: collapse;
  border: 2vh solid royalblue;
}
td {
  width: calc( 90vh / 7 );
  background: royalblue;
  cursor: default;
  user-select: none;
}
td:before {
  content: "";
  display: block;
  width: calc( 90vh / 7 );
  height: calc( 90vh / 7 );
  border-radius: 50%;
  box-shadow: inset .5vh .5vh 2vh .5vh rgba( 0, 0, 0, .5 );
  background: white;
}
td.red:before {
  background: red;
}
td.yellow:before {
  background: yellow;
}
output {
  position: fixed;
  display: none;
  width: 90vh;
  height: 10vh;
  top: 10vh;
  left: 5vh;
  background: white;
  text-align: center;
  font: 5vh sans-serif;
  line-height: 10vh;
  cursor: pointer;
}
output:before {
  content: attr( class );
}
output.red,
output.yellow {
  display: block;
}</code>```

<output> wins!</output>```

P.S. I enjoyed building this, so thanks for asking :-)

ContentLicense: CC BY-SA 3.0

Title: Connect 4 algorithm in javascript

Body:
What is the best way to check 4 in a row in connect 4?

I won't copy the code for the array but it is basically an array of length 42. Each array element holds the X, Y position for drawing and the color

var board_array = [{x:60, y:55, c:"Red"}, // ... and so on

and looks like this:

Initially I took this approach. Here are all the different possible ways someone can win the game. It's not all the possible 4 in a row positions but all the different ways someone can win vertically, horizontally and vertically - you still need to check using some sort of nested for loop

// Winning vertically
wins[0]  = new Array(0, 7,  14, 21, 28, 35);
wins[1]  = new Array(1, 8,  15, 22, 29, 36);
wins[2]  = new Array(2, 9,  16, 23, 30, 37);
wins[3]  = new Array(3, 10, 17, 24, 31, 38);
wins[4]  = new Array(4, 11, 18, 25, 32, 39);
wins[5]  = new Array(5, 12, 19, 26, 33, 40);
wins[6]  = new Array(6, 13, 20, 27, 34, 41);
// Winning horizontally
wins[7]  = new Array(0,   1,  2,  3,  4,  5,  6);
wins[8]  = new Array(7,   8,  9, 10, 11, 12, 13);
wins[9]  = new Array(14, 15, 16, 17, 18, 19, 20);
wins[10] = new Array(21, 22, 23, 24, 25, 26, 27);
wins[11] = new Array(28, 29, 30, 31, 32, 33, 34);
wins[12] = new Array(35, 36, 37, 38, 39, 40, 41);
// Winning diagonally, left to right
wins[13] = new Array(14, 22, 30, 38);
wins[14] = new Array(7, 15, 23, 31, 39);
wins[15] = new Array(0, 8, 16, 24, 32, 40);
wins[16] = new Array(1, 9, 17, 25, 33, 41);
wins[17] = new Array(2, 10, 18, 26, 34);
wins[18] = new Array(3, 11, 19, 27);
//Winning diagonally, right to left
wins[19] = new Array(20, 26, 32, 38);
wins[20] = new Array(13, 19, 25, 31, 37);
wins[21] = new Array(6,  12, 18, 24, 30, 36);
wins[22] = new Array(5,  11, 17, 23, 29, 35);
wins[23] = new Array(4,  10, 16, 22, 28);
wins[24] = new Array(3,   9, 15, 21);

If you think of the board_array as this:

//0  1  2  3  4  5  6
//7  8  9  10 11 12 13
//14 15 16 17 18 19 20
//21 22 23 24 25 26 27
//28 29 30 31 32 33 34
//35 36 37 38 39 40 41

I used a 3-layer for loop and a counter to check wins array against board_array but to no avail. I just wondered if there is a simpler way.

Body:
"What is the best way to check 4 in a row in connect 4?"

I wouldn't claim that this is "the best way", but it is a way.

Mostly ignoring the UI gubbins, the process is (somewhat) simply to read the grid each time a counter is dropped in a dynamically created search pattern of strips which could contain a connection of four.

Each row, column and forward and backward leaning diagonal strip is a string concatenated from the values of the color found at each point along it.

The strips are tested against a simple RegEx to see if the same four counter colors (red or yellow) are mentioned consecutively.

Although it's quite loopy, the objects are trivially short, and the first nested loop(s) in check4Winner() (which reads the grid) collates all the data needed to finish checking whilst simultaneously checking the rows for winning connections.

The following loop of loops checks the columnal and diagonal strips only if a winner hasn't been found.

An optimization not included (hardly worth the extra code to be honest) could be to remove twelve diagonal strips (three in each corner) it is unnecessary to check, as they're too short.

If it were desired to export or import game data, the temporary object of arrays of strings (being console.logged for demo) could be easily utilized.

The UI gubbins, although not strictly important regarding the algorithm to find a winner, was designed with the algorithm in mind, and as such the state of the DOM is the source of the data being read.

I purposefully turned off the console output in the snippet, but you can see in your browser's console the data generated by reading the DOM (in this specific way).

var player = "red";
const players = { "red": "yellow", "yellow": "red" },
  output = document.querySelector( "output" ),
  tbody = document.querySelector( "tbody" ),
  rows = tbody.querySelectorAll( "tr" ),
  prepArray = ( n ) => {
    return Array( n ).fill( "" );
  },
  connect4 = ( strip ) => {
    const rslt = /(?:(red){4}|(yellow){4})/.exec( strip );
    if ( !!rslt ) {
      output.classList.add( rslt[ 1 ] || rslt[ 2 ] );
      return true;
    }
    return false;
  },
  check4Winner = () => {
    var strips = {
          h: [],
          v: prepArray( 7 ),
          f: prepArray( 12 ),
          b: prepArray( 12 )
        },
        strip, color, winner, dir;
    rows.forEach( ( row, ri ) => {
      strip = "";
      row.querySelectorAll( "td" ).forEach( ( cell, ci ) => {
        color = cell.getAttribute( "class" ) || " ";
        strips.b[ ci - ri + rows.length - 1 ] += color;
        strips.f[ ci + ri ] += color;
        strips.v[ ci ] += color;
        strip += color;
      } );
      strips.h.push( strip );
      winner = winner || connect4( strip );
    } );

    console.log( strips ); // game data object

    for ( dir in strips ) {
      if ( !winner && strips.hasOwnProperty( dir ) ) {
        strips[ dir ].forEach( ( s ) => {
          winner = winner || connect4( s );
        } );
      }
    }
  },
  dropCounter = ( ci ) => {
    var cell, pc;
    rows.forEach( ( row ) => {
      if ( !( pc = row.childNodes[ ci ] ).getAttribute( "class" ) ) {
        cell = pc;
      }
    } );
    if ( cell ) {
      cell.classList.add( player = players[ player ] );
      check4Winner();
    }
  };
output.addEventListener( "click", () => {
  output.removeAttribute( "class" );
  tbody.querySelectorAll( "td" ).forEach( ( c ) => {
    c.removeAttribute( "class" );
  } );
}, false );
tbody.addEventListener( "click", ( evt ) => {
  const trg = evt.target;
  if ( !output.getAttribute( "class" ) && trg.tagName.toLowerCase() === "td" ) {
    dropCounter( trg.cellIndex );
  }
}, false );

table,
output {
  box-shadow: .5vh .5vh 2vh .5vh rgba( 0, 0, 0, .5 );
}
table {
  width: 90vh;
  border-collapse: collapse;
  border: 2vh solid royalblue;
}
td {
  width: calc( 90vh / 7 );
  background: royalblue;
  cursor: default;
  user-select: none;
}
td:before {
  content: "";
  display: block;
  width: calc( 90vh / 7 );
  height: calc( 90vh / 7 );
  border-radius: 50%;
  box-shadow: inset .5vh .5vh 2vh .5vh rgba( 0, 0, 0, .5 );
  background: white;
}
td.red:before {
  background: red;
}
td.yellow:before {
  background: yellow;
}
output {
  position: fixed;
  display: none;
  width: 90vh;
  height: 10vh;
  top: 10vh;
  left: 5vh;
  background: white;
  text-align: center;
  font: 5vh sans-serif;
  line-height: 10vh;
  cursor: pointer;
}
output:before {
  content: attr( class );
}
output.red,
output.yellow {
  display: block;
}

<table><tbody>
  <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
  <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
  <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
  <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
  <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
  <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
</tbody></table>
<output> wins!</output>

P.S. I enjoyed building this, so thanks for asking :-)


问:
MVC5 how to find root path in code?
I have some helper methods to build Html output but it only comes out correct on my local dev and not my staging server. The ~ doesn't work since this is not Razor.

My local site path is http://localhost/testSite

My staging path is http://192.168.1.2/

On my local this produces
    src="/testSite/images.test.jpg"

On my staging instance it produces src="//images.test.jpg"

```<code>var baseUrl = HttpRuntime.AppDomainAppPath;
var tb = new TagBuilder("img");
tb.MergeAttribute("title", "Main Image");
tb.MergeAttribute("src", baseUrl +"\images\test.jpg");
return new MvcHtmlString(tb.ToString(TagRenderMode.SelfClosing));
</code>```

I'm sure there is a method built in to do this on the code side

答:
Ugh... after reviewing all the helpers and context objects available, I must conclude there is no function or method that provides exactly what you want (other than to use the tilde in one of the functions, as shown in the other answers). All of them require some sort of string processing (e.g. Split() or TrimEnd()) in order to work.

Instead, Microsoft kindly gave us a band-aid function, AppendTrailingSlash, which you can use to solve the problem like this:

```<code>var baseUrl = VirtualPathUtility.AppendTrailingSlash(HttpRuntime.AppDomainAppPath);
var tb = new TagBuilder("img");
tb.MergeAttribute("title", "Main Image");
tb.MergeAttribute("src", baseUrl +"images/test.jpg");  //notice I removed the initial slash
return new MvcHtmlString(tb.ToString(TagRenderMode.SelfClosing));
</code>```

AppendTrailingSlash is guaranteed not to "double up" on the forward slash when the virtual directory is "/", so this should work for both your staging and development environments.

P.S. I'm pretty sure you should be using AppDomainAppVirtualPath and not AppDomainAppPath, which provides the physical path and not the virtual one.

Title: MVC5 how to find root path in code?

Body:
I have some helper methods to build Html output but it only comes out correct on my local dev and not my staging server. The ~ doesn't work since this is not Razor.

My local site path is http://localhost/testSite

My staging path is http://192.168.1.2/

On my local this produces
    src="/testSite/images.test.jpg"

On my staging instance it produces src="//images.test.jpg"

var baseUrl = HttpRuntime.AppDomainAppPath;
var tb = new TagBuilder("img");
tb.MergeAttribute("title", "Main Image");
tb.MergeAttribute("src", baseUrl +"\images\test.jpg");
return new MvcHtmlString(tb.ToString(TagRenderMode.SelfClosing));

I'm sure there is a method built in to do this on the code side

Body:
Ugh... after reviewing all the helpers and context objects available, I must conclude there is no function or method that provides exactly what you want (other than to use the tilde in one of the functions, as shown in the other answers). All of them require some sort of string processing (e.g. Split() or TrimEnd()) in order to work.

Instead, Microsoft kindly gave us a band-aid function, AppendTrailingSlash, which you can use to solve the problem like this:

var baseUrl = VirtualPathUtility.AppendTrailingSlash(HttpRuntime.AppDomainAppPath);
var tb = new TagBuilder("img");
tb.MergeAttribute("title", "Main Image");
tb.MergeAttribute("src", baseUrl +"images/test.jpg");  //notice I removed the initial slash
return new MvcHtmlString(tb.ToString(TagRenderMode.SelfClosing));

AppendTrailingSlash is guaranteed not to "double up" on the forward slash when the virtual directory is "/", so this should work for both your staging and development environments.

P.S. I'm pretty sure you should be using AppDomainAppVirtualPath and not AppDomainAppPath, which provides the physical path and not the virtual one.


问:
Push Item to Array and Delete in the Same Request
I have a document that stores sensor data where the sensor readings are objects stored in an array. Example:

```<code>{
  "readings": [
    {
      "timestamp": 1499475320,
      "temperature": 121
    },
    {
      "timestamp": 1499475326,
      "temperature": 93
    },
    {
      "timestamp": 1499475340,
      "temperature": 142
    }
  ]
}
</code>```

I know how to push/add an item to the "readings" array. But what I need is when I add an item to the array, I also want to "clean" the array by removing items that have "timestamp" value older than a cutoff time.

Is this possible in mongodb?

答:
The way I see this you basically have two options here that have varying approaches.

Restrict Arrays to Capped Size

The first option here is "not exactly" what you are asking for, but it is the option with the least implementation and execution overhead. The variance from your question is that instead of "removing past a certain age", we instead simply place a "limit/cap" on the total number of entries in the array.

This is actually done using the $slice modifier to $push:

```<code>Model.update(
  { "_id": docId },
  { "$push": {
    "readings": {
      "$each": [{ "timestamp": 1499478496679, "temperature": 100 }],
      "$slice": -10
    }
  }
)
</code>```

In this case the -10 argument restricts the array to only have the "last ten" entries from the end of the array since we are "appending" with $push. If you wanted instead the "latest" as the first entry then you would modify with $position and instead provide the "positive" value to $slice, which means "first ten" in contrast.

So it's not the same thing you asked for, but it is practical since the arrays do not have "unlimited growth" and you can simply "cap" them as each update is made and the "oldest" item will be removed once at the maximum length. This means the overall document never actually grows beyond a set size, and this is a very good thing for MongoDB.

Issue with Bulk Operations

The next case which actually does exactly what you ask uses "Bulk Operations" to issue "two" update operations in a "single" request to the server. The reason why it is "two" is because there is a rule that you cannot have different update operators "assigned to the same path" in a singe update operation.

Therefore what you want actually involves a $push AND a $pull operation, and on the "same array path" we need to issue those as "separate" operations. This is where the Bulk API can help:

```<code>Model.collection.bulkWrite([
  { "updateOne": {
    "filter": { "_id": docId },
    "update": {
      "$pull": {
        "readings": { "timestamp": { "$lt": cutOff } }
      }
    }
  }},
  { "updateOne": {
    "filter": { "_id": docId },
    "update": {
      "$push": { "timestamp": 1499478496679, "temperature": 100 }
    }
  }}
])
</code>```

This uses the .bulkWrite() method from the underlying driver which you access from the model via .collection as shown. This will actually return a BulkWriteOpResult within the callback or Promise which contains information about the actual operations performed within the "batch". In this case it will be the "matched" and "modified" numbers which will be appropriate to the operations that were actually performed.

Hence if the $pull did not actually "remove" anything since the timestamp values were actually newer than the given constraint, then the modified count would only reflect the $push operation. But most of the time this need not concern you, where instead you would just accept that the operations completed without error and did something according to what you actually asked.

Conclude

So the general case of "both" is that it's really all done in one request and one response. The differences come in that "under the hood" the second approach which matches your request actually does do "two" operations per request and therefore takes microseconds longer.

There is actually no reason why you could not "combine" the logic of "both", and remove past your "cutoFF" as well as keeping a "cap" on the overall array size. But the general idea here is that the first implementation, though not exactly the same thing as asked will actually do a "good enough" job of "housekeeping" with little to no additional overhead on the request, or indeed the implementation of the actual code.

Also, whilst you can always "read the data" -> "modify" -> "save". That is not a really great pattern. And for best performance as well as "consistency" without conflict, you should be using the atomic operations to modify in just the same way as is outlined here.

Body:
I have a document that stores sensor data where the sensor readings are objects stored in an array. Example:

{
  "readings": [
    {
      "timestamp": 1499475320,
      "temperature": 121
    },
    {
      "timestamp": 1499475326,
      "temperature": 93
    },
    {
      "timestamp": 1499475340,
      "temperature": 142
    }
  ]
}

I know how to push/add an item to the "readings" array. But what I need is when I add an item to the array, I also want to "clean" the array by removing items that have "timestamp" value older than a cutoff time.

Is this possible in mongodb?

Body:
The way I see this you basically have two options here that have varying approaches.

Restrict Arrays to Capped Size

The first option here is "not exactly" what you are asking for, but it is the option with the least implementation and execution overhead. The variance from your question is that instead of "removing past a certain age", we instead simply place a "limit/cap" on the total number of entries in the array.

This is actually done using the $slice modifier to $push:

Model.update(
  { "_id": docId },
  { "$push": {
    "readings": {
      "$each": [{ "timestamp": 1499478496679, "temperature": 100 }],
      "$slice": -10
    }
  }
)

In this case the -10 argument restricts the array to only have the "last ten" entries from the end of the array since we are "appending" with $push. If you wanted instead the "latest" as the first entry then you would modify with $position and instead provide the "positive" value to $slice, which means "first ten" in contrast.

So it's not the same thing you asked for, but it is practical since the arrays do not have "unlimited growth" and you can simply "cap" them as each update is made and the "oldest" item will be removed once at the maximum length. This means the overall document never actually grows beyond a set size, and this is a very good thing for MongoDB.

Issue with Bulk Operations

The next case which actually does exactly what you ask uses "Bulk Operations" to issue "two" update operations in a "single" request to the server. The reason why it is "two" is because there is a rule that you cannot have different update operators "assigned to the same path" in a singe update operation.

Therefore what you want actually involves a $push AND a $pull operation, and on the "same array path" we need to issue those as "separate" operations. This is where the Bulk API can help:

Model.collection.bulkWrite([
  { "updateOne": {
    "filter": { "_id": docId },
    "update": {
      "$pull": {
        "readings": { "timestamp": { "$lt": cutOff } }
      }
    }
  }},
  { "updateOne": {
    "filter": { "_id": docId },
    "update": {
      "$push": { "timestamp": 1499478496679, "temperature": 100 }
    }
  }}
])

This uses the .bulkWrite() method from the underlying driver which you access from the model via .collection as shown. This will actually return a BulkWriteOpResult within the callback or Promise which contains information about the actual operations performed within the "batch". In this case it will be the "matched" and "modified" numbers which will be appropriate to the operations that were actually performed.

Hence if the $pull did not actually "remove" anything since the timestamp values were actually newer than the given constraint, then the modified count would only reflect the $push operation. But most of the time this need not concern you, where instead you would just accept that the operations completed without error and did something according to what you actually asked.

Conclude

So the general case of "both" is that it's really all done in one request and one response. The differences come in that "under the hood" the second approach which matches your request actually does do "two" operations per request and therefore takes microseconds longer.

There is actually no reason why you could not "combine" the logic of "both", and remove past your "cutoFF" as well as keeping a "cap" on the overall array size. But the general idea here is that the first implementation, though not exactly the same thing as asked will actually do a "good enough" job of "housekeeping" with little to no additional overhead on the request, or indeed the implementation of the actual code.

Also, whilst you can always "read the data" -> "modify" -> "save". That is not a really great pattern. And for best performance as well as "consistency" without conflict, you should be using the atomic operations to modify in just the same way as is outlined here.


问:
URL request failing with in Python - cannot find SSL certificate
I have a simple screen scraping routine that gets an HTML page via BeautifulSoup, using a proxy crawling service (Scrapinghub):

```<code>def make_soup(self,current_url):
    soup = None
    r = requests.get(current_url, proxies=self.proxies, auth=self.proxy_auth,
         verify='static/crawlera-ca.crt')
    if r.status_code == 200:
        soup = bs4.BeautifulSoup(r.text, "html.parser")
        if soup:
            return soup
    return False
</code>```

When I run it on an http:// site it works properly.

When I run it on an https:// site it returns this:

```<code>Traceback (most recent call last):
  File "/home/danny/Documents/virtualenvs/AskArbyEnv/lib/python3.5/site-packages/requests/packages/urllib3/util/ssl_.py", line 295, in ssl_wrap_socket
    context.load_verify_locations(ca_certs, ca_cert_dir)
FileNotFoundError: [Errno 2] No such file or directory
</code>```

Even weirder is that it works when I run it in a unit test accessing the same https:// site.

The only thing that changes between the unit test and the running code is the search terms that I append to the URL that I pass to 'make_soup'. Each resulting URL is well-formed, and I can access both of them in the browser.

This makes me think that it can't be to do with missing SSL certificates. So why does it seem to be complaining that it can't find certificate files?

答:
By specifying verify='static/crawlera-ca.crt' in your call to requests.get, you are saying that all sites you visit have to have certificates signed by crawlera-ca.crt. If your proxy is not rewriting requests/responses and server certificates on fly (which it shouldn't, but check the update below), than all your requests to https sites will fail.

In addition, if you read the error message carefully, you can see you don't even have that crawlera-ca.crt file on disk.

To resolve your issue, just remove the verify argument. That way the requests will use the default, the certifi bundle (for requests>=2.4.0). For non-invasive proxies this is the right solution. Optionally, if you really need to, you can add some of the CA certs you trust to your local certifi store, but be very careful which certs you are adding.

Update. Looks like Crawlera proxy is a man-in-the-middle after all! Bad Crawlera, bad, bad, bad!

```<code>$ curl -vvv -x proxy.crawlera.com:8010 --cacert crawlera-ca.crt https://google.com/
[...snip...]
* Proxy replied OK to CONNECT request
* found 1 certificates in crawlera-ca.crt
* found 697 certificates in /etc/ssl/certs
* ALPN, offering http/1.1
* SSL connection using TLS1.2 / ECDHE_RSA_AES_256_GCM_SHA384
*    server certificate verification OK
*    server certificate status verification SKIPPED
*    common name: google.com (matched)
*    server certificate expiration date OK
*    server certificate activation date OK
*    certificate public key: RSA
*    certificate version: #1
*    subject: CN=google.com
*    start date: Sat, 08 Jul 2017 13:33:53 GMT
*    expire date: Tue, 06 Jul 2027 13:33:53 GMT
*    issuer: C=IE,ST=Munster,L=Cork,O=ScrapingHub,OU=Leading Technology and Professional Services,CN=Crawlera CA,EMAIL=support@scrapinghub.com
*    compression: NULL
</code>```

Notice the CN=google.com there is issued by O=ScrapingHub,CN=Crawlera CA.

This means Crawlera/ScrapingHub is re-encrypting each request you make to your target URL, and reading all private and sensitive data you exchange with that site! I understand that's the only way for them to cache origin requests and save some bandwidth across all users scraping the same site, and the only way to inspect the legality of the content, but still. They should put is somewhere in their FAQ, and I'm not sure they do.

Body:
I have a simple screen scraping routine that gets an HTML page via BeautifulSoup, using a proxy crawling service (Scrapinghub):

def make_soup(self,current_url):
    soup = None
    r = requests.get(current_url, proxies=self.proxies, auth=self.proxy_auth,
         verify='static/crawlera-ca.crt')
    if r.status_code == 200:
        soup = bs4.BeautifulSoup(r.text, "html.parser")
        if soup:
            return soup
    return False

When I run it on an http:// site it works properly.

When I run it on an https:// site it returns this:

Traceback (most recent call last):
  File "/home/danny/Documents/virtualenvs/AskArbyEnv/lib/python3.5/site-packages/requests/packages/urllib3/util/ssl_.py", line 295, in ssl_wrap_socket
    context.load_verify_locations(ca_certs, ca_cert_dir)
FileNotFoundError: [Errno 2] No such file or directory

Even weirder is that it works when I run it in a unit test accessing the same https:// site.

The only thing that changes between the unit test and the running code is the search terms that I append to the URL that I pass to 'make_soup'. Each resulting URL is well-formed, and I can access both of them in the browser.

This makes me think that it can't be to do with missing SSL certificates. So why does it seem to be complaining that it can't find certificate files?

Body:
By specifying verify='static/crawlera-ca.crt' in your call to requests.get, you are saying that all sites you visit have to have certificates signed by crawlera-ca.crt. If your proxy is not rewriting requests/responses and server certificates on fly (which it shouldn't, but check the update below), than all your requests to https sites will fail.

In addition, if you read the error message carefully, you can see you don't even have that crawlera-ca.crt file on disk.

To resolve your issue, just remove the verify argument. That way the requests will use the default, the certifi bundle (for requests>=2.4.0). For non-invasive proxies this is the right solution. Optionally, if you really need to, you can add some of the CA certs you trust to your local certifi store, but be very careful which certs you are adding.

Update. Looks like Crawlera proxy is a man-in-the-middle after all! Bad Crawlera, bad, bad, bad!

$ curl -vvv -x proxy.crawlera.com:8010 --cacert crawlera-ca.crt https://google.com/
[...snip...]
* Proxy replied OK to CONNECT request
* found 1 certificates in crawlera-ca.crt
* found 697 certificates in /etc/ssl/certs
* ALPN, offering http/1.1
* SSL connection using TLS1.2 / ECDHE_RSA_AES_256_GCM_SHA384
*    server certificate verification OK
*    server certificate status verification SKIPPED
*    common name: google.com (matched)
*    server certificate expiration date OK
*    server certificate activation date OK
*    certificate public key: RSA
*    certificate version: #1
*    subject: CN=google.com
*    start date: Sat, 08 Jul 2017 13:33:53 GMT
*    expire date: Tue, 06 Jul 2027 13:33:53 GMT
*    issuer: C=IE,ST=Munster,L=Cork,O=ScrapingHub,OU=Leading Technology and Professional Services,CN=Crawlera CA,EMAIL=support@scrapinghub.com
*    compression: NULL

Notice the CN=google.com there is issued by O=ScrapingHub,CN=Crawlera CA.

This means Crawlera/ScrapingHub is re-encrypting each request you make to your target URL, and reading all private and sensitive data you exchange with that site! I understand that's the only way for them to cache origin requests and save some bandwidth across all users scraping the same site, and the only way to inspect the legality of the content, but still. They should put is somewhere in their FAQ, and I'm not sure they do.


问:
In Java should I copy a volatile reference locally before I foreach it
If I have the following

```<code>private volatile Collection<Integer> ints;

private void myMethod()
{
   for ( Integer i : ints )
   {
      ...
   }
}
</code>```

The ints collection is never changed but the entire collection maybe replaced by another thread (so it's an immutable collection).

Should I be copying the ints variable locally before I iterate it?  I'm not sure if it will be accessed multiple times.  ie Iterating the collection, another thread replaces the collection, the code continues iterating but with the new collection.

EDIT : This question is relevant for additional info on how foreach works internally.

答:
Should not be necessary, because the for loop will get an Iterator once and loop over that.
That Iterator is tied to the Collection that created it.

So it will not switch collections mid-loop.

ContentLicense: CC BY-SA 2.5

Body:
If I have the following

private volatile Collection<Integer> ints;

private void myMethod()
{
   for ( Integer i : ints )
   {
      ...
   }
}

The ints collection is never changed but the entire collection maybe replaced by another thread (so it's an immutable collection).

Should I be copying the ints variable locally before I iterate it?  I'm not sure if it will be accessed multiple times.  ie Iterating the collection, another thread replaces the collection, the code continues iterating but with the new collection.

EDIT : This question is relevant for additional info on how foreach works internally.


问:
Laravel 5.4 unable to set email from option
I am using global from option in config/mail.php as mentioned in the documentation to use the same from address for all of my emails being sent. This works as expected. However, when I attempt to explicitly set a from address within the build function of a Mailable class, the global address is still used. Is there something I could be missing, all of this seems to come straight from the documentation for 5.4. My Mailable class is as follows (there is definitely a value in the $this->email property as it is displayed when echoed):

```<code>namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;

class ContactMessage extends Mailable
{
    use Queueable, SerializesModels;

    public $user_email;
    public $user_message;

    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct($user_email, $user_message)
    {
        $this->user_email = $user_email;
        $this->user_message = $user_message;
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
//        echo '```';
//        echo var_export($this->user_email, true);
//        echo '

';
//        echo var_export($this->message, true);
//        die;

        return $this->from($this->user_email)
                ->subject('Contact Message')
                ->view('mail.contactMessage');
    }

}
```

答:
Your code is correct. Thing is, setting the From header is a privileged operation in most MTA.

If you use sendmail, postfix, or other similars on a local machine you can usually set the From. However, when using an authenticated account at a third party, you usually cannot.

To change the From header with a third party, you need to either use an authenticated account that matches your From (eg with GMail), or configure the allowed From in your account (eg at AWS SES).

Body:
I am using global from option in config/mail.php as mentioned in the documentation to use the same from address for all of my emails being sent. This works as expected. However, when I attempt to explicitly set a from address within the build function of a Mailable class, the global address is still used. Is there something I could be missing, all of this seems to come straight from the documentation for 5.4. My Mailable class is as follows (there is definitely a value in the $this->email property as it is displayed when echoed):

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;

class ContactMessage extends Mailable
{
    use Queueable, SerializesModels;

    public $user_email;
    public $user_message;

    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct($user_email, $user_message)
    {
        $this->user_email = $user_email;
        $this->user_message = $user_message;
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
//        echo '
';
//        echo var_export($this->user_email, true);
//        echo '

';
//        echo var_export($this->message, true);
//        die;

        return $this->from($this->user_email)
                ->subject('Contact Message')
                ->view('mail.contactMessage');
    }

}


问:
Change dataframe in sample by sampling unit format to incidence-frequency format (Prep dataframe for iNext incidence dataframe)
I have a dataframe like so:

```<code>df<- data.frame(region = c("1","1","1","1","1","2","3","3","3"),
                loc = c("104","104","104","105","105","106","107", "108", "109"),
                interact = c("A_B","A_B", "B_C", "C_D", "A_B", "E_F", "E_F", "F_G", "A_B"))
</code>```

I would like to make a dataframe that:

1) counts the incidence frequency of a given interaction occurring among loc levels for each region subset. Therefore, in the example above, in region 1 there are two loc (104 and 105) that both have the interact A_B. Thus, the incidence frequency of A_B for region 1 = 2. Duplicate interact levels in the same loc are not counted. So while A_B occurs 3 times in region 1, it occurs only in two unique loc. The incidence frequency counts how many unique loc level this interact occurs in.

2) The new dataframe should vectorize all possible interact levels among all regions, and count incidences of these for each region. As a consequence,  0's should be included for all levels of interact that did not occur in that region.

3) The first row needs to be a count of unique loc levels in that region. In region1 there were 2 loc levels(104,105), region2 1 loc level(106) and  in region 3, 3 loc levels(107-109).

The final output will look like:

```<code>output<- data.frame(interact = c("","A_B","B_C","C_D","E_F","F_G"),
                    region1 = c("2","2","1","0","1","0"),
                    region2 = c("1","0","0","0","1","0"),
                    region3 = c("3","1","0","0","1","1"))
</code>```

I do not know where to start with this, but here is what I have adapted from @akrun in a similar question posted on Convert from long to wide format counting frequency of eliminated factor level (Prepping dataframe for input into iNEXT Online), but get errors with:

```<code>library(tidyverse)
df %>%
 group_by(region = paste0('region', region)) %>%
        summarise(interact = "", V1 = n_distinct(loc)) %>%
        spread(region, V1),
      df %>%
        group_by(region = paste0('region', region) & loc),
                interact = as.character(interact)) %>%
        summarise(V1 = length(unique((interact)) %>%
        spread(region, V1, fill = 0))
</code>```

答:
With the clarifying comment (and re-reading the question), I'm amending my advice, but it's still using base-R methods. Try this instead:

```<code> my_table <- with(df, table(interact, loc, region) )
 apply(my_table, c(1,3), function(x){sum(x > 0)})
   # 2nd arg to apply ( 1 & 3) give num of pos "loc"'s by interact and region
</code>```

will give you:

```<code>        region
interact 1 2 3
     A_B 2 0 1
     B_C 1 0 0
     C_D 1 0 0
     E_F 0 1 1
     F_G 0 0 1
</code>```

If you really need to relabel the region dimension, that's not particularly difficult. This is how I would proceed (assuming you assigned that value to collapse_tbl:

```<code>colnames(collapse_tbl) <-
           paste0 ("region",  attr( collapse_tbl, 'dimnames')$region)
collapse_tbl
        region
interact region1 region2 region3
     A_B       2       0       1
     B_C       1       0       0
     C_D       1       0       0
     E_F       0       1       1
     F_G       0       0       1
</code>```

That is a matrix-object, rather than a dataframe. And unlike an R 'table'-object, you can use as.data.frame if you want it in that class. The "natural" way to handle data is to use the "long" arrangement. You can still use the usual indexing with matrix (or table) objects.

```<code>> collapse_tbl["F_G", "region3"]
[1] 1
</code>```

The xtabs function is often used for this purpose. Both table and xtabs are in the "original-R-verse".

Body:
I have a dataframe like so:

df<- data.frame(region = c("1","1","1","1","1","2","3","3","3"),
                loc = c("104","104","104","105","105","106","107", "108", "109"),
                interact = c("A_B","A_B", "B_C", "C_D", "A_B", "E_F", "E_F", "F_G", "A_B"))

I would like to make a dataframe that:

1) counts the incidence frequency of a given interaction occurring among loc levels for each region subset. Therefore, in the example above, in region 1 there are two loc (104 and 105) that both have the interact A_B. Thus, the incidence frequency of A_B for region 1 = 2. Duplicate interact levels in the same loc are not counted. So while A_B occurs 3 times in region 1, it occurs only in two unique loc. The incidence frequency counts how many unique loc level this interact occurs in.

2) The new dataframe should vectorize all possible interact levels among all regions, and count incidences of these for each region. As a consequence,  0's should be included for all levels of interact that did not occur in that region.

3) The first row needs to be a count of unique loc levels in that region. In region1 there were 2 loc levels(104,105), region2 1 loc level(106) and  in region 3, 3 loc levels(107-109).

The final output will look like:

output<- data.frame(interact = c("","A_B","B_C","C_D","E_F","F_G"),
                    region1 = c("2","2","1","0","1","0"),
                    region2 = c("1","0","0","0","1","0"),
                    region3 = c("3","1","0","0","1","1"))

I do not know where to start with this, but here is what I have adapted from @akrun in a similar question posted on Convert from long to wide format counting frequency of eliminated factor level (Prepping dataframe for input into iNEXT Online), but get errors with:

library(tidyverse)
df %>%
 group_by(region = paste0('region', region)) %>%
        summarise(interact = "", V1 = n_distinct(loc)) %>%
        spread(region, V1),
      df %>%
        group_by(region = paste0('region', region) & loc),
                interact = as.character(interact)) %>%
        summarise(V1 = length(unique((interact)) %>%
        spread(region, V1, fill = 0))

Body:
With the clarifying comment (and re-reading the question), I'm amending my advice, but it's still using base-R methods. Try this instead:

 my_table <- with(df, table(interact, loc, region) )
 apply(my_table, c(1,3), function(x){sum(x > 0)})
   # 2nd arg to apply ( 1 & 3) give num of pos "loc"'s by interact and region

will give you:

        region
interact 1 2 3
     A_B 2 0 1
     B_C 1 0 0
     C_D 1 0 0
     E_F 0 1 1
     F_G 0 0 1

If you really need to relabel the region dimension, that's not particularly difficult. This is how I would proceed (assuming you assigned that value to collapse_tbl:

colnames(collapse_tbl) <-
           paste0 ("region",  attr( collapse_tbl, 'dimnames')$region)
collapse_tbl
        region
interact region1 region2 region3
     A_B       2       0       1
     B_C       1       0       0
     C_D       1       0       0
     E_F       0       1       1
     F_G       0       0       1

That is a matrix-object, rather than a dataframe. And unlike an R 'table'-object, you can use as.data.frame if you want it in that class. The "natural" way to handle data is to use the "long" arrangement. You can still use the usual indexing with matrix (or table) objects.

> collapse_tbl["F_G", "region3"]
[1] 1

The xtabs function is often used for this purpose. Both table and xtabs are in the "original-R-verse".


问:
Error: setuid user id does not exist npm ERR! when npm install forever -g
os: debian 7

node.js is installed in the defalut folder .

root@10-4-4-159:/usr/local# npm install forever -g

npm ERR! Error: setuid user id does not exist

npm ERR!     at /usr/local/lib/node_modules/npm/node_modules/uid-number/uid-number.js:44:16

npm ERR!     at ChildProcess.exithandler (child_process.js:635:7)

npm ERR!     at ChildProcess.EventEmitter.emit (events.js:98:17)

npm ERR!     at maybeClose (child_process.js:735:16)

npm ERR!     at Process.ChildProcess._handle.onexit (child_process.js:802:5)

npm ERR! If you need help, you may report this log at:

npm ERR!     http://github.com/isaacs/npm/issues

npm ERR! or email it to:

npm ERR!

npm ERR! System Linux 3.2.0-4-amd64

npm ERR! command "/usr/local/bin/node" "/usr/local/bin/npm" "install" "forever" "-g"

npm ERR! cwd /usr/local

npm ERR! node -v v0.10.21

npm ERR! npm -v 1.3.11

npm ERR!

npm ERR! Additional logging details can be found in:

npm ERR!     /usr/local/npm-debug.log

npm ERR! not ok code 0

答:
Root cause: npm assumes nobody as user while calling process.getuid, which fails if your system does not have an user called nobody.

Solution: create a new user called nobody and try again!

sudo adduser --no-create-home --shell /dev/null --disabled-password --disabled-login --gecos '' nobody


问:
Is there a distributed VCS that can manage large files?
Is there a distributed version control system (git, bazaar, mercurial, darcs etc.) that can handle files larger than available RAM?

I need to be able to commit large binary files (i.e. datasets, source video/images, archives), but I don't need to be able to diff them, just be able to commit and then update when the file changes.

I last looked at this about a year ago, and none of the obvious candidates allowed this, since they're all designed to diff in memory for speed. That left me with a VCS for managing code and something else ("asset management" software or just rsync and scripts) for large files, which is pretty ugly when the directory structures of the two overlap.

答:
I came to the conclusion that the best solution in this case would be to use the ZFS.

Yes ZFS is not a DVCS but:

You can allocate space for repository via creating new FS

You can track changes by creating snapshots

You can send snapshots (commits) to another ZFS dataset

OwnerDisplayName: joelhardi

LastEditorDisplayName: joelhardi


问:
ArgumentError in AttendancesController#create
Sorry for ask but i've have like 40 hours with this problem, (I´m a newbie) I've reviewed similar questions related to this error but haven't been able to find a solution.

I have a Branch model who has Employees, those Employees have Attendances so when I want to save attendances to Employees I got this error:
https://s3.amazonaws.com/refaccionariasdelvalle/rails-error.png

Error Code

```<code>ArgumentError in AttendancesController#create
wrong number of arguments (given 0, expected 1)

Extracted source (around line #82):
 80
 81
 82 def attendance_params(my_params)
 83  my_params.permit(:present, :employee_id)
 84 end
 85
</code>```

My Controller:

```<code>class AttendancesController < ApplicationController
 before_action :authenticate_user!
 load_and_authorize_resource
 before_action :set_and_authorize_branch, except: :index_employees
 layout :user_profile_layout

def show
 @attendances = Attendance.joins(:employee).where(date: params[:date], employee_id: @branch.employees.ids).order('first_name')
 @date = Date.parse(params[:date])
end

def index_employees
 @employee = Employee.find(params[:id])
 @attendances = @employee.attendances
 @events = []
 @attendances.each do |attendance|
  event = {}
  event[:title] = attendance.present.to_s
  event[:start] = attendance.date.to_s
  event[:rendering] = "background"
  attendance.present ? event[:backgroundColor] = "#9EB25D" :
  event[:backgroundColor] = "#CC4B4B"
  @events << event
 end
end

def new
 redirect_to attendance_branch_path(id: @branch, date: Date.today) if !Attendance.where(date: Date.today, employee_id: @branch.employees.ids).empty?
 @attendances = []
 @branch.employees.each do |employee|
  @attendances << Attendance.new(employee_id: employee.id)
 end
 @attendances = @attendances.sort_by { |att| att.employee.first_name }
end

def create
 params[:attendances].each do |attendance|
  new_attendance = Attendance.new(attendance_params(attendance))
  new_attendance.date = Date.today
  new_attendance.save
 end
redirect_to branch_class_path(@branch), notice: 'Attendance taken
successfully'
end

def edit
 @attendances = Attendance.joins(:employee).where(date: params[:date],
 employee_id: @branch.employees.ids).order('first_name')
 @date = Date.parse(params[:date])
end

def update
 params[:attendances].each do |id, params|
  attendance = Attendance.find(id)
  attendance.update(attendance_params(params))
 end
redirect_to attendance_branch_path(id: @branch, date: params[:date])
end

private

def user_profile_layout
 if  user_signed_in?  && current_user.role.name === "Branch"
  "layout_for_user_branch"
 #elsif  user_signed_in?  && current_user.role.name === "Admin"
 else
  "application_for_user_admin"
 end
end

def set_and_authorize_branch
 @branch = Branch.find(params[:id])
end

def attendance_params(my_params)
 my_params.permit(:present, :employee_id)
end

end
</code>```

My Model:

```<code>class Attendance < ApplicationRecord
 belongs_to :employee
 validates :employee_id, uniqueness: { scope: :date }
end
</code>```

attendances/_form.html.erb

```<code><%= form_tag path, form_options do %>
    <h4>Swipe left for absent, right for present!</h4>
      <div class="attendance">
        <% @attendances.each_with_index do |attendance, index| %>
          <%= fields_for 'attendances[]', attendance do |f| %>
            <div class="attendance-card <%= set_background_color(attendance) %>" data-id="<%= attendance.employee.id %>">
              <div class="employee-name">
                <h4><%= attendance.employee.first_name %> <%= attendance.employee.last_name.first %>.</h4>
              </div>
              <div class="attendance-status">
                <% if attendance.present %>
                  <div class="employee-present"><i class="fa fa-check color-green" aria-hidden="true"></i></div>
                <% elsif attendance.present == false %>
                  <div class="employee-absent"><i class="fa fa-times color-red" aria-hidden="true"></i></div>
                <% else %>
                  <% if index == 0 %>
                    <div class="swipe-instructions-left"><i class="fa fa-hand-o-left color-red floating-horizontal-left" aria-hidden="true"></i></i></div>
                    <div class="swipe-instructions-right"><i class="fa fa-hand-o-right color-green floating-horizontal-right" aria-hidden="true"></i></div>
                  <% end %>
                <% end %>
              </div>
              <%= f.text_field :present, type: 'hidden'%>
              <%= f.text_field :employee_id, type: 'hidden'%>
            </div>
          <% end %>
        <% end %>
      </div>
      <div class="sticky-footer">
        <input class='btn edu-button' type="submit" value="Submit" form="attendance">
      </div>
    <% end %>

    <script>
      var swipe_present = function() {
        $('.attendance-card').hammer().bind("swiperight", function(event){
          var id = $(this).attr('data-id');
          $('[data-id=' + id + '] input').first().val('true');
          var $employee = $('[data-id=' + id + '].attendance-card');
          $employee.removeClass("attendance-red");
          $employee.addClass("attendance-green");
          $('[data-id=' + id + '] .attendance-status').html('<div class="employee-present"><i class="fa fa-check color-green" aria-hidden="true"></i></div>');
          $employee.hide("slide", {direction: "right"}, 200, function(){
            $employee.appendTo('.attendance').show();
          });
        });
      };
      var swipe_absent = function(){
        $('.attendance-card').hammer().bind("swipeleft", function(event){
          var id = $(this).attr('data-id');
          $('[data-id=' + id + '] input').first().val('false');
          var $employee = $('[data-id=' + id + '].attendance-card');
          $employee.removeClass("attendance-green");
          $employee.addClass("attendance-red");
          $('[data-id=' + id + '] .attendance-status').html('<div class="employee-absent"><i class="fa fa-times color-red" aria-hidden="true"></i></div>');
          $employee.hide("slide", {direction: "left"}, 200, function(){
            $employee.appendTo('.attendance').show();
          });
        });
      };
      $(document).ready(function(){
        swipe_present();
        swipe_absent();
      });
    </script>
</code>```

routes

```<code>resources :branches do
      resources :employees, only: [ :index, :new, :create ]
      member do
        resources :attendances, only: [ :new, :create ]
        get 'attendance/:date', to: 'attendances#show', as: 'attendance'
        get 'attendance/:date/edit', to: 'attendances#edit', as: 'edit_attendance'
        patch 'attendance/:date', to: 'attendances#update', as: 'update_attendance'
      end
    end
</code>```

table

```<code>create_table "attendances", force: :cascade do |t|
 t.date     "date"
 t.boolean  "present"
 t.boolean  "excused"
 t.integer  "employee_id"
 t.datetime "created_at",  null: false
 t.datetime "updated_at",  null: false
 t.index ["employee_id", "created_at"], name: "index_attendances_on_employee_id_and_created_at", using: :btree
 t.index ["employee_id"], name: "index_attendances_on_employee_id", using: :btree
end
</code>```

I think the problem is in the way I pass the value of boolean :present to the DB but if so, anyway I do not know how to make it work.

Thanks for the help!

Update

First off all, thanks to @Sebastían, @Gerry and @Pavan for the interest on help me.

Now, how is this working from the console but not from the application?

```<code>2.3.0 :019 >   Employee.where(branch_id: b).each do |e|
2.3.0 :020 >     new_attendance = Attendance.new(employee_id: e.id, date: Date.today)
2.3.0 :021?>   new_attendance.present = [true, false].sample
2.3.0 :022?>   new_attendance.save
2.3.0 :023?>   end

Employee Load (0.7ms)  SELECT "employees".* FROM "employees" WHERE "employees"."branch_id" = 3
(0.2ms)  BEGIN
Attendance Exists (0.5ms)  SELECT  1 AS one FROM "attendances" WHERE "attendances"."employee_id" = $1 AND "attendances"."date" = $2 LIMIT $3  [["employee_id", 4], ["date", Sat, 08 Jul 2017], ["LIMIT", 1]]
(0.6ms)  SELECT MAX("attendances"."id") FROM "attendances"
SQL (1.3ms)  INSERT INTO "attendances" ("id", "date", "present", "employee_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id"  [["id", 35], ["date", Sat, 08 Jul 2017], ["present", true], ["employee_id", 4], ["created_at", 2017-07-08 18:51:01 UTC], ["updated_at", 2017-07-08 18:51:01 UTC]]
(5.8ms)  COMMIT
(0.3ms)  BEGIN
Attendance Exists (0.5ms)  SELECT  1 AS one FROM "attendances" WHERE "attendances"."employee_id" = $1 AND "attendances"."date" = $2 LIMIT $3  [["employee_id", 2], ["date", Sat, 08 Jul 2017], ["LIMIT", 1]]
(0.5ms)  SELECT MAX("attendances"."id") FROM "attendances"
SQL (0.6ms)  INSERT INTO "attendances" ("id", "date", "present", "employee_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id"  [["id", 36], ["date", Sat, 08 Jul 2017], ["present", false], ["employee_id", 2], ["created_at", 2017-07-08 18:51:01 UTC], ["updated_at", 2017-07-08 18:51:01 UTC]]
(5.9ms)  COMMIT
</code>```

Create Action

```<code>def create
 params[:attendances].each do |attendance|
  new_attendance = Attendance.new(attendance_params(attendance))
  new_attendance.date = Date.today
  new_attendance.save
 end
 redirect_to attendance_branch_path(id: @branch, date: new_attendance.date), notice: 'Attendance taken successfully'
end
</code>```

Update Action

```<code>def update
 params[:attendances].each do |id, params|
  attendance = Attendance.find(id)
  attendance.update(attendance_params(params))
 end
 redirect_to attendance_branch_path(id: @branch, date: params[:date])
end
</code>```

Params

```<code>def attendance_params(my_params)
 my_params.permit(:present, :employee_id)
end
</code>```

And after create those records from console, I´m able to go to application and make updates on those records and works fine.
But if I go to console and delete those 2 last records previously created to make it appear again for mark the attendance in the the application I get the same error:

```<code>class AttendancesController < ApplicationController
 before_action :authenticate_user!
 load_and_authorize_resource
 before_action :set_and_authorize_branch, except: :index_employees
 layout :user_profile_layout

def show
 @attendances = Attendance.joins(:employee).where(date: params[:date], employee_id: @branch.employees.ids).order('first_name')
 @date = Date.parse(params[:date])
end

def index_employees
 @employee = Employee.find(params[:id])
 @attendances = @employee.attendances
 @events = []
 @attendances.each do |attendance|
  event = {}
  event[:title] = attendance.present.to_s
  event[:start] = attendance.date.to_s
  event[:rendering] = "background"
  attendance.present ? event[:backgroundColor] = "#9EB25D" :
  event[:backgroundColor] = "#CC4B4B"
  @events << event
 end
end

def new
 redirect_to attendance_branch_path(id: @branch, date: Date.today) if !Attendance.where(date: Date.today, employee_id: @branch.employees.ids).empty?
 @attendances = []
 @branch.employees.each do |employee|
  @attendances << Attendance.new(employee_id: employee.id)
 end
 @attendances = @attendances.sort_by { |att| att.employee.first_name }
end

def create
 params[:attendances].each do |attendance|
  new_attendance = Attendance.new(attendance_params(attendance))
  new_attendance.date = Date.today
  new_attendance.save
 end
redirect_to branch_class_path(@branch), notice: 'Attendance taken
successfully'
end

def edit
 @attendances = Attendance.joins(:employee).where(date: params[:date],
 employee_id: @branch.employees.ids).order('first_name')
 @date = Date.parse(params[:date])
end

def update
 params[:attendances].each do |id, params|
  attendance = Attendance.find(id)
  attendance.update(attendance_params(params))
 end
redirect_to attendance_branch_path(id: @branch, date: params[:date])
end

private

def user_profile_layout
 if  user_signed_in?  && current_user.role.name === "Branch"
  "layout_for_user_branch"
 #elsif  user_signed_in?  && current_user.role.name === "Admin"
 else
  "application_for_user_admin"
 end
end

def set_and_authorize_branch
 @branch = Branch.find(params[:id])
end

def attendance_params(my_params)
 my_params.permit(:present, :employee_id)
end

end
</code>```0

I really don´t understand

答:
strong_params doesn't take arguments. You can mark as required a hash that'll go through your params to your controller and there to specify the permitted keys.

So, instead defining attendance_params to expect for an argument called my_params, then you can just make it a "non-argument" method, and there instead working with my_params, then use the params instance public method which will return a new ActionController::Parameters object, which is initialized with the request.parameters.

You could try with:

```<code>def attendance_params
  params.permit(:present, :employee_id)
end
</code>```

Body:
Sorry for ask but i've have like 40 hours with this problem, (I´m a newbie) I've reviewed similar questions related to this error but haven't been able to find a solution.

I have a Branch model who has Employees, those Employees have Attendances so when I want to save attendances to Employees I got this error:
https://s3.amazonaws.com/refaccionariasdelvalle/rails-error.png

Error Code

ArgumentError in AttendancesController#create
wrong number of arguments (given 0, expected 1)

Extracted source (around line #82):
 80
 81
 82 def attendance_params(my_params)
 83  my_params.permit(:present, :employee_id)
 84 end
 85

My Controller:

class AttendancesController < ApplicationController
 before_action :authenticate_user!
 load_and_authorize_resource
 before_action :set_and_authorize_branch, except: :index_employees
 layout :user_profile_layout

def show
 @attendances = Attendance.joins(:employee).where(date: params[:date], employee_id: @branch.employees.ids).order('first_name')
 @date = Date.parse(params[:date])
end

def index_employees
 @employee = Employee.find(params[:id])
 @attendances = @employee.attendances
 @events = []
 @attendances.each do |attendance|
  event = {}
  event[:title] = attendance.present.to_s
  event[:start] = attendance.date.to_s
  event[:rendering] = "background"
  attendance.present ? event[:backgroundColor] = "#9EB25D" :
  event[:backgroundColor] = "#CC4B4B"
  @events << event
 end
end

def new
 redirect_to attendance_branch_path(id: @branch, date: Date.today) if !Attendance.where(date: Date.today, employee_id: @branch.employees.ids).empty?
 @attendances = []
 @branch.employees.each do |employee|
  @attendances << Attendance.new(employee_id: employee.id)
 end
 @attendances = @attendances.sort_by { |att| att.employee.first_name }
end

def create
 params[:attendances].each do |attendance|
  new_attendance = Attendance.new(attendance_params(attendance))
  new_attendance.date = Date.today
  new_attendance.save
 end
redirect_to branch_class_path(@branch), notice: 'Attendance taken
successfully'
end

def edit
 @attendances = Attendance.joins(:employee).where(date: params[:date],
 employee_id: @branch.employees.ids).order('first_name')
 @date = Date.parse(params[:date])
end

def update
 params[:attendances].each do |id, params|
  attendance = Attendance.find(id)
  attendance.update(attendance_params(params))
 end
redirect_to attendance_branch_path(id: @branch, date: params[:date])
end

private

def user_profile_layout
 if  user_signed_in?  && current_user.role.name === "Branch"
  "layout_for_user_branch"
 #elsif  user_signed_in?  && current_user.role.name === "Admin"
 else
  "application_for_user_admin"
 end
end

def set_and_authorize_branch
 @branch = Branch.find(params[:id])
end

def attendance_params(my_params)
 my_params.permit(:present, :employee_id)
end

end

My Model:

class Attendance < ApplicationRecord
 belongs_to :employee
 validates :employee_id, uniqueness: { scope: :date }
end

attendances/_form.html.erb

<%= form_tag path, form_options do %>

Swipe left for absent, right for present!

        <% @attendances.each_with_index do |attendance, index| %>
          <%= fields_for 'attendances[]', attendance do |f| %>
            <div class="attendance-card <%= set_background_color(attendance) %>" data-id="<%= attendance.employee.id %>">

<%= attendance.employee.first_name %> <%= attendance.employee.last_name.first %>.

                <% if attendance.present %>

                <% elsif attendance.present == false %>

                <% else %>
                  <% if index == 0 %>

                  <% end %>
                <% end %>

              <%= f.text_field :present, type: 'hidden'%>
              <%= f.text_field :employee_id, type: 'hidden'%>

          <% end %>
        <% end %>

        <input class='btn edu-button' type="submit" value="Submit" form="attendance">

    <% end %>

routes

resources :branches do
      resources :employees, only: [ :index, :new, :create ]
      member do
        resources :attendances, only: [ :new, :create ]
        get 'attendance/:date', to: 'attendances#show', as: 'attendance'
        get 'attendance/:date/edit', to: 'attendances#edit', as: 'edit_attendance'
        patch 'attendance/:date', to: 'attendances#update', as: 'update_attendance'
      end
    end

table

create_table "attendances", force: :cascade do |t|
 t.date     "date"
 t.boolean  "present"
 t.boolean  "excused"
 t.integer  "employee_id"
 t.datetime "created_at",  null: false
 t.datetime "updated_at",  null: false
 t.index ["employee_id", "created_at"], name: "index_attendances_on_employee_id_and_created_at", using: :btree
 t.index ["employee_id"], name: "index_attendances_on_employee_id", using: :btree
end

I think the problem is in the way I pass the value of boolean :present to the DB but if so, anyway I do not know how to make it work.

Thanks for the help!

Update

First off all, thanks to @Sebastían, @Gerry and @Pavan for the interest on help me.

Now, how is this working from the console but not from the application?

2.3.0 :019 >   Employee.where(branch_id: b).each do |e|
2.3.0 :020 >     new_attendance = Attendance.new(employee_id: e.id, date: Date.today)
2.3.0 :021?>   new_attendance.present = [true, false].sample
2.3.0 :022?>   new_attendance.save
2.3.0 :023?>   end

Employee Load (0.7ms)  SELECT "employees".* FROM "employees" WHERE "employees"."branch_id" = 3
(0.2ms)  BEGIN
Attendance Exists (0.5ms)  SELECT  1 AS one FROM "attendances" WHERE "attendances"."employee_id" = $1 AND "attendances"."date" = $2 LIMIT $3  [["employee_id", 4], ["date", Sat, 08 Jul 2017], ["LIMIT", 1]]
(0.6ms)  SELECT MAX("attendances"."id") FROM "attendances"
SQL (1.3ms)  INSERT INTO "attendances" ("id", "date", "present", "employee_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id"  [["id", 35], ["date", Sat, 08 Jul 2017], ["present", true], ["employee_id", 4], ["created_at", 2017-07-08 18:51:01 UTC], ["updated_at", 2017-07-08 18:51:01 UTC]]
(5.8ms)  COMMIT
(0.3ms)  BEGIN
Attendance Exists (0.5ms)  SELECT  1 AS one FROM "attendances" WHERE "attendances"."employee_id" = $1 AND "attendances"."date" = $2 LIMIT $3  [["employee_id", 2], ["date", Sat, 08 Jul 2017], ["LIMIT", 1]]
(0.5ms)  SELECT MAX("attendances"."id") FROM "attendances"
SQL (0.6ms)  INSERT INTO "attendances" ("id", "date", "present", "employee_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id"  [["id", 36], ["date", Sat, 08 Jul 2017], ["present", false], ["employee_id", 2], ["created_at", 2017-07-08 18:51:01 UTC], ["updated_at", 2017-07-08 18:51:01 UTC]]
(5.9ms)  COMMIT

Create Action

def create
 params[:attendances].each do |attendance|
  new_attendance = Attendance.new(attendance_params(attendance))
  new_attendance.date = Date.today
  new_attendance.save
 end
 redirect_to attendance_branch_path(id: @branch, date: new_attendance.date), notice: 'Attendance taken successfully'
end

Update Action

def update
 params[:attendances].each do |id, params|
  attendance = Attendance.find(id)
  attendance.update(attendance_params(params))
 end
 redirect_to attendance_branch_path(id: @branch, date: params[:date])
end

Params

def attendance_params(my_params)
 my_params.permit(:present, :employee_id)
end

And after create those records from console, I´m able to go to application and make updates on those records and works fine.
But if I go to console and delete those 2 last records previously created to make it appear again for mark the attendance in the the application I get the same error:

ArgumentError in AttendancesController#create
 wrong number of arguments (given 0, expected 1)

 Extracted source (around line #81):

  81: def attendance_params(my_params)
  82:  my_params.permit(:present, :employee_id)
  83: end

I really don´t understand

Body:
strong_params doesn't take arguments. You can mark as required a hash that'll go through your params to your controller and there to specify the permitted keys.

So, instead defining attendance_params to expect for an argument called my_params, then you can just make it a "non-argument" method, and there instead working with my_params, then use the params instance public method which will return a new ActionController::Parameters object, which is initialized with the request.parameters.

You could try with:

def attendance_params
  params.permit(:present, :employee_id)
end


问:
Determine if a character appears before first occurrence of another character
I want to be able to input a list of letters (there are only four options for letters in the list), however the list can be up to ten or so items long, for example:

```<code>letter_options = ['A', 'B', 'C', 'D']

s = ['B', 'C', 'A', 'C', 'D', 'A']
s = ['C', 'A', 'D', 'C', 'A']
s = ['A', 'B', 'A', 'A', 'D', 'B', 'B']
</code>```

My question is how would I go about determining if 'B' occurs before a 'D' or an 'A' occurs? If 'B' does not exist in the list, then the code would output 0. If 'B' does occur before an 'A' or 'D', then the code would output 1.

Here is what I have, but it does not work for the case where 'B' does not occur.

```<code>letters = ['A', 'A', 'A', 'A']
fkt = []

check = ' '.join(letters).split('B')[0].split()
if letters!=[] and letters[0]=='B':
    fkt.append(1)
elif letters!=[] and any(idx in check for idx in ['A', 'D']):
    fkt.append(0)
else:
    fkt.append(1)
</code>```

答:
You could try this method:

```<code>def code(lst):
    for i in lst:
        # loop through the list, if find the element A or D, return 0 and break out of
        # the loop
        if i in ['A', 'D']:
            return 0
        # if find B, return 1 and break out of the loop
        elif i == 'B':
            return 1
    # if not find B at all return 0 and break out of the loop
    return 0

s1 = ['B', 'C', 'A', 'C', 'D', 'A']
s2 = ['C', 'A', 'D', 'C', 'A']
s3 = ['A', 'B', 'A', 'A', 'D', 'B', 'B']

code(s1)
#1

code(s2)
#0

code(s3)
#0
</code>```

Or equivalently:

```<code>bfirst = 0
for i in lst:
    if i in ['A', 'D']:
        bfirst = 0
        break
    elif i == 'B':
        bfirst = 1
        break
</code>```

Justification:

Use a simple for loop, and if else to check values, if 'AD' were found firstly, then bfirst is 0 and short circuit (break out of the loop), since there is no need to check other elements anymore; Similarly if 'B' was found firstly, then assign bfirst 1 and short circuit (break out of the loop) for the same reason above; If you have a long list and very few options of letters, this would potentially be very efficient since it only checks a few letters at the beginning of the list without having to thoroughly loop through the list; Under the worst cases (the list is totally made up irrelevant letters), it is still O(N), one pass of the list.

Body:
I want to be able to input a list of letters (there are only four options for letters in the list), however the list can be up to ten or so items long, for example:

letter_options = ['A', 'B', 'C', 'D']

s = ['B', 'C', 'A', 'C', 'D', 'A']
s = ['C', 'A', 'D', 'C', 'A']
s = ['A', 'B', 'A', 'A', 'D', 'B', 'B']

My question is how would I go about determining if 'B' occurs before a 'D' or an 'A' occurs? If 'B' does not exist in the list, then the code would output 0. If 'B' does occur before an 'A' or 'D', then the code would output 1.

Here is what I have, but it does not work for the case where 'B' does not occur.

letters = ['A', 'A', 'A', 'A']
fkt = []

check = ' '.join(letters).split('B')[0].split()
if letters!=[] and letters[0]=='B':
    fkt.append(1)
elif letters!=[] and any(idx in check for idx in ['A', 'D']):
    fkt.append(0)
else:
    fkt.append(1)

Body:
You could try this method:

def code(lst):
    for i in lst:
        # loop through the list, if find the element A or D, return 0 and break out of
        # the loop
        if i in ['A', 'D']:
            return 0
        # if find B, return 1 and break out of the loop
        elif i == 'B':
            return 1
    # if not find B at all return 0 and break out of the loop
    return 0

s1 = ['B', 'C', 'A', 'C', 'D', 'A']
s2 = ['C', 'A', 'D', 'C', 'A']
s3 = ['A', 'B', 'A', 'A', 'D', 'B', 'B']

code(s1)
#1

code(s2)
#0

code(s3)
#0

Or equivalently:

bfirst = 0
for i in lst:
    if i in ['A', 'D']:
        bfirst = 0
        break
    elif i == 'B':
        bfirst = 1
        break

Justification:

Use a simple for loop, and if else to check values, if 'AD' were found firstly, then bfirst is 0 and short circuit (break out of the loop), since there is no need to check other elements anymore; Similarly if 'B' was found firstly, then assign bfirst 1 and short circuit (break out of the loop) for the same reason above; If you have a long list and very few options of letters, this would potentially be very efficient since it only checks a few letters at the beginning of the list without having to thoroughly loop through the list; Under the worst cases (the list is totally made up irrelevant letters), it is still O(N), one pass of the list.


问:
How do I allow www-data user to execute bash script with nginx
I an Ubuntu 16.04 machine running NGINX and PHP. I would like to enable the www-data user (via web browser) to be able to access a PHP page (php-test.php) that will execute either a bash script (script_test.sh) or execute Linux CLI commands using shell_exec or exec.

I have done the following.

Created my bash script file script_test.sh

```<code>#!/bin/bash

whoami
echo $USER
echo 'test'

exit
</code>```

when I run this from CLI, using

```<code>./ script_test.sh
</code>```

It does indeed work and I can see the info echoed out in the CLI.

I then pursued the goal of being able to allow the www-data user run this bash script through a PHP page running on this same machine from NGINX.

I created my php page (php_test.php) and it contains the following

```<code><?php

    chdir('/path/to/my/files/');
    shell_exec('./script_test.sh');  // ATTEMPT RUN SCRIPT
    shell_exec('/path/to/my/files/script_test.sh');  // ATTEMPT RUN SCRIPT

    echo 'test 123';  // SIMPLE ECHO IN THE PHP PAGE
?>
</code>```

I then ran the following to modify the sudoers file, giving www-data access to the bash script

```<code>sudo nano /etc/sudoers
</code>```

to which I added the following line

```<code>www-data ALL=NOPASSWD: /path/to/my/files/script_test.sh
</code>```

I then made sure the script was executable, for the sake of my testing, not worrying about security, I just set it to 777 with the following command

```<code>sudo chmod 777 script_test.sh
</code>```

From there I opened a web browser and browsed to the localhost (NGINX) web server (php_test.php) and the only thing I see on the page is the 'test 123' that I echo from PHP... none of the bash script appears to have run at all.  I tailed the NGINX error log and don't see any error at all.

Is there another log that could contain clues on this?

What else should I check here?

答:
Can you try to use passthru instead of shell_exec, and see the output anything?

Also try this, and see if it shows on the log file:

```<code>if(file_exists('/path/to/my/files/script_test.sh')) { die('File not found!'); }
shell_exec("nohup /path/to/my/files/script_test.sh > /path/to/my/files/output.log &");
</code>```

Also, are you running PHP with the www-data user (check your fpm pool)?
Do you have any error on /var/log/syslog or /var/log/auth.log ?
Have you restarted the server after changing the sudo permissions?

What does su - www-data -c "whoami" and su - www-data -s /bin/bash -c "whoami" outputs?

Does su - www-data -s /bin/bash -c "/path/to/my/files/script_test.sh" output something?

Body:
I an Ubuntu 16.04 machine running NGINX and PHP. I would like to enable the www-data user (via web browser) to be able to access a PHP page (php-test.php) that will execute either a bash script (script_test.sh) or execute Linux CLI commands using shell_exec or exec.

I have done the following.

Created my bash script file script_test.sh

#!/bin/bash

whoami
echo $USER
echo 'test'

exit

when I run this from CLI, using

./ script_test.sh

It does indeed work and I can see the info echoed out in the CLI.

I then pursued the goal of being able to allow the www-data user run this bash script through a PHP page running on this same machine from NGINX.

I created my php page (php_test.php) and it contains the following

<?php

    chdir('/path/to/my/files/');
    shell_exec('./script_test.sh');  // ATTEMPT RUN SCRIPT
    shell_exec('/path/to/my/files/script_test.sh');  // ATTEMPT RUN SCRIPT

    echo 'test 123';  // SIMPLE ECHO IN THE PHP PAGE
?>

I then ran the following to modify the sudoers file, giving www-data access to the bash script

sudo nano /etc/sudoers

to which I added the following line

www-data ALL=NOPASSWD: /path/to/my/files/script_test.sh

I then made sure the script was executable, for the sake of my testing, not worrying about security, I just set it to 777 with the following command

sudo chmod 777 script_test.sh

From there I opened a web browser and browsed to the localhost (NGINX) web server (php_test.php) and the only thing I see on the page is the 'test 123' that I echo from PHP... none of the bash script appears to have run at all.  I tailed the NGINX error log and don't see any error at all.

Is there another log that could contain clues on this?

What else should I check here?

Body:
Can you try to use passthru instead of shell_exec, and see the output anything?

Also try this, and see if it shows on the log file:

if(file_exists('/path/to/my/files/script_test.sh')) { die('File not found!'); }
shell_exec("nohup /path/to/my/files/script_test.sh > /path/to/my/files/output.log &");

Also, are you running PHP with the www-data user (check your fpm pool)?
Do you have any error on /var/log/syslog or /var/log/auth.log ?
Have you restarted the server after changing the sudo permissions?

What does su - www-data -c "whoami" and su - www-data -s /bin/bash -c "whoami" outputs?

Does su - www-data -s /bin/bash -c "/path/to/my/files/script_test.sh" output something?


问:
Export JAR with Netbeans
How to export java project to JAR with Netbeans ? I cannot find options like in Eclipse.</p>

答:
You need to enable the option

Project Properties -> Build -> Packaging -> Build JAR after compiling

(but this is enabled by default)

Title: Export JAR with Netbeans


问:
file_get_contents echoes something, but fgets returns false
This is my code:

```<code><?php
                extract ($_POST);
                $fh = fopen ("./s.txt", "a");
                echo file_get_contents( "./s.txt" );
                if(($line = fgets($fh)) !== false) {}
                echo($line);
                file_put_contents("./signup.txt", "");

                if($line!=false && $line!='') {
                        echo '<script language="javascript">';echo 'alert($line)';echo '</script>';
                        fwrite ($fh, "$line \n");
                        $n = $line;
                }
                else {
                        fwrite ($fh, "$_POST[n] \n");
                        $n = $_POST[n];
                }
                fclose ($fh);

  $script = $_SERVER['PHP_SELF'];
  print <<<TOP
  <html>
  <body>
  <form method = "post" action = "$script">
  <table border = "1">
        <tr>
          <td> Name</td>
          <td> <input type = "text" value = "$n" name = "n" size = "30" /></td>
        </tr>

TOP;
  print <<<BOTTOM
  <tr><td><input type = "submit" name = "order" value = "Submit Order" /></td></tr>
  </table></form></body></html>
BOTTOM;
?>
</code>```

Basically, this has one entry spot which someone can enter into, and once someone enters into it, the data is written to a file. Every time after that the page is loaded, the data should be read from the file and set as the value to the input.

But when I load the program, enter "Word" as the field, and press submit, then open a new tab (to ensure it's not just the data being saved) and reenter the URL, "Word" is echoed as file_get_contents, but nothing is echoed for echo($line) and nothing is in the field for the input.

Why is this and how can I fix it?

答:
While this doesn't appear to be documented explicitly/clearly in php.net (I'll provide links to relevant documentations below), having just run a test on my end, I've found that fgets() will always return false if you run it on a file resource where you used 'a' as the mode in fopen()

This I imagine is a side-effect of the 'a' mode opening the file for writing only. Running the exact same test, using 'a+' (Open the file for writing and reading) as the mode instead, has both fgets() and file_get_contents() output 'word'. The fopen documentation has details on the different modes.

http://php.net/manual/en/function.fopen.php

http://php.net/manual/en/function.fgets.php

And a couple screenshots of my testing this on my end, if you want to see the code I tested with and the results yourself:

Body:
This is my code:

<?php
                extract ($_POST);
                $fh = fopen ("./s.txt", "a");
                echo file_get_contents( "./s.txt" );
                if(($line = fgets($fh)) !== false) {}
                echo($line);
                file_put_contents("./signup.txt", "");

                if($line!=false && $line!='') {
                        echo '';
                        fwrite ($fh, "$line \n");
                        $n = $line;
                }
                else {
                        fwrite ($fh, "$_POST[n] \n");
                        $n = $_POST[n];
                }
                fclose ($fh);

  $script = $_SERVER['PHP_SELF'];
  print <<<TOP

  <form method = "post" action = "$script">

           Name
           <input type = "text" value = "$n" name = "n" size = "30" />

TOP;
  print <<<BOTTOM

<input type = "submit" name = "order" value = "Submit Order" />

</form>
BOTTOM;
?>

Basically, this has one entry spot which someone can enter into, and once someone enters into it, the data is written to a file. Every time after that the page is loaded, the data should be read from the file and set as the value to the input.

But when I load the program, enter "Word" as the field, and press submit, then open a new tab (to ensure it's not just the data being saved) and reenter the URL, "Word" is echoed as file_get_contents, but nothing is echoed for echo($line) and nothing is in the field for the input.

Why is this and how can I fix it?


问:
matplotlab: plt.figure() creates empty figure
I am playing with the example at

https://github.com/seanabu/seanabu.github.io/blob/master/Seasonal_ARIMA_model_Portland_transit.ipynb

However, on my own Jupyter Notebook, the following piece of code creates an empty figure. Any idea? Thanks!

答: Try adding plt.show() at the end.

Body: Try adding plt.show() at the end.


问:
How to get Real IP from Visitor?
I'm using this PHP code to get a visitor's IP address:

```<code><?php echo $_SERVER['REMOTE_ADDR']; ?>
</code>```

But, I can't get the real IP address from visitors when they are using a proxy. Is there any way to get a visitor's IP address in this case?

答:
If the Proxy is which you trust, you can try: (Assume the Proxy IP is 151.101.2.10)

```<code><?php

$trustProxyIPs = ['151.101.2.10'];

$clientIP  = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : NULL;

if (in_array($clientIP, $trustProxyIPs)) {

    $headers = ['HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR'];

    foreach ($headers as $key => $header) {

        if (isset($_SERVER[$header]) && filter_var($_SERVER[$header], FILTER_VALIDATE_IP)) {

            $clientIP = $_SERVER[$header];

            break;
        }
    }
}

echo $clientIP;
</code>```

This will prevent forged forward header by direct requested clients, and get real IP via trusted Proxies.

Title: How to get Real IP from Visitor?

Body:
I'm using this PHP code to get a visitor's IP address:

<?php echo $_SERVER['REMOTE_ADDR']; ?>

But, I can't get the real IP address from visitors when they are using a proxy. Is there any way to get a visitor's IP address in this case?

Body:
If the Proxy is which you trust, you can try: (Assume the Proxy IP is 151.101.2.10)

<?php

$trustProxyIPs = ['151.101.2.10'];

$clientIP  = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : NULL;

if (in_array($clientIP, $trustProxyIPs)) {

    $headers = ['HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR'];

    foreach ($headers as $key => $header) {

        if (isset($_SERVER[$header]) && filter_var($_SERVER[$header], FILTER_VALIDATE_IP)) {

            $clientIP = $_SERVER[$header];

            break;
        }
    }
}

echo $clientIP;

This will prevent forged forward header by direct requested clients, and get real IP via trusted Proxies.


问:
How to grab the nth occurence of a float on a line using regex?
The text file I'm searching through looks like a lot of text blocks like this:

MKC,2017-06-23 07:54,-94.5930,39.1230,79.00,73.90,84.41,220.00,4.00,0.00,29.68,1003.90,10.00,M,FEW,M,M,M,9500.00,M,M,M,M,KMKC 230754Z 22004KT 10SM FEW095 26/23 A2968 RMK AO2 SLP039 T02610233

(That's all one line)

I'm looking to grab the 2nd occurrence in the line that matches r',\d\.\d{2},', which in this case would be 0.00

I don't know how to specify that I want the nth occurrence of the pattern.

Extra: I've never seen the first value that matches the same pattern go over 9.99, meaning 10.00 and then it would no longer match the same pattern, but it would be nice if there was a way to take this into account.

答:
You can avoid capturing all and save some resources (noticeable only on particularly large strings) by dynamically building your pattern to skip several occurrences and then capture your pattern:

```<code>def get_nth_occurrence(pattern, data, n=0):  # n is zero indexed
    result = re.search("(?:{0}.*?){{{1}}}({0})".format(pattern, n), data)
    return result.group(1) if result else None
</code>```

You can test it as:

```<code>test = "MKC,2017-06-23 07:54,-94.5930,39.1230,79.00,73.90,84.41,220.00,4.00,0.00,29.68," \
       "1003.90,10.00,M,FEW,M,M,M,9500.00,M,M,M,M,KMKC 230754Z 22004KT 10SM FEW095 26/23 " \
       "A2968 RMK AO2 SLP039 T02610233 "

print(get_nth_occurrence(r"\d+\.\d{2}", test, 1))  # 39.12
</code>```

Of course, this has a limited use as you cannot really create complex patterns this way - for example, if you used a group in your pattern it will return that group instead.

Body:
You can avoid capturing all and save some resources (noticeable only on particularly large strings) by dynamically building your pattern to skip several occurrences and then capture your pattern:

def get_nth_occurrence(pattern, data, n=0):  # n is zero indexed
    result = re.search("(?:{0}.*?){{{1}}}({0})".format(pattern, n), data)
    return result.group(1) if result else None

You can test it as:

test = "MKC,2017-06-23 07:54,-94.5930,39.1230,79.00,73.90,84.41,220.00,4.00,0.00,29.68," \
       "1003.90,10.00,M,FEW,M,M,M,9500.00,M,M,M,M,KMKC 230754Z 22004KT 10SM FEW095 26/23 " \
       "A2968 RMK AO2 SLP039 T02610233 "

print(get_nth_occurrence(r"\d+\.\d{2}", test, 1))  # 39.12

Of course, this has a limited use as you cannot really create complex patterns this way - for example, if you used a group in your pattern it will return that group instead.


问:
Does Idris support unfolding function definitions?
With dependent types, it's possible to define an inductive type for sorted lists, e.g.:

```<code>data IsSorted : {a: Type} -> (ltRel: (a -> a -> Type)) -> List a -> Type where
  IsSortedZero : IsSorted {a=a} ltRel Nil
  IsSortedOne : (x: a) -> IsSorted ltRel [x]
  IsSortedMany : (x: a) -> (y: a) -> .IsSorted rel (y::ys) -> .(rel x y) -> IsSorted rel (x::y::ys)
</code>```

This can then be used to reason about sorted lists.

In Coq, one could also write a function Fixpoint is_sorted: {A: Type} (l: List A) : bool, and then make use of a type like is_sorted someList = true to prove things, by unfolding the definition of is_sorted. Is this latter approach possible in Idris, or does it only support the former approach?

Furthermore, for my own understanding: is the latter case an example of "proof by reflection", and is there any situation in which the latter approach would be preferable to the former?

答:
I think the following partially does what you want (I will add the caveat that I have no experience of using Coq):

```<code>infixl 4 &

(&) : Bool -> Bool -> Bool
(&) True True = True
(&) _ _ = False

elim_and : x & y = True -> (x = True, y = True)
elim_and {x = False} {y = False} x_and_y_is_true = (x_and_y_is_true, x_and_y_is_true)
elim_and {x = False} {y = True} x_and_y_is_true = (x_and_y_is_true, Refl)
elim_and {x = True} {y = False} x_and_y_is_true = (Refl, x_and_y_is_true)
elim_and {x = True} {y = True} x_and_y_is_true = (Refl, Refl)

is_sorted : {a: Type} -> (ltRel: a -> a -> Bool) -> List a -> Bool
is_sorted ltRel [] = True
is_sorted ltRel (x :: []) = True
is_sorted ltRel (x :: y :: xs) = (ltRel x y) & (is_sorted ltRel (y :: xs))

is_sorted_true_elim : {x : a} -> is_sorted ltRel (x :: y :: xs) = True -> (ltRel x y = True,
                                                                           is_sorted ltRel (y :: xs) = True)
is_sorted_true_elim {x} {y} {xs} {ltRel} is_sorted_x_y_xs = elim_and is_sorted_x_y_xs
</code>```

The important detail is that if your function definition is a simple set of equations, then the unification will somewhat magically substitute one side of the equation for the other when required. (I used a less efficient non-shortcircuited version of the logical "and" operator, because the standard "&&" or "if/then/else" operators introduce complications of laziness.)

Ideally there should be some straightforward way to unfold definitions that include 'with'-based pattern matching, but I don't know how to make that work, eg:

```<code>is_sorted : {a: Type} -> (ltRel: a -> a -> Bool) -> List a -> Bool
is_sorted ltRel [] = True
is_sorted ltRel (x :: []) = True
is_sorted ltRel (x :: y :: xs) with (ltRel x y)
  | True = is_sorted ltRel (y :: xs)
  | False = False

is_sorted_true_elim : {x : a} -> is_sorted ltRel (x :: y :: xs) = True -> (ltRel x y = True,
                                                                           is_sorted ltRel (y :: xs) = True)
is_sorted_true_elim {x} {y} {xs} {ltRel} is_sorted_x_y_xs with (ltRel x y) proof x_lt_y_value
  | True = ?hole
  | False = ?hole2
</code>```

Body:
With dependent types, it's possible to define an inductive type for sorted lists, e.g.:

data IsSorted : {a: Type} -> (ltRel: (a -> a -> Type)) -> List a -> Type where
  IsSortedZero : IsSorted {a=a} ltRel Nil
  IsSortedOne : (x: a) -> IsSorted ltRel [x]
  IsSortedMany : (x: a) -> (y: a) -> .IsSorted rel (y::ys) -> .(rel x y) -> IsSorted rel (x::y::ys)

This can then be used to reason about sorted lists.

In Coq, one could also write a function Fixpoint is_sorted: {A: Type} (l: List A) : bool, and then make use of a type like is_sorted someList = true to prove things, by unfolding the definition of is_sorted. Is this latter approach possible in Idris, or does it only support the former approach?

Furthermore, for my own understanding: is the latter case an example of "proof by reflection", and is there any situation in which the latter approach would be preferable to the former?

Body:
I think the following partially does what you want (I will add the caveat that I have no experience of using Coq):

infixl 4 &

(&) : Bool -> Bool -> Bool
(&) True True = True
(&) _ _ = False

elim_and : x & y = True -> (x = True, y = True)
elim_and {x = False} {y = False} x_and_y_is_true = (x_and_y_is_true, x_and_y_is_true)
elim_and {x = False} {y = True} x_and_y_is_true = (x_and_y_is_true, Refl)
elim_and {x = True} {y = False} x_and_y_is_true = (Refl, x_and_y_is_true)
elim_and {x = True} {y = True} x_and_y_is_true = (Refl, Refl)

is_sorted : {a: Type} -> (ltRel: a -> a -> Bool) -> List a -> Bool
is_sorted ltRel [] = True
is_sorted ltRel (x :: []) = True
is_sorted ltRel (x :: y :: xs) = (ltRel x y) & (is_sorted ltRel (y :: xs))

is_sorted_true_elim : {x : a} -> is_sorted ltRel (x :: y :: xs) = True -> (ltRel x y = True,
                                                                           is_sorted ltRel (y :: xs) = True)
is_sorted_true_elim {x} {y} {xs} {ltRel} is_sorted_x_y_xs = elim_and is_sorted_x_y_xs

The important detail is that if your function definition is a simple set of equations, then the unification will somewhat magically substitute one side of the equation for the other when required. (I used a less efficient non-shortcircuited version of the logical "and" operator, because the standard "&&" or "if/then/else" operators introduce complications of laziness.)

Ideally there should be some straightforward way to unfold definitions that include 'with'-based pattern matching, but I don't know how to make that work, eg:

is_sorted : {a: Type} -> (ltRel: a -> a -> Bool) -> List a -> Bool
is_sorted ltRel [] = True
is_sorted ltRel (x :: []) = True
is_sorted ltRel (x :: y :: xs) with (ltRel x y)
  | True = is_sorted ltRel (y :: xs)
  | False = False

is_sorted_true_elim : {x : a} -> is_sorted ltRel (x :: y :: xs) = True -> (ltRel x y = True,
                                                                           is_sorted ltRel (y :: xs) = True)
is_sorted_true_elim {x} {y} {xs} {ltRel} is_sorted_x_y_xs with (ltRel x y) proof x_lt_y_value
  | True = ?hole
  | False = ?hole2