问:
How to play and pause the audio by using the media player?
I want to perform the three functions by using the single play button.
  First process - when we click the play button the mediaplayer should play the audio.
  second process - when user click second time the play button the audio should be paused.
  Third process - when user click the third time play button the audio should resume from the paused song.

The tried the below code

```<code> if (!mediaPlayer.isPlaying()) {
                mediaPlayer.reset();
                try {
                    mediaPlayer.setDataSource(path);
                    //  mediaPlayer.setOnPreparedListener((MediaPlayer.OnPreparedListener) getActivity());
                    mediaPlayer.prepare();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                mediaPlayer.start();

            }
           else if (mediaPlayer.isPlaying()) {
                mediaPlayer.pause();
            }

            else if (!mediaPlayer.isPlaying() && mediaPlayer.getCurrentPosition() > 0) {
                long currentPosition = mediaPlayer.getCurrentPosition();
                mediaPlayer.seekTo((int) currentPosition);
                mediaPlayer.start();

            }
</code>```

The above code is not working ,please help me how to solve this.

答:
You can try this</p>

```<code>protected void initViews(Context context) {
    mContext = context;
    oneTimeOnly = 0;
    mRootView = LayoutInflater.from(context).inflate(R.layout.view_digital_audio_content, this);
    btn_delete = (ImageButton) mRootView.findViewById(R.id.btn_delete);
    tv_current_duration = (TextView) mRootView.findViewById(R.id.tv_current_duration);
    tv_total_duration = (TextView) mRootView.findViewById(R.id.tv_total_duration);
    seekbar = (SeekBar) mRootView.findViewById(R.id.seekbar);
    btn_Play = (ImageButton) mRootView.findViewById(R.id.btn_play);
    seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
            if (mediaPlayer != null && fromUser) {
                mediaPlayer.seekTo(progress);
            }
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {

        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {

        }
    });

    initMediaPlayer();

    btn_delete.setOnClickListener(this);
    btn_Play.setOnClickListener(this);
}

private void initMediaPlayer() {
    transactionDetail = FCSingleton.getTransactionDetails();
    TransactionDetail.DigitalContent digitalContent = transactionDetail.getDigtalContent(DigitalContentActivity.DigitalContentType.AUDIO);
    try {
        if (digitalContent != null) {
            Uri audioUri = Uri.parse(digitalContent.getmThumbContent());
            QLog.i("Play audio " + audioUri.getPath());
            mediaPlayer = MediaPlayer.create(mContext, audioUri);
            mediaPlayer.prepare();
            updateMediaTime();
            mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mediaPlayer) {
                    mediaPlayer.start();
                    mediaPlayer.seekTo(0);
                    finalTime = mediaPlayer.getDuration();
                    startTime = mediaPlayer.getCurrentPosition();
                }
            });
            mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mediaPlayer) {
                    mediaPlayer.pause();
                    updateMediaUI();
                    startTime = 0;
                    seekbar.setProgress((int) startTime);
                    updateMediaTime();
                }
            });
        }
    } catch (Exception e) {
        QLog.e(e);
    }
}

private void updateMediaUI() {
    if (mediaPlayer.isPlaying()) {
        btn_Play.setBackgroundResource(R.drawable.digital_audio_pause);
    } else {
        btn_Play.setBackgroundResource(R.drawable.digital_audioplay);
        startTime = mediaPlayer.getCurrentPosition();
        seekbar.setProgress((int) startTime);
        updateMediaTime();
    }
}

@Override
public void onClick(View view) {
    switch (view.getId()) {
        case R.id.btn_delete:
            oneTimeOnly = 0;
            transactionDetail.removeDigtalContent(DigitalContentActivity.DigitalContentType.AUDIO);
            if (mediaPlayer != null) {
                mediaPlayer.stop();
                mediaPlayer.release();
                mediaPlayer = null;
            }
            ((ViewGroup) getParent()).removeView(this);
            if (mFragment.get() != null) {
                mFragment.get().removeDigitalContent(transactionDetail, DigitalContentActivity.DigitalContentType.AUDIO);
            }
            break;
        case R.id.btn_play:
            if (mediaPlayer.getDuration() <= 0) {
                initMediaPlayer();
            }
            if (!mediaPlayer.isPlaying()) {
                mediaPlayer.start();
                if (finalTime <= 0) {
                    finalTime = mediaPlayer.getDuration();
                }

                startTime = mediaPlayer.getCurrentPosition();

                if (oneTimeOnly == 0) {
                    seekbar.setMax((int) finalTime);
                    oneTimeOnly = 1;
                }

                updateMediaTime();

                seekbar.setProgress((int) startTime);

                durationHandler.postDelayed(updateSeekBarTime, 100);
            } else {
                mediaPlayer.pause();
                durationHandler.removeCallbacks(updateSeekBarTime);
            }
            updateMediaUI();
            break;
    }
}

private void updateMediaTime() {
    tv_total_duration.setText(String.format("%2d:%02d",
            TimeUnit.MILLISECONDS.toMinutes((long) finalTime),
            TimeUnit.MILLISECONDS.toSeconds((long) finalTime) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes((long) finalTime)))
    );

    tv_current_duration.setText(String.format("%2d:%02d",
            TimeUnit.MILLISECONDS.toMinutes((long) startTime),
            TimeUnit.MILLISECONDS.toSeconds((long) startTime) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes((long) startTime)))
    );
}

//handler to change seekBarTime
private Runnable updateSeekBarTime = new Runnable() {
    public void run() {
        if (mediaPlayer == null) {
            return;
        }
        if (mediaPlayer.isPlaying()) {
            //get current position
            startTime = mediaPlayer.getCurrentPosition();
            //set seekbar progress
            seekbar.setProgress((int) startTime);
            //set time remaing
            double timeRemaining = finalTime - startTime;
            updateMediaTime();

            //repeat yourself that again in 100 miliseconds
            durationHandler.postDelayed(this, 100);
        }else{
            for (int i = mediaPlayer.getDuration(); i >= mediaPlayer.getCurrentPosition(); i--){

            }
        }
        updateMediaUI();
    }
};

@Override
public void pauseMedia() {
    if (mediaPlayer != null) {
        mediaPlayer.pause();
        updateMediaUI();
        durationHandler.removeCallbacks(updateSeekBarTime);
    }
}
</code>```

Body:
I want to perform the three functions by using the single play button.
  First process - when we click the play button the mediaplayer should play the audio.
  second process - when user click second time the play button the audio should be paused.
  Third process - when user click the third time play button the audio should resume from the paused song.

The tried the below code

 if (!mediaPlayer.isPlaying()) {
                mediaPlayer.reset();
                try {
                    mediaPlayer.setDataSource(path);
                    //  mediaPlayer.setOnPreparedListener((MediaPlayer.OnPreparedListener) getActivity());
                    mediaPlayer.prepare();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                mediaPlayer.start();

            }
           else if (mediaPlayer.isPlaying()) {
                mediaPlayer.pause();
            }

            else if (!mediaPlayer.isPlaying() && mediaPlayer.getCurrentPosition() > 0) {
                long currentPosition = mediaPlayer.getCurrentPosition();
                mediaPlayer.seekTo((int) currentPosition);
                mediaPlayer.start();

            }

The above code is not working ,please help me how to solve this.

Body:
You can try this

protected void initViews(Context context) {
    mContext = context;
    oneTimeOnly = 0;
    mRootView = LayoutInflater.from(context).inflate(R.layout.view_digital_audio_content, this);
    btn_delete = (ImageButton) mRootView.findViewById(R.id.btn_delete);
    tv_current_duration = (TextView) mRootView.findViewById(R.id.tv_current_duration);
    tv_total_duration = (TextView) mRootView.findViewById(R.id.tv_total_duration);
    seekbar = (SeekBar) mRootView.findViewById(R.id.seekbar);
    btn_Play = (ImageButton) mRootView.findViewById(R.id.btn_play);
    seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
            if (mediaPlayer != null && fromUser) {
                mediaPlayer.seekTo(progress);
            }
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {

        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {

        }
    });

    initMediaPlayer();

    btn_delete.setOnClickListener(this);
    btn_Play.setOnClickListener(this);
}

private void initMediaPlayer() {
    transactionDetail = FCSingleton.getTransactionDetails();
    TransactionDetail.DigitalContent digitalContent = transactionDetail.getDigtalContent(DigitalContentActivity.DigitalContentType.AUDIO);
    try {
        if (digitalContent != null) {
            Uri audioUri = Uri.parse(digitalContent.getmThumbContent());
            QLog.i("Play audio " + audioUri.getPath());
            mediaPlayer = MediaPlayer.create(mContext, audioUri);
            mediaPlayer.prepare();
            updateMediaTime();
            mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mediaPlayer) {
                    mediaPlayer.start();
                    mediaPlayer.seekTo(0);
                    finalTime = mediaPlayer.getDuration();
                    startTime = mediaPlayer.getCurrentPosition();
                }
            });
            mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mediaPlayer) {
                    mediaPlayer.pause();
                    updateMediaUI();
                    startTime = 0;
                    seekbar.setProgress((int) startTime);
                    updateMediaTime();
                }
            });
        }
    } catch (Exception e) {
        QLog.e(e);
    }
}

private void updateMediaUI() {
    if (mediaPlayer.isPlaying()) {
        btn_Play.setBackgroundResource(R.drawable.digital_audio_pause);
    } else {
        btn_Play.setBackgroundResource(R.drawable.digital_audioplay);
        startTime = mediaPlayer.getCurrentPosition();
        seekbar.setProgress((int) startTime);
        updateMediaTime();
    }
}

@Override
public void onClick(View view) {
    switch (view.getId()) {
        case R.id.btn_delete:
            oneTimeOnly = 0;
            transactionDetail.removeDigtalContent(DigitalContentActivity.DigitalContentType.AUDIO);
            if (mediaPlayer != null) {
                mediaPlayer.stop();
                mediaPlayer.release();
                mediaPlayer = null;
            }
            ((ViewGroup) getParent()).removeView(this);
            if (mFragment.get() != null) {
                mFragment.get().removeDigitalContent(transactionDetail, DigitalContentActivity.DigitalContentType.AUDIO);
            }
            break;
        case R.id.btn_play:
            if (mediaPlayer.getDuration() <= 0) {
                initMediaPlayer();
            }
            if (!mediaPlayer.isPlaying()) {
                mediaPlayer.start();
                if (finalTime <= 0) {
                    finalTime = mediaPlayer.getDuration();
                }

                startTime = mediaPlayer.getCurrentPosition();

                if (oneTimeOnly == 0) {
                    seekbar.setMax((int) finalTime);
                    oneTimeOnly = 1;
                }

                updateMediaTime();

                seekbar.setProgress((int) startTime);

                durationHandler.postDelayed(updateSeekBarTime, 100);
            } else {
                mediaPlayer.pause();
                durationHandler.removeCallbacks(updateSeekBarTime);
            }
            updateMediaUI();
            break;
    }
}

private void updateMediaTime() {
    tv_total_duration.setText(String.format("%2d:%02d",
            TimeUnit.MILLISECONDS.toMinutes((long) finalTime),
            TimeUnit.MILLISECONDS.toSeconds((long) finalTime) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes((long) finalTime)))
    );

    tv_current_duration.setText(String.format("%2d:%02d",
            TimeUnit.MILLISECONDS.toMinutes((long) startTime),
            TimeUnit.MILLISECONDS.toSeconds((long) startTime) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes((long) startTime)))
    );
}

//handler to change seekBarTime
private Runnable updateSeekBarTime = new Runnable() {
    public void run() {
        if (mediaPlayer == null) {
            return;
        }
        if (mediaPlayer.isPlaying()) {
            //get current position
            startTime = mediaPlayer.getCurrentPosition();
            //set seekbar progress
            seekbar.setProgress((int) startTime);
            //set time remaing
            double timeRemaining = finalTime - startTime;
            updateMediaTime();

            //repeat yourself that again in 100 miliseconds
            durationHandler.postDelayed(this, 100);
        }else{
            for (int i = mediaPlayer.getDuration(); i >= mediaPlayer.getCurrentPosition(); i--){

            }
        }
        updateMediaUI();
    }
};

@Override
public void pauseMedia() {
    if (mediaPlayer != null) {
        mediaPlayer.pause();
        updateMediaUI();
        durationHandler.removeCallbacks(updateSeekBarTime);
    }
}


来源: stackexchange

问:
Reading Oracle Explain plan
```<code>explain plan for
    SELECT * FROM schema2.mv_a_data mv
      WHERE mv.routing_code_type_id    = 3
      AND mv.static_data_status_id    IN(5, 8)
      AND mv.acct_currency_ind_id NOT IN
         (SELECT DISTINCT te.acct_currency_ind_id
          FROM schema1.tem_ele te
          WHERE te.lis_tem_id IN
                  (SELECT lis_tem_id
                   FROM schema1.lis_tem
                   WHERE lis_tem.template_type_id = 2
                   AND lis_tem.deleted_flag       = 'N'      )
      AND te.acct_currency_ind_id IS NOT NULL
    )
 ORDER BY mv.treasury_region_code,
          mv.legal_entity_mnemonic,
          mv.currency_code;

 select *
 from TABLE(DBMS_XPLAN.DISPLAY('PLAN_TABLE', null,'ADVANCED'));
</code>```

------------------------------------------------------------------------------------
|  Id  | Operation             | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |           |   892 |   318K|    69   (2)| 00:00:01 |
|   1 |  SORT ORDER BY         |           |   892 |   318K|    69   (2)| 00:00:01 |
|*  2 |   HASH JOIN RIGHT ANTI |           |   892 |   318K|    68   (0)| 00:00:01 | `
|   3 |    VIEW                | VW_NSO_1  |  1457 |  8742 |    11  (0) | 00:00:01 |
|*  4 |     HASH JOIN          |           |  1457 | 33511 |    11   (0)| 00:00:01 |
|*  5 |      TABLE ACCESS FULL | lis_tem   |   100 |  1100 |     3   (0)| 00:00:01 |
|*  6 |      TABLE ACCESS FULL | tem_ele   |  3271 | 39252 |     8   (0)| 00:00:01 |
|*  7 |    MAT_VIEW ACCESS FULL| mv_a_data |  2348 |   825K|    57   (0)| 00:00:01 |
```

I am trying to read the given explain plan. After looking at the explain plan and according
    to my understanding, first of all, FTS of LIS_TEM table and TEM_ELE are done and then they are joined using HASH JOIN.

Question 1 - can I change this HASH JOIN to NESTED LOOP?

I am asking just for learning purpose. I know HASH JOIN is good here.
        After HASH JOIN, I guess it is going to ID3 ie VIEW VW_NSO_1 and ID7 MAT_VIEW.

Question 2 - what is this VIEW VW_NSO_1, which clause of the SQL query was responsible to brought it here?

Question 3 - How I will read the rest of the plan?

Question 4 - Why HASH JOIN RIGHT ANTI came in picture?

Please assist me to understand the above explain plan in detail. Thanks and let me know if you need any further details.

答:
You can use query hints to 'force' a query to use a specific join although i wouldn't recommend it. If its using a hash then it is probably the best thing for it. Make sure your statistics are upto date if you think it would be better using a different join

Oracle docs are helpful to look at what each operation is doing:
https://docs.oracle.com/cd/B10501_01/server.920/a96533/ex_plan.htm

ContentLicense: CC BY-SA 3.0

Title: Reading Oracle Explain plan

Body:
explain plan for
    SELECT * FROM schema2.mv_a_data mv
      WHERE mv.routing_code_type_id    = 3
      AND mv.static_data_status_id    IN(5, 8)
      AND mv.acct_currency_ind_id NOT IN
         (SELECT DISTINCT te.acct_currency_ind_id
          FROM schema1.tem_ele te
          WHERE te.lis_tem_id IN
                  (SELECT lis_tem_id
                   FROM schema1.lis_tem
                   WHERE lis_tem.template_type_id = 2
                   AND lis_tem.deleted_flag       = 'N'      )
      AND te.acct_currency_ind_id IS NOT NULL
    )
 ORDER BY mv.treasury_region_code,
          mv.legal_entity_mnemonic,
          mv.currency_code;

 select *
 from TABLE(DBMS_XPLAN.DISPLAY('PLAN_TABLE', null,'ADVANCED'));

------------------------------------------------------------------------------------
|  Id  | Operation             | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |           |   892 |   318K|    69   (2)| 00:00:01 |
|   1 |  SORT ORDER BY         |           |   892 |   318K|    69   (2)| 00:00:01 |
|*  2 |   HASH JOIN RIGHT ANTI |           |   892 |   318K|    68   (0)| 00:00:01 | `
|   3 |    VIEW                | VW_NSO_1  |  1457 |  8742 |    11  (0) | 00:00:01 |
|*  4 |     HASH JOIN          |           |  1457 | 33511 |    11   (0)| 00:00:01 |
|*  5 |      TABLE ACCESS FULL | lis_tem   |   100 |  1100 |     3   (0)| 00:00:01 |
|*  6 |      TABLE ACCESS FULL | tem_ele   |  3271 | 39252 |     8   (0)| 00:00:01 |
|*  7 |    MAT_VIEW ACCESS FULL| mv_a_data |  2348 |   825K|    57   (0)| 00:00:01 |

I am trying to read the given explain plan. After looking at the explain plan and according
    to my understanding, first of all, FTS of LIS_TEM table and TEM_ELE are done and then they are joined using HASH JOIN.

Question 1 - can I change this HASH JOIN to NESTED LOOP?

I am asking just for learning purpose. I know HASH JOIN is good here.
        After HASH JOIN, I guess it is going to ID3 ie VIEW VW_NSO_1 and ID7 MAT_VIEW.

Question 2 - what is this VIEW VW_NSO_1, which clause of the SQL query was responsible to brought it here?

Question 3 - How I will read the rest of the plan?

Question 4 - Why HASH JOIN RIGHT ANTI came in picture?

Please assist me to understand the above explain plan in detail. Thanks and let me know if you need any further details.


问:
How to stop index count increment using Array.map iteration based on certain condition inside loop?
like for e.g.

```<code>Array.map((obj, index) => (
    condition === true ?
    default index counter increment
    : do not increase index count
))
</code>```

I want my counter to increase only if my condition is true, is there any work around for this? I am facing problems when I like adding alternate colors to rows based on object and in case I want to reject certain objects and don't create any rows, even though the row doesn't create, still my counter increases, colors apply on the row which is actually not there and produces UI flaw.

答:
You could use Array#reduce with a counter, like

```<code>var count = array.reduce(function (r, a, i) {
    return r + (condition);
}, 0);
</code>```

instead of Array#map, because you need a single value and not a new array with all undefined values.

Body:
like for e.g.

Array.map((obj, index) => (
    condition === true ?
    default index counter increment
    : do not increase index count
))

I want my counter to increase only if my condition is true, is there any work around for this? I am facing problems when I like adding alternate colors to rows based on object and in case I want to reject certain objects and don't create any rows, even though the row doesn't create, still my counter increases, colors apply on the row which is actually not there and produces UI flaw.

Body:
You could use Array#reduce with a counter, like

var count = array.reduce(function (r, a, i) {
    return r + (condition);
}, 0);

instead of Array#map, because you need a single value and not a new array with all undefined values.


问:
Div with text wont stay centered
I'm creating a simple image gallery. Above the images I name the place where the pictures were taken, but the second and every another row has issues - div with the name is being pushed to the right instead of staying centered. Here is how it looks: http://prntscr.com/fg10u4

@import url(https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css);
.locationName {
  text-align: center;
  padding: 0px 0px 20px 20px;
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><div class="row" id="locations">

  <div class="locationName">
    City
  </div>

  <div class="col-lg-4 col-sm-6">
    <div class="thumbnail">
      <img src="2.jpg">
    </div>
  </div>

  <div class="col-lg-4 col-sm-6">
    <div class="thumbnail">
      <img src="1.jpg">
    </div>
  </div>

  <div class="col-lg-4 col-sm-6">
    <div class="thumbnail">
      <img src="2.jpg">
    </div>
  </div>
</div></code>```

Obviously the code is doubled inside the "row" div.

答:
try this:</p>

```<code>        <div class="container" id="locations">
<div class="row">
        <div class="col-lg-4 col-sm-6">
            <div class="thumbnail">
                <img src="2.jpg">
            </div>
        </div>
        <div class="col-lg-4 col-sm-6">
            <div class="thumbnail">
                <img src="1.jpg">
            </div>
        </div>
        <div class="col-lg-4 col-sm-6">
            <div class="thumbnail">
                <img src="2.jpg">
            </div>
        </div>
        </div>
        <div class="locationName">
            City
        </div>
<div class="row">
        <div class="col-lg-4 col-sm-6">
            <div class="thumbnail">
                <img src="2.jpg">
            </div>
        </div>
        <div class="col-lg-4 col-sm-6">
            <div class="thumbnail">
                <img src="1.jpg">
            </div>
        </div>
        <div class="col-lg-4 col-sm-6">
            <div class="thumbnail">
                <img src="2.jpg">
            </div>
        </div>
</div>
</div>
</code>```

Title: Div with text wont stay centered

Body:
I'm creating a simple image gallery. Above the images I name the place where the pictures were taken, but the second and every another row has issues - div with the name is being pushed to the right instead of staying centered. Here is how it looks: http://prntscr.com/fg10u4

@import url(https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css);
.locationName {
  text-align: center;
  padding: 0px 0px 20px 20px;
}

    City

Obviously the code is doubled inside the "row" div.

Body:
try this:

        <div class="container" id="locations">
<div class="row">
        <div class="col-lg-4 col-sm-6">
            <div class="thumbnail">
                <img src="2.jpg">
            </div>
        </div>
        <div class="col-lg-4 col-sm-6">
            <div class="thumbnail">
                <img src="1.jpg">
            </div>
        </div>
        <div class="col-lg-4 col-sm-6">
            <div class="thumbnail">
                <img src="2.jpg">
            </div>
        </div>
        </div>
        <div class="locationName">
            City
        </div>
<div class="row">
        <div class="col-lg-4 col-sm-6">
            <div class="thumbnail">
                <img src="2.jpg">
            </div>
        </div>
        <div class="col-lg-4 col-sm-6">
            <div class="thumbnail">
                <img src="1.jpg">
            </div>
        </div>
        <div class="col-lg-4 col-sm-6">
            <div class="thumbnail">
                <img src="2.jpg">
            </div>
        </div>
</div>
</div>


问:
How to use passed parameter in other method calls?
I have read that I can use the Answer object for this but in my case there is a problem. The situation is like this:

SecondObject secondObject = firstObject.getByType(String type);

then

List list = secondObject.getSomeOtherValues();

Practically I want to use the argument type when mocking the call for the secondObject. Is this possible?

答:
Do something like:

```<code>when(firstObject.getByType(anyString())).thenAnswer(
     new Answer() {
         public Object answer(InvocationOnMock invocation) {
             String type= invocation.getArguments()[0];
             SecondObject  second = Mockito.mock(SecondObject  );

             //do something
            if(type== ....){
                when(second.getSomeOtherValues() ).thenReturn(....)
            } else{
                .....................................
            }

             return second ;
         }
 });
</code>```

SecondObject secondObject = firstObject.getByType(String type);

I have not tested it, but the key is

```<code> if(type== ....){
        when(second.getSomeOtherValues() ).thenReturn(....)
    } else{
        .....................................
    }
</code>```

And the home page of mockito answer http://static.javadoc.io/org.mockito/mockito-core/2.8.9/org/mockito/stubbing/Answer.html

Body:
Do something like:

when(firstObject.getByType(anyString())).thenAnswer(
     new Answer() {
         public Object answer(InvocationOnMock invocation) {
             String type= invocation.getArguments()[0];
             SecondObject  second = Mockito.mock(SecondObject  );

             //do something
            if(type== ....){
                when(second.getSomeOtherValues() ).thenReturn(....)
            } else{
                .....................................
            }

             return second ;
         }
 });

SecondObject secondObject = firstObject.getByType(String type);

I have not tested it, but the key is

 if(type== ....){
        when(second.getSomeOtherValues() ).thenReturn(....)
    } else{
        .....................................
    }

And the home page of mockito answer http://static.javadoc.io/org.mockito/mockito-core/2.8.9/org/mockito/stubbing/Answer.html


问:
How to set a different entry point on first app launch?
I have a Main.storyboard containing the root view controller of my app. However, I would like to display an onboarding view (without a navigation controller) on first app launch in order for the user to fill some data that's needed only once. So I was thinking about creating an Onboarding.storyboard, but I don't know how to choose which storyboard to set, where to do it (AppDelegate?) and when data is filled, how to change the current storyboard.

Thanks for your help.

答:
You need to change this in AppDelegate's didFinishLaunchingWithOptions method.This method call's during app launch every time.

How:

Consider this example. Store the values in NSUserdefaults and retrieve it during app launch.

Example

Objective C:

```<code>BOOL isCompletedSetupWizard =[[NSUserDefaults standardUserDefaults] boolForKey:@"isCompletedSetupWizard"];

if (isCompletedSetupWizard)
{
   //Your code goes here
   //....
   //....
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    viewController = [storyboard instantiateViewControllerWithIdentifier:@"yourFirstView"];
    self.window.rootViewController = viewController;
}
else
{
  //Your code goes here for another view controller.
  //....
  //....
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"onBoarding" bundle:nil];
    viewController = [storyboard instantiateViewControllerWithIdentifier:@"yourSecondView"];
    self.window.rootViewController = viewController;
}
</code>```

Body:
You need to change this in AppDelegate's didFinishLaunchingWithOptions method.This method call's during app launch every time.

How:

Consider this example. Store the values in NSUserdefaults and retrieve it during app launch.

Example

Objective C:

BOOL isCompletedSetupWizard =[[NSUserDefaults standardUserDefaults] boolForKey:@"isCompletedSetupWizard"];

if (isCompletedSetupWizard)
{
   //Your code goes here
   //....
   //....
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    viewController = [storyboard instantiateViewControllerWithIdentifier:@"yourFirstView"];
    self.window.rootViewController = viewController;
}
else
{
  //Your code goes here for another view controller.
  //....
  //....
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"onBoarding" bundle:nil];
    viewController = [storyboard instantiateViewControllerWithIdentifier:@"yourSecondView"];
    self.window.rootViewController = viewController;
}

ContentLicense: CC BY-SA 4.0


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

When compiled, the directory looks like

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

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

Linked the compiler to include and library directories in x64.

Linked the libraries.

Copied the libraries to C:\Windows\SysWOW64.

Included <Windows.h>.

Used compatibility mode.

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

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

Here's the main source file:

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

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

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

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

Graphics Global;
Event Loop;

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

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

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

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

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

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

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

    SDL_SetTextInputRect(&Global.rcTextInput);
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

答:
I inserted SDL_Log() after every successful initialisation to find the error. I used gdb to monitor the log.

It turned out that

```<code>Global.Font = TTF_OpenFont("src/graphics/resources/notomono-regular.ttf", 14);
</code>```

was faulty.

Replacing it with a simple

```<code>Global.Font = TTF_OpenFont("notomono-regular.ttf", 14);
</code>```

corrected the error.

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

When compiled, the directory looks like

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

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

Linked the compiler to include and library directories in x64.

Linked the libraries.

Copied the libraries to C:\Windows\SysWOW64.

Included <Windows.h>.

Used compatibility mode.

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

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

Here's the main source file:

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

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

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

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

Graphics Global;
Event Loop;

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

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

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

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

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

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

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

    SDL_SetTextInputRect(&Global.rcTextInput);
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Body:
I inserted SDL_Log() after every successful initialisation to find the error. I used gdb to monitor the log.

It turned out that

Global.Font = TTF_OpenFont("src/graphics/resources/notomono-regular.ttf", 14);

was faulty.

Replacing it with a simple

Global.Font = TTF_OpenFont("notomono-regular.ttf", 14);

corrected the error.


问:
How to store a map or json object as a property in neo4j?
I'm trying store a map or json object as a property in Neo4j, but it doesn't work.</p>

答:
That's a limitation of node properties right now. You have a few workarounds to choose from.

You can turn your json object into a string and save it as a property. You can use APOC Procedures to convert JSON strings to and from Cypher map objects.

You can instead save the map properties as properties on the node, though that loses the grouping you would get from the object itself.

If #2 isn't enough, you could also alter your graph model so the data in the JSON object corresponds to graph objects, nodes and properties related to the original node.


问:
Bash linux, Hour, Minutes and Seconds of a JPG Image
I am trying to get the complete date of an image in JPG format. The format I want to get is 14:25:38 (Hour:Minutes:Seconds).

I tried with the commands:

```<code>$ stat -c %y DSC_0002.JPG | sed 's/^\([0-9\-]*\).*/\1/'
=> 2017-05-19  -Not that way

$ file DSC_0002.JPG
=> DSC_0002.JPG: JPEG image data, Exif standard: [TIFF image data, little-endian, direntries=11, manufacturer=NIKON CORPORATION, model=NIKON D5200, orientation=upper-left, xresolution=180, yresolution=188, resolutionunit=2, software=Ver.1.01 , datetime=2017:05:19 13:30:34, GPS-Data], baseline, precision 8, 6000x4000, frames 3
</code>```

This last (file DSC_0002.JPG) command displays datetime=2017:05:19 13:30:34, but I need to get only 13:30:34

Preferably without using add-ons or programs external to Linux bash.

Thank you very much for any help.

答:
My 2 cents...

As exif is a big part of my job and because I already spent a lot of time building my own scripts, time is comming to make a little bench.

Getting result of jhead using bash:

This use jhead because it's my prefered. See further to know why...

```<code>DateTime=$(jhead -nofinfo DSC_0002.JPG)
DateTime=${DateTime#*Date/Time*: }
DateTime=${DateTime%%$'\n'*}
</code>```

This is the quickest way, (a lot quicker than using bash regex)!

```<code>echo $DateTime
2011:02:27 14:53:32
</code>```

Different ways

Inquiring a jpeg file for knowing his date is possible by using at least 4 different tools:

file The magic file recognition command make some light inquiring on any file for determining is nature and print some more informations.

```<code>file  DSC_0002.JPG
DSC_0002.JPG: JPEG image data, Exif standard: [TIFF image data, big-endian,
direntries=10, manufacturer=CANIKON, model=CANIKON AB12, orientation=upper-
left, xresolution=168, yresolution=176, resolutionunit=2, software=Ver.1.00
, datetime=2011:02:27 14:53:32], baseline, precision 8, 3872x2592, frames 3
</code>```

file print size, resolution and dateTime from a jpeg file.

jhead is a jpeg's header dedicated tool:

```<code>jhead DSC_0002.JPG
File name    : DSC_0002.JPG
File size    : 4940925 bytes
File date    : 2011:02:27 14:53:32
Camera make  : CANIKON
Camera model : CANIKON AB12
Date/Time    : 2011:02:27 14:53:32
Resolution   : 3872 x 2592
Flash used   : No
Focal length : 55.0mm  (35mm equivalent: 82mm)
Exposure time: 0.0080 s  (1/125)
Aperture     : f/5.6
ISO equiv.   : 180
Whitebalance : Auto
Metering Mode: pattern
JPEG Quality : 97
</code>```

identify is part of ImageMagick package wich is a kind of all purpose tool for bitmap images... (Due to some security bugs in past and overall perfomance, I'ts not my personal choice).

```<code>identify DSC_0002.JPG
DSC_0002.JPG JPEG 3872x2592 3872x2592+0+0 8-bit sRGB 4.941MB 0.010u 0:00.020
identify -format "%[EXIF:DateTime]\n" DSC_0002.JPG
2011:02:27 14:53:32
</code>```

exiftool is a dedicated tool using libimage.

```<code>exiftool DSC_0002.JPG
ExifTool Version Number         : 9.74
File Name                       : DSC_0002.JPG
Directory                       : .
File Size                       : 4.7 MB
File Modification Date/Time     : 2011:02:27 14:53:32+01:00
File Access Date/Time           : 2017:06:05 08:40:26+02:00
File Inode Change Date/Time     : 2017:06:05 08:40:04+02:00
File Permissions                : rw-r--r--
File Type                       : JPEG
MIME Type                       : image/jpeg
Exif Byte Order                 : Big-endian (Motorola, MM)
...
Modify Date                     : 2011:02:27 14:53:32
...
Thumbnail Image                 : (Binary data 8965 bytes, use -b option to extract)
Circle Of Confusion             : 0.020 mm
Depth Of Field                  : 15.07 m (8.58 - 23.65)
Field Of View                   : 24.7 deg (5.50 m)
Focal Length                    : 55.0 mm (35 mm equivalent: 82.0 mm)
Hyperfocal Distance             : 26.80 m
Light Value                     : 11.1
</code>```

The default output of this is 185 lines length, I've dropped a lot.

pure bash As requested and because Toby Speight recommend to not doing this:

```<code>FDate=;while IFS= read -d  $'\0'  -n 1024 raw;do
  [ "$raw" ] && \
  [ -z "${raw#[0-9][0-9][0-9][0-9]:[0-9][0-9]:[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]}" ] &&
  FDate=$raw && break
done <DSC_0002.JPG
echo $FDate
2011:02:27 14:53:32
</code>```

Ok, this a far away a perfect function: first date found in file is considered, regardless of fieldname.

Little bench

As the goal is to extract date time part of exif infos, the bench would only do this.

```<code>time for i in {1..100};do ... done >/dev/null
export TIMEFORMAT="R:%4R u:%4U s:%4S"
</code>```

Like this (from quicker to slower):

```<code># quicker: jhead
time for i in {1..100};do jhead DSC_0002.JPG ;done >/dev/null
R:0.115  u:0.000  s:0.028

# 2nd: file
time for i in {1..100};do file DSC_0002.JPG; done >/dev/null
R:0.226  u:0.000  s:0.044

# 3nd: pure bash
time for i in {1..100};do
    while IFS= read -d  $'\0' -n 1024 raw ;do
        [ "$raw" ] &&
        [ -z "${raw#[0-9][0-9][0-9][0-9]:[0-9][0-9]:[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]}" ] &&
         ftim=$raw && break
      done <DSC_0002.JPG
   done >/dev/null
R:0.393  u:0.380  s:0.012

# 4nd: best dedicated: exiftool
time for i in {1..100};do exiftool -time:CreateDate DSC_0002.JPG ;done >/dev/null
R:14.921  u:13.064  s:0.956

# slower: imagemagick's identify
time for i in {1..100};do identify -format "%[EXIF:DateTime]\n" DSC_0002.JPG ;done >/dev/null
R:21.609  u:15.712  s:5.060
</code>```

Sorry, I agree with Toby Speight: Doing this in pure bash is a not so good idea!

Setting file date

Doing date manipulation is very easy under pure bash, but working on file date. For this, I asked my system to set all photos files datetime to creation date found in exif.

For this, exiftool offer a specific syntax:

```<code>exiftool '-FileModifyDate<DateTimeOriginal /path/to/myphotos
</code>```

and jhead too:

```<code>echo $DateTime
2011:02:27 14:53:32
</code>```0

This will set all creation file date based on creation date in exif infos. Once done, you could use standard tools for filesystem inquiry:

```<code>echo $DateTime
2011:02:27 14:53:32
</code>```1

And so on...

Body:
I am trying to get the complete date of an image in JPG format. The format I want to get is 14:25:38 (Hour:Minutes:Seconds).

I tried with the commands:

$ stat -c %y DSC_0002.JPG | sed 's/^\([0-9\-]*\).*/\1/'
=> 2017-05-19  -Not that way

$ file DSC_0002.JPG
=> DSC_0002.JPG: JPEG image data, Exif standard: [TIFF image data, little-endian, direntries=11, manufacturer=NIKON CORPORATION, model=NIKON D5200, orientation=upper-left, xresolution=180, yresolution=188, resolutionunit=2, software=Ver.1.01 , datetime=2017:05:19 13:30:34, GPS-Data], baseline, precision 8, 6000x4000, frames 3

This last (file DSC_0002.JPG) command displays datetime=2017:05:19 13:30:34, but I need to get only 13:30:34

Preferably without using add-ons or programs external to Linux bash.

Thank you very much for any help.

Body:
My 2 cents...

As exif is a big part of my job and because I already spent a lot of time building my own scripts, time is comming to make a little bench.

Getting result of jhead using bash:

This use jhead because it's my prefered. See further to know why...

DateTime=$(jhead -nofinfo DSC_0002.JPG)
DateTime=${DateTime#*Date/Time*: }
DateTime=${DateTime%%$'\n'*}

This is the quickest way, (a lot quicker than using bash regex)!

echo $DateTime
2011:02:27 14:53:32

Different ways

Inquiring a jpeg file for knowing his date is possible by using at least 4 different tools:

file The magic file recognition command make some light inquiring on any file for determining is nature and print some more informations.

file  DSC_0002.JPG
DSC_0002.JPG: JPEG image data, Exif standard: [TIFF image data, big-endian,
direntries=10, manufacturer=CANIKON, model=CANIKON AB12, orientation=upper-
left, xresolution=168, yresolution=176, resolutionunit=2, software=Ver.1.00
, datetime=2011:02:27 14:53:32], baseline, precision 8, 3872x2592, frames 3

file print size, resolution and dateTime from a jpeg file.

jhead is a jpeg's header dedicated tool:

jhead DSC_0002.JPG
File name    : DSC_0002.JPG
File size    : 4940925 bytes
File date    : 2011:02:27 14:53:32
Camera make  : CANIKON
Camera model : CANIKON AB12
Date/Time    : 2011:02:27 14:53:32
Resolution   : 3872 x 2592
Flash used   : No
Focal length : 55.0mm  (35mm equivalent: 82mm)
Exposure time: 0.0080 s  (1/125)
Aperture     : f/5.6
ISO equiv.   : 180
Whitebalance : Auto
Metering Mode: pattern
JPEG Quality : 97

identify is part of ImageMagick package wich is a kind of all purpose tool for bitmap images... (Due to some security bugs in past and overall perfomance, I'ts not my personal choice).

identify DSC_0002.JPG
DSC_0002.JPG JPEG 3872x2592 3872x2592+0+0 8-bit sRGB 4.941MB 0.010u 0:00.020
identify -format "%[EXIF:DateTime]\n" DSC_0002.JPG
2011:02:27 14:53:32

exiftool is a dedicated tool using libimage.

exiftool DSC_0002.JPG
ExifTool Version Number         : 9.74
File Name                       : DSC_0002.JPG
Directory                       : .
File Size                       : 4.7 MB
File Modification Date/Time     : 2011:02:27 14:53:32+01:00
File Access Date/Time           : 2017:06:05 08:40:26+02:00
File Inode Change Date/Time     : 2017:06:05 08:40:04+02:00
File Permissions                : rw-r--r--
File Type                       : JPEG
MIME Type                       : image/jpeg
Exif Byte Order                 : Big-endian (Motorola, MM)
...
Modify Date                     : 2011:02:27 14:53:32
...
Thumbnail Image                 : (Binary data 8965 bytes, use -b option to extract)
Circle Of Confusion             : 0.020 mm
Depth Of Field                  : 15.07 m (8.58 - 23.65)
Field Of View                   : 24.7 deg (5.50 m)
Focal Length                    : 55.0 mm (35 mm equivalent: 82.0 mm)
Hyperfocal Distance             : 26.80 m
Light Value                     : 11.1

The default output of this is 185 lines length, I've dropped a lot.

pure bash As requested and because Toby Speight recommend to not doing this:

FDate=;while IFS= read -d  $'\0'  -n 1024 raw;do
  [ "$raw" ] && \
  [ -z "${raw#[0-9][0-9][0-9][0-9]:[0-9][0-9]:[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]}" ] &&
  FDate=$raw && break
done <DSC_0002.JPG
echo $FDate
2011:02:27 14:53:32

Ok, this a far away a perfect function: first date found in file is considered, regardless of fieldname.

Little bench

As the goal is to extract date time part of exif infos, the bench would only do this.

time for i in {1..100};do ... done >/dev/null
export TIMEFORMAT="R:%4R u:%4U s:%4S"

Like this (from quicker to slower):

# quicker: jhead
time for i in {1..100};do jhead DSC_0002.JPG ;done >/dev/null
R:0.115  u:0.000  s:0.028

# 2nd: file
time for i in {1..100};do file DSC_0002.JPG; done >/dev/null
R:0.226  u:0.000  s:0.044

# 3nd: pure bash
time for i in {1..100};do
    while IFS= read -d  $'\0' -n 1024 raw ;do
        [ "$raw" ] &&
        [ -z "${raw#[0-9][0-9][0-9][0-9]:[0-9][0-9]:[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]}" ] &&
         ftim=$raw && break
      done <DSC_0002.JPG
   done >/dev/null
R:0.393  u:0.380  s:0.012

# 4nd: best dedicated: exiftool
time for i in {1..100};do exiftool -time:CreateDate DSC_0002.JPG ;done >/dev/null
R:14.921  u:13.064  s:0.956

# slower: imagemagick's identify
time for i in {1..100};do identify -format "%[EXIF:DateTime]\n" DSC_0002.JPG ;done >/dev/null
R:21.609  u:15.712  s:5.060

Sorry, I agree with Toby Speight: Doing this in pure bash is a not so good idea!

Setting file date

Doing date manipulation is very easy under pure bash, but working on file date. For this, I asked my system to set all photos files datetime to creation date found in exif.

For this, exiftool offer a specific syntax:

exiftool '-FileModifyDate<DateTimeOriginal /path/to/myphotos

and jhead too:

jhead -q -ft /path/to/myphotos/*.JPG

This will set all creation file date based on creation date in exif infos. Once done, you could use standard tools for filesystem inquiry:

ls -l DSC_0002.JPG
stat DSC_0002.JPG

find /path/to/myphotos -type f -name 'DSC*JPG' -mtime +400 -mtime -410 -ls

And so on...


问:
Class Lock And Object Lock In Multithreading
I tried an interview question with static functions and non static functions as synchronized and one function was non synchronized. As in below code:

```<code>public class Resource {

public static synchronized void m1() throws InterruptedException {
    System.out.println("Entering m1 method");
    Thread.sleep(10000);
    System.out.println("Leaving m1 method");
    System.out.println();
}

public synchronized void m2() throws InterruptedException {
    System.out.println("Entering m2 method");
    Thread.sleep(2000);
    System.out.println("Leaving m2 method");
    System.out.println();
}

public void m3() throws InterruptedException {
    System.out.println("Entering m3 method");
    Thread.sleep(2000);
    System.out.println("Leaving m3 method");
    System.out.println();
}

public synchronized void m4() throws InterruptedException {
    System.out.println("Entering m4 method");
    Thread.sleep(2000);
    System.out.println("Leaving m4 method");
    System.out.println();
}

}

public class ThreadDemo {

public static void main(String[] args) {

    final Resource resource = new Resource();

    Thread t1 = new Thread(new Runnable() {

        @Override
        public void run() {
            try {
                resource.m1();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    });

    Thread t2 = new Thread(new Runnable() {

        @Override
        public void run() {
            try {
                resource.m2();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    });

    Thread t3 = new Thread(new Runnable() {

        @Override
        public void run() {
            try {
                resource.m3();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    });

    Thread t4 = new Thread(new Runnable() {

        @Override
        public void run() {
            try {
                resource.m4();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    });

    t1.start();
    t2.start();
    t3.start();
    t4.start();
}

}
</code>```

Here four threads are created.

T1 is calling static synchronized(m1)

T2, T4 are calling synchronized(m2, m4) and

T3 is calling non synnchronized(m3).

It's output is:

```<code>Entering m1 method
Entering m3 method
Entering m2 method
Leaving m3 method

Leaving m2 method

Entering m4 method
Leaving m4 method

Leaving m1 method
</code>```

My question is:

1) static synchronized method make class level lock. Here what is the meaning of class level locking? If one thread has taken lock and class level lock is occupied then why thread T2 and T3 starts execution?

2) T4 is waiting to complete T2. Although synchronization is applied on two different methods, then why T4 has to wait? If object level lock is working in T2, T4 then in above point why class level locking is not working?

答:
Static method synchronization is an equivalent for

```<code>public static void m1() {
    synchronize (Resource.class) {
    ...
    }
}
</code>```

Non-static method synchronization is an equivalent for

```<code>public void m2() {
    synchronize (this) {
        ...
    }
}
</code>```

Now if you will have a look where this is using as monitor and where Resource.class object is using as monitor everything should become clear.

A synchronized block in Java is synchronized on some object. All synchronized blocks synchronized on the same object can only have one thread executing inside them at the same time. All other threads attempting to enter the synchronized block are blocked until the thread inside the synchronized block exits the block.

In your case there are two objects. So, this rule is applicable for each object, but not to both.

Body:
I tried an interview question with static functions and non static functions as synchronized and one function was non synchronized. As in below code:

public class Resource {

public static synchronized void m1() throws InterruptedException {
    System.out.println("Entering m1 method");
    Thread.sleep(10000);
    System.out.println("Leaving m1 method");
    System.out.println();
}

public synchronized void m2() throws InterruptedException {
    System.out.println("Entering m2 method");
    Thread.sleep(2000);
    System.out.println("Leaving m2 method");
    System.out.println();
}

public void m3() throws InterruptedException {
    System.out.println("Entering m3 method");
    Thread.sleep(2000);
    System.out.println("Leaving m3 method");
    System.out.println();
}

public synchronized void m4() throws InterruptedException {
    System.out.println("Entering m4 method");
    Thread.sleep(2000);
    System.out.println("Leaving m4 method");
    System.out.println();
}

}

public class ThreadDemo {

public static void main(String[] args) {

    final Resource resource = new Resource();

    Thread t1 = new Thread(new Runnable() {

        @Override
        public void run() {
            try {
                resource.m1();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    });

    Thread t2 = new Thread(new Runnable() {

        @Override
        public void run() {
            try {
                resource.m2();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    });

    Thread t3 = new Thread(new Runnable() {

        @Override
        public void run() {
            try {
                resource.m3();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    });

    Thread t4 = new Thread(new Runnable() {

        @Override
        public void run() {
            try {
                resource.m4();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    });

    t1.start();
    t2.start();
    t3.start();
    t4.start();
}

}

Here four threads are created.

T1 is calling static synchronized(m1)

T2, T4 are calling synchronized(m2, m4) and

T3 is calling non synnchronized(m3).

It's output is:

Entering m1 method
Entering m3 method
Entering m2 method
Leaving m3 method

Leaving m2 method

Entering m4 method
Leaving m4 method

Leaving m1 method

My question is:

1) static synchronized method make class level lock. Here what is the meaning of class level locking? If one thread has taken lock and class level lock is occupied then why thread T2 and T3 starts execution?

2) T4 is waiting to complete T2. Although synchronization is applied on two different methods, then why T4 has to wait? If object level lock is working in T2, T4 then in above point why class level locking is not working?

Body:
Static method synchronization is an equivalent for

public static void m1() {
    synchronize (Resource.class) {
    ...
    }
}

Non-static method synchronization is an equivalent for

public void m2() {
    synchronize (this) {
        ...
    }
}

Now if you will have a look where this is using as monitor and where Resource.class object is using as monitor everything should become clear.

A synchronized block in Java is synchronized on some object. All synchronized blocks synchronized on the same object can only have one thread executing inside them at the same time. All other threads attempting to enter the synchronized block are blocked until the thread inside the synchronized block exits the block.

In your case there are two objects. So, this rule is applicable for each object, but not to both.


答:
Try this for Swift 3.x, make sure you're setting Initial View Controller in both the storyboards. In your AppDelegate.swift file, application:didFinishLaunchingWithOptions

```<code>var storyboardName:String?
if someCondition {
    storyboardName = "Onboarding"
}else{
    storyboardName = "Main"
}

let storyboard = UIStoryboard(name: storyboardName, bundle: nil)

let intialVC = storyboard.instantiateInitialViewController()

self.window?.rootViewController = intialVC
</code>```

Title: How to set a different entry point on first app launch?

Body:
I have a Main.storyboard containing the root view controller of my app. However, I would like to display an onboarding view (without a navigation controller) on first app launch in order for the user to fill some data that's needed only once. So I was thinking about creating an Onboarding.storyboard, but I don't know how to choose which storyboard to set, where to do it (AppDelegate?) and when data is filled, how to change the current storyboard.

Thanks for your help.

Body:
Try this for Swift 3.x, make sure you're setting Initial View Controller in both the storyboards. In your AppDelegate.swift file, application:didFinishLaunchingWithOptions

var storyboardName:String?
if someCondition {
    storyboardName = "Onboarding"
}else{
    storyboardName = "Main"
}

let storyboard = UIStoryboard(name: storyboardName, bundle: nil)

let intialVC = storyboard.instantiateInitialViewController()

self.window?.rootViewController = intialVC


问:
Android Room - Get the id of new inserted row with auto-generate
This is how I am inserting data into database using Room Persistence Library:

Entity:

```<code>@Entity
class User {
    @PrimaryKey(autoGenerate = true)
    public int id;
    //...
}
</code>```

Data access object:

```<code>@Dao
public interface UserDao{
    @Insert(onConflict = IGNORE)
    void insertUser(User user);
    //...
}
</code>```

Is it possible to return the id of User once the insertion is completed in the above method itself without writing a separate select query?

答:
@Insert function can return void, long, long[] or List<Long>.  Please try this.

```<code> @Insert(onConflict = OnConflictStrategy.REPLACE)
  long insert(User user);

 // Insert multiple items
 @Insert(onConflict = OnConflictStrategy.REPLACE)
  long[] insert(User... user);
</code>```

Body:
This is how I am inserting data into database using Room Persistence Library:

Entity:

@Entity
class User {
    @PrimaryKey(autoGenerate = true)
    public int id;
    //...
}

Data access object:

@Dao
public interface UserDao{
    @Insert(onConflict = IGNORE)
    void insertUser(User user);
    //...
}

Is it possible to return the id of User once the insertion is completed in the above method itself without writing a separate select query?

Body:
@Insert function can return void, long, long[] or List<Long>.  Please try this.

 @Insert(onConflict = OnConflictStrategy.REPLACE)
  long insert(User user);

 // Insert multiple items
 @Insert(onConflict = OnConflictStrategy.REPLACE)
  long[] insert(User... user);


问:
Number of features of the model must match the input. Model n_features is 40 and input n_features is 38
i am getting this error.please give me any suggestion to resolve it.here is my code.i am taking traing data from train.csv and testing data from another file test.csv.i am new to machine learning so i could not understand what is the problem.give me any suggestion. </p>

```<code>import quandl,math
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import style
import datetime
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import LabelEncoder
from sklearn.feature_extraction.text import CountVectorizer
from sklearn import metrics
train = pd.read_csv("train.csv", index_col=None)
test = pd.read_csv("test.csv", index_col=None)
vectorizer = CountVectorizer(min_df=1)
X1 = vectorizer.fit_transform(train['question'])
Y1 = vectorizer.fit_transform(test['testing'])
X=X1.toarray()
Y=Y1.toarray()
#print(Y.shape)
number=LabelEncoder()
train['answer']=number.fit_transform(train['answer'].astype('str'))
features = ['question','answer']
y = train['answer']
clf=RandomForestClassifier(n_estimators=100)
clf.fit(X[:25],y)
predicted_result=clf.predict(Y[17])
p_result=number.inverse_transform(predicted_result)
f = open('output.txt', 'w')
t=str(p_result)
f.write(t)
print(p_result)
</code>```

答:
There are multiple problems with your code.
But the thing related to this question is that you are fitting the CountVectorizer (vectorizer) on both train and test data, which is why you are getting different features.

What you should do is:

```<code>X1 = vectorizer.fit_transform(train['question'])

# The following line is changed
Y1 = vectorizer.transform(test['testing'])
</code>```

Body:
i am getting this error.please give me any suggestion to resolve it.here is my code.i am taking traing data from train.csv and testing data from another file test.csv.i am new to machine learning so i could not understand what is the problem.give me any suggestion.

import quandl,math
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import style
import datetime
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import LabelEncoder
from sklearn.feature_extraction.text import CountVectorizer
from sklearn import metrics
train = pd.read_csv("train.csv", index_col=None)
test = pd.read_csv("test.csv", index_col=None)
vectorizer = CountVectorizer(min_df=1)
X1 = vectorizer.fit_transform(train['question'])
Y1 = vectorizer.fit_transform(test['testing'])
X=X1.toarray()
Y=Y1.toarray()
#print(Y.shape)
number=LabelEncoder()
train['answer']=number.fit_transform(train['answer'].astype('str'))
features = ['question','answer']
y = train['answer']
clf=RandomForestClassifier(n_estimators=100)
clf.fit(X[:25],y)
predicted_result=clf.predict(Y[17])
p_result=number.inverse_transform(predicted_result)
f = open('output.txt', 'w')
t=str(p_result)
f.write(t)
print(p_result)

Body:
There are multiple problems with your code.
But the thing related to this question is that you are fitting the CountVectorizer (vectorizer) on both train and test data, which is why you are getting different features.

What you should do is:

X1 = vectorizer.fit_transform(train['question'])

# The following line is changed
Y1 = vectorizer.transform(test['testing'])


问:
Why would I need Docker for nodejs?
I am relatively new to Docker. And it's pretty amazing.

Well, I understand that for language like PHP. I think it does really make sense to use Docker, because of the PHP environment.

But why would i need to use docker for Node.js while i can simply 'npm install' and 'npm start' and I am all done.

I believe I have missed something here I think. What did I miss?

答:
The main point worth noting is that all applications depend on a machine build. Trivial apps (in Node or PHP or anything) can just be started on the console, but they still need a server and a package manager.

The list then might comprise of any of the following:

The base server is chosen for a balance of speed, image size, security approach or update cautiousness (Ubuntu for features, CentOS for caution, Alpine for image size, etc)

Run-time software such as PHP, Apache, NginX, Node, etc.

server write permissions set up on an internal cache folder

the installation of a specific version of cURL

a local cache or queue installation (Redis, Memcache, etc)

a specific PHP extension installed, such as a database extension (or system equivalent in another language)

User accounts

Package management software like Composer and NPM

Your app, fetched from version control or a build server

An installation of your packages for your app

Install fonts

Set timezone and localisations

Here is a Dockerfile I wrote recently (for a relatively simple set of functional tests):

```<code># Docker build script for the Command Agent system

FROM ubuntu

# Do a system update
RUN apt-get update && apt-get install -y

# Basic dependencies
RUN apt-get install -y git openssl

# Install PHP
# Composer needs openssl, json, phar, iconv/mbstring
# Composer recommends zlib
# PHPUnit needs dom, mbstring
RUN apt-get install -y php php-json php-phar php-mbstring php-dom php-zip
# @todo What names are php-ssl and php-zlib under?

# Install SSH server
# Expect is to handle tty automation
# Netcat is required to send messages
RUN apt-get install -y openssh-server expect netcat

RUN adduser --disabled-password --gecos "" nonpriv
# It looks like passwordless access does not work unless the user has a password!
RUN echo 'nonpriv:Password123' | chpasswd

# We need to be able to ask for a root password (so lets give it one)
RUN echo 'root:Password123' | chpasswd

# Copy over installation scripts
COPY install /tmp/install
RUN chmod u+rx /tmp/install/_*.sh && \
    chown -R nonpriv:nonpriv /tmp/install

# Install Composer
# See https://getcomposer.org/doc/faqs/how-to-install-composer-programmatically.md
RUN cd /tmp && sh /tmp/install/composer.sh

# Copy dependendencies
COPY composer.json /root/command-agent/composer.json
COPY composer.lock /root/command-agent/composer.lock

# Install deps using Composer (include dev deps)
# @todo Don't run composer as root, https://getcomposer.org/root
RUN cd /root/command-agent && php /tmp/composer.phar install

# Apply patch to PHPUnit. This is a bit hacky, but the only way I can see to
# fully turn off output buffering. Unfortunately these methods are private,
# so standard approaches to removing them (an override method) would not work.
# The only other alternative is using runkit, and I think that might be +more+
# hacky :)
COPY patch /root/command-agent/patch
RUN patch -p1 \
    /root/command-agent/vendor/phpunit/phpunit/src/Framework/TestCase.php \
    /root/command-agent/patch/disable_ob.patch

# Copy code
COPY bin /root/command-agent/bin
COPY src /root/command-agent/src
COPY test /root/command-agent/test
COPY entry-point.sh /root/command-agent/entry-point.sh
COPY expect.sh /root/command-agent/expect.sh
COPY phpunit.xml /root/command-agent/phpunit.xml
RUN ln -s /root/command-agent/vendor/bin/phpunit /root/command-agent/phpunit

# Allow non-priv user to read/exec root files
RUN chown -R root:nonpriv /root && \
    chmod -R g-w /root && \
    chmod -R g+rx /root

# This should be privileged access only
COPY test/functional/assets/agent_auth /root/.agent_auth
COPY test/functional/assets/agent_auth_wrong /root/.agent_auth_wrong
COPY test/functional/assets/bad_perms_agent_auth /root/.bad_perms_agent_auth
RUN chmod 400 /root/.agent_auth*

# Run tests
ENTRYPOINT ["sh", "/root/command-agent/entry-point.sh"]
</code>```

That is quite lengthy, and is certainly something I do not want to repeat every time I make a fresh deployment.

Title: Why would I need Docker for nodejs?

Body:
The main point worth noting is that all applications depend on a machine build. Trivial apps (in Node or PHP or anything) can just be started on the console, but they still need a server and a package manager.

The list then might comprise of any of the following:

The base server is chosen for a balance of speed, image size, security approach or update cautiousness (Ubuntu for features, CentOS for caution, Alpine for image size, etc)

Run-time software such as PHP, Apache, NginX, Node, etc.

server write permissions set up on an internal cache folder

the installation of a specific version of cURL

a local cache or queue installation (Redis, Memcache, etc)

a specific PHP extension installed, such as a database extension (or system equivalent in another language)

User accounts

Package management software like Composer and NPM

Your app, fetched from version control or a build server

An installation of your packages for your app

Install fonts

Set timezone and localisations

Here is a Dockerfile I wrote recently (for a relatively simple set of functional tests):

# Docker build script for the Command Agent system

FROM ubuntu

# Do a system update
RUN apt-get update && apt-get install -y

# Basic dependencies
RUN apt-get install -y git openssl

# Install PHP
# Composer needs openssl, json, phar, iconv/mbstring
# Composer recommends zlib
# PHPUnit needs dom, mbstring
RUN apt-get install -y php php-json php-phar php-mbstring php-dom php-zip
# @todo What names are php-ssl and php-zlib under?

# Install SSH server
# Expect is to handle tty automation
# Netcat is required to send messages
RUN apt-get install -y openssh-server expect netcat

RUN adduser --disabled-password --gecos "" nonpriv
# It looks like passwordless access does not work unless the user has a password!
RUN echo 'nonpriv:Password123' | chpasswd

# We need to be able to ask for a root password (so lets give it one)
RUN echo 'root:Password123' | chpasswd

# Copy over installation scripts
COPY install /tmp/install
RUN chmod u+rx /tmp/install/_*.sh && \
    chown -R nonpriv:nonpriv /tmp/install

# Install Composer
# See https://getcomposer.org/doc/faqs/how-to-install-composer-programmatically.md
RUN cd /tmp && sh /tmp/install/composer.sh

# Copy dependendencies
COPY composer.json /root/command-agent/composer.json
COPY composer.lock /root/command-agent/composer.lock

# Install deps using Composer (include dev deps)
# @todo Don't run composer as root, https://getcomposer.org/root
RUN cd /root/command-agent && php /tmp/composer.phar install

# Apply patch to PHPUnit. This is a bit hacky, but the only way I can see to
# fully turn off output buffering. Unfortunately these methods are private,
# so standard approaches to removing them (an override method) would not work.
# The only other alternative is using runkit, and I think that might be +more+
# hacky :)
COPY patch /root/command-agent/patch
RUN patch -p1 \
    /root/command-agent/vendor/phpunit/phpunit/src/Framework/TestCase.php \
    /root/command-agent/patch/disable_ob.patch

# Copy code
COPY bin /root/command-agent/bin
COPY src /root/command-agent/src
COPY test /root/command-agent/test
COPY entry-point.sh /root/command-agent/entry-point.sh
COPY expect.sh /root/command-agent/expect.sh
COPY phpunit.xml /root/command-agent/phpunit.xml
RUN ln -s /root/command-agent/vendor/bin/phpunit /root/command-agent/phpunit

# Allow non-priv user to read/exec root files
RUN chown -R root:nonpriv /root && \
    chmod -R g-w /root && \
    chmod -R g+rx /root

# This should be privileged access only
COPY test/functional/assets/agent_auth /root/.agent_auth
COPY test/functional/assets/agent_auth_wrong /root/.agent_auth_wrong
COPY test/functional/assets/bad_perms_agent_auth /root/.bad_perms_agent_auth
RUN chmod 400 /root/.agent_auth*

# Run tests
ENTRYPOINT ["sh", "/root/command-agent/entry-point.sh"]

That is quite lengthy, and is certainly something I do not want to repeat every time I make a fresh deployment.


问:
python - Steganography - UnicodeDecode Error
I am writing a Python script to hide data in an image. It basically hides the bits in the last two bits of the red color in RGB map of each pixel in a .PNG. The script works fine for lowercase letters but produces an error with a full stop. It produces this error:

Traceback (most recent call last):   File
  "E:\Python\Steganography\main.py", line 65, in
      print(unhide('coded-img.png'))   File "E:\Python\Steganography\main.py", line 60, in unhide
      message = bin2str(binary)   File "E:\Python\Steganography\main.py", line 16, in bin2str
      return n.to_bytes((n.bit_length() + 7) // 8, 'big').decode() UnicodeDecodeError: 'utf-8' codec can't decode byte 0x80 in position
  6: invalid start byte

Here, is my code:

```<code>from PIL import Image

def str2bin(message):
    binary = bin(int.from_bytes(message.encode('utf-8'), 'big'))
    return binary[2:]

def bin2str(binary):
    n = int(binary, 2)
    return n.to_bytes((n.bit_length() + 7) // 8, 'big').decode()

def hide(filename, message):
    image = Image.open(filename)
    binary = str2bin(message) + '00000000'

    data = list(image.getdata())

    newData = []

    index = 0
    for pixel in data:
        if index < len(binary):
            pixel = list(pixel)
            pixel[0] >>= 2
            pixel[0] <<= 2
            pixel[0] += int('0b' + binary[index:index+2], 2)
            pixel = tuple(pixel)
            index += 2

        newData.append(pixel)

    print(binary)

    image.putdata(newData)
    image.save('coded-'+filename, 'PNG')

def unhide(filename):
    image = Image.open(filename)
    data = image.getdata()

    binary = '0'

    index = 0

    while binary[-8:] != '00000000':
        binary += bin(data[index][0])[-2:]
        index += 1

    binary = binary[:-1]

    print(binary)
    print(index*2)

    message = bin2str(binary)
    return message

hide('img.png', 'alpha.')
print(unhide('coded-img.png'))
</code>```

Please help. Thanks!

答:
There are at least two problems with your code.

The first problem is that your encoding can be misaligned by 1 bit since leading null bits are not included in the output of the bin() function:

```<code>>>> bin(int.from_bytes('a'.encode('utf-8'), 'big'))[2:]
'1100001'
# This string is of odd length and (when joined with the terminating '00000000')
# turns into a still odd-length '110000100000000' which is then handled by your
# code as if there was an extra trailing zero (so that the length is even).
# During decoding you compensate for that effect with the
#
#       binary = binary[:-1]
#
# line. The latter is responsible for your stated problem when the binary
# representation of your string is in fact of even length and doesn't need
# the extra bit as in the below example:
>>> bin(int.from_bytes('.'.encode('utf-8'), 'big'))[2:]
'101110'
</code>```

You better complement your binary string  to even length by prepending an extra null bit (if needed).

The other problem is that while restoring the hidden message the stopping condition binary[-8:] == '00000000' can be prematurely satisfied through leading bits of one (partially restored) symbol being concatenated to trailing bits of another symbol. This can happen, for example, in the following cases

the symbol @ (with ASCII code=64, i.e. 6 low order bits unset) followed by any character having an ASCII code value less than 64 (i.e. with 2 highest order bits unset);

a space character (with ASCII code=32, i.e. 4 low order bits unset) followed by a linefeed/newline character(with ASCII code=10, i.e. 4 high order bits unset).

You can fix that bug by requiring that a full byte is decoded at the time when the last 8 bits appear to all be unset:

```<code>while not (len(binary) % 8 == 0 and binary[-8:] == '00000000'):
    # ...
</code>```

Body:
I am writing a Python script to hide data in an image. It basically hides the bits in the last two bits of the red color in RGB map of each pixel in a .PNG. The script works fine for lowercase letters but produces an error with a full stop. It produces this error:

Traceback (most recent call last):   File
  "E:\Python\Steganography\main.py", line 65, in
      print(unhide('coded-img.png'))   File "E:\Python\Steganography\main.py", line 60, in unhide
      message = bin2str(binary)   File "E:\Python\Steganography\main.py", line 16, in bin2str
      return n.to_bytes((n.bit_length() + 7) // 8, 'big').decode() UnicodeDecodeError: 'utf-8' codec can't decode byte 0x80 in position
  6: invalid start byte

Here, is my code:

from PIL import Image

def str2bin(message):
    binary = bin(int.from_bytes(message.encode('utf-8'), 'big'))
    return binary[2:]

def bin2str(binary):
    n = int(binary, 2)
    return n.to_bytes((n.bit_length() + 7) // 8, 'big').decode()

def hide(filename, message):
    image = Image.open(filename)
    binary = str2bin(message) + '00000000'

    data = list(image.getdata())

    newData = []

    index = 0
    for pixel in data:
        if index < len(binary):
            pixel = list(pixel)
            pixel[0] >>= 2
            pixel[0] <<= 2
            pixel[0] += int('0b' + binary[index:index+2], 2)
            pixel = tuple(pixel)
            index += 2

        newData.append(pixel)

    print(binary)

    image.putdata(newData)
    image.save('coded-'+filename, 'PNG')

def unhide(filename):
    image = Image.open(filename)
    data = image.getdata()

    binary = '0'

    index = 0

    while binary[-8:] != '00000000':
        binary += bin(data[index][0])[-2:]
        index += 1

    binary = binary[:-1]

    print(binary)
    print(index*2)

    message = bin2str(binary)
    return message

hide('img.png', 'alpha.')
print(unhide('coded-img.png'))

Please help. Thanks!

Body:
There are at least two problems with your code.

The first problem is that your encoding can be misaligned by 1 bit since leading null bits are not included in the output of the bin() function:

>>> bin(int.from_bytes('a'.encode('utf-8'), 'big'))[2:]
'1100001'
# This string is of odd length and (when joined with the terminating '00000000')
# turns into a still odd-length '110000100000000' which is then handled by your
# code as if there was an extra trailing zero (so that the length is even).
# During decoding you compensate for that effect with the
#
#       binary = binary[:-1]
#
# line. The latter is responsible for your stated problem when the binary
# representation of your string is in fact of even length and doesn't need
# the extra bit as in the below example:
>>> bin(int.from_bytes('.'.encode('utf-8'), 'big'))[2:]
'101110'

You better complement your binary string  to even length by prepending an extra null bit (if needed).

The other problem is that while restoring the hidden message the stopping condition binary[-8:] == '00000000' can be prematurely satisfied through leading bits of one (partially restored) symbol being concatenated to trailing bits of another symbol. This can happen, for example, in the following cases

the symbol @ (with ASCII code=64, i.e. 6 low order bits unset) followed by any character having an ASCII code value less than 64 (i.e. with 2 highest order bits unset);

a space character (with ASCII code=32, i.e. 4 low order bits unset) followed by a linefeed/newline character(with ASCII code=10, i.e. 4 high order bits unset).

You can fix that bug by requiring that a full byte is decoded at the time when the last 8 bits appear to all be unset:

while not (len(binary) % 8 == 0 and binary[-8:] == '00000000'):
    # ...


问:
Odoo - Give a warning when editing some field with empty value
I want to add an entry to the suppliers table if one creates a new or edits a product. Each product must have a supplier.
If a supplier is not selected, system must give a warning “You should fill in the supplier details, at least one.”

Here is my code:

```<code>class warning_supplier(models.Model):
_inherit = 'product.template'

@api.multi
def write(self, vals):
    res = super(warning_supplier, self).write(vals)
    supplier_id = self.env['res.partner'].search([('name','=','No Supplier')])
    for this in self:
        seller_ids = this.seller_ids
        if len(seller_ids)==0:
            raise Warning('You should fill in the supplier details, at least one.')
    return res
</code>```

When I create products, the code runs correctly.

But when I edit a product & remove the selected supplier, it does not work any more.

Can someone pinpoint the error to me? Thanks!

Edit: Fixed by using constraints.

答:
When you are creating product create function is called, and on edit always write function.

In create you should check vals parameter and if it doesn't meet the requirements you should warn user to correct it and after that edit actual record.

Try something like this

```<code># For example boolean
if vals["myBoolean"] == False:
    raise Warning('myBoolean should be true always!')
</code>```

Body:
I want to add an entry to the suppliers table if one creates a new or edits a product. Each product must have a supplier.
If a supplier is not selected, system must give a warning “You should fill in the supplier details, at least one.”

Here is my code:

class warning_supplier(models.Model):
_inherit = 'product.template'

@api.multi
def write(self, vals):
    res = super(warning_supplier, self).write(vals)
    supplier_id = self.env['res.partner'].search([('name','=','No Supplier')])
    for this in self:
        seller_ids = this.seller_ids
        if len(seller_ids)==0:
            raise Warning('You should fill in the supplier details, at least one.')
    return res

When I create products, the code runs correctly.

But when I edit a product & remove the selected supplier, it does not work any more.

Can someone pinpoint the error to me? Thanks!

Edit: Fixed by using constraints.

Body:
When you are creating product create function is called, and on edit always write function.

In create you should check vals parameter and if it doesn't meet the requirements you should warn user to correct it and after that edit actual record.

Try something like this

# For example boolean
if vals["myBoolean"] == False:
    raise Warning('myBoolean should be true always!')


问:
How to replace only one digit in text in python?
I have a file with pairs of numbers as following:

```<code>0,21
0,52
0,464
100,478
1,101
1,729
1,730
</code>```

And I want to replace the single "0"s with "2000". The expected output should be:

```<code>2000,21
2000,52
2000,464
100,478
1,101
1,729
1,730
</code>```

However, with my code, it changes all 0s to 2000s and I end up with this output:

```<code>2000,21
2000,52
2000,464
120002000,478
1,120001
1,729
1,732000
</code>```

My code is:

```<code>textToSearch = "0"
textToReplace = "2000"
fileToSearch = "example.csv"
with fileinput.FileInput(fileToSearch, inplace=True, backup='.bak') as file:
    for line in file:
        print(line.replace(textToSearch, textToReplace), end='')
</code>```

Plus : I never know how many 0s will be on the left side of the comma, therefore I cannot limit the number of 0s to be changed. The file is randomly generated, as sometimes I have twelve 0s and sometimes only one.
I have tried this:

```<code>textToSearch = "0,"
textToReplace = "2000,"
fileToSearch = "example.csv"
with fileinput.FileInput(fileToSearch, inplace=True, backup='.bak') as file:
    for line in file:
        print(line.replace(textToSearch, textToReplace), end='')
</code>```

However,this time it is not working for numbers such as "100" or "200", as it is making them "102000" and "202000" respectively.

How can I fix it?

答:
This is slightly modified to save your data to file. The basic algorithm hasn't changed.</p>

```<code>import re

temp = []

with open("example.csv", "r") as inputf:
    for line in inputf:
        line = line.strip("\n")
        match = re.search("^0", line)
        if match:
            list1 = line.split(",")
            list1[0] = 2000
            line = str(list1[0]) + "," + str(list1[1])
        temp.append(line)
inputf.close()

# overwrite original file

with open("example.csv", "w") as outputf:
    for item in temp:
        outputf.write(item + "\n")
outputf.close()
</code>```

Body:
I have a file with pairs of numbers as following:

0,21
0,52
0,464
100,478
1,101
1,729
1,730

And I want to replace the single "0"s with "2000". The expected output should be:

2000,21
2000,52
2000,464
100,478
1,101
1,729
1,730

However, with my code, it changes all 0s to 2000s and I end up with this output:

2000,21
2000,52
2000,464
120002000,478
1,120001
1,729
1,732000

My code is:

textToSearch = "0"
textToReplace = "2000"
fileToSearch = "example.csv"
with fileinput.FileInput(fileToSearch, inplace=True, backup='.bak') as file:
    for line in file:
        print(line.replace(textToSearch, textToReplace), end='')

Plus : I never know how many 0s will be on the left side of the comma, therefore I cannot limit the number of 0s to be changed. The file is randomly generated, as sometimes I have twelve 0s and sometimes only one.
I have tried this:

textToSearch = "0,"
textToReplace = "2000,"
fileToSearch = "example.csv"
with fileinput.FileInput(fileToSearch, inplace=True, backup='.bak') as file:
    for line in file:
        print(line.replace(textToSearch, textToReplace), end='')

However,this time it is not working for numbers such as "100" or "200", as it is making them "102000" and "202000" respectively.

How can I fix it?

Body:
This is slightly modified to save your data to file. The basic algorithm hasn't changed.

import re

temp = []

with open("example.csv", "r") as inputf:
    for line in inputf:
        line = line.strip("\n")
        match = re.search("^0", line)
        if match:
            list1 = line.split(",")
            list1[0] = 2000
            line = str(list1[0]) + "," + str(list1[1])
        temp.append(line)
inputf.close()

# overwrite original file

with open("example.csv", "w") as outputf:
    for item in temp:
        outputf.write(item + "\n")
outputf.close()