问:
gpgp key request fails in dockerfile but not bash
I have an issue in that my attempts to receive a gpg key fails when building my docker container. The command that I am providing works correctly when executed at the command line.

I am behind a firewall; I have the proxy settings detailed below for this.

Host: CentOS 7.4; Docker version 17.09.0-ce, build afdb6d4

No environment variables for proxies are set for the account being used.

The Docker service has the environment variables for the proxies set according to Docker:

In /etc/systemd/system/docker.service.d/http-proxy.conf:

```<code>[Service]
Environment="HTTP_PROXY=http://<corporate proxy>/" "HTTPS_PROXY="<corporate proxy>/" "NO_PROXY=localhost,127.0.0.1,.domain.local,.corp"
</code>```

I use a build.sh shell script to build the image:

```<code>#/bin/bash
docker build -t hgk/test-container .
</code>```

The shell script is in the same location as my Dockerfile. These are the only two things in that directory.

```<code>FROM openjdk:8
ARG KEYSERV=hkp://p80.pool.sks-keyservers.net:80
ARG THEPROXY=<my corporate proxy>

# grab gosu for easy step-down from root
# (see docker-sonarqube pull request #115)
RUN set -x \
    && wget -e https_proxy=$THEPROXY -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.10/gosu-$(dpkg --print-architecture)" \
    && wget -e https_proxy=$THEPROXY-O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/1.10/gosu-$(dpkg --print-architecture).asc" \
    && export GNUPGHOME="$(mktemp -d)" \
    && gpg --version \
    && gpg -vv --keyserver $KEYSERV --keyserver-options http-proxy=$THEPROXY --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \
    && gpg --list-keys \
    && gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu \
    && rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc \
    && chmod +x /usr/local/bin/gosu \
    && gosu nobody true
</code>```

The two wget commands work correctly and they retrieve the files. The first gpg command eventually times out:

```<code>+ mktemp -d
+ export GNUPGHOME=/tmp/tmp.LJ1EVFQmpO
+ gpg --version
gpg (GnuPG) 2.1.18
libgcrypt 1.7.6-beta
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
<https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Home: /tmp/tmp.LJlEVFQmpO
Supported algorithms:
Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
        CAMELLIA128, CAMELLIA192, CAMELLIA256
Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
Compression: Uncompressed, ZIP, ZLIB, BZIP2
+ gpg -vv --keyserver hkp://p80.pool.sks-keyservers.net:80 --keyserver-options http-proxy=<corp proxy> --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4
gpg: keybox '/tmp/tmp.LJlEVFQmpO/pubring.kbx' created
gpg: no running Dirmngr - starting '/usr/bin/dirmngr'
gpg: waiting for the dirmngr to come up ... (5s)
gpg: connection to the dirmngr established

[[I am hung here - It just waits for ... something? I'll update the question if anything prints after this]]
</code>```

I put the gpg --list-keys command in the Dockerfile to see if we got past there. However, if I run it via the command line, it successfully retrieves the key:

```<code>[root@me foo]# printenv | grep proxy
[root@me foo]# gpg --keyserver hkp://p80.pool.sks-keyservers.net:80 --
keyserver-options http-proxy=<corp proxy> --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4
gpg: keyring `/root/.gnupg/pubring.gpg' created
gpg: requesting key BF357DD4 from hkp server p80.pool.sks-keyservers.net
Version: SKS 1.1.6
gpg: armor header:
Comment: Hostname: sks.okoyono.de
gpg: armor header:
gpg: pub  4096R/BF357DD4 2014-02-28  Tianon Gravi <tianon@debian.org>
gpg: key BF357DD4: removed multiple subkey binding
gpg: key BF357DD4: removed multiple subkey binding
gpg: /tmp/tmp.DIX6yQQf25/trustdb.gpg: trustdb created
gpg: using PGP trust model
gpg: key BF357DD4: public key "Tianon Gravi <tianon@tianon.xyz>" imported
gpg: 1 keys cached (126 signatures)
gpg: 0 keys processed (0 validity counts cleared)
gpg: no ultimately trusted keys found
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)

[root@me foo]# gpg --list-keys
/root/.gnupg/pubring.gpg
------------------------
pub   4096R/BF357DD4 2014-02-28 [expires: 2019-07-06]
uid                  Tianon Gravi <tianon@tianon.xyz>
uid                  Tianon Gravi <tianon@debian.org>
uid                  Tianon Gravi <tianon@dockerproject.org>
uid                  Andrew Page (tianon) <andrew@infosiftr.com>
uid                  Andrew Page (tianon) <andrew@vitalroute.com>
uid                  Andrew Page (Tianon Gravi) <admwiggin@gmail.com>
uid                  Tianon Gravi (Andrew Page) <tianon@infosiftr.com>
sub   4096R/769826E6 2014-02-28 [expires: 2019-07-06]
</code>```

I've tried different sks-keyservers (ubuntu, MIT, and other sks) with the same behavior - correct from bash, wrong from Docker.

Any thoughts/tips/suggestions?

Update: My "openjdk:8" version had not been updated in a while (since 8u121). I found I was running gpg v1.4.18. I did a docker image pull openjdk:8 which brought me up to 8u151 and gpg 2.1.18. The version of gpg on the CentOS 7 machine is 2.0.22.

答:
My solution to the problem (whether it is the right solution or not is up for debate) was to add the http_proxy and https_proxy environment variables to the Dockerfile.

```<code>FROM openjdk:8
ARG KEYSERV=hkp://p80.pool.sks-keyservers.net:80
ARG THEPROXY=<my corporate proxy>
ENV http_proxy $THEPROXY
ENV https_proxy $THEPROXY

# grab gosu for easy step-down from root
# (see docker-sonarqube pull request #115)
RUN set -x \
    && wget -e https_proxy=$THEPROXY -O /usr/local/bin/gosu
"https://github.com/tianon/gosu/releases/download/1.10/gosu-$(dpkg --print-architecture)" \
    && wget -e https_proxy=$THEPROXY-O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/1.10/gosu-$(dpkg --print-architecture).asc" \
    && export GNUPGHOME="$(mktemp -d)" \
    && gpg --version \
    && gpg -vv --keyserver $KEYSERV --keyserver-options http-proxy=$THEPROXY --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \
    && gpg --list-keys \
    && gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu \
    && rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc \
    && chmod +x /usr/local/bin/gosu \
    && gosu nobody true
</code>```

My interpretation of this fix is that gpg spins up dirmngr. dirmngr "is a server for managing and downloading certificate revocation lists (CRLs) for X.509 certificates and for downloading the certificates themselves." This hints at some form of network connectivity being necessary. Reading the [dirmngr options][2] page, there is a --http-proxy argument that does not seem to get passed to the startup arguments for dirmngr.

Somehow, adding the http_proxy to the environment allows dirmngr to do it's job successfully.

I'm not sure if this is a bug (there's an --honor-http-proxy option that appears to be set to 0 by default in the gnupg source code, so I'm not sure why it's picking up the http_proxy, but my solution is working and meets my needs. I'll try to read the source code a little more in detail this weekend, but this isn't a high priority any more for me and my team.

Body:
I have an issue in that my attempts to receive a gpg key fails when building my docker container. The command that I am providing works correctly when executed at the command line.

I am behind a firewall; I have the proxy settings detailed below for this.

Host: CentOS 7.4; Docker version 17.09.0-ce, build afdb6d4

No environment variables for proxies are set for the account being used.

The Docker service has the environment variables for the proxies set according to Docker:

In /etc/systemd/system/docker.service.d/http-proxy.conf:

[Service]
Environment="HTTP_PROXY=http://<corporate proxy>/" "HTTPS_PROXY="<corporate proxy>/" "NO_PROXY=localhost,127.0.0.1,.domain.local,.corp"

I use a build.sh shell script to build the image:

#/bin/bash
docker build -t hgk/test-container .

The shell script is in the same location as my Dockerfile. These are the only two things in that directory.

FROM openjdk:8
ARG KEYSERV=hkp://p80.pool.sks-keyservers.net:80
ARG THEPROXY=<my corporate proxy>

# grab gosu for easy step-down from root
# (see docker-sonarqube pull request #115)
RUN set -x \
    && wget -e https_proxy=$THEPROXY -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.10/gosu-$(dpkg --print-architecture)" \
    && wget -e https_proxy=$THEPROXY-O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/1.10/gosu-$(dpkg --print-architecture).asc" \
    && export GNUPGHOME="$(mktemp -d)" \
    && gpg --version \
    && gpg -vv --keyserver $KEYSERV --keyserver-options http-proxy=$THEPROXY --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \
    && gpg --list-keys \
    && gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu \
    && rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc \
    && chmod +x /usr/local/bin/gosu \
    && gosu nobody true

The two wget commands work correctly and they retrieve the files. The first gpg command eventually times out:

+ mktemp -d
+ export GNUPGHOME=/tmp/tmp.LJ1EVFQmpO
+ gpg --version
gpg (GnuPG) 2.1.18
libgcrypt 1.7.6-beta
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
<https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Home: /tmp/tmp.LJlEVFQmpO
Supported algorithms:
Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
        CAMELLIA128, CAMELLIA192, CAMELLIA256
Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
Compression: Uncompressed, ZIP, ZLIB, BZIP2
+ gpg -vv --keyserver hkp://p80.pool.sks-keyservers.net:80 --keyserver-options http-proxy=<corp proxy> --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4
gpg: keybox '/tmp/tmp.LJlEVFQmpO/pubring.kbx' created
gpg: no running Dirmngr - starting '/usr/bin/dirmngr'
gpg: waiting for the dirmngr to come up ... (5s)
gpg: connection to the dirmngr established

[[I am hung here - It just waits for ... something? I'll update the question if anything prints after this]]

I put the gpg --list-keys command in the Dockerfile to see if we got past there. However, if I run it via the command line, it successfully retrieves the key:

[root@me foo]# printenv | grep proxy
[root@me foo]# gpg --keyserver hkp://p80.pool.sks-keyservers.net:80 --
keyserver-options http-proxy=<corp proxy> --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4
gpg: keyring `/root/.gnupg/pubring.gpg' created
gpg: requesting key BF357DD4 from hkp server p80.pool.sks-keyservers.net
Version: SKS 1.1.6
gpg: armor header:
Comment: Hostname: sks.okoyono.de
gpg: armor header:
gpg: pub  4096R/BF357DD4 2014-02-28  Tianon Gravi <tianon@debian.org>
gpg: key BF357DD4: removed multiple subkey binding
gpg: key BF357DD4: removed multiple subkey binding
gpg: /tmp/tmp.DIX6yQQf25/trustdb.gpg: trustdb created
gpg: using PGP trust model
gpg: key BF357DD4: public key "Tianon Gravi <tianon@tianon.xyz>" imported
gpg: 1 keys cached (126 signatures)
gpg: 0 keys processed (0 validity counts cleared)
gpg: no ultimately trusted keys found
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)

[root@me foo]# gpg --list-keys
/root/.gnupg/pubring.gpg
------------------------
pub   4096R/BF357DD4 2014-02-28 [expires: 2019-07-06]
uid                  Tianon Gravi <tianon@tianon.xyz>
uid                  Tianon Gravi <tianon@debian.org>
uid                  Tianon Gravi <tianon@dockerproject.org>
uid                  Andrew Page (tianon) <andrew@infosiftr.com>
uid                  Andrew Page (tianon) <andrew@vitalroute.com>
uid                  Andrew Page (Tianon Gravi) <admwiggin@gmail.com>
uid                  Tianon Gravi (Andrew Page) <tianon@infosiftr.com>
sub   4096R/769826E6 2014-02-28 [expires: 2019-07-06]

I've tried different sks-keyservers (ubuntu, MIT, and other sks) with the same behavior - correct from bash, wrong from Docker.

Any thoughts/tips/suggestions?

Update: My "openjdk:8" version had not been updated in a while (since 8u121). I found I was running gpg v1.4.18. I did a docker image pull openjdk:8 which brought me up to 8u151 and gpg 2.1.18. The version of gpg on the CentOS 7 machine is 2.0.22.

Body:
My solution to the problem (whether it is the right solution or not is up for debate) was to add the http_proxy and https_proxy environment variables to the Dockerfile.

FROM openjdk:8
ARG KEYSERV=hkp://p80.pool.sks-keyservers.net:80
ARG THEPROXY=<my corporate proxy>
ENV http_proxy $THEPROXY
ENV https_proxy $THEPROXY

# grab gosu for easy step-down from root
# (see docker-sonarqube pull request #115)
RUN set -x \
    && wget -e https_proxy=$THEPROXY -O /usr/local/bin/gosu
"https://github.com/tianon/gosu/releases/download/1.10/gosu-$(dpkg --print-architecture)" \
    && wget -e https_proxy=$THEPROXY-O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/1.10/gosu-$(dpkg --print-architecture).asc" \
    && export GNUPGHOME="$(mktemp -d)" \
    && gpg --version \
    && gpg -vv --keyserver $KEYSERV --keyserver-options http-proxy=$THEPROXY --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \
    && gpg --list-keys \
    && gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu \
    && rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc \
    && chmod +x /usr/local/bin/gosu \
    && gosu nobody true

My interpretation of this fix is that gpg spins up dirmngr. dirmngr "is a server for managing and downloading certificate revocation lists (CRLs) for X.509 certificates and for downloading the certificates themselves." This hints at some form of network connectivity being necessary. Reading the [dirmngr options][2] page, there is a --http-proxy argument that does not seem to get passed to the startup arguments for dirmngr.

Somehow, adding the http_proxy to the environment allows dirmngr to do it's job successfully.

I'm not sure if this is a bug (there's an --honor-http-proxy option that appears to be set to 0 by default in the gnupg source code, so I'm not sure why it's picking up the http_proxy, but my solution is working and meets my needs. I'll try to read the source code a little more in detail this weekend, but this isn't a high priority any more for me and my team.


来源: stackexchange

问:
Xcode Bots Set Current Integration Number
I had to restore my OSX Server from backup and now the latest integration number is lower than I need it to be. I am using the integration number to set the build number for beta distribution. </p>

<p>Is there a way to set the current integration number i.e. XCS_INTEGRATION_NUMBER? </p>

答:
Xcode server has a REST API that allows changing the integration counter value.

Basically, you can use cURL to update the integration counter with the following command:

curl -u <xcode-server-user>:<password> -H "Content-Type: application/json" -X PATCH -d '{"set_props":{"integration_counter":<desired-integration-counter>}}'
--insecure https://<xcode-server-address>:20343/api/bots/<bot-id>

The bot-id can be obtained easily from any of the past integration logs.

For more information, check out the documentation here:
https://developer.apple.com/library/content/documentation/Xcode/Conceptual/XcodeServerAPIReference/Bots.html

And also, the answer to this question:
https://forums.developer.apple.com/thread/19868

ContentLicense: CC BY-SA 3.0

Body:
I had to restore my OSX Server from backup and now the latest integration number is lower than I need it to be. I am using the integration number to set the build number for beta distribution.

Is there a way to set the current integration number i.e. XCS_INTEGRATION_NUMBER?


问:
I would like to create a nxn matrix from two length n arrays using an addition function in python
I have two arrays n and k and I would like to create a matrix with the formula n + ik. I would like the matrix to have the following form;

```<code>n[0]+ik[0] n[0]+ik[1] n[0]+ik[2] etc.
n[1]+ik[0] n[1]+ik[1] n[0]+ik[2] etc.
etc.
</code>```

so far I have;

```<code>z = 0 + 1j

for i,j in n
    for i,j in k
    n_com = n + k*z
</code>```

but I know that its not working, and I realise it doesnt really make any sense. Do I have to use append?

答:
I think the following code is clear

```<code>n = [1, 2, 3]
k = [4, 5, 6]
mat = []
for i in range(len(n)):
    row = []                # ready to make a row
    for j in range(len(k)):
        row.append(n[i] + 1j * k[j])
    mat.append(row)         # add the row to the mat
print(mat)                  # we get it
</code>```

A more pythonic way would be (if you are interested)

```<code>mat = [[x + 1j * y for y in k] for x in n]
</code>```

Further, many science people would use numpy, you may expect better performance and usability when matrix is large.

```<code>import numpy as np
n = np.array(n)
k = np.array(k).reshape((-1, 1))
mat = n + k.repeat(len(n), 1) * 1j
</code>```

Body:
I have two arrays n and k and I would like to create a matrix with the formula n + ik. I would like the matrix to have the following form;

n[0]+ik[0] n[0]+ik[1] n[0]+ik[2] etc.
n[1]+ik[0] n[1]+ik[1] n[0]+ik[2] etc.
etc.

so far I have;

z = 0 + 1j

for i,j in n
    for i,j in k
    n_com = n + k*z

but I know that its not working, and I realise it doesnt really make any sense. Do I have to use append?

Body:
I think the following code is clear

n = [1, 2, 3]
k = [4, 5, 6]
mat = []
for i in range(len(n)):
    row = []                # ready to make a row
    for j in range(len(k)):
        row.append(n[i] + 1j * k[j])
    mat.append(row)         # add the row to the mat
print(mat)                  # we get it

A more pythonic way would be (if you are interested)

mat = [[x + 1j * y for y in k] for x in n]

Further, many science people would use numpy, you may expect better performance and usability when matrix is large.

import numpy as np
n = np.array(n)
k = np.array(k).reshape((-1, 1))
mat = n + k.repeat(len(n), 1) * 1j


问:
java Capture sound and hear it and record it to WAV simultaneously
I'm making a program that captures sound from microphone, hearing it on sound speakers (that's done) and save it to wav file simultaneously. I was searching about this problem for three-four days. I believe, that Stackoverflow could help me.

All I need to do is to write sound coming from mic to a wav file, while the user is listening to it live. Please help or point at right direction. I think that somehow I could write bytes to file directly, but it will be the mess because lack of header.

Here is my class:

```<code>public class RadioListener {
private Runnable mRunnable, mFounderR;
private Thread mThread, mFounderT;

private SourceDataLine mSourceLine;
private TargetDataLine mTargetLine;
private DataLine.Info mTargetInfo;
private DataLine.Info mSourceInfo;
private static final AudioFormat mFormat = new AudioFormat(44100, 16, 2, true, false);

private Mixer.Info[] mixers;
private Mixer mFoundMixer = null;

private Config mConfig;

private boolean isCommunicating = false;
private boolean isRetranslating = false;

File wavFile = null;
AudioFileFormat.Type fileType = AudioFileFormat.Type.WAVE;
AudioInputStream ais;

public RadioListener (Config cfg) {
    mConfig = cfg;

    mixers = AudioSystem.getMixerInfo();
    mSourceInfo = new DataLine.Info(SourceDataLine.class, mFormat);
    mTargetInfo = new DataLine.Info(TargetDataLine.class, mFormat);
    try {mSourceLine = (SourceDataLine) AudioSystem.getLine(mSourceInfo);}
    catch (LineUnavailableException e) {System.out.println("RadioListener output error");}

    wavFile = new File("E:/RecordAudio.wav");
}

public void Start() {
    if (Defines.strToIntDef(mConfig.getProperty("debugOut"), 0) == 1)
        showMixers();

    if (mFoundMixer == null) searchDevice();
    else startCommunication();
}

public void Stop() {
    if (mFoundMixer == null) return;

    try {
        mSourceLine.stop();
        mSourceLine.close();

        mTargetLine.stop();
        mTargetLine.close();
    } catch (Exception e) {}
    finally {
        isCommunicating = false;
    }
}

public void Mute() {
    isRetranslating = false;
}

private void searchDevice() {
    mFounderR = new RadioFinder();
    mFounderT = new Thread(mFounderR);
    mFounderT.start();
}

private void startThread() {
    startCommunication();
    mRunnable = new Communicator();
    mThread = new Thread(mRunnable);
    mThread.start();
}

private void startCommunication() {
    if (isCommunicating) {
        isRetranslating = true;
        return;
    }
    try {
        mTargetLine.open(mFormat);
        mTargetLine.start();

        mSourceLine.open(mFormat);
        mSourceLine.start();

        //Line line = mFoundMixer.getLine(mSourceInfo);
        //FloatControl control = (FloatControl)line.getControl(FloatControl.Type.MASTER_GAIN);
        //control.setValue(limit(control,10000));
        //control.setValue(-10);

        isCommunicating = true;
        isRetranslating = true;

        //When I'm uncommenting this two lines sound is writing to file, but I don't hear it.
        //ais = new AudioInputStream(mTargetLine);
        //AudioSystem.write(ais, fileType, wavFile);
    } catch (Exception e) {
        isCommunicating = false;
        isRetranslating = false;
    }
}

private class RadioFinder implements Runnable {
    @Override
    public void run() {
        Line.Info targetDLInfo = new Line.Info(TargetDataLine.class);
        for (Mixer.Info info : mixers) {
            Mixer tmp = AudioSystem.getMixer(info);
            //if (myMixer.isLineSupported(Port.Info.LINE_IN) || myMixer.isLineSupported(Port.Info.MICROPHONE)) {
            if (tmp.isLineSupported(targetDLInfo)) {
                String s = tmp.getMixerInfo().getName();
                if (s.toLowerCase().contains(mConfig.getProperty("radioName").toLowerCase())) {
                    mFoundMixer = tmp;
                    try {
                        mTargetInfo = new DataLine.Info(TargetDataLine.class, mFormat);
                        mTargetLine = (TargetDataLine) mFoundMixer.getLine(mTargetInfo);

                        System.out.println("Found radio device: " + mFoundMixer.getMixerInfo().getName());

                        startThread();
                    } catch (Exception e) {
                        System.out.println("RadioListener input error");
                        mFoundMixer = null;
                    }
                    break;
                }
            }
        }
    }
}

private static void showMixers() {
    ArrayList<Mixer.Info> mixInfos = new ArrayList<Mixer.Info>(Arrays.asList(AudioSystem.getMixerInfo()));

    Line.Info sourceDLInfo = new Line.Info(SourceDataLine.class);
    Line.Info targetDLInfo = new Line.Info(TargetDataLine.class);
    Line.Info clipInfo = new Line.Info(Clip.class);
    Line.Info portInfo = new Line.Info(Port.class);

    String support;

    for (Mixer.Info mixInfo: mixInfos) {
        Mixer mixer = AudioSystem.getMixer(mixInfo);

        support = ", supports ";
        if (mixer.isLineSupported(sourceDLInfo))
            support += "SourceDataLine ";
        if (mixer.isLineSupported(clipInfo))
            support += "Clip ";
        if (mixer.isLineSupported(targetDLInfo))
            support += "TargetDataLine ";
        if (mixer.isLineSupported(portInfo))
            support += "Port ";

        System.out.println("Mixer: " + mixInfo.getName() + support + ", " + mixInfo.getDescription());
    }
}

private class Communicator implements Runnable {
    @Override
    public void run() {
        int numBytesRead;
        byte[] targetData = new byte[mTargetLine.getBufferSize() / 5];

        while (isCommunicating) {
            numBytesRead = mTargetLine.read(targetData, 0, targetData.length);
            System.out.println(numBytesRead);

            if (numBytesRead == -1) break;

            if (isRetranslating)
                mSourceLine.write(targetData, 0, numBytesRead);
        }
    }
}
}}
</code>```

Thank you!

答:
Well, I'm came to the following working code.

I created new "empty" wav file with

```<code>ais = new AudioInputStream(mTargetLine);
AudioSystem.write(ais, fileType, wavFile);
</code>```

I got 44 bytes wav file, where header was storing.

When I need to record a wav file, when I'm listetning to it in live, I need to do the following: create an empty wav file, write that header (stored in jar), append bytes in linking thread. (Communicator class in my case) It is directing bytes from SourceLine to TargetLine (from a mic to speakers basically). Here is the code of my updated class from my question.

P.S.: header is for a specified AudioFormat only. If you need another, than you could "generate" them separately.
P.S.S: sorry for my bad english :)

The code:

```<code>public class RadioListener {
private Runnable mRunnable, mFounderR;
private Thread mThread = null, mFounderT = null;

private SourceDataLine mSourceLine;
private TargetDataLine mTargetLine;
private DataLine.Info mTargetInfo;
private DataLine.Info mSourceInfo;
private static final AudioFormat mFormat = new AudioFormat(44100, 16, 2, true, false);

private Mixer.Info[] mixers;
private Mixer mFoundMixer = null;

private Config mConfig;

private boolean isCommunicating = false;
private boolean isRetranslating = false;

private static final String mHeader = "header.wav";
//private File wavFile = null;
AudioFileFormat.Type fileType = AudioFileFormat.Type.WAVE;
AudioInputStream ais;
private FileOutputStream fos;
private boolean isRecording = false;

public RadioListener (Config cfg) {
    mConfig = cfg;

    mixers = AudioSystem.getMixerInfo();
    mSourceInfo = new DataLine.Info(SourceDataLine.class, mFormat);
    mTargetInfo = new DataLine.Info(TargetDataLine.class, mFormat);
    try {mSourceLine = (SourceDataLine) AudioSystem.getLine(mSourceInfo);}
    catch (LineUnavailableException e) {System.out.println("RadioListener output error");}

    //wavFile = new File("E:/RecordAudio.wav");
}

public void Start() {
    if (Defines.strToIntDef(mConfig.getProperty("debugOut"), 0) == 1)
        showMixers();

    if (mFoundMixer == null) searchDevice();
    else startCommunication();
}

public void Stop() {
    if (mFoundMixer == null) return;

    try {
        mSourceLine.stop();
        mSourceLine.close();

        mTargetLine.stop();
        mTargetLine.close();
    } catch (Exception e) {}
    finally {
        isCommunicating = false;
    }
}

public void disposeListener() {
    if (isRecording) stopRecording();

    Stop();

    if (mFounderT != null)
        if (mFounderT.isAlive())
            mFounderT.interrupt();

    if (mThread != null)
        if (mThread.isAlive())
            mThread.interrupt();
}

public void Mute() {
    isRetranslating = false;
}

public void enableRecording (boolean f) {
    if (f) startRecording();
    else stopRecording();
}

public boolean isRecording() {
    return isRecording;
}

private void startRecording() {
    final DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
    Date date = new Date(System.currentTimeMillis());
    String dt = formatter.format(date);
    final InputStream stream = this.getClass().getResourceAsStream("/" + mHeader);
    byte b[] = new byte[44];
    try {
        fos = new FileOutputStream(Defines.getCurrentFolder() + File.separator + dt + ".wav", true);
        try {
            stream.read(b, 0, 44);
            fos.write(b);
        } catch (IOException e) {
            try {fos.close();}
            catch (IOException e1) {;}
            isRecording = false;
            return;
        }

    } catch (FileNotFoundException e) {
        isRecording = false;
    }
    isRecording = true;
}

private void stopRecording() {
    isRecording = false;

    try {fos.close();}
    catch (IOException e) {;}
    isRecording = false;
}

private void searchDevice() {
    mFounderR = new RadioFinder();
    mFounderT = new Thread(mFounderR);
    mFounderT.start();
}

private void startThread() {
    startCommunication();
    mRunnable = new Communicator();
    mThread = new Thread(mRunnable);
    mThread.start();
}

private void startCommunication() {
    if (isCommunicating) {
        isRetranslating = true;
        return;
    }
    try {
        mTargetLine.open(mFormat);
        mTargetLine.start();

        mSourceLine.open(mFormat);
        mSourceLine.start();

        //Line line = mFoundMixer.getLine(mSourceInfo);
        //FloatControl control = (FloatControl)line.getControl(FloatControl.Type.MASTER_GAIN);
        //control.setValue(limit(control,10000));
        //control.setValue(-10);

        isCommunicating = true;
        isRetranslating = true;

        //ais = new AudioInputStream(mTargetLine); //ok
        //AudioSystem.write(ais, fileType, wavFile); //ok
    } catch (Exception e) {
        isCommunicating = false;
        isRetranslating = false;
    }
}

private class RadioFinder implements Runnable {
    @Override
    public void run() {
        Line.Info targetDLInfo = new Line.Info(TargetDataLine.class);
        for (Mixer.Info info : mixers) {
            Mixer tmp = AudioSystem.getMixer(info);
            //if (myMixer.isLineSupported(Port.Info.LINE_IN) || myMixer.isLineSupported(Port.Info.MICROPHONE)) {
            if (tmp.isLineSupported(targetDLInfo)) {
                String s = tmp.getMixerInfo().getName();
                if (s.toLowerCase().contains(mConfig.getProperty("radioName").toLowerCase())) {
                    mFoundMixer = tmp;
                    try {
                        mTargetInfo = new DataLine.Info(TargetDataLine.class, mFormat);
                        mTargetLine = (TargetDataLine) mFoundMixer.getLine(mTargetInfo);

                        System.out.println("Found radio device: " + mFoundMixer.getMixerInfo().getName());

                        startThread();
                    } catch (Exception e) {
                        System.out.println("RadioListener input error");
                        mFoundMixer = null;
                    }
                    break;
                }
            }
        }
    }
}

private static void showMixers() {
    ArrayList<Mixer.Info> mixInfos = new ArrayList<Mixer.Info>(Arrays.asList(AudioSystem.getMixerInfo()));

    Line.Info sourceDLInfo = new Line.Info(SourceDataLine.class);
    Line.Info targetDLInfo = new Line.Info(TargetDataLine.class);
    Line.Info clipInfo = new Line.Info(Clip.class);
    Line.Info portInfo = new Line.Info(Port.class);

    String support;

    for (Mixer.Info mixInfo: mixInfos) {
        Mixer mixer = AudioSystem.getMixer(mixInfo);

        support = ", supports ";
        if (mixer.isLineSupported(sourceDLInfo))
            support += "SourceDataLine ";
        if (mixer.isLineSupported(clipInfo))
            support += "Clip ";
        if (mixer.isLineSupported(targetDLInfo))
            support += "TargetDataLine ";
        if (mixer.isLineSupported(portInfo))
            support += "Port ";

        System.out.println("Mixer: " + mixInfo.getName() + support + ", " + mixInfo.getDescription());
    }
}

private class Communicator implements Runnable {
    @Override
    public void run() {
        int numBytesRead;
        byte[] targetData = new byte[mTargetLine.getBufferSize() / 5];

        while (isCommunicating) {
            numBytesRead = mTargetLine.read(targetData, 0, targetData.length);

            if (numBytesRead == -1) break;

            if (isRetranslating)
                mSourceLine.write(targetData, 0, numBytesRead);

            if (isRecording) {
                try {fos.write(targetData);}
                catch (IOException e) {stopRecording();}
            }
        }
    }
}

}
</code>```

Body:
I'm making a program that captures sound from microphone, hearing it on sound speakers (that's done) and save it to wav file simultaneously. I was searching about this problem for three-four days. I believe, that Stackoverflow could help me.

All I need to do is to write sound coming from mic to a wav file, while the user is listening to it live. Please help or point at right direction. I think that somehow I could write bytes to file directly, but it will be the mess because lack of header.

Here is my class:

public class RadioListener {
private Runnable mRunnable, mFounderR;
private Thread mThread, mFounderT;

private SourceDataLine mSourceLine;
private TargetDataLine mTargetLine;
private DataLine.Info mTargetInfo;
private DataLine.Info mSourceInfo;
private static final AudioFormat mFormat = new AudioFormat(44100, 16, 2, true, false);

private Mixer.Info[] mixers;
private Mixer mFoundMixer = null;

private Config mConfig;

private boolean isCommunicating = false;
private boolean isRetranslating = false;

File wavFile = null;
AudioFileFormat.Type fileType = AudioFileFormat.Type.WAVE;
AudioInputStream ais;

public RadioListener (Config cfg) {
    mConfig = cfg;

    mixers = AudioSystem.getMixerInfo();
    mSourceInfo = new DataLine.Info(SourceDataLine.class, mFormat);
    mTargetInfo = new DataLine.Info(TargetDataLine.class, mFormat);
    try {mSourceLine = (SourceDataLine) AudioSystem.getLine(mSourceInfo);}
    catch (LineUnavailableException e) {System.out.println("RadioListener output error");}

    wavFile = new File("E:/RecordAudio.wav");
}

public void Start() {
    if (Defines.strToIntDef(mConfig.getProperty("debugOut"), 0) == 1)
        showMixers();

    if (mFoundMixer == null) searchDevice();
    else startCommunication();
}

public void Stop() {
    if (mFoundMixer == null) return;

    try {
        mSourceLine.stop();
        mSourceLine.close();

        mTargetLine.stop();
        mTargetLine.close();
    } catch (Exception e) {}
    finally {
        isCommunicating = false;
    }
}

public void Mute() {
    isRetranslating = false;
}

private void searchDevice() {
    mFounderR = new RadioFinder();
    mFounderT = new Thread(mFounderR);
    mFounderT.start();
}

private void startThread() {
    startCommunication();
    mRunnable = new Communicator();
    mThread = new Thread(mRunnable);
    mThread.start();
}

private void startCommunication() {
    if (isCommunicating) {
        isRetranslating = true;
        return;
    }
    try {
        mTargetLine.open(mFormat);
        mTargetLine.start();

        mSourceLine.open(mFormat);
        mSourceLine.start();

        //Line line = mFoundMixer.getLine(mSourceInfo);
        //FloatControl control = (FloatControl)line.getControl(FloatControl.Type.MASTER_GAIN);
        //control.setValue(limit(control,10000));
        //control.setValue(-10);

        isCommunicating = true;
        isRetranslating = true;

        //When I'm uncommenting this two lines sound is writing to file, but I don't hear it.
        //ais = new AudioInputStream(mTargetLine);
        //AudioSystem.write(ais, fileType, wavFile);
    } catch (Exception e) {
        isCommunicating = false;
        isRetranslating = false;
    }
}

private class RadioFinder implements Runnable {
    @Override
    public void run() {
        Line.Info targetDLInfo = new Line.Info(TargetDataLine.class);
        for (Mixer.Info info : mixers) {
            Mixer tmp = AudioSystem.getMixer(info);
            //if (myMixer.isLineSupported(Port.Info.LINE_IN) || myMixer.isLineSupported(Port.Info.MICROPHONE)) {
            if (tmp.isLineSupported(targetDLInfo)) {
                String s = tmp.getMixerInfo().getName();
                if (s.toLowerCase().contains(mConfig.getProperty("radioName").toLowerCase())) {
                    mFoundMixer = tmp;
                    try {
                        mTargetInfo = new DataLine.Info(TargetDataLine.class, mFormat);
                        mTargetLine = (TargetDataLine) mFoundMixer.getLine(mTargetInfo);

                        System.out.println("Found radio device: " + mFoundMixer.getMixerInfo().getName());

                        startThread();
                    } catch (Exception e) {
                        System.out.println("RadioListener input error");
                        mFoundMixer = null;
                    }
                    break;
                }
            }
        }
    }
}

private static void showMixers() {
    ArrayList<Mixer.Info> mixInfos = new ArrayList<Mixer.Info>(Arrays.asList(AudioSystem.getMixerInfo()));

    Line.Info sourceDLInfo = new Line.Info(SourceDataLine.class);
    Line.Info targetDLInfo = new Line.Info(TargetDataLine.class);
    Line.Info clipInfo = new Line.Info(Clip.class);
    Line.Info portInfo = new Line.Info(Port.class);

    String support;

    for (Mixer.Info mixInfo: mixInfos) {
        Mixer mixer = AudioSystem.getMixer(mixInfo);

        support = ", supports ";
        if (mixer.isLineSupported(sourceDLInfo))
            support += "SourceDataLine ";
        if (mixer.isLineSupported(clipInfo))
            support += "Clip ";
        if (mixer.isLineSupported(targetDLInfo))
            support += "TargetDataLine ";
        if (mixer.isLineSupported(portInfo))
            support += "Port ";

        System.out.println("Mixer: " + mixInfo.getName() + support + ", " + mixInfo.getDescription());
    }
}

private class Communicator implements Runnable {
    @Override
    public void run() {
        int numBytesRead;
        byte[] targetData = new byte[mTargetLine.getBufferSize() / 5];

        while (isCommunicating) {
            numBytesRead = mTargetLine.read(targetData, 0, targetData.length);
            System.out.println(numBytesRead);

            if (numBytesRead == -1) break;

            if (isRetranslating)
                mSourceLine.write(targetData, 0, numBytesRead);
        }
    }
}
}}

Thank you!

Body:
Well, I'm came to the following working code.

I created new "empty" wav file with

ais = new AudioInputStream(mTargetLine);
AudioSystem.write(ais, fileType, wavFile);

I got 44 bytes wav file, where header was storing.

When I need to record a wav file, when I'm listetning to it in live, I need to do the following: create an empty wav file, write that header (stored in jar), append bytes in linking thread. (Communicator class in my case) It is directing bytes from SourceLine to TargetLine (from a mic to speakers basically). Here is the code of my updated class from my question.

P.S.: header is for a specified AudioFormat only. If you need another, than you could "generate" them separately.
P.S.S: sorry for my bad english :)

The code:

public class RadioListener {
private Runnable mRunnable, mFounderR;
private Thread mThread = null, mFounderT = null;

private SourceDataLine mSourceLine;
private TargetDataLine mTargetLine;
private DataLine.Info mTargetInfo;
private DataLine.Info mSourceInfo;
private static final AudioFormat mFormat = new AudioFormat(44100, 16, 2, true, false);

private Mixer.Info[] mixers;
private Mixer mFoundMixer = null;

private Config mConfig;

private boolean isCommunicating = false;
private boolean isRetranslating = false;

private static final String mHeader = "header.wav";
//private File wavFile = null;
AudioFileFormat.Type fileType = AudioFileFormat.Type.WAVE;
AudioInputStream ais;
private FileOutputStream fos;
private boolean isRecording = false;

public RadioListener (Config cfg) {
    mConfig = cfg;

    mixers = AudioSystem.getMixerInfo();
    mSourceInfo = new DataLine.Info(SourceDataLine.class, mFormat);
    mTargetInfo = new DataLine.Info(TargetDataLine.class, mFormat);
    try {mSourceLine = (SourceDataLine) AudioSystem.getLine(mSourceInfo);}
    catch (LineUnavailableException e) {System.out.println("RadioListener output error");}

    //wavFile = new File("E:/RecordAudio.wav");
}

public void Start() {
    if (Defines.strToIntDef(mConfig.getProperty("debugOut"), 0) == 1)
        showMixers();

    if (mFoundMixer == null) searchDevice();
    else startCommunication();
}

public void Stop() {
    if (mFoundMixer == null) return;

    try {
        mSourceLine.stop();
        mSourceLine.close();

        mTargetLine.stop();
        mTargetLine.close();
    } catch (Exception e) {}
    finally {
        isCommunicating = false;
    }
}

public void disposeListener() {
    if (isRecording) stopRecording();

    Stop();

    if (mFounderT != null)
        if (mFounderT.isAlive())
            mFounderT.interrupt();

    if (mThread != null)
        if (mThread.isAlive())
            mThread.interrupt();
}

public void Mute() {
    isRetranslating = false;
}

public void enableRecording (boolean f) {
    if (f) startRecording();
    else stopRecording();
}

public boolean isRecording() {
    return isRecording;
}

private void startRecording() {
    final DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
    Date date = new Date(System.currentTimeMillis());
    String dt = formatter.format(date);
    final InputStream stream = this.getClass().getResourceAsStream("/" + mHeader);
    byte b[] = new byte[44];
    try {
        fos = new FileOutputStream(Defines.getCurrentFolder() + File.separator + dt + ".wav", true);
        try {
            stream.read(b, 0, 44);
            fos.write(b);
        } catch (IOException e) {
            try {fos.close();}
            catch (IOException e1) {;}
            isRecording = false;
            return;
        }

    } catch (FileNotFoundException e) {
        isRecording = false;
    }
    isRecording = true;
}

private void stopRecording() {
    isRecording = false;

    try {fos.close();}
    catch (IOException e) {;}
    isRecording = false;
}

private void searchDevice() {
    mFounderR = new RadioFinder();
    mFounderT = new Thread(mFounderR);
    mFounderT.start();
}

private void startThread() {
    startCommunication();
    mRunnable = new Communicator();
    mThread = new Thread(mRunnable);
    mThread.start();
}

private void startCommunication() {
    if (isCommunicating) {
        isRetranslating = true;
        return;
    }
    try {
        mTargetLine.open(mFormat);
        mTargetLine.start();

        mSourceLine.open(mFormat);
        mSourceLine.start();

        //Line line = mFoundMixer.getLine(mSourceInfo);
        //FloatControl control = (FloatControl)line.getControl(FloatControl.Type.MASTER_GAIN);
        //control.setValue(limit(control,10000));
        //control.setValue(-10);

        isCommunicating = true;
        isRetranslating = true;

        //ais = new AudioInputStream(mTargetLine); //ok
        //AudioSystem.write(ais, fileType, wavFile); //ok
    } catch (Exception e) {
        isCommunicating = false;
        isRetranslating = false;
    }
}

private class RadioFinder implements Runnable {
    @Override
    public void run() {
        Line.Info targetDLInfo = new Line.Info(TargetDataLine.class);
        for (Mixer.Info info : mixers) {
            Mixer tmp = AudioSystem.getMixer(info);
            //if (myMixer.isLineSupported(Port.Info.LINE_IN) || myMixer.isLineSupported(Port.Info.MICROPHONE)) {
            if (tmp.isLineSupported(targetDLInfo)) {
                String s = tmp.getMixerInfo().getName();
                if (s.toLowerCase().contains(mConfig.getProperty("radioName").toLowerCase())) {
                    mFoundMixer = tmp;
                    try {
                        mTargetInfo = new DataLine.Info(TargetDataLine.class, mFormat);
                        mTargetLine = (TargetDataLine) mFoundMixer.getLine(mTargetInfo);

                        System.out.println("Found radio device: " + mFoundMixer.getMixerInfo().getName());

                        startThread();
                    } catch (Exception e) {
                        System.out.println("RadioListener input error");
                        mFoundMixer = null;
                    }
                    break;
                }
            }
        }
    }
}

private static void showMixers() {
    ArrayList<Mixer.Info> mixInfos = new ArrayList<Mixer.Info>(Arrays.asList(AudioSystem.getMixerInfo()));

    Line.Info sourceDLInfo = new Line.Info(SourceDataLine.class);
    Line.Info targetDLInfo = new Line.Info(TargetDataLine.class);
    Line.Info clipInfo = new Line.Info(Clip.class);
    Line.Info portInfo = new Line.Info(Port.class);

    String support;

    for (Mixer.Info mixInfo: mixInfos) {
        Mixer mixer = AudioSystem.getMixer(mixInfo);

        support = ", supports ";
        if (mixer.isLineSupported(sourceDLInfo))
            support += "SourceDataLine ";
        if (mixer.isLineSupported(clipInfo))
            support += "Clip ";
        if (mixer.isLineSupported(targetDLInfo))
            support += "TargetDataLine ";
        if (mixer.isLineSupported(portInfo))
            support += "Port ";

        System.out.println("Mixer: " + mixInfo.getName() + support + ", " + mixInfo.getDescription());
    }
}

private class Communicator implements Runnable {
    @Override
    public void run() {
        int numBytesRead;
        byte[] targetData = new byte[mTargetLine.getBufferSize() / 5];

        while (isCommunicating) {
            numBytesRead = mTargetLine.read(targetData, 0, targetData.length);

            if (numBytesRead == -1) break;

            if (isRetranslating)
                mSourceLine.write(targetData, 0, numBytesRead);

            if (isRecording) {
                try {fos.write(targetData);}
                catch (IOException e) {stopRecording();}
            }
        }
    }
}

}


问:
POST list of objects in rails. How can I whitelist the list of objects in strong params?
I'm trying to post a list of objects called tasks that looks like the following.

```<code>{
  // Shared attributes
  "parent_id": "1",
  "author": "Name Name",
  // Task list
  "tasks": [
   {"name":"task 1"},
   {"name":"task 2"}...
  ]
}
</code>```

In my controller, I have the following, which iterates through tasks, appends the shared attributes, and creates a new Task object:

```<code>task_params[:tasks].each do |task|
      new_params = task
      new_params[:parent_id] = task_params[:parent_id]
      new_params[:author] = task_params[:author]

      new_task = Task.new(new_params)
end
</code>```

The problem is that :tasks isn't showing up in my task_params despite being passed in as a parameter. This seems to be because it isn't whitelisted in strong_params, but that doesn't seem to make a difference. It looks to me like I can only whitelist parameters that correspond to attr_accessors. So how can I pass in the custom parameter tasks through strong_params and into the controller method?

Edit:

My params definition:

```<code>def task_params
     params.require(:task).permit(:parent_id, :author, tasks: [:name])
end
</code>```

Rails output:

```<code>  Parameters: {"parent_id"=>1, "author"=> "Name name", "tasks"=>[{"name"=>"task 1"}, {"name"=>"task 2"}], "task"=>{"job_id"=>1, "author"=>"Name name"}}
</code>```

But when I print the task params in the controller:

```<code>{"parent_id"=>1, "author"=>"Name name"}
</code>```

答:
Your params, as posted in your question, are malformed (missing a comma, a close bracket, etc.). That's probably a cut and paste error, I'm guessing. So, let's assume they are supposed to look like this:

```<code>{
  task: {
    "parent_id"=>1,
    "author": "Name name",
    "tasks"=>[
      {"name"=>"task 1"},
      {"name"=>"task 2", "task"=>{"job_id"=>1, "author"=>"Name name"}}
    ]
  }
}
</code>```

Then if I do this in console:

```<code>params = ActionController::Parameters.new(task: {"parent_id"=>1, "author": "Name name", "tasks"=>[{"name"=>"task 1"}, {"name"=>"task 2", "task"=>{"job_id"=>1, "author"=>"Name name"}}]})

task_params = params.require(:task).permit(:parent_id, :author, tasks: [:name, task: [:job_id, :author]])

task_params[:tasks].each do |task|
  puts task.merge!(parent_id: task_params[:parent_id], author: task_params[:author])
end
</code>```

Then I see from the puts statements:

```<code>{"name"=>"task 1", "parent_id"=>1, "author"=>"Name name"}
{"name"=>"task 2", "task"=>{"job_id"=>1, "author"=>"Name name"}, "parent_id"=>1, "author"=>"Name name"}
</code>```

Which would be your arguments for Task.new, which you could do as:

```<code>task_params[:tasks].each do |task|
  new_task = Task.new(task.merge!(parent_id: task_params[:parent_id], author: task_params[:author]))
end
</code>```

Body:
I'm trying to post a list of objects called tasks that looks like the following.

{
  // Shared attributes
  "parent_id": "1",
  "author": "Name Name",
  // Task list
  "tasks": [
   {"name":"task 1"},
   {"name":"task 2"}...
  ]
}

In my controller, I have the following, which iterates through tasks, appends the shared attributes, and creates a new Task object:

task_params[:tasks].each do |task|
      new_params = task
      new_params[:parent_id] = task_params[:parent_id]
      new_params[:author] = task_params[:author]

      new_task = Task.new(new_params)
end

The problem is that :tasks isn't showing up in my task_params despite being passed in as a parameter. This seems to be because it isn't whitelisted in strong_params, but that doesn't seem to make a difference. It looks to me like I can only whitelist parameters that correspond to attr_accessors. So how can I pass in the custom parameter tasks through strong_params and into the controller method?

Edit:

My params definition:

def task_params
     params.require(:task).permit(:parent_id, :author, tasks: [:name])
end

Rails output:

  Parameters: {"parent_id"=>1, "author"=> "Name name", "tasks"=>[{"name"=>"task 1"}, {"name"=>"task 2"}], "task"=>{"job_id"=>1, "author"=>"Name name"}}

But when I print the task params in the controller:

{"parent_id"=>1, "author"=>"Name name"}

Body:
Your params, as posted in your question, are malformed (missing a comma, a close bracket, etc.). That's probably a cut and paste error, I'm guessing. So, let's assume they are supposed to look like this:

{
  task: {
    "parent_id"=>1,
    "author": "Name name",
    "tasks"=>[
      {"name"=>"task 1"},
      {"name"=>"task 2", "task"=>{"job_id"=>1, "author"=>"Name name"}}
    ]
  }
}

Then if I do this in console:

params = ActionController::Parameters.new(task: {"parent_id"=>1, "author": "Name name", "tasks"=>[{"name"=>"task 1"}, {"name"=>"task 2", "task"=>{"job_id"=>1, "author"=>"Name name"}}]})

task_params = params.require(:task).permit(:parent_id, :author, tasks: [:name, task: [:job_id, :author]])

task_params[:tasks].each do |task|
  puts task.merge!(parent_id: task_params[:parent_id], author: task_params[:author])
end

Then I see from the puts statements:

{"name"=>"task 1", "parent_id"=>1, "author"=>"Name name"}
{"name"=>"task 2", "task"=>{"job_id"=>1, "author"=>"Name name"}, "parent_id"=>1, "author"=>"Name name"}

Which would be your arguments for Task.new, which you could do as:

task_params[:tasks].each do |task|
  new_task = Task.new(task.merge!(parent_id: task_params[:parent_id], author: task_params[:author]))
end


问:
Are there platforms where the size of shorts is actually larger than 16bits
As far as I know the standard says that the size of the short type must be at least 16 bits.

Now I'm wondering if there are actually platforms where shorts are 32 bit or even larger.

I'm aware of stddef.h and that the types defined there should be used if a certain size is required.

答:
IIRC some exotic implementation of C99 above (in/for) Common Lisp (or perhaps only SBCL) has been coded with all of char, short, int being 32 bits exactly.

But I could be wrong.


问:
How can I add a table with multi-row cells to a readme in VSTS?
How can you add tables with multi-row cells to markdown in Microsoft VSTS?

I have previously used asciidoc for readme files on github as it is both richer and less ambiguous. The company now has projects on VSTS which does not support asciidoc so I need to use markdown instead.
However, it is unclear what flavour of markdown is actually supported

This page says that github flavoured markdown can be used

https://learn.microsoft.com/en-us/vsts/collaborate/markdown-guidance

I found another page saying they use commonmark via the markdown-it library.

Q: Does VS Code support GitHub Flavored Markdown?

A: No, VS Code targets the CommonMark Markdown specification using the
  markdown-it library. GitHub is moving toward the CommonMark
  specification which you can read about in this update.

I've been using a combination of asciidoctor and pandoc to convert files but nothing gets it quite right.
(Asciidoctor converts to docbook which pandoc can then parse)

```<code>asciidoctor -b docbook -v -o "$OUTPUT".xml "$INPUT" &&
pandoc -f docbook -t markdown_github -i "$OUTPUT".xml -o "$OUTPUT"
</code>```

I have to re-add the title manually.
My current stumbling block is multi-row cells.
Github supports grid tables,
see Newline in markdown table?:

```<code>+---------------+---------------+--------------------+
| Fruit         | Price         | Advantages         |
+===============+===============+====================+
| Bananas       | first line\   | first line\        |
|               | next line     | next line          |
+---------------+---------------+--------------------+
| Bananas       | first line\   | first line\        |
|               | next line     | next line          |
+---------------+---------------+--------------------+
</code>```

But neither this nor embedded html seem to work in VSTS.
I would be happy to use html readmes instead if that was permitted.

Update 17-Nov-2017:

I found the link to markdown-it and added it above. I've raised an issue there for clarification (or enhancement). Its unclear which version VSTS actually uses under the hood.

I would like to ask the question of Microsoft themselves but their ask a question link goes straight to stack overflow.

The markdown-it library does support the usage suggested by @Waylan:

```<code>| Fruit         | Price                   | Advantages              |
| ------------- | ----------------------- | ----------------------- |
| Bananas       | first line<br>next line | first line<br>next line |
| Bananas       | first line<br>next line | first line<br>next line |
</code>```

See https://github.com/markdown-it/markdown-it/issues/406.
The issue is most likely Microsoft disabling html.
A solution thus waits on a reply to @starian's suggestion: https://visualstudio.uservoice.com/forums/330519-visual-studio-team-services/suggestions/32312290-multi-line-in-the-cell-of-a-table-in-markdown-in-v

答:
In short, each row must be on one line and should use
 to indicate a line break. Like this:

```<code>| Fruit         | Price                   | Advantages              |
| ------------- | ----------------------- | ----------------------- |
| Bananas       | first line<br>next line | first line<br>next line |
| Bananas       | first line<br>next line | first line<br>next line |
</code>```

Below is an explanation of each tool with an analysis of that tool's documentation:

GitHub

CommonMark is a Markdown variant with a strict spec. GitHub-Flavored Markdown (GFM) is an extension of CommonMark (which adds features to CommonMark such as tables), with its own spec. Therefore, to say that an implementation supports GFM is to say that it supports CommonMark with extensions. Note that GitHub adopted the current spec on March 14, 2017, so any information older that that may not be relevant for the current implementation.

Whether VSTS actually uses a CommonMark/GFM implementation or a close approximation is unclear from the documentation. However, as the documentation clearly states that "GitHub-flavored extensions" are supported, that would indicate to me that the GFM Spec would be a good reference. Regardless, the GFM Spec is the controlling spec for any Markdown rendered on github.com.

The Tables section of the GFM Spec plainly states:

Block-level elements cannot be inserted in a table.

And gives this simple example:

```<code>| foo | bar |
| --- | --- |
| baz | bim |
</code>```

While the spec does not specifically mention multiple line cells, there are no examples with any cells that contain multiple lines. It is my understanding that that is not supported by GFM. Therefore, the only way to include line breaks in GFM Table cells is with the
 tag, which is not a block-level element.

Pandoc

Pandoc supports multiple different styles of table syntax. If you are passing your Markdown to both Pandoc and GFM, then you need to use Pandoc's table style which most closely matches GFM's style. For example, GFM Tables do not include support for + at the corners. That syntax is specific to Pandoc's Grid Tables. Fortunately, Pandoc's documentation tells us which style most closely matches GFM.

Pandoc has support for various "Markdown Variants", one of which is gfm. The docs have this to stay about that variant:

We also support gfm (GitHub-Flavored Markdown) as a set of
  extensions on commonmark:

: pipe_tables, raw_html, fenced_code_blocks, auto_identifiers,
  ascii_identifiers, backtick_code_blocks, autolink_bare_uris,
  intraword_underscores, strikeout, hard_line_breaks, emoji,
  shortcut_reference_links, angle_brackets_escapable.

Note that the gfm variant of Pandoc uses Pipe Tables. It is also noteworthy that the markdown_github variant of Pandoc is deprecated since GitHub adopted Commonmark. But even the markdown_github variant uses Pipe Tables.

Pandocs' documentation for Pipe Tables states (emphasis added):

The cells of pipe tables cannot contain block elements like paragraphs and lists, and cannot span multiple lines.

And gives this example:

```<code>| Right | Left | Default | Center |
|------:|:-----|---------|:------:|
|   12  |  12  |    12   |    12  |
|  123  |  123 |   123   |   123  |
|    1  |    1 |     1   |     1  |
</code>```

That is clearly the same as GFM tables and does not include any support for block level elements or multi-line cells.

VSTS

The VSTS Documentation for Tables closely matches GFM and Pandoc Pipe Tables with this example:

```<code>| Heading 1 | Heading 2 | Heading 3 |
|-----------|:---------:|----------:|
| Cell A1   | Cell A2   | Cell A3   |
| Cell B1   | Cell B2   | Cell B3   |
</code>```

While the the VSTS Documentation makes no specific mention of block-level elements or multiple lines, is seems safe to assume that it is in fact the same style.

We can make that assumption because in all three instances (VSTS, GFM and Pandoc Pipe Tables), the syntax does not provide a divider between individual rows of the table (compare with Pandoc Grid Tables, which supports row dividers). While there is a divider between the header and data rows, with no divider between individual data rows, there is no way to indicate how many lines of text belong to each row. Therefore, each row can only be represented by one line of text.

Conclusion

Given the above, to be parsed properly by VSTS, GFM and Pandoc (gfm variant), your table should be formatted like this:

```<code>| Fruit         | Price                   | Advantages              |
| ------------- | ----------------------- | ----------------------- |
| Bananas       | first line<br>next line | first line<br>next line |
| Bananas       | first line<br>next line | first line<br>next line |
</code>```

And when using Pandoc, be sure to use the gfm format (pandoc -f gfm ...).

Body:
How can you add tables with multi-row cells to markdown in Microsoft VSTS?

I have previously used asciidoc for readme files on github as it is both richer and less ambiguous. The company now has projects on VSTS which does not support asciidoc so I need to use markdown instead.
However, it is unclear what flavour of markdown is actually supported

This page says that github flavoured markdown can be used

https://learn.microsoft.com/en-us/vsts/collaborate/markdown-guidance

I found another page saying they use commonmark via the markdown-it library.

Q: Does VS Code support GitHub Flavored Markdown?

A: No, VS Code targets the CommonMark Markdown specification using the
  markdown-it library. GitHub is moving toward the CommonMark
  specification which you can read about in this update.

I've been using a combination of asciidoctor and pandoc to convert files but nothing gets it quite right.
(Asciidoctor converts to docbook which pandoc can then parse)

asciidoctor -b docbook -v -o "$OUTPUT".xml "$INPUT" &&
pandoc -f docbook -t markdown_github -i "$OUTPUT".xml -o "$OUTPUT"

I have to re-add the title manually.
My current stumbling block is multi-row cells.
Github supports grid tables,
see Newline in markdown table?:

+---------------+---------------+--------------------+
| Fruit         | Price         | Advantages         |
+===============+===============+====================+
| Bananas       | first line\   | first line\        |
|               | next line     | next line          |
+---------------+---------------+--------------------+
| Bananas       | first line\   | first line\        |
|               | next line     | next line          |
+---------------+---------------+--------------------+

But neither this nor embedded html seem to work in VSTS.
I would be happy to use html readmes instead if that was permitted.

Update 17-Nov-2017:

I found the link to markdown-it and added it above. I've raised an issue there for clarification (or enhancement). Its unclear which version VSTS actually uses under the hood.

I would like to ask the question of Microsoft themselves but their ask a question link goes straight to stack overflow.

The markdown-it library does support the usage suggested by @Waylan:

| Fruit         | Price                   | Advantages              |
| ------------- | ----------------------- | ----------------------- |
| Bananas       | first line
next line | first line
next line |
| Bananas       | first line
next line | first line
next line |

See https://github.com/markdown-it/markdown-it/issues/406.
The issue is most likely Microsoft disabling html.
A solution thus waits on a reply to @starian's suggestion: https://visualstudio.uservoice.com/forums/330519-visual-studio-team-services/suggestions/32312290-multi-line-in-the-cell-of-a-table-in-markdown-in-v

Body:
In short, each row must be on one line and should use <br> to indicate a line break. Like this:

| Fruit         | Price                   | Advantages              |
| ------------- | ----------------------- | ----------------------- |
| Bananas       | first line<br>next line | first line<br>next line |
| Bananas       | first line<br>next line | first line<br>next line |

Below is an explanation of each tool with an analysis of that tool's documentation:

GitHub

CommonMark is a Markdown variant with a strict spec. GitHub-Flavored Markdown (GFM) is an extension of CommonMark (which adds features to CommonMark such as tables), with its own spec. Therefore, to say that an implementation supports GFM is to say that it supports CommonMark with extensions. Note that GitHub adopted the current spec on March 14, 2017, so any information older that that may not be relevant for the current implementation.

Whether VSTS actually uses a CommonMark/GFM implementation or a close approximation is unclear from the documentation. However, as the documentation clearly states that "GitHub-flavored extensions" are supported, that would indicate to me that the GFM Spec would be a good reference. Regardless, the GFM Spec is the controlling spec for any Markdown rendered on github.com.

The Tables section of the GFM Spec plainly states:

Block-level elements cannot be inserted in a table.

And gives this simple example:

| foo | bar |
| --- | --- |
| baz | bim |

While the spec does not specifically mention multiple line cells, there are no examples with any cells that contain multiple lines. It is my understanding that that is not supported by GFM. Therefore, the only way to include line breaks in GFM Table cells is with the <br> tag, which is not a block-level element.

Pandoc

Pandoc supports multiple different styles of table syntax. If you are passing your Markdown to both Pandoc and GFM, then you need to use Pandoc's table style which most closely matches GFM's style. For example, GFM Tables do not include support for + at the corners. That syntax is specific to Pandoc's Grid Tables. Fortunately, Pandoc's documentation tells us which style most closely matches GFM.

Pandoc has support for various "Markdown Variants", one of which is gfm. The docs have this to stay about that variant:

We also support gfm (GitHub-Flavored Markdown) as a set of
  extensions on commonmark:

: pipe_tables, raw_html, fenced_code_blocks, auto_identifiers,
  ascii_identifiers, backtick_code_blocks, autolink_bare_uris,
  intraword_underscores, strikeout, hard_line_breaks, emoji,
  shortcut_reference_links, angle_brackets_escapable.

Note that the gfm variant of Pandoc uses Pipe Tables. It is also noteworthy that the markdown_github variant of Pandoc is deprecated since GitHub adopted Commonmark. But even the markdown_github variant uses Pipe Tables.

Pandocs' documentation for Pipe Tables states (emphasis added):

The cells of pipe tables cannot contain block elements like paragraphs and lists, and cannot span multiple lines.

And gives this example:

| Right | Left | Default | Center |
|------:|:-----|---------|:------:|
|   12  |  12  |    12   |    12  |
|  123  |  123 |   123   |   123  |
|    1  |    1 |     1   |     1  |

That is clearly the same as GFM tables and does not include any support for block level elements or multi-line cells.

VSTS

The VSTS Documentation for Tables closely matches GFM and Pandoc Pipe Tables with this example:

| Heading 1 | Heading 2 | Heading 3 |
|-----------|:---------:|----------:|
| Cell A1   | Cell A2   | Cell A3   |
| Cell B1   | Cell B2   | Cell B3   |

While the the VSTS Documentation makes no specific mention of block-level elements or multiple lines, is seems safe to assume that it is in fact the same style.

We can make that assumption because in all three instances (VSTS, GFM and Pandoc Pipe Tables), the syntax does not provide a divider between individual rows of the table (compare with Pandoc Grid Tables, which supports row dividers). While there is a divider between the header and data rows, with no divider between individual data rows, there is no way to indicate how many lines of text belong to each row. Therefore, each row can only be represented by one line of text.

Conclusion

Given the above, to be parsed properly by VSTS, GFM and Pandoc (gfm variant), your table should be formatted like this:

| Fruit         | Price                   | Advantages              |
| ------------- | ----------------------- | ----------------------- |
| Bananas       | first line<br>next line | first line<br>next line |
| Bananas       | first line<br>next line | first line<br>next line |

And when using Pandoc, be sure to use the gfm format (pandoc -f gfm ...).


问:
IE object set to active IE window
I am trying to login to a website using VBA macro that accesses IE,
once I get to this URL and am login in using user and pass and then I want the IE object in VBA to use this new URL of the pop up to be able to manipulate it (insert to form etc..)
This is my code:

Sub Automate_IE_Load_Page()
'This will load a webpage in IE
    Dim IE As Object
    Dim URL As String

```<code>'Create InternetExplorer Object
Set IE = CreateObject("InternetExplorer.Application")

'Set IE.Visible = True to make IE visible, or False for IE to run in the background
IE.Visible = True

'Define URL
URL = "http://www.web app that requiers login credentials.com"

'Navigate to URL
IE.Navigate URL

' Wait while IE loading...
'IE ReadyState = 4 signifies the webpage has loaded (the first loop is set to avoid inadvertently skipping over the second loop)
Do While IE.ReadyState = 4: DoEvents: Loop   'Do While
Do Until IE.ReadyState = 4: DoEvents: Loop   'Do Until

'Webpage Loaded
Application.StatusBar = URL & " Loaded"

'Insert login credentials
IE.document.getElementById("UserName").Value = "123"
IE.document.getElementById("Password").Value = "123!"
IE.document.getElementById("loginbutton").Click
</code>```

End Sub

*** The next getElementById wont work! I think this is becasue right after login there is a new IE window that pops up and that my "IE" object is not set to use it, how do I make this new session "active" on my "IE" object so to speak?
thanks.

答:
```<code> Set objCollection = ie.Document.getElementsByTagName("input")

    i = 0

   Do While i < objCollection.length

        Select Case objCollection(i).ID
            Case "UserName"

                Debug.Print "Found username field, setting value"
                objCollection(i).Value = ufLoginDetails.txtUID

             Case "Password"

                Debug.Print "Found password field, setting value"
                objCollection(i).Value = ufLoginDetails.txtPWD
                ufLoginDetails.txtPWD = ""

            Case "loginbutton"

                Debug.Print
                objCollection(i).Click

                 Exit Do

     '  i = objCollection.length
       End Select
        i = i + 1
     Loop
</code>```

You have to validate whether the button label is an input or button.

Title: IE object set to active IE window

Body:
I am trying to login to a website using VBA macro that accesses IE,
once I get to this URL and am login in using user and pass and then I want the IE object in VBA to use this new URL of the pop up to be able to manipulate it (insert to form etc..)
This is my code:

Sub Automate_IE_Load_Page()
'This will load a webpage in IE
    Dim IE As Object
    Dim URL As String

'Create InternetExplorer Object
Set IE = CreateObject("InternetExplorer.Application")

'Set IE.Visible = True to make IE visible, or False for IE to run in the background
IE.Visible = True

'Define URL
URL = "http://www.web app that requiers login credentials.com"

'Navigate to URL
IE.Navigate URL

' Wait while IE loading...
'IE ReadyState = 4 signifies the webpage has loaded (the first loop is set to avoid inadvertently skipping over the second loop)
Do While IE.ReadyState = 4: DoEvents: Loop   'Do While
Do Until IE.ReadyState = 4: DoEvents: Loop   'Do Until

'Webpage Loaded
Application.StatusBar = URL & " Loaded"

'Insert login credentials
IE.document.getElementById("UserName").Value = "123"
IE.document.getElementById("Password").Value = "123!"
IE.document.getElementById("loginbutton").Click

End Sub

*** The next getElementById wont work! I think this is becasue right after login there is a new IE window that pops up and that my "IE" object is not set to use it, how do I make this new session "active" on my "IE" object so to speak?
thanks.

Body:
 Set objCollection = ie.Document.getElementsByTagName("input")

    i = 0

   Do While i < objCollection.length

        Select Case objCollection(i).ID
            Case "UserName"

                Debug.Print "Found username field, setting value"
                objCollection(i).Value = ufLoginDetails.txtUID

             Case "Password"

                Debug.Print "Found password field, setting value"
                objCollection(i).Value = ufLoginDetails.txtPWD
                ufLoginDetails.txtPWD = ""

            Case "loginbutton"

                Debug.Print
                objCollection(i).Click

                 Exit Do

     '  i = objCollection.length
       End Select
        i = i + 1
     Loop

You have to validate whether the button label is an input or button.


问:
Error in options object during creating Network graph in VisJs (Angular 4)
I am trying create 'network', and getting error

```<code>ERROR in F:/vis-test/src/app/app.component.ts (58,53): Argument of type '{ edges: { smooth: { type: string; roundness: number; }; }; nodes: { color: string; fixed: boolea...' is not assignable to parameter of type 'Options'.
  Types of property 'edges' are incompatible.
    Type '{ smooth: { type: string; roundness: number; }; }' is not assignable to type 'EdgeOptions'.
      Types of property 'smooth' are incompatible.
        Type '{ type: string; roundness: number; }' is not assignable to type 'boolean | { enabled: boolean; type: string; forceDirection?: string | boolean; roundness: number; }'.
          Type '{ type: string; roundness: number; }' is not assignable to type '{ enabled: boolean; type: string; forceDirection?: string | boolean; roundness: number; }'.
            Property 'enabled' is missing in type '{ type: string; roundness: number; }'.
</code>```

but in docs said that it is optional prop: http://visjs.org/docs/network/edges.html

With pure JS error not reproduced.

update:

after add prop have next error in browser console -

```<code>ERROR TypeError: Cannot create property 'enabled' on boolean 'true'
    at Object.e.mergeOptions (vis.js:1353)
    at Function.value (vis.js:36856)
    at t.value (vis.js:35888)
    at o.setOptions (vis.js:33348)
    at new o (vis.js:33315)
    at AppComponent.webpackJsonp.../../../../../src/app/app.component.ts.AppComponent.makeTree (app.component.ts:61)
    at SafeSubscriber._next (app.component.ts:21)
    at SafeSubscriber.webpackJsonp.../../../../rxjs/Subscriber.js.SafeSubscriber.__tryOrUnsub (Subscriber.js:238)
    at SafeSubscriber.webpackJsonp.../../../../rxjs/Subscriber.js.SafeSubscriber.next (Subscriber.js:185)
    at Subscriber.webpackJsonp.../../../../rxjs/Subscriber.js.Subscriber._next (Subscriber.js:125)
defaultErrorLogger @ core.es5.js:1020
VM129 htmlfile?c=_jp.aktje5b:8 Uncaught DOMException: Blocked a frame with origin "http://localhost:4200" from accessing a cross-origin frame.
    at http://localhost:4200/sockjs-node/893/bn1xx0t1/htmlfile?c=_jp.aktje5b:8:19
(anonymous) @ VM129 htmlfile?c=_jp.aktje5b:8
</code>```

my code

```<code> const data = {
      nodes: new vis.DataSet(this._generateNodesData(treeData.nodes)),
      edges: new vis.DataSet(this._generateEdgesData(treeData.edges))
    };

    const options = {
      edges: {
        smooth: {
          enabled: true, // error in this place
          type: 'cubicBezier',
          roundness: 0.4,
        }
      },
      nodes: {
        color: '#ff0000',
        fixed: false,
        font: '12px arial red',
        scaling: {
          label: true
        },
        shadow: true
      },
      layout: {
        hierarchical: {
          direction: 'UD'
        }
      },
      physics: false,
      interaction: {
        dragNodes: false,
        dragView: true,
        hover: true
      }
    };

    const container = document.getElementById('vis-tree');
    this.network = new vis.Network(container, data, options);
</code>```

答:
you must put the complete object with all your options:</p>

```<code>const options = {
  edges: {
    smooth: {
      enabled: true,
      type: 'cubicBezier',
      roundness: 0.4 //remove ","
    }
  },
  nodes: {
    color: '#ff0000',
    fixed: false,
    font: '12px arial red',
    scaling: { //add all options
      min: 10,
      max: 30,
      label: {
      enabled: false,
      min: 14,
      max: 30,
      maxVisible: 30,
      drawThreshold: 5
    },
    shadow: true
  },
  layout: {
    hierarchical: {
      direction: 'UD',
      sortMethod: "directed"
    }
  },
  physics: false,
  interaction: {
    dragNodes: false,
    dragView: true,
    hover: true
  }
};
</code>```

Body:
I am trying create 'network', and getting error

ERROR in F:/vis-test/src/app/app.component.ts (58,53): Argument of type '{ edges: { smooth: { type: string; roundness: number; }; }; nodes: { color: string; fixed: boolea...' is not assignable to parameter of type 'Options'.
  Types of property 'edges' are incompatible.
    Type '{ smooth: { type: string; roundness: number; }; }' is not assignable to type 'EdgeOptions'.
      Types of property 'smooth' are incompatible.
        Type '{ type: string; roundness: number; }' is not assignable to type 'boolean | { enabled: boolean; type: string; forceDirection?: string | boolean; roundness: number; }'.
          Type '{ type: string; roundness: number; }' is not assignable to type '{ enabled: boolean; type: string; forceDirection?: string | boolean; roundness: number; }'.
            Property 'enabled' is missing in type '{ type: string; roundness: number; }'.

but in docs said that it is optional prop: http://visjs.org/docs/network/edges.html

With pure JS error not reproduced.

update:

after add prop have next error in browser console -

ERROR TypeError: Cannot create property 'enabled' on boolean 'true'
    at Object.e.mergeOptions (vis.js:1353)
    at Function.value (vis.js:36856)
    at t.value (vis.js:35888)
    at o.setOptions (vis.js:33348)
    at new o (vis.js:33315)
    at AppComponent.webpackJsonp.../../../../../src/app/app.component.ts.AppComponent.makeTree (app.component.ts:61)
    at SafeSubscriber._next (app.component.ts:21)
    at SafeSubscriber.webpackJsonp.../../../../rxjs/Subscriber.js.SafeSubscriber.__tryOrUnsub (Subscriber.js:238)
    at SafeSubscriber.webpackJsonp.../../../../rxjs/Subscriber.js.SafeSubscriber.next (Subscriber.js:185)
    at Subscriber.webpackJsonp.../../../../rxjs/Subscriber.js.Subscriber._next (Subscriber.js:125)
defaultErrorLogger @ core.es5.js:1020
VM129 htmlfile?c=_jp.aktje5b:8 Uncaught DOMException: Blocked a frame with origin "http://localhost:4200" from accessing a cross-origin frame.
    at http://localhost:4200/sockjs-node/893/bn1xx0t1/htmlfile?c=_jp.aktje5b:8:19
(anonymous) @ VM129 htmlfile?c=_jp.aktje5b:8

my code

 const data = {
      nodes: new vis.DataSet(this._generateNodesData(treeData.nodes)),
      edges: new vis.DataSet(this._generateEdgesData(treeData.edges))
    };

    const options = {
      edges: {
        smooth: {
          enabled: true, // error in this place
          type: 'cubicBezier',
          roundness: 0.4,
        }
      },
      nodes: {
        color: '#ff0000',
        fixed: false,
        font: '12px arial red',
        scaling: {
          label: true
        },
        shadow: true
      },
      layout: {
        hierarchical: {
          direction: 'UD'
        }
      },
      physics: false,
      interaction: {
        dragNodes: false,
        dragView: true,
        hover: true
      }
    };

    const container = document.getElementById('vis-tree');
    this.network = new vis.Network(container, data, options);

Body:
you must put the complete object with all your options:

const options = {
  edges: {
    smooth: {
      enabled: true,
      type: 'cubicBezier',
      roundness: 0.4 //remove ","
    }
  },
  nodes: {
    color: '#ff0000',
    fixed: false,
    font: '12px arial red',
    scaling: { //add all options
      min: 10,
      max: 30,
      label: {
      enabled: false,
      min: 14,
      max: 30,
      maxVisible: 30,
      drawThreshold: 5
    },
    shadow: true
  },
  layout: {
    hierarchical: {
      direction: 'UD',
      sortMethod: "directed"
    }
  },
  physics: false,
  interaction: {
    dragNodes: false,
    dragView: true,
    hover: true
  }
};


问:
MySQL - How to combine INSERT, INSERT IGNORE and ON DUPLICATE UPDATE into one working query?
Case 1:

```<code>ID                Loc                In                    Out
----------------------------------------------------------------
null              null               null                  null
</code>```

Working query for this case:

```<code>INSERT INTO Inventory VALUES( 'PA', 'Area 1', now(), NULL );
</code>```

Case 2:

```<code>ID                 Loc                In                    Out
----------------------------------------------------------------
PA                 Area 1             2017-11-16 11:20:09   null
</code>```

Working query for this case:

```<code>INSERT IGNORE INTO Inventory VALUES( 'PA', 'Area 1', now(), NULL );
</code>```

Case 3:

```<code>ID                 Loc                In                    Out
----------------------------------------------------------------
PA                 Area 1             null                  2017-11-16 11:20:09
</code>```

Working query for this case:

```<code>INSERT INTO Inventory VALUES( 'PA', 'Area 1', now(), NULL )
ON DUPLICATE KEY UPDATE In = now(), Out = NULL;
</code>```

How can I combine the above 3 "Working query" into one?

Basically, the goal is to only execute case 3 if PK == Duplicate and In == NULL. Thanks.

答:
INSERT IGNORE and INSERT ... ON DUPLICATE KEY UPDATE are mutually exclusive. They both handle the situation when the row to be inserted conflicts with an already existing row on an UNIQUE INDEX.

IGNORE converts the errors into warnings and this basically lets the query succeed and ignore the new values.

ON DUPLICATE KEY UPDATE updates some of the fields of the existing row with the new values.

Both clauses are used only if an UNIQUE INDEX conflict happens; they are ignored otherwise. This makes both of them work in your case #1

Basically, the goal is to only execute case 3 if PK == Duplicate and In == NULL.

A carefully crafted ON DUPLICATE KEY UPDATE clause can do the job:

```<code>INSERT INTO Inventory VALUES('PA', 'Area 1', NOW(), NULL)
ON DUPLICATE KEY UPDATE
    `In` = IF(ISNULL(`In`), VALUES(`In`), `In`),
    `Out` = NULL
</code>```

The value of expression IF(ISNULL(`In`), VALUES(`In`), `In`) is VALUES(`In`) (the value of In in the VALUES() list to be inserted) if  the current value of column In is NULL or the current value of column In if it is not NULL.

This way, the value of column In is replaced by the value provided by the INSERT query only if its current value is NULL.

Body:
Case 1:

ID                Loc                In                    Out
----------------------------------------------------------------
null              null               null                  null

Working query for this case:

INSERT INTO Inventory VALUES( 'PA', 'Area 1', now(), NULL );

Case 2:

ID                 Loc                In                    Out
----------------------------------------------------------------
PA                 Area 1             2017-11-16 11:20:09   null

Working query for this case:

INSERT IGNORE INTO Inventory VALUES( 'PA', 'Area 1', now(), NULL );

Case 3:

ID                 Loc                In                    Out
----------------------------------------------------------------
PA                 Area 1             null                  2017-11-16 11:20:09

Working query for this case:

INSERT INTO Inventory VALUES( 'PA', 'Area 1', now(), NULL )
ON DUPLICATE KEY UPDATE In = now(), Out = NULL;

How can I combine the above 3 "Working query" into one?

Basically, the goal is to only execute case 3 if PK == Duplicate and In == NULL. Thanks.

Body:
INSERT IGNORE and INSERT ... ON DUPLICATE KEY UPDATE are mutually exclusive. They both handle the situation when the row to be inserted conflicts with an already existing row on an UNIQUE INDEX.

IGNORE converts the errors into warnings and this basically lets the query succeed and ignore the new values.

ON DUPLICATE KEY UPDATE updates some of the fields of the existing row with the new values.

Both clauses are used only if an UNIQUE INDEX conflict happens; they are ignored otherwise. This makes both of them work in your case #1

Basically, the goal is to only execute case 3 if PK == Duplicate and In == NULL.

A carefully crafted ON DUPLICATE KEY UPDATE clause can do the job:

INSERT INTO Inventory VALUES('PA', 'Area 1', NOW(), NULL)
ON DUPLICATE KEY UPDATE
    `In` = IF(ISNULL(`In`), VALUES(`In`), `In`),
    `Out` = NULL

The value of expression IF(ISNULL(`In`), VALUES(`In`), `In`) is VALUES(`In`) (the value of In in the VALUES() list to be inserted) if  the current value of column In is NULL or the current value of column In if it is not NULL.

This way, the value of column In is replaced by the value provided by the INSERT query only if its current value is NULL.


问:
enquo() error in function: the argument has already been evaluated
I'm trying to write several embedded functions that end up filtering a set of columns (id_type in filter_data()) that is defined by a vector (id_types in load_data()).  Based on the new dplyr programming vignette, I'm trying to use enquo to make my code run, but am getting an error that I don't know how to deal with.

The actual code is more complicated (and actually requires the different functions), but this is the simplest code I can use to replicate the error:

```<code>library(dplyr)
library(purrr)

data <- tibble(id_a = c(1,1,2,2,3),
             id_b = 991,
             id_c = c(45,45,45,1,80),
             units_sold = c(21,20,24,4,5))
id_types <- c("id_a", "id_b", "id_c")

load_data <- function(){

  bind_rows(pmap(list(list(data),
                  id_types),
             filter_data))
}

filter_data <- function(df, id_type) {
  quo_id_type <- enquo(id_type)

  filter(df, !!quo_id_type == 1)
}

load_data()
</code>```

throws the following error:

```<code>Error in (function (x, strict = TRUE)  :
  the argument has already been evaluated
Called from: (function (x, strict = TRUE)
    {
    caller_env <- parent.frame()
    if (identical(caller_env, globalenv())) {
        stop("must be called in a function")
    }
    if (missing(x)) {
        stop("argument \"x\" is missing")
    }
    .Call(rlang_capturearg, NULL, NULL, pairlist(caller_env,
        strict), get_env())
})(id_type)
</code>```

My desired output: I want the code to iterate through all the id_types, filtering df where either id_a == 1, id_b == 1, or id_c == 1 (rows 1, 2, and 4 on the original df), and bind those together in a new data frame.

How can I get this code to work without removing the nested functions?

Thank you.

答:
Quick fix:

If you need the filter_data function, you can switch to this, which is a bit easier and more obvious (.data refers to your df you pass into filter, and [[ selects the id_type column when id_type is a string):

```<code>filter_data <- function(df, id_type) {
  filter(df, .data[[id_type]] == 1)
}
</code>```

If you can drop the filter_data function altogether, you can go with:

```<code>filter_at(data, vars(id_types), any_vars(. == 1))
</code>```

(Also dropping the bind_rows and pmap calls). Note that you'll need to change all_vars to any_vars, since you're evaluating all of the vars in id_types at once.

Why the original won't work:

In this example, the argument you pass to filter is a string (i.e., "id_a"), but even this by itself won't work:

```<code>> filter(data, "id_a" == 1)
# A tibble: 0 x 4
# ... with 4 variables: id_a <dbl>, id_b <dbl>, id_c <dbl>,
#   units_sold <dbl>
</code>```

The filter condition evaluates to FALSE, since the string "id_a" is not equal to the integer 1, so no rows satisfy the condition, so it returns an empty tibble.

The argument you pass to the function is really id_types[[1]], not "id_a", so that's what you're enquo()ing. You can see that by trying:

```<code>f <- function(id_type) enquo(id_type)
f(id_types[[1]])
f("id_a")
</code>```

Which returns:

```<code><quosure: global>
~id_types[[1]]
<quosure: empty>
~"id_a"
</code>```

You can fix that (and print the other problem) by changing filter_data to this (but I wouldn't recommend actually doing this):

```<code>filter_data <- function(df, id_type) {
  id_type <- id_type
  quo_id_type <- enquo(id_type)
  print(quo(filter(df, !!quo_id_type == 1)))

  filter(df, !!quo_id_type == 1)
}
</code>```

Body:
I'm trying to write several embedded functions that end up filtering a set of columns (id_type in filter_data()) that is defined by a vector (id_types in load_data()).  Based on the new dplyr programming vignette, I'm trying to use enquo to make my code run, but am getting an error that I don't know how to deal with.

The actual code is more complicated (and actually requires the different functions), but this is the simplest code I can use to replicate the error:

library(dplyr)
library(purrr)

data <- tibble(id_a = c(1,1,2,2,3),
             id_b = 991,
             id_c = c(45,45,45,1,80),
             units_sold = c(21,20,24,4,5))
id_types <- c("id_a", "id_b", "id_c")

load_data <- function(){

  bind_rows(pmap(list(list(data),
                  id_types),
             filter_data))
}

filter_data <- function(df, id_type) {
  quo_id_type <- enquo(id_type)

  filter(df, !!quo_id_type == 1)
}

load_data()

throws the following error:

Error in (function (x, strict = TRUE)  :
  the argument has already been evaluated
Called from: (function (x, strict = TRUE)
    {
    caller_env <- parent.frame()
    if (identical(caller_env, globalenv())) {
        stop("must be called in a function")
    }
    if (missing(x)) {
        stop("argument \"x\" is missing")
    }
    .Call(rlang_capturearg, NULL, NULL, pairlist(caller_env,
        strict), get_env())
})(id_type)

My desired output: I want the code to iterate through all the id_types, filtering df where either id_a == 1, id_b == 1, or id_c == 1 (rows 1, 2, and 4 on the original df), and bind those together in a new data frame.

How can I get this code to work without removing the nested functions?

Thank you.

Body:
Quick fix:

If you need the filter_data function, you can switch to this, which is a bit easier and more obvious (.data refers to your df you pass into filter, and [[ selects the id_type column when id_type is a string):

filter_data <- function(df, id_type) {
  filter(df, .data[[id_type]] == 1)
}

If you can drop the filter_data function altogether, you can go with:

filter_at(data, vars(id_types), any_vars(. == 1))

(Also dropping the bind_rows and pmap calls). Note that you'll need to change all_vars to any_vars, since you're evaluating all of the vars in id_types at once.

Why the original won't work:

In this example, the argument you pass to filter is a string (i.e., "id_a"), but even this by itself won't work:

> filter(data, "id_a" == 1)
# A tibble: 0 x 4
# ... with 4 variables: id_a <dbl>, id_b <dbl>, id_c <dbl>,
#   units_sold <dbl>

The filter condition evaluates to FALSE, since the string "id_a" is not equal to the integer 1, so no rows satisfy the condition, so it returns an empty tibble.

The argument you pass to the function is really id_types[[1]], not "id_a", so that's what you're enquo()ing. You can see that by trying:

f <- function(id_type) enquo(id_type)
f(id_types[[1]])
f("id_a")

Which returns:

<quosure: global>
~id_types[[1]]
<quosure: empty>
~"id_a"

You can fix that (and print the other problem) by changing filter_data to this (but I wouldn't recommend actually doing this):

filter_data <- function(df, id_type) {
  id_type <- id_type
  quo_id_type <- enquo(id_type)
  print(quo(filter(df, !!quo_id_type == 1)))

  filter(df, !!quo_id_type == 1)
}


问:
Swift 4 - How to enable / disable keyboard by using buttons
My tricky problem is :

I've 2 buttons with 2 UITextView.
Like you know, when I push an UITextView, keyboard appear. Well, this is not what I want.

I want to enable / disable the display's keyboard according a specific @IBAction taped.

The scenario is the following:
- First button (Keyboard icon) allow the user to display the keyboard to type something in one of the UITextView, with a FirstResponder init on the top one.

Second button (REC icon) allow the user to speak and display in pre-selected TextView but without displaying keyboard.

I already known that there is :

isUserInteractionEnabled

and

textViewDidBeginEditing

But it doesn't really fit well and/or fix my issue.

Here a screen to be more explicit (don't give a mind about the third green validate button, it's just for the .POST feature) :

Thanks for any help!

答:
You say

But it's not really working in my case.

Why?

You can disable the textfields interaction with (swift 3):

```<code>textField.isUserInteractionEnabled = false
</code>```

Next, when you click on the keyboard button you can reenable the interaction so when the user click on one of the textfield the keyboard opens.

On the keyboard dismiss (you can see the UIKeyboardWillHideNotification callback notification) you can set the interaction to false.

Body:
You say

But it's not really working in my case.

Why?

You can disable the textfields interaction with (swift 3):

textField.isUserInteractionEnabled = false

Next, when you click on the keyboard button you can reenable the interaction so when the user click on one of the textfield the keyboard opens.

On the keyboard dismiss (you can see the UIKeyboardWillHideNotification callback notification) you can set the interaction to false.


问:
Counting high of p showing average on d
```<code>module try2(p,d,q1,q2,q3,q4,q5,q6,q7,q8,c,a);
input p,c;
output [15:0]q1,q2,q3,q4,q5,q6,q7,q8,d,a;
reg [15:0] d=16'b0;//may be error
reg [15:0]a;
always @ (posedge p) begin
d<=d+1;
end

DFF dff0(q1,d,p);
DFF dff1(q2,q1,p);
DFF dff2(q3,q2,p);
DFF dff3(q4,q3,p);
DFF dff4(q5,q4,p);
DFF dff5(q6,q5,p);
DFF dff6(q7,q6,p);
DFF dff7(q8,q7,p);
always @ ( posedge c )begin
a = ( q1 + q2 + q3 + q4 + q5 + q6 + q7 + q8 )/8;
end

endmodule

module DFF(q,d,clk);
input [15:0]d;
input clk;
output [15:0]q;
reg [15:0]q;
always @ (posedge  clk)begin
q <=d;
end

endmodule
</code>```

Here I am counting the high of pulse p and showing the value in 16 bit d.
And whenever another input c goes from 0 to 1 I am showing the average of last 8 values of d.

Problem:Here everything is working fine but the average value showing deviation of 1 and program is stimulating but not synthesizing .

答:
Depending on which synthesis tool you are using, you may not use a variable initialization. You may need to use a reset signal. You can even make it synchronous with</p>

```<code>always @ (posedge p) begin
  d<=reset ? 0 :d+1;
end
</code>```

Title: Counting high of p showing average on d

Body:
module try2(p,d,q1,q2,q3,q4,q5,q6,q7,q8,c,a);
input p,c;
output [15:0]q1,q2,q3,q4,q5,q6,q7,q8,d,a;
reg [15:0] d=16'b0;//may be error
reg [15:0]a;
always @ (posedge p) begin
d<=d+1;
end

DFF dff0(q1,d,p);
DFF dff1(q2,q1,p);
DFF dff2(q3,q2,p);
DFF dff3(q4,q3,p);
DFF dff4(q5,q4,p);
DFF dff5(q6,q5,p);
DFF dff6(q7,q6,p);
DFF dff7(q8,q7,p);
always @ ( posedge c )begin
a = ( q1 + q2 + q3 + q4 + q5 + q6 + q7 + q8 )/8;
end

endmodule

module DFF(q,d,clk);
input [15:0]d;
input clk;
output [15:0]q;
reg [15:0]q;
always @ (posedge  clk)begin
q <=d;
end

endmodule

Here I am counting the high of pulse p and showing the value in 16 bit d.
And whenever another input c goes from 0 to 1 I am showing the average of last 8 values of d.

Problem:Here everything is working fine but the average value showing deviation of 1 and program is stimulating but not synthesizing .

Body:
Depending on which synthesis tool you are using, you may not use a variable initialization. You may need to use a reset signal. You can even make it synchronous with

always @ (posedge p) begin
  d<=reset ? 0 :d+1;
end


问:
Mercurial: Indicating that a branch has passed testing?
I am working on establishing a workflow at my company if we were to migrate to DVCS (most likely Mercurial).  One of the things I would like to do is to have a repository for QA.  The idea being that each developer works on a branch and when they are done the branch is pushed to QA.  From there the test team can do their testing and report back any bugs.  Once the branch is fully tested and acceptable it will be pushed to a staging repository where the merge back to the mainline will happen before pushing to the central repository.

This can work quite easily if everyone just communicates the status of their work in some way, but I know this doesn't always happen as you would want it to.  What I am worried about is branches in the QA repo waiting around but nobody knows if it is waiting to be tested, currently being tested, waiting for fixes, waiting to be pushed to the staging area etc.  So what I am looking for are ideas of how a status can be added to a branch?  What would also be good would be to do it in a way that we could use hooks to also notify people of changes in the status.

Any ideas would be appreciated.

答:
Unfortunately I think you need a different system to keep track of this part of your workflow.

A repository consists of things that aren't supposed to change all willy nilly, yet the current Q&A status will by necessity change orthogonal to the contents of the repository.

Let me rephrase that. You have 10 changesets in the Q&A repository, ready to be tested. Exactly what each tester focuses on, the status of each test, etc. will change, even though those 10 changesets stay the same.

I would definitely try to use a bugtracking system where you can integrate the repository history in some way, even if it is just by linking an issue in the system to its changeset.

I notice your comment about not getting support for buying Kiln, but there are other systems you should be able to integrate that would give you something similar.

I would very much resist trying to press Mercurial into service of something it wasn't built to support, trying to use tags for this would fail miserably, and bookmarks would give you problems, as you've already noted.

So again, try to find a separate system for keeping track of Q&A status.

ContentLicense: CC BY-SA 2.5


问:
I don't know how to make this shape in python using "#'s" and "*'s"
I'm trying to create a simple python code that will create fairly simple shapes using "#'s" and "*'s" and I'm quite new to python and would like to only use for loops and the range() function. My code may be more complicated than it needs to be, but anyway, Heres my code so far:

```<code>Shapes = int(input("please enter the number size of the shape you want"))
sShapes = input("Would you like a square, triangle, Triangle 2 or Pyramid?")
s = 0
ss = Shapes + 1

##This is the code to make a square##
if sShapes == "Square":
    for i in range(0, Shapes):
        print('*'*Shapes)

##This is the code to make a triangle##
elif sShapes == "Triangle":
    for b in range(0, ss, 1):
        print('*'*(s+1)*b)

##This is the code that does not work##
elif sShapes == "T2":
    for c in range(ss,0,-1):
        print('#'*(s+1)*c, '*')
</code>```

The code that does not work is supposed to look like this:

```<code>####*
###**
##***
#****
*****
</code>```

答:
You may use a single variable to control the loop:

line_shape_number = 5 # Total number of shapes
for step in range(1, line_shape_number + 1):
    print '{}{}'.format('#' * (line_shape_number - step), '*' * step)
```

Body:
I'm trying to create a simple python code that will create fairly simple shapes using "#'s" and "*'s" and I'm quite new to python and would like to only use for loops and the range() function. My code may be more complicated than it needs to be, but anyway, Heres my code so far:

Shapes = int(input("please enter the number size of the shape you want"))
sShapes = input("Would you like a square, triangle, Triangle 2 or Pyramid?")
s = 0
ss = Shapes + 1

##This is the code to make a square##
if sShapes == "Square":
    for i in range(0, Shapes):
        print('*'*Shapes)

##This is the code to make a triangle##
elif sShapes == "Triangle":
    for b in range(0, ss, 1):
        print('*'*(s+1)*b)

##This is the code that does not work##
elif sShapes == "T2":
    for c in range(ss,0,-1):
        print('#'*(s+1)*c, '*')

The code that does not work is supposed to look like this:

####*
###**
##***
#****
*****