问:
R Shiny Leaflet Marker Zoom Issues
I want to be able to double click on a custom marker and have the map recenter and zoom. Im not sure if it should be doing it automatically and just isnt or if i need a special code.

Below is my current marker code:
Thanks!

```<code>ui <- bootstrapPage(
  tags$style(type = "text/css", "html, body {width:100%;height:100%}"),
  leafletOutput("map", width = "100%", height = "100%"))
server <- function(input, output){
  output$map <- renderLeaflet({
    m <- leaflet(wins) %>% addProviderTiles(providers$OpenStreetMap)
    m %>% setView(-72.690940, 41.651426, zoom = 12)
    m %>% addMarkers(~lng, ~lat,
      icon = greenLeafIcon,
      popup = paste("Where:", wins$Where,"<br>", "What:", wins$What,"<br>", "Who:", wins$Who,"<br>", "Why:", wins$Why,"<br>", "Order Date:", wins$OrderDate,"<br>", "Go Live Date:", wins$GoLiveDate, "<br>","<a href='",wins$link,"' target='_blank'>",wins$link,"</a>"),
      clusterOptions = markerClusterOptions(color="#0017bb"),
      centerMap
      label = wins$Name,
      labelOptions = labelOptions(noHide = F))
  })
}
shinyApp(ui, server)

> dput(wins)
structure(list(Name = structure(c(9L, 6L, 11L, 4L, 2L, 10L, 5L,
3L, 8L, 1L, 7L), .Label = c("Brigam", "Brown", "Buffalo", "Cornell",
"Maine Medical", "MGH", "Middlesex", "North Maine", "Tufts",
"UVM", "Yale"), class = "factor"), Where = structure(c(9L, 6L,
11L, 4L, 2L, 10L, 5L, 3L, 8L, 1L, 7L), .Label = c("Brigam", "Brown",
"Buffalo", "Cornell", "Maine Medical", "MGH", "Middlesex Medical Hospital",
"North Maine", "Tufts", "UVM", "Yale"), class = "factor"), What = structure(c(1L,
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "saple3", class = "factor"),
    Who = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,
    1L), .Label = "RML-  SAM-", class = "factor"),
    Why = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,
    1L), .Label = "sample", class = "factor"), OrderDate = structure(c(1L,
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "Q1", class = "factor"),
    GoLiveDate = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,
    1L, 1L, 1L), .Label = "Q2", class = "factor"), lat = c(42.349598,
    42.361542, 41.303229, 40.764991, 41.819064, 44.47972, 43.653243,
    42.886447, 47.140694, 42.33597, 41.55466), lng = c(-71.063541,
    -71.0688334, -72.933826, -73.95479, -71.408277, -73.194072,
    -70.276184, -78.87836, -68.269043, -71.10766, -72.64815),
    link = structure(c(1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,
    3L), .Label = c("http:\\\\www.google.com", "http:\\\\www.google.org",
    "https://google.com"
    ), class = "factor")), .Names = c("Name", "Where", "What",
"Who", "Why", "OrderDate", "GoLiveDate", "lat", "lng", "link"
), class = "data.frame", row.names = c(NA, -11L))
</code>```

答:
Unfortunately AFAIK there is no double_click event in leaflet (I'd love to be proved wrong).

If you are ok with a single click, we can do:

```<code>server <- function(input, output){
    output$map <- renderLeaflet({
        m <- leaflet(wins) %>%
            addProviderTiles(providers$OpenStreetMap) %>%
            addMarkers(~lng, ~lat,
                       #icon = 'greenLeafIcon',
                       popup = paste("Where:", wins$Where,"<br>", "What:", wins$What,"<br>", "Who:", wins$Who,"<br>", "Why:", wins$Why,"<br>", "Order Date:", wins$OrderDate,"<br>", "Go Live Date:", wins$GoLiveDate, "<br>","<a href='",wins$link,"' target='_blank'>",wins$link,"</a>"),
                       clusterOptions = markerClusterOptions(color="#0017bb"),
                       #centerMap,
                       label = ~Name,
                       labelOptions = labelOptions(noHide = F))
    })

    observe({
        click <- input$map_marker_click
        zoom <- isolate(input$map_zoom)
        if(is.null(click))
            return()

        leafletProxy('map') %>%
            setView(click$lng, click$lat, zoom = zoom)
    })
}
</code>```

What it does it's observe the map_marker_click event, when that happen leafletProxy() will update the 'map' output to the specified lng, lat and zoom. We need to isolate input$zoom, otherwise the observe would launch every time we change the zoom, causing weird behaviors.

Title: R Shiny Leaflet Marker Zoom Issues

Body:
I want to be able to double click on a custom marker and have the map recenter and zoom. Im not sure if it should be doing it automatically and just isnt or if i need a special code.

Below is my current marker code:
Thanks!

ui <- bootstrapPage(
  tags$style(type = "text/css", "html, body {width:100%;height:100%}"),
  leafletOutput("map", width = "100%", height = "100%"))
server <- function(input, output){
  output$map <- renderLeaflet({
    m <- leaflet(wins) %>% addProviderTiles(providers$OpenStreetMap)
    m %>% setView(-72.690940, 41.651426, zoom = 12)
    m %>% addMarkers(~lng, ~lat,
      icon = greenLeafIcon,
      popup = paste("Where:", wins$Where,"
", "What:", wins$What,"
", "Who:", wins$Who,"
", "Why:", wins$Why,"
", "Order Date:", wins$OrderDate,"
", "Go Live Date:", wins$GoLiveDate, "
","",wins$link,""),
      clusterOptions = markerClusterOptions(color="#0017bb"),
      centerMap
      label = wins$Name,
      labelOptions = labelOptions(noHide = F))
  })
}
shinyApp(ui, server)

> dput(wins)
structure(list(Name = structure(c(9L, 6L, 11L, 4L, 2L, 10L, 5L,
3L, 8L, 1L, 7L), .Label = c("Brigam", "Brown", "Buffalo", "Cornell",
"Maine Medical", "MGH", "Middlesex", "North Maine", "Tufts",
"UVM", "Yale"), class = "factor"), Where = structure(c(9L, 6L,
11L, 4L, 2L, 10L, 5L, 3L, 8L, 1L, 7L), .Label = c("Brigam", "Brown",
"Buffalo", "Cornell", "Maine Medical", "MGH", "Middlesex Medical Hospital",
"North Maine", "Tufts", "UVM", "Yale"), class = "factor"), What = structure(c(1L,
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "saple3", class = "factor"),
    Who = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,
    1L), .Label = "RML-  SAM-", class = "factor"),
    Why = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,
    1L), .Label = "sample", class = "factor"), OrderDate = structure(c(1L,
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "Q1", class = "factor"),
    GoLiveDate = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,
    1L, 1L, 1L), .Label = "Q2", class = "factor"), lat = c(42.349598,
    42.361542, 41.303229, 40.764991, 41.819064, 44.47972, 43.653243,
    42.886447, 47.140694, 42.33597, 41.55466), lng = c(-71.063541,
    -71.0688334, -72.933826, -73.95479, -71.408277, -73.194072,
    -70.276184, -78.87836, -68.269043, -71.10766, -72.64815),
    link = structure(c(1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,
    3L), .Label = c("http:\\\\www.google.com", "http:\\\\www.google.org",
    "https://google.com"
    ), class = "factor")), .Names = c("Name", "Where", "What",
"Who", "Why", "OrderDate", "GoLiveDate", "lat", "lng", "link"
), class = "data.frame", row.names = c(NA, -11L))

Body:
Unfortunately AFAIK there is no double_click event in leaflet (I'd love to be proved wrong).

If you are ok with a single click, we can do:

server <- function(input, output){
    output$map <- renderLeaflet({
        m <- leaflet(wins) %>%
            addProviderTiles(providers$OpenStreetMap) %>%
            addMarkers(~lng, ~lat,
                       #icon = 'greenLeafIcon',
                       popup = paste("Where:", wins$Where,"<br>", "What:", wins$What,"<br>", "Who:", wins$Who,"<br>", "Why:", wins$Why,"<br>", "Order Date:", wins$OrderDate,"<br>", "Go Live Date:", wins$GoLiveDate, "<br>","<a href='",wins$link,"' target='_blank'>",wins$link,"</a>"),
                       clusterOptions = markerClusterOptions(color="#0017bb"),
                       #centerMap,
                       label = ~Name,
                       labelOptions = labelOptions(noHide = F))
    })

    observe({
        click <- input$map_marker_click
        zoom <- isolate(input$map_zoom)
        if(is.null(click))
            return()

        leafletProxy('map') %>%
            setView(click$lng, click$lat, zoom = zoom)
    })
}

What it does it's observe the map_marker_click event, when that happen leafletProxy() will update the 'map' output to the specified lng, lat and zoom. We need to isolate input$zoom, otherwise the observe would launch every time we change the zoom, causing weird behaviors.


来源: stackexchange

问:
Asp.Net Core HTML Helper does not select the value it is provided
I am trying to add a Select List to my view. In the razor template I have:

```<code>@foreach (var item in Model.ProjectRecordGroupParsed)
{
    <div>
        <!-- Code: @item.Code -->
        @Html.DropDownList("ProjectRecordGroup", new SelectList(AllProjectRecordGroups, "Code", "Name", item.Code), "Select Project Record Group", htmlAttributes: new { @class = "form-control" })
    </div>
}
</code>```

The result of this is a drop down with the values from AllProjectRecordGroup which does contain this option:

```<code><option value="MARKPROJECT">MARK Project</option>
</code>```

and the comment line contains this:

```<code><!-- Code: MARKPROJECT -->
</code>```

So, I am wondering what is going on here? Why is the value not selected?

答: where AllProjectRecordGroups come from, if i understood this class populating this selectbox right?? maybe you need return this from controller with data, give more details please, and i trying help you

ContentLicense: CC BY-SA 3.0

Body:
I am trying to add a Select List to my view. In the razor template I have:

@foreach (var item in Model.ProjectRecordGroupParsed)
{

        @Html.DropDownList("ProjectRecordGroup", new SelectList(AllProjectRecordGroups, "Code", "Name", item.Code), "Select Project Record Group", htmlAttributes: new { @class = "form-control" })

}

The result of this is a drop down with the values from AllProjectRecordGroup which does contain this option:

<option value="MARKPROJECT">MARK Project</option>

and the comment line contains this:

So, I am wondering what is going on here? Why is the value not selected?


问:
Chronicle Queue V3. Can Entries be lost on data block roll-over?
I have an application that writes entries to a Chronicle Queue (V3) that also retains excerpt entry index values in other (Chronicle)Maps by way of providing indexed access in the queue.  Sometimes we fail to find a given entry that we've earlier saved and I believe it maybe related to data-block roll-over.

Below is a stand-alone test program that reproduces such use-cases at small-scale.  It repeatedly writes an entry and immediately attempts to find the resulting index value up using a separate ExcerptTailer.  All is well for a while until the first data-block is used up and a second data file is assigned, then the retrieval failures start.  If the data block size is increased to avoid roll-overs, then no entries are lost.  Also using a small index data-block size, causing multiple index files to be created, doesn't cause a problem.

The test program also tries using an ExcerptListener running in parallel to see if the entries apparently 'lost' by the writer, are ever received by the reader thread - they're not.  Also tries to re-read the resulting queue from start until end, which reconfirms that they really are lost.

Stepping thru' the code, I see that when looking up a 'missing entry', within AbstractVanillarExcerpt#index, it appears to successfully locate the correct VanillaMappedBytes object from the dataCache, but determines that there is no entry and the data-offset as the len == 0.  In addition to the entries not being found, at some point after the problems start occurring post-roll-over, an NPE is thrown from within the VanillaMappedFile#fileChannel method due to it having been passed a null File path.  The code-path assumes that when resolving a entry looked up successfully in the index that a file will always have been found, but isn't in this case.

Is it possible to reliably use Chronicle Queue across data-block roll-overs, and if so, what am I doing that maybe causing the problem I'm experiencing?

```<code>import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Set;

import org.junit.Before;
import org.junit.Test;

import net.openhft.affinity.AffinitySupport;
import net.openhft.chronicle.Chronicle;
import net.openhft.chronicle.ChronicleQueueBuilder;
import net.openhft.chronicle.ExcerptAppender;
import net.openhft.chronicle.ExcerptCommon;
import net.openhft.chronicle.ExcerptTailer;
import net.openhft.chronicle.VanillaChronicle;

public class ChronicleTests {
    private static final int CQ_LEN = VanillaChronicle.Cycle.DAYS.length();
    private static final long CQ_ENT = VanillaChronicle.Cycle.DAYS.entries();
    private static final String ROOT_DIR = System.getProperty(ChronicleTests.class.getName() + ".ROOT_DIR",
            "C:/Temp/chronicle/");
    private static final String QDIR = System.getProperty(ChronicleTests.class.getName() + ".QDIR", "chronicleTests");
    private static final int DATA_SIZE = Integer
            .parseInt(System.getProperty(ChronicleTests.class.getName() + ".DATA_SIZE", "100000"));
    // Chunk file size of CQ index
    private static final int INDX_SIZE = Integer
            .parseInt(System.getProperty(ChronicleTests.class.getName() + ".INDX_SIZE", "10000"));
    private static final int Q_ENTRIES = Integer
            .parseInt(System.getProperty(ChronicleTests.class.getName() + ".Q_ENTRIES", "5000"));
    // Data type id
    protected static final byte FSYNC_DATA = 1;
    protected static final byte NORMAL_DATA = 0;
    protected static final byte TH_START_DATA = -1;
    protected static final byte TH_END_DATA = -2;
    protected static final byte CQ_START_DATA = -3;
    private static final long MAX_RUNTIME_MILLISECONDS = 30000;

    private static String PAYLOAD_STRING = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    private static byte PAYLOAD_BYTES[] = PAYLOAD_STRING.getBytes();

    private Chronicle _chronicle;
    private String _cqPath = ROOT_DIR + QDIR;

    @Before
    public void init() {
        buildCQ();
    }

    @Test
    public void test() throws IOException, InterruptedException {
        boolean passed = true;
        Collection<Long> missingEntries = new LinkedList<Long>();
        long sent = 0;
        Thread listener = listen();
        try {
            listener.start();
            // Write entries to CQ,
            for (int i = 0; i < Q_ENTRIES; i++) {
                long entry = writeQEntry(PAYLOAD_BYTES, (i % 100) == 0);
                sent++;
                // check each entry can be looked up
                boolean found = checkEntry(i, entry);
                if (!found)
                    missingEntries.add(entry);
                passed &= found;
            }
            // Wait awhile for the listener
            listener.join(MAX_RUNTIME_MILLISECONDS);
            if (listener.isAlive())
                listener.interrupt();
        } finally {
            if (listener.isAlive()) { // => exception raised so wait for listener
                log("Give listener a chance....");
                sleep(MAX_RUNTIME_MILLISECONDS);
                listener.interrupt();
            }
            log("Sent: " + sent + " Received: " + _receivedEntries.size());
            // Look for missing entries in receivedEntries
            missingEntries.forEach(me -> checkMissingEntry(me));
            log("All passed? " + passed);
            // Try to find missing entries by searching from the start...
            searchFromStartFor(missingEntries);
            _chronicle.close();
            _chronicle = null;
            // Re-initialise CQ and look for missing entries again...
            log("Re-initialise");
            init();
            searchFromStartFor(missingEntries);
        }
    }

    private void buildCQ() {
        try {
            // build chronicle queue
            _chronicle = ChronicleQueueBuilder.vanilla(_cqPath).cycleLength(CQ_LEN).entriesPerCycle(CQ_ENT)
                    .indexBlockSize(INDX_SIZE).dataBlockSize(DATA_SIZE).build();
        } catch (IOException e) {
            throw new InitializationException("Failed to initialize Active Trade Store.", e);
        }
    }

    private long writeQEntry(byte dataArray[], boolean fsync) throws IOException {
        ExcerptAppender appender = _chronicle.createAppender();
        return writeData(appender, dataArray, fsync);
    }

    private boolean checkEntry(int seqNo, long entry) throws IOException {
        ExcerptTailer tailer = _chronicle.createTailer();
        if (!tailer.index(entry)) {
            log("SeqNo: " + seqNo + " for entry + " + entry + " not found");
            return false;
        }
        boolean isMarker = isMarker(tailer);
        boolean isFsyncData = isFsyncData(tailer);
        boolean isNormalData = isNormalData(tailer);
        String type = isMarker ? "MARKER" : isFsyncData ? "FSYNC" : isNormalData ? "NORMALDATA" : "UNKNOWN";
        log("Entry: " + entry + "(" + seqNo + ") is " + type);
        return true;
    }

    private void log(String string) {
        System.out.println(string);
    }

    private void searchFromStartFor(Collection<Long> missingEntries) throws IOException {
        Set<Long> foundEntries = new HashSet<Long>(Q_ENTRIES);
        ExcerptTailer tailer = _chronicle.createTailer();
        tailer.toStart();
        while (tailer.nextIndex())
            foundEntries.add(tailer.index());
        Iterator<Long> iter = missingEntries.iterator();
        long foundCount = 0;
        while (iter.hasNext()) {
            long me = iter.next();
            if (foundEntries.contains(me)) {
                log("Found missing entry: " + me);
                foundCount++;
            }
        }
        log("searchFromStartFor Found: " + foundCount + " of: " + missingEntries.size() + " missing entries");
    }

    private void checkMissingEntry(long missingEntry) {
        if (_receivedEntries.contains(missingEntry))
            log("Received missing entry:" + missingEntry);
    }

    Set<Long> _receivedEntries = new HashSet<Long>(Q_ENTRIES);

    private Thread listen() {
        Thread returnVal = new Thread("Listener") {

            public void run() {
                try {
                    int receivedCount = 0;
                    ExcerptTailer tailer = _chronicle.createTailer();
                    tailer.toStart();
                    while (receivedCount < Q_ENTRIES) {
                        if (tailer.nextIndex()) {
                            _receivedEntries.add(tailer.index());
                        } else {
                            ChronicleTests.this.sleep(1);
                        }
                    }
                    log("listener complete");
                } catch (IOException e) {
                    log("Interupted before receiving all entries");
                }
            }
        };
        return returnVal;
    }

    private void sleep(long interval) {
        try {
            Thread.sleep(interval);
        } catch (InterruptedException e) {
            // No action required
        }
    }

    protected static final int THREAD_ID_LEN = Integer.SIZE / Byte.SIZE;
    protected static final int DATA_TYPE_LEN = Byte.SIZE / Byte.SIZE;
    protected static final int TIMESTAMP_LEN = Long.SIZE / Byte.SIZE;
    protected static final int CRC_LEN = Long.SIZE / Byte.SIZE;

    protected static long writeData(ExcerptAppender appender, byte dataArray[],
            boolean fsync) {
        appender.startExcerpt(DATA_TYPE_LEN + THREAD_ID_LEN + dataArray.length
                + CRC_LEN);
        appender.nextSynchronous(fsync);
        if (fsync) {
            appender.writeByte(FSYNC_DATA);
        } else {
            appender.writeByte(NORMAL_DATA);
        }
        appender.writeInt(AffinitySupport.getThreadId());
        appender.write(dataArray);
        appender.writeLong(CRCCalculator.calcDataAreaCRC(appender));
        appender.finish();
        return appender.lastWrittenIndex();
    }

    protected static boolean isMarker(ExcerptCommon excerpt) {
        if (isCqStartMarker(excerpt) || isStartMarker(excerpt) || isEndMarker(excerpt)) {
            return true;
        }
        return false;
    }

    protected static boolean isCqStartMarker(ExcerptCommon excerpt) {
        return isDataTypeMatched(excerpt, CQ_START_DATA);
    }

    protected static boolean isStartMarker(ExcerptCommon excerpt) {
        return isDataTypeMatched(excerpt, TH_START_DATA);
    }

    protected static boolean isEndMarker(ExcerptCommon excerpt) {
        return isDataTypeMatched(excerpt, TH_END_DATA);
    }

    protected static boolean isData(ExcerptTailer tailer, long index) {
        if (!tailer.index(index)) {
            return false;
        }
        return isData(tailer);
    }

    private static void movePosition(ExcerptCommon excerpt, long position) {
        if (excerpt.position() != position)
            excerpt.position(position);
    }

    private static void moveToFsyncFlagPos(ExcerptCommon excerpt) {
        movePosition(excerpt, 0);
    }

    private static boolean isDataTypeMatched(ExcerptCommon excerpt, byte type) {
        moveToFsyncFlagPos(excerpt);
        byte b = excerpt.readByte();
        if (b == type) {
            return true;
        }
        return false;
    }

    protected static boolean isNormalData(ExcerptCommon excerpt) {
        return isDataTypeMatched(excerpt, NORMAL_DATA);
    }

    protected static boolean isFsyncData(ExcerptCommon excerpt) {
        return isDataTypeMatched(excerpt, FSYNC_DATA);
    }

    /**
     * Check if this entry is Data
     *
     * @param excerpt
     * @return true if the entry is data
     */
    protected static boolean isData(ExcerptCommon excerpt) {
        if (isNormalData(excerpt) || isFsyncData(excerpt)) {
            return true;
        }
        return false;
    }

}
</code>```

答:
The problem only occurs when initialising the data-block size with a value that is not a power of two.  The built-in configurations on IndexedChronicleQueueBuilder (small(), medium(), large()) take care to initialise using powers of two which provided the clue as to the appropriate usage.

Notwithstanding the above response regarding support, which I totally appreciate, it would be useful if a knowledgeable Chronicle user could confirm that the integrity of Chronicle Queue depends on using a data-block size of a power of two.

Body:
I have an application that writes entries to a Chronicle Queue (V3) that also retains excerpt entry index values in other (Chronicle)Maps by way of providing indexed access in the queue.  Sometimes we fail to find a given entry that we've earlier saved and I believe it maybe related to data-block roll-over.

Below is a stand-alone test program that reproduces such use-cases at small-scale.  It repeatedly writes an entry and immediately attempts to find the resulting index value up using a separate ExcerptTailer.  All is well for a while until the first data-block is used up and a second data file is assigned, then the retrieval failures start.  If the data block size is increased to avoid roll-overs, then no entries are lost.  Also using a small index data-block size, causing multiple index files to be created, doesn't cause a problem.

The test program also tries using an ExcerptListener running in parallel to see if the entries apparently 'lost' by the writer, are ever received by the reader thread - they're not.  Also tries to re-read the resulting queue from start until end, which reconfirms that they really are lost.

Stepping thru' the code, I see that when looking up a 'missing entry', within AbstractVanillarExcerpt#index, it appears to successfully locate the correct VanillaMappedBytes object from the dataCache, but determines that there is no entry and the data-offset as the len == 0.  In addition to the entries not being found, at some point after the problems start occurring post-roll-over, an NPE is thrown from within the VanillaMappedFile#fileChannel method due to it having been passed a null File path.  The code-path assumes that when resolving a entry looked up successfully in the index that a file will always have been found, but isn't in this case.

Is it possible to reliably use Chronicle Queue across data-block roll-overs, and if so, what am I doing that maybe causing the problem I'm experiencing?

import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Set;

import org.junit.Before;
import org.junit.Test;

import net.openhft.affinity.AffinitySupport;
import net.openhft.chronicle.Chronicle;
import net.openhft.chronicle.ChronicleQueueBuilder;
import net.openhft.chronicle.ExcerptAppender;
import net.openhft.chronicle.ExcerptCommon;
import net.openhft.chronicle.ExcerptTailer;
import net.openhft.chronicle.VanillaChronicle;

public class ChronicleTests {
    private static final int CQ_LEN = VanillaChronicle.Cycle.DAYS.length();
    private static final long CQ_ENT = VanillaChronicle.Cycle.DAYS.entries();
    private static final String ROOT_DIR = System.getProperty(ChronicleTests.class.getName() + ".ROOT_DIR",
            "C:/Temp/chronicle/");
    private static final String QDIR = System.getProperty(ChronicleTests.class.getName() + ".QDIR", "chronicleTests");
    private static final int DATA_SIZE = Integer
            .parseInt(System.getProperty(ChronicleTests.class.getName() + ".DATA_SIZE", "100000"));
    // Chunk file size of CQ index
    private static final int INDX_SIZE = Integer
            .parseInt(System.getProperty(ChronicleTests.class.getName() + ".INDX_SIZE", "10000"));
    private static final int Q_ENTRIES = Integer
            .parseInt(System.getProperty(ChronicleTests.class.getName() + ".Q_ENTRIES", "5000"));
    // Data type id
    protected static final byte FSYNC_DATA = 1;
    protected static final byte NORMAL_DATA = 0;
    protected static final byte TH_START_DATA = -1;
    protected static final byte TH_END_DATA = -2;
    protected static final byte CQ_START_DATA = -3;
    private static final long MAX_RUNTIME_MILLISECONDS = 30000;

    private static String PAYLOAD_STRING = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    private static byte PAYLOAD_BYTES[] = PAYLOAD_STRING.getBytes();

    private Chronicle _chronicle;
    private String _cqPath = ROOT_DIR + QDIR;

    @Before
    public void init() {
        buildCQ();
    }

    @Test
    public void test() throws IOException, InterruptedException {
        boolean passed = true;
        Collection<Long> missingEntries = new LinkedList<Long>();
        long sent = 0;
        Thread listener = listen();
        try {
            listener.start();
            // Write entries to CQ,
            for (int i = 0; i < Q_ENTRIES; i++) {
                long entry = writeQEntry(PAYLOAD_BYTES, (i % 100) == 0);
                sent++;
                // check each entry can be looked up
                boolean found = checkEntry(i, entry);
                if (!found)
                    missingEntries.add(entry);
                passed &= found;
            }
            // Wait awhile for the listener
            listener.join(MAX_RUNTIME_MILLISECONDS);
            if (listener.isAlive())
                listener.interrupt();
        } finally {
            if (listener.isAlive()) { // => exception raised so wait for listener
                log("Give listener a chance....");
                sleep(MAX_RUNTIME_MILLISECONDS);
                listener.interrupt();
            }
            log("Sent: " + sent + " Received: " + _receivedEntries.size());
            // Look for missing entries in receivedEntries
            missingEntries.forEach(me -> checkMissingEntry(me));
            log("All passed? " + passed);
            // Try to find missing entries by searching from the start...
            searchFromStartFor(missingEntries);
            _chronicle.close();
            _chronicle = null;
            // Re-initialise CQ and look for missing entries again...
            log("Re-initialise");
            init();
            searchFromStartFor(missingEntries);
        }
    }

    private void buildCQ() {
        try {
            // build chronicle queue
            _chronicle = ChronicleQueueBuilder.vanilla(_cqPath).cycleLength(CQ_LEN).entriesPerCycle(CQ_ENT)
                    .indexBlockSize(INDX_SIZE).dataBlockSize(DATA_SIZE).build();
        } catch (IOException e) {
            throw new InitializationException("Failed to initialize Active Trade Store.", e);
        }
    }

    private long writeQEntry(byte dataArray[], boolean fsync) throws IOException {
        ExcerptAppender appender = _chronicle.createAppender();
        return writeData(appender, dataArray, fsync);
    }

    private boolean checkEntry(int seqNo, long entry) throws IOException {
        ExcerptTailer tailer = _chronicle.createTailer();
        if (!tailer.index(entry)) {
            log("SeqNo: " + seqNo + " for entry + " + entry + " not found");
            return false;
        }
        boolean isMarker = isMarker(tailer);
        boolean isFsyncData = isFsyncData(tailer);
        boolean isNormalData = isNormalData(tailer);
        String type = isMarker ? "MARKER" : isFsyncData ? "FSYNC" : isNormalData ? "NORMALDATA" : "UNKNOWN";
        log("Entry: " + entry + "(" + seqNo + ") is " + type);
        return true;
    }

    private void log(String string) {
        System.out.println(string);
    }

    private void searchFromStartFor(Collection<Long> missingEntries) throws IOException {
        Set<Long> foundEntries = new HashSet<Long>(Q_ENTRIES);
        ExcerptTailer tailer = _chronicle.createTailer();
        tailer.toStart();
        while (tailer.nextIndex())
            foundEntries.add(tailer.index());
        Iterator<Long> iter = missingEntries.iterator();
        long foundCount = 0;
        while (iter.hasNext()) {
            long me = iter.next();
            if (foundEntries.contains(me)) {
                log("Found missing entry: " + me);
                foundCount++;
            }
        }
        log("searchFromStartFor Found: " + foundCount + " of: " + missingEntries.size() + " missing entries");
    }

    private void checkMissingEntry(long missingEntry) {
        if (_receivedEntries.contains(missingEntry))
            log("Received missing entry:" + missingEntry);
    }

    Set<Long> _receivedEntries = new HashSet<Long>(Q_ENTRIES);

    private Thread listen() {
        Thread returnVal = new Thread("Listener") {

            public void run() {
                try {
                    int receivedCount = 0;
                    ExcerptTailer tailer = _chronicle.createTailer();
                    tailer.toStart();
                    while (receivedCount < Q_ENTRIES) {
                        if (tailer.nextIndex()) {
                            _receivedEntries.add(tailer.index());
                        } else {
                            ChronicleTests.this.sleep(1);
                        }
                    }
                    log("listener complete");
                } catch (IOException e) {
                    log("Interupted before receiving all entries");
                }
            }
        };
        return returnVal;
    }

    private void sleep(long interval) {
        try {
            Thread.sleep(interval);
        } catch (InterruptedException e) {
            // No action required
        }
    }

    protected static final int THREAD_ID_LEN = Integer.SIZE / Byte.SIZE;
    protected static final int DATA_TYPE_LEN = Byte.SIZE / Byte.SIZE;
    protected static final int TIMESTAMP_LEN = Long.SIZE / Byte.SIZE;
    protected static final int CRC_LEN = Long.SIZE / Byte.SIZE;

    protected static long writeData(ExcerptAppender appender, byte dataArray[],
            boolean fsync) {
        appender.startExcerpt(DATA_TYPE_LEN + THREAD_ID_LEN + dataArray.length
                + CRC_LEN);
        appender.nextSynchronous(fsync);
        if (fsync) {
            appender.writeByte(FSYNC_DATA);
        } else {
            appender.writeByte(NORMAL_DATA);
        }
        appender.writeInt(AffinitySupport.getThreadId());
        appender.write(dataArray);
        appender.writeLong(CRCCalculator.calcDataAreaCRC(appender));
        appender.finish();
        return appender.lastWrittenIndex();
    }

    protected static boolean isMarker(ExcerptCommon excerpt) {
        if (isCqStartMarker(excerpt) || isStartMarker(excerpt) || isEndMarker(excerpt)) {
            return true;
        }
        return false;
    }

    protected static boolean isCqStartMarker(ExcerptCommon excerpt) {
        return isDataTypeMatched(excerpt, CQ_START_DATA);
    }

    protected static boolean isStartMarker(ExcerptCommon excerpt) {
        return isDataTypeMatched(excerpt, TH_START_DATA);
    }

    protected static boolean isEndMarker(ExcerptCommon excerpt) {
        return isDataTypeMatched(excerpt, TH_END_DATA);
    }

    protected static boolean isData(ExcerptTailer tailer, long index) {
        if (!tailer.index(index)) {
            return false;
        }
        return isData(tailer);
    }

    private static void movePosition(ExcerptCommon excerpt, long position) {
        if (excerpt.position() != position)
            excerpt.position(position);
    }

    private static void moveToFsyncFlagPos(ExcerptCommon excerpt) {
        movePosition(excerpt, 0);
    }

    private static boolean isDataTypeMatched(ExcerptCommon excerpt, byte type) {
        moveToFsyncFlagPos(excerpt);
        byte b = excerpt.readByte();
        if (b == type) {
            return true;
        }
        return false;
    }

    protected static boolean isNormalData(ExcerptCommon excerpt) {
        return isDataTypeMatched(excerpt, NORMAL_DATA);
    }

    protected static boolean isFsyncData(ExcerptCommon excerpt) {
        return isDataTypeMatched(excerpt, FSYNC_DATA);
    }

    /**
     * Check if this entry is Data
     *
     * @param excerpt
     * @return true if the entry is data
     */
    protected static boolean isData(ExcerptCommon excerpt) {
        if (isNormalData(excerpt) || isFsyncData(excerpt)) {
            return true;
        }
        return false;
    }

}


问:
ios - Determine if image picker media type is video or photo
I have UIImagePickerController which is choosing photo or video from gallery, after selecting item, I want to determine which one is chosen, photo or video

```<code> func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
    let mediaType = info[UIImagePickerControllerMediaType]

 }
</code>```

I've found this: How to select any Video or Movie file from UIImagePickerController

but could not translate to Swift:

```<code> if (CFStringCompare ((__bridge CFStringRef) mediaType, kUTTypeMovie, 0) == kCFCompareEqualTo) {

 }
</code>```

thank you in advance

答:
Use this </p>

```<code>if let mediaType = info[UIImagePickerControllerMediaType] as? String {

    if mediaType  == "public.image" {
        print("Image Selected")
    }

    if mediaType == "public.movie" {
        print("Video Selected")
    }
}
</code>```

Body:
I have UIImagePickerController which is choosing photo or video from gallery, after selecting item, I want to determine which one is chosen, photo or video

 func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
    let mediaType = info[UIImagePickerControllerMediaType]

 }

I've found this: How to select any Video or Movie file from UIImagePickerController

but could not translate to Swift:

 if (CFStringCompare ((__bridge CFStringRef) mediaType, kUTTypeMovie, 0) == kCFCompareEqualTo) {

 }

thank you in advance

Body:
Use this

if let mediaType = info[UIImagePickerControllerMediaType] as? String {

    if mediaType  == "public.image" {
        print("Image Selected")
    }

    if mediaType == "public.movie" {
        print("Video Selected")
    }
}


问:
jsessionid cookie set in jmeter request not recognised
I would like to execute some jmeter thread group requests in parallel using the same session. To do this, I have created a setUp thread group which authenticates and writes the JSESSIONID cookie (as well as other data) to a CSV file. This file is then to be used by the subsequent thread groups to allow them to use these already authenticated sessions.
To do this, I am basically following the solution outlined here: http://theworkaholic.blogspot.co.uk/2013/03/sharing-session-ids-across-threads.html.

The setUp thread group is authenticating and generating the CSV file as expected. However, I cannot get the requests in the subsequent thread groups to use the sessions provided. I can add the JSESSIONID cookie (either by using a BeanShell PreProcessor or using a HTTP Cookie Manager, both give the same results) but this does not seem to be recognised. The request being sent is the following:

```<code>POST https://test.mydomain.com:8443/prv/p/getUploadedfiles.action

POST data:
start=0&limit=10&sort=createdDate&dir=DESC&days=6

Cookie Data:
$Version=1; JSESSIONID="D0720DD3B06B5752DF6AC83A1B245EDA"; $Path="/";
$Domain="test.mydomain.com"

Request Headers:
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 49
Host: test.mydomain.com:8443
User-Agent: Apache-HttpClient/4.5.3 (Java/1.8.0_121)
</code>```

This request has a return status of 302 to re-direct to the login page. This compares to the same request executed successfully in the setUp thread group:

```<code>POST https://test.mydomain.com:8443/prv/p/getUploadedfiles.action

POST data:
start=0&limit=10&sort=createdDate&dir=DESC&days=6

Cookie Data:
JSESSIONID=D0720DD3B06B5752DF6AC83A1B245EDA

Request Headers:
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 49
Host: test.mydomain.com:8443
User-Agent: Apache-HttpClient/4.5.3 (Java/1.8.0_121)
</code>```

The only difference between the requests seem to be the $Version, $Path and $Domain explicitly set on the cookie data. [Interestingly, the 'Cookie Data' in the solution from the link above seems to be correct, by which I mean does not contain the $Version, $Path or $Domain in the request output]
BeanShell PreProcessor code is:

```<code>import org.apache.jmeter.protocol.http.control.CookieManager;
import org.apache.jmeter.protocol.http.control.Cookie;

Cookie cookie = new Cookie("JSESSIONID", vars.get("jsessionid"), "test.mydomain.com", "/", true, -1);
CookieManager manager = sampler.getCookieManager();
manager.add(cookie);
log.info("Cookie added: " + vars.get("jsessionid"));
</code>```

Does anyone know why the JSESSIONID cookie is not being recognised?

答: I solved this by removing the BeanShell PreProcessor and using a HTTP Cookie Manager to add the cookie, and setting the 'Cookie Policy' to "standard" (previously was set to "compatibility").</p>

Body:
I would like to execute some jmeter thread group requests in parallel using the same session. To do this, I have created a setUp thread group which authenticates and writes the JSESSIONID cookie (as well as other data) to a CSV file. This file is then to be used by the subsequent thread groups to allow them to use these already authenticated sessions.
To do this, I am basically following the solution outlined here: http://theworkaholic.blogspot.co.uk/2013/03/sharing-session-ids-across-threads.html.

The setUp thread group is authenticating and generating the CSV file as expected. However, I cannot get the requests in the subsequent thread groups to use the sessions provided. I can add the JSESSIONID cookie (either by using a BeanShell PreProcessor or using a HTTP Cookie Manager, both give the same results) but this does not seem to be recognised. The request being sent is the following:

POST https://test.mydomain.com:8443/prv/p/getUploadedfiles.action

POST data:
start=0&limit=10&sort=createdDate&dir=DESC&days=6

Cookie Data:
$Version=1; JSESSIONID="D0720DD3B06B5752DF6AC83A1B245EDA"; $Path="/";
$Domain="test.mydomain.com"

Request Headers:
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 49
Host: test.mydomain.com:8443
User-Agent: Apache-HttpClient/4.5.3 (Java/1.8.0_121)

This request has a return status of 302 to re-direct to the login page. This compares to the same request executed successfully in the setUp thread group:

POST https://test.mydomain.com:8443/prv/p/getUploadedfiles.action

POST data:
start=0&limit=10&sort=createdDate&dir=DESC&days=6

Cookie Data:
JSESSIONID=D0720DD3B06B5752DF6AC83A1B245EDA

Request Headers:
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 49
Host: test.mydomain.com:8443
User-Agent: Apache-HttpClient/4.5.3 (Java/1.8.0_121)

The only difference between the requests seem to be the $Version, $Path and $Domain explicitly set on the cookie data. [Interestingly, the 'Cookie Data' in the solution from the link above seems to be correct, by which I mean does not contain the $Version, $Path or $Domain in the request output]
BeanShell PreProcessor code is:

import org.apache.jmeter.protocol.http.control.CookieManager;
import org.apache.jmeter.protocol.http.control.Cookie;

Cookie cookie = new Cookie("JSESSIONID", vars.get("jsessionid"), "test.mydomain.com", "/", true, -1);
CookieManager manager = sampler.getCookieManager();
manager.add(cookie);
log.info("Cookie added: " + vars.get("jsessionid"));

Does anyone know why the JSESSIONID cookie is not being recognised?


问:
Overwrite initial filename
With a little bit of help in places, I have written the below code which works perfectly but I need to be able to overwrite the initial file name (the one which we are asked to select with GetOpenFilename) to include !DNU! so users know after they have selected it, not to select the same file again especially as the files they will use are all fairly similar. You can see I tried with the line underneath 'Rename original text file but it doesn't do anything! Any help with this will be greatly appreciated.</p>

```<code> Sub BACSConversion()

 Dim MyNewBook As String
 Dim MySaveFile As String
 Dim fileToOpen As Variant
 Dim fileName As String
 Dim sheetName As String
 Dim rCopy As Range

 'Turn off display alerts
  Application.DisplayAlerts = False
 'Turn off screen updates
  Application.ScreenUpdating = False

 'Ensures that the file open directory is always the same
   ChDir "S:\MERIT OUTPUTS FOLDER\MSI Recruitment Limited\"

 'Opens the folder to location to select txt file
  fileToOpen = Application.GetOpenFilename("Text Files (*.txt), *.txt")
    If fileToOpen <> False Then
    Workbooks.OpenText fileName:=fileToOpen, _
    DataType:=xlDelimited, Tab:=True
    End If
 'Creates the file name based on txt file name
  fileName = Mid(fileToOpen, InStrRev(fileToOpen, "\") + 1)
 'Creates the sheet name based on the active txt file
  sheetName = Left(ActiveWorkbook.Name, Len(ActiveWorkbook.Name) - 4)

 'Rename the original text file
  ActiveWorkbook.SaveAs ("S:\MERIT OUTPUTS FOLDER\MSI Recruitment
 Limited" & sheetName & "!DNU!" & ".txt")

 'Save active file as...
  ActiveWorkbook.SaveAs ("S:\MERIT OUTPUTS FOLDER\MSI Recruitment
 Limited\BACS File Original\" & _
   fileName & ".CSV"), FileFormat:=xlCSV

 'Selects all data in column A and copies to clipboard
  Set rCopy = Range("A1", Range("A1").End(xlDown))

 'Open the original document where the BACS file is located
  Workbooks.Open "S:\Accounts (New)\Management Information
 (Analysis)\Phil Hanmore - Analysis\bacs conversation calc.xlsx"
 'Selects the worksheet called "Original"
  Sheets("Original").Range("A:A").ClearContents

 'Paste selected values from previous sheet
 rCopy.Copy
 Sheets("Original").Range("A1").PasteSpecial Paste:=xlPasteValues

 'Selects appropriate worksheet - Non-MyPayFINAL
  Sheets("Non-MyPay FINAL").Select

 'Selects all data in column A and copies to clipboard
 Range("A1", Range("A1").End(xlDown)).Select
 Selection.Copy

  'Add a new workbook
   Workbooks.Add
 'Paste selected values from previous sheet
  Selection.PasteSpecial Paste:=xlPasteValues

  'Build SaveAs file name (for CSV file)
   MySaveFile = Format(Now(), "DDMMYYYY") & "NonMyPayFINAL" & ".CSV"
  'Save template file as...(for CSV file)
   ActiveWorkbook.SaveAs ("S:\MERIT OUTPUTS FOLDER\MSI Recruitment
   Limited\" & MySaveFile), FileFormat:=xlCSV

  'Build SaveAs file name (for Txt file)
   MySaveFile = Format(Now(), "DDMMYYYY") & "NonMyPayFINAL" & ".Txt"
  'Save template file as...(for Txt file)
   ActiveWorkbook.SaveAs ("S:\MERIT OUTPUTS FOLDER\MSI Recruitment
  Limited\" & MySaveFile), FileFormat:=xlTextWindows

  'Close the new saved file
   ActiveWorkbook.Close

 'Selects appropriate worksheet - MyPayFINAL
   Sheets("MyPay FINAL").Select

  'Selects all data in column A and copies to clipboard
   Range("A1", Range("A1").End(xlDown)).Select
   Selection.Copy

  'Add a new workbook
   Workbooks.Add
 'Paste selected values from previous sheet
   Selection.PasteSpecial Paste:=xlPasteValues

  'Build SaveAs file name (for CSV file)
   MySaveFile = Format(Now(), "DDMMYYYY") & "MyPayFINAL" & ".CSV"
  'Save template file as...(for CSV file)
    ActiveWorkbook.SaveAs ("S:\MERIT OUTPUTS FOLDER\MSI Recruitment
  Limited\"
  & MySaveFile), FileFormat:=xlCSV

'Build SaveAs file name (for Txt file)
  MySaveFile = Format(Now(), "DDMMYYYY") & "MyPayFINAL" & ".Txt"
 'Save template file as...(for Txt file)
  ActiveWorkbook.SaveAs ("S:\MERIT OUTPUTS FOLDER\MSI Recruitment
  Limited\" & MySaveFile), FileFormat:=xlTextWindows

 'Close the new saved file
  ActiveWorkbook.Close
 'Close original source workbook (template)
  Workbooks("bacs conversation calc").Close
 'Close final workbook
  ActiveWorkbook.Close savechanges:=True

  MsgBox "Your file has been processed successfully!", vbExclamation

 'Turn on display alerts
   Application.DisplayAlerts = True
 'Turn on screen updates
  Application.ScreenUpdating = True

  End Sub

  Sub FileNameChange()

  Dim oldPath As String
  Dim newPath As String

  oldPath = "S:\Accounts (New)\Management Information (Analysis)\Phil
  Hanmore - Analysis\Neil Test\" & Test & ".xlsx"
  newPath = "S:\Accounts (New)\Management Information (Analysis)\Phil
  Hanmore - Analysis\Neil Test\" & Test & "!DNU!.xlsx"

  End Sub
</code>```

答:
There is a built-in function in VBA called Name, it works as follows:

```<code>Name [old/current path/name] [new path/name]
</code>```

So for your code, you would want to do:

```<code>Name ("S:\MERIT OUTPUTS FOLDER\MSI Recruitment Limited\" & Filename) ("S:\MERIT OUTPUTS FOLDER\MSI Recruitment Limited\" & Filename & "!DNU!")
</code>```

I would recommend assigning variables to the paths, call them oldpath and newpath. So

```<code>Dim oldPath As String, newPath as String

oldPath = "S:\MERIT OUTPUTS FOLDER\MSI Recruitment Limited\" & sheetname & ".txt"
newPath = "S:\MERIT OUTPUTS FOLDER\MSI Recruitment Limited\" & sheetname & "!DNU!.txt"

Name oldPath newPath
</code>```

BUT, the file needs to be closed before you can do this.  So make sure the file is closed by looping through the open workbooks and closing them all.  Then by running this, it should rename the file from the old name to the new name.

I would recommend making a new workbook and placing it on your desktop and testing first before using it with your real code/workbooks.  Make a new workbook, save it to your desktop, call it test.xlsx and then close it.  In a separate workbook start a new Sub and paste the code in, but change the oldPath and newPath to reflect your desktop path and test.xlsx file.  Give this a shot.

Title: Overwrite initial filename

Body:
With a little bit of help in places, I have written the below code which works perfectly but I need to be able to overwrite the initial file name (the one which we are asked to select with GetOpenFilename) to include !DNU! so users know after they have selected it, not to select the same file again especially as the files they will use are all fairly similar. You can see I tried with the line underneath 'Rename original text file but it doesn't do anything! Any help with this will be greatly appreciated.

 Sub BACSConversion()

 Dim MyNewBook As String
 Dim MySaveFile As String
 Dim fileToOpen As Variant
 Dim fileName As String
 Dim sheetName As String
 Dim rCopy As Range

 'Turn off display alerts
  Application.DisplayAlerts = False
 'Turn off screen updates
  Application.ScreenUpdating = False

 'Ensures that the file open directory is always the same
   ChDir "S:\MERIT OUTPUTS FOLDER\MSI Recruitment Limited\"

 'Opens the folder to location to select txt file
  fileToOpen = Application.GetOpenFilename("Text Files (*.txt), *.txt")
    If fileToOpen <> False Then
    Workbooks.OpenText fileName:=fileToOpen, _
    DataType:=xlDelimited, Tab:=True
    End If
 'Creates the file name based on txt file name
  fileName = Mid(fileToOpen, InStrRev(fileToOpen, "\") + 1)
 'Creates the sheet name based on the active txt file
  sheetName = Left(ActiveWorkbook.Name, Len(ActiveWorkbook.Name) - 4)

 'Rename the original text file
  ActiveWorkbook.SaveAs ("S:\MERIT OUTPUTS FOLDER\MSI Recruitment
 Limited" & sheetName & "!DNU!" & ".txt")

 'Save active file as...
  ActiveWorkbook.SaveAs ("S:\MERIT OUTPUTS FOLDER\MSI Recruitment
 Limited\BACS File Original\" & _
   fileName & ".CSV"), FileFormat:=xlCSV

 'Selects all data in column A and copies to clipboard
  Set rCopy = Range("A1", Range("A1").End(xlDown))

 'Open the original document where the BACS file is located
  Workbooks.Open "S:\Accounts (New)\Management Information
 (Analysis)\Phil Hanmore - Analysis\bacs conversation calc.xlsx"
 'Selects the worksheet called "Original"
  Sheets("Original").Range("A:A").ClearContents

 'Paste selected values from previous sheet
 rCopy.Copy
 Sheets("Original").Range("A1").PasteSpecial Paste:=xlPasteValues

 'Selects appropriate worksheet - Non-MyPayFINAL
  Sheets("Non-MyPay FINAL").Select

 'Selects all data in column A and copies to clipboard
 Range("A1", Range("A1").End(xlDown)).Select
 Selection.Copy

  'Add a new workbook
   Workbooks.Add
 'Paste selected values from previous sheet
  Selection.PasteSpecial Paste:=xlPasteValues

  'Build SaveAs file name (for CSV file)
   MySaveFile = Format(Now(), "DDMMYYYY") & "NonMyPayFINAL" & ".CSV"
  'Save template file as...(for CSV file)
   ActiveWorkbook.SaveAs ("S:\MERIT OUTPUTS FOLDER\MSI Recruitment
   Limited\" & MySaveFile), FileFormat:=xlCSV

  'Build SaveAs file name (for Txt file)
   MySaveFile = Format(Now(), "DDMMYYYY") & "NonMyPayFINAL" & ".Txt"
  'Save template file as...(for Txt file)
   ActiveWorkbook.SaveAs ("S:\MERIT OUTPUTS FOLDER\MSI Recruitment
  Limited\" & MySaveFile), FileFormat:=xlTextWindows

  'Close the new saved file
   ActiveWorkbook.Close

 'Selects appropriate worksheet - MyPayFINAL
   Sheets("MyPay FINAL").Select

  'Selects all data in column A and copies to clipboard
   Range("A1", Range("A1").End(xlDown)).Select
   Selection.Copy

  'Add a new workbook
   Workbooks.Add
 'Paste selected values from previous sheet
   Selection.PasteSpecial Paste:=xlPasteValues

  'Build SaveAs file name (for CSV file)
   MySaveFile = Format(Now(), "DDMMYYYY") & "MyPayFINAL" & ".CSV"
  'Save template file as...(for CSV file)
    ActiveWorkbook.SaveAs ("S:\MERIT OUTPUTS FOLDER\MSI Recruitment
  Limited\"
  & MySaveFile), FileFormat:=xlCSV

'Build SaveAs file name (for Txt file)
  MySaveFile = Format(Now(), "DDMMYYYY") & "MyPayFINAL" & ".Txt"
 'Save template file as...(for Txt file)
  ActiveWorkbook.SaveAs ("S:\MERIT OUTPUTS FOLDER\MSI Recruitment
  Limited\" & MySaveFile), FileFormat:=xlTextWindows

 'Close the new saved file
  ActiveWorkbook.Close
 'Close original source workbook (template)
  Workbooks("bacs conversation calc").Close
 'Close final workbook
  ActiveWorkbook.Close savechanges:=True

  MsgBox "Your file has been processed successfully!", vbExclamation

 'Turn on display alerts
   Application.DisplayAlerts = True
 'Turn on screen updates
  Application.ScreenUpdating = True

  End Sub

  Sub FileNameChange()

  Dim oldPath As String
  Dim newPath As String

  oldPath = "S:\Accounts (New)\Management Information (Analysis)\Phil
  Hanmore - Analysis\Neil Test\" & Test & ".xlsx"
  newPath = "S:\Accounts (New)\Management Information (Analysis)\Phil
  Hanmore - Analysis\Neil Test\" & Test & "!DNU!.xlsx"

  End Sub

Body:
There is a built-in function in VBA called Name, it works as follows:

Name [old/current path/name] [new path/name]

So for your code, you would want to do:

Name ("S:\MERIT OUTPUTS FOLDER\MSI Recruitment Limited\" & Filename) ("S:\MERIT OUTPUTS FOLDER\MSI Recruitment Limited\" & Filename & "!DNU!")

I would recommend assigning variables to the paths, call them oldpath and newpath. So

Dim oldPath As String, newPath as String

oldPath = "S:\MERIT OUTPUTS FOLDER\MSI Recruitment Limited\" & sheetname & ".txt"
newPath = "S:\MERIT OUTPUTS FOLDER\MSI Recruitment Limited\" & sheetname & "!DNU!.txt"

Name oldPath newPath

BUT, the file needs to be closed before you can do this.  So make sure the file is closed by looping through the open workbooks and closing them all.  Then by running this, it should rename the file from the old name to the new name.

I would recommend making a new workbook and placing it on your desktop and testing first before using it with your real code/workbooks.  Make a new workbook, save it to your desktop, call it test.xlsx and then close it.  In a separate workbook start a new Sub and paste the code in, but change the oldPath and newPath to reflect your desktop path and test.xlsx file.  Give this a shot.


问:
Redirect on success and show error on failure
I have implemented a controller to create new users. When it creates the user successfully it redirects to Index().

What I want is to get redirected when all is OK, but stay in the current page and see the error when something failed.

I'm using jQuery ajax with MVC.

My controller looks like this:

```<code>[Authorize]
public ActionResult CreateUser(string username)
{
    try
    {
        //here the logic to create the user
    }
    catch (Exception ex)
    {
        string error = string.Format("Error creating user: {0}", ex.Message);
        Response.StatusCode = 500;
        Response.Write(error);
    }
    return RedirectToAction("Index");
}
</code>```

The form submit is intercepted with jQuery, and then the call is made with ajax:

```<code>$("#new-user-form").submit(function() {
    var form = $(this);
    $.ajax({
    type: "GET",
        url: form.attr('action'),
        data: form.serialize(),
        success: function(data, textStatus, xhr) {
            //At this point I would like to redirect
        },
        error: function(xhr, textStatus, errorThrown) {
            $(".error-summary").html(xhr.responseText);
        }
    });

    //cancel the event
    return false;
});
</code>```

It works fine when an error occurs, but I don't know how to implement the success case.

I'm opened to other alternatives.

答:
If you are going to redirect in the success action why are you using AJAX? The purpose of AJAX is to refresh only parts of a site without reloading the whole page. If in the success action you are going to redirect that totally defeats all the purpose and benefits you get from AJAX. But because you asked here's what you could do:

```<code>[Authorize]
public ActionResult CreateUser(string username)
{
    ...
    if (Request.IsAjaxRequest())
    {
        return Json(new { redirectToUrl = Url.Action("Index") });
    }
    return RedirectToAction("Index");
}
</code>```

And then:

```<code>success: function(data, textStatus, xhr) {
    window.location.href = data.redirectToUrl;
},
</code>```

Body:
I have implemented a controller to create new users. When it creates the user successfully it redirects to Index().

What I want is to get redirected when all is OK, but stay in the current page and see the error when something failed.

I'm using jQuery ajax with MVC.

My controller looks like this:

[Authorize]
public ActionResult CreateUser(string username)
{
    try
    {
        //here the logic to create the user
    }
    catch (Exception ex)
    {
        string error = string.Format("Error creating user: {0}", ex.Message);
        Response.StatusCode = 500;
        Response.Write(error);
    }
    return RedirectToAction("Index");
}

The form submit is intercepted with jQuery, and then the call is made with ajax:

$("#new-user-form").submit(function() {
    var form = $(this);
    $.ajax({
    type: "GET",
        url: form.attr('action'),
        data: form.serialize(),
        success: function(data, textStatus, xhr) {
            //At this point I would like to redirect
        },
        error: function(xhr, textStatus, errorThrown) {
            $(".error-summary").html(xhr.responseText);
        }
    });

    //cancel the event
    return false;
});

It works fine when an error occurs, but I don't know how to implement the success case.

I'm opened to other alternatives.

Body:
If you are going to redirect in the success action why are you using AJAX? The purpose of AJAX is to refresh only parts of a site without reloading the whole page. If in the success action you are going to redirect that totally defeats all the purpose and benefits you get from AJAX. But because you asked here's what you could do:

[Authorize]
public ActionResult CreateUser(string username)
{
    ...
    if (Request.IsAjaxRequest())
    {
        return Json(new { redirectToUrl = Url.Action("Index") });
    }
    return RedirectToAction("Index");
}

And then:

success: function(data, textStatus, xhr) {
    window.location.href = data.redirectToUrl;
},

ContentLicense: CC BY-SA 2.5


问:
plotly stacked bar chart with over 100 categories
I have a dataset that contains over 100 categories. If I am going to plot it, I have to write over 100 lines code for it. Here is the example from plotly official website:

```<code>library(plotly)
Animals <- c("giraffes", "orangutans", "monkeys")
SF_Zoo <- c(20, 14, 23)
LA_Zoo <- c(12, 18, 29)
data <- data.frame(Animals, SF_Zoo, LA_Zoo)
p <- plot_ly(data, x = ~Animals, y = ~SF_Zoo, type = 'bar', name = 'SF Zoo') %>%
add_trace(y = ~LA_Zoo, name = 'LA Zoo') %>%
layout(yaxis = list(title = 'Count'), barmode = 'stack')
</code>```

As you can see, if I have over 100 zoos that are going to be plotted, I need to write add_trace for over 100 times, which is inefficient. Does anyone know of ways to simplify it? I tried using for loop but I failed.

Or if anyone know how to use ggplotly to transfer a ggplot to an interactive format, it will also solve my problem. The plot produced by ggplot is a stacked grouped bar chart which x-axis have 10 facet_grid and about 100 categories in each grid. I tried using ggplotly directly and save it as an .html, however the plot's scale is very weird. It should looks like a rectangular with width about 40 and height about 8, but in html, it just shows like a square which is unreadable.

答:
You can melt the data and then plot them like below:

```<code>library(data.table)
library(plotly)

data.table::melt(data, id.vars='Animals') %>%
plot_ly(x = ~Animals, y = ~value, type = 'bar',
                name = ~variable, color = ~variable) %>%
      layout(yaxis = list(title = 'Count'), barmode = 'stack')
</code>```

This will plot:

ContentLicense: CC BY-SA 4.0

Body:
I have a dataset that contains over 100 categories. If I am going to plot it, I have to write over 100 lines code for it. Here is the example from plotly official website:

library(plotly)
Animals <- c("giraffes", "orangutans", "monkeys")
SF_Zoo <- c(20, 14, 23)
LA_Zoo <- c(12, 18, 29)
data <- data.frame(Animals, SF_Zoo, LA_Zoo)
p <- plot_ly(data, x = ~Animals, y = ~SF_Zoo, type = 'bar', name = 'SF Zoo') %>%
add_trace(y = ~LA_Zoo, name = 'LA Zoo') %>%
layout(yaxis = list(title = 'Count'), barmode = 'stack')

As you can see, if I have over 100 zoos that are going to be plotted, I need to write add_trace for over 100 times, which is inefficient. Does anyone know of ways to simplify it? I tried using for loop but I failed.

Or if anyone know how to use ggplotly to transfer a ggplot to an interactive format, it will also solve my problem. The plot produced by ggplot is a stacked grouped bar chart which x-axis have 10 facet_grid and about 100 categories in each grid. I tried using ggplotly directly and save it as an .html, however the plot's scale is very weird. It should looks like a rectangular with width about 40 and height about 8, but in html, it just shows like a square which is unreadable.

Body:
You can melt the data and then plot them like below:

library(data.table)
library(plotly)

data.table::melt(data, id.vars='Animals') %>%
plot_ly(x = ~Animals, y = ~value, type = 'bar',
                name = ~variable, color = ~variable) %>%
      layout(yaxis = list(title = 'Count'), barmode = 'stack')

This will plot:


问:
java jpanel how to optimise painting
I am trying to implement langton's ant , and i did it well :
langton's ant java simulation screen

for painting in my jPanel, i override the paintComponent at each step but it take so much time for painting every black or white rectangle , i just want that at each step i only paint the two rectangle who have changed!?
So my question is, how to only paint a rectangle without changing what was painted in previous frame?

here is my code for painting

```<code>public void paintComponent(Graphics g){
        g.setColor(Color.white);
        g.fillRect(0,0,getWidth(),getHeight());
        g.setColor(Color.black);
        int careLargeur = getWidth() / m;
        int careHauteur = getHeight() / n;
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++){
                if(map[i][j])
                    g.fillRect(j*careLargeur,i*careHauteur,careLargeur,careHauteur);
            }
        //draw fourmi
        g.setColor(Color.red);
        g.fillOval(jF*careLargeur, iF*careHauteur, careLargeur, careHauteur);
    }
</code>```

any help? or should i give more details ?
here is the jar :

答:
Paint your rectangles to a BufferedImage, and then draw that BufferedImage within your paintComponent method. You could also limit how much is re-drawn by using one of the repaint(...) overrides that specifies the exact rectangular region to repaint.

So your paintComponent method could be as simple as this:

```<code>@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    if (img != null) {
        g.drawImage(img, 0, 0, this);
    }
    g.setColor(Color.red);
    g.fillOval(jF*careLargeur, iF*careHauteur, careLargeur, careHauteur);
}
</code>```

With drawing changes being made to the img BufferedImage.

Assuming that you're using a Swing Timer to drive the state changes to your model, you could

change the model, and then

update the BufferedImage based on the model changes, and

call repaint(...) on only the updated region.

Incomplete code attempt.... not yet done!

```<code>import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.*;
import javax.swing.event.SwingPropertyChangeSupport;

/**
 * https://en.wikipedia.org/wiki/Langton%27s_ant
 * https://stackoverflow.com/a/44930371/522444
 * @author Pete
 *
 */
public class LangtonsAnt {

    private static final int TIMER_DELAY = 30;

    private static void createAndShowGui() {
        Model model = new Model(800);
        View view = new View(800);
        Controller controller = new Controller(model, view);

        JFrame frame = new JFrame("Langtons Ant");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(view);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

        controller.startTimer(TIMER_DELAY);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }

    private static class Model {
        public static final String POINT = "point";
        private SwingPropertyChangeSupport support = new SwingPropertyChangeSupport(this);
        private int gridSize;
        private boolean[][] grid; // false is white. Better to use enums
        private Point oldValue;
        private Point point; // ant location

        public Model(int gridSize) {
            this.gridSize = gridSize;
            grid = new boolean[gridSize][gridSize];
            int x = gridSize / 2;
            int y = gridSize / 2;
            setPoint(new Point(x, y));
        }

        public void setPoint(Point point) {
            this.oldValue = this.point;
            Point newValue = point;
            this.point = point;
            support.firePropertyChange(POINT, oldValue, newValue);
        }

        public Point getPoint() {
            return point;
        }

        public boolean[][] getGrid() {
            return grid;
        }

        public int getGridSize() {
            return gridSize;
        }

        public void step() {
            // first will hold relative new positions
            int newX = 0;
            int newY = 0;
            boolean gridPoint = getGridPoint(point);
            if (oldValue == null) {
                newX = point.x;
                newY = point.y - 1;
            } else {
                int dX = point.x - oldValue.x;
                int dY = point.y - oldValue.y;
                if (dX != 0) {
                    // from left or right
                    newY = dX > 0 ? 1 : -1;  // assume "white" or false
                    newY = gridPoint ? -newY : newY;  // if "black" then reverse
                } else {
                    // from up or down
                    newX = dY > 0 ? -1 : 1; // assume "white" or false
                    newX = gridPoint ? -newX : newX; // if "black" then reverse
                }

                // convert from relative to absolute new positions
                newX = point.x + newX;
                newY = point.y + newY;
            }
            setGridPoint(point, !gridPoint);
            setPoint(new Point(newX, newY));
        }

        public boolean getGridPoint(int x, int y) {
            return grid[x][y];
        }

        public boolean getGridPoint(Point p) {
            return getGridPoint(p.x, p.y);
        }

        public void setGridPoint(int x, int y, boolean b) {
            grid[x][y] = b;
        }

        public void setGridPoint(Point p, boolean b) {
            setGridPoint(p.x, p.y, b);
        }

        public void addPropertyChangeListener(String propertyName, PropertyChangeListener l) {
            support.addPropertyChangeListener(propertyName, l);
        }
    }

    private static class Controller {

        private Model model;
        private View view;
        private Timer timer;

        public Controller(Model model, View view) {
            this.model = model;
            this.view = view;
            view.setAntImg(createAntImg());
            model.addPropertyChangeListener(Model.POINT, new ModelListener());
        }

        private BufferedImage createAntImg() {
            // trivial image for now
            BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
            Graphics g = img.getGraphics();
            g.setColor(Color.RED);
            g.fillRect(0, 0, 1, 1);
            g.dispose();
            return img;
        }

        public void startTimer(int delay) {
            timer = new Timer(delay, new TimerListener());
        }

        private class TimerListener implements ActionListener {
            @Override
            public void actionPerformed(ActionEvent e) {
                model.step();
            }
        }

        private class ModelListener implements PropertyChangeListener {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                // TODO Finish this.
                // get the new point and old point
                // translate model coord to view coord
                // Change the state of the view's buffered image
                // repaint the limited region that was changed

            }
        }

    }

    private static class View extends JPanel {
        private static final Color BACKGROUND = Color.WHITE;
        private BufferedImage gridImg;
        private BufferedImage antImg;
        private Point guiAntLocation;
        private int pixelWidth;

        public View(int pixelWidth) {
            this.pixelWidth = pixelWidth;
            gridImg = new BufferedImage(pixelWidth, pixelWidth, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2 = gridImg.createGraphics();
            g2.setColor(BACKGROUND);
            g2.fillRect(0, 0, pixelWidth, pixelWidth);
            g2.dispose();
        }

        public int getPixelWidth() {
            return pixelWidth;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (getGridImg() != null) {
                g.drawImage(getGridImg(), 0, 0, this);
            }
            if (guiAntLocation != null && antImg != null) {
                int x = guiAntLocation.x;
                int y = guiAntLocation.y;
                g.drawImage(antImg, x, y, this);
            }
        }

        public void setGuiAntLocation(Point guiAntLocation) {
            this.guiAntLocation = guiAntLocation;
        }

        public Point getGuiAntLocation() {
            return guiAntLocation;
        }

        @Override
        public Dimension getPreferredSize() {
            if (isPreferredSizeSet() || getGridImg() == null) {
                return super.getPreferredSize();
            }
            return new Dimension(getGridImg().getWidth(), getGridImg().getHeight());
        }

        public BufferedImage getGridImg() {
            return gridImg;
        }

        public void setGridImg(BufferedImage gridImg) {
            this.gridImg = gridImg;
        }

        public void setAntImg(BufferedImage antImg) {
            this.antImg = antImg;
        }
    }
}
</code>```

Title: java jpanel how to optimise painting

Body:
I am trying to implement langton's ant , and i did it well :
langton's ant java simulation screen

for painting in my jPanel, i override the paintComponent at each step but it take so much time for painting every black or white rectangle , i just want that at each step i only paint the two rectangle who have changed!?
So my question is, how to only paint a rectangle without changing what was painted in previous frame?

here is my code for painting

public void paintComponent(Graphics g){
        g.setColor(Color.white);
        g.fillRect(0,0,getWidth(),getHeight());
        g.setColor(Color.black);
        int careLargeur = getWidth() / m;
        int careHauteur = getHeight() / n;
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++){
                if(map[i][j])
                    g.fillRect(j*careLargeur,i*careHauteur,careLargeur,careHauteur);
            }
        //draw fourmi
        g.setColor(Color.red);
        g.fillOval(jF*careLargeur, iF*careHauteur, careLargeur, careHauteur);
    }

any help? or should i give more details ?
here is the jar :

Body:
Paint your rectangles to a BufferedImage, and then draw that BufferedImage within your paintComponent method. You could also limit how much is re-drawn by using one of the repaint(...) overrides that specifies the exact rectangular region to repaint.

So your paintComponent method could be as simple as this:

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    if (img != null) {
        g.drawImage(img, 0, 0, this);
    }
    g.setColor(Color.red);
    g.fillOval(jF*careLargeur, iF*careHauteur, careLargeur, careHauteur);
}

With drawing changes being made to the img BufferedImage.

Assuming that you're using a Swing Timer to drive the state changes to your model, you could

change the model, and then

update the BufferedImage based on the model changes, and

call repaint(...) on only the updated region.

Incomplete code attempt.... not yet done!

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.*;
import javax.swing.event.SwingPropertyChangeSupport;

/**
 * https://en.wikipedia.org/wiki/Langton%27s_ant
 * https://stackoverflow.com/a/44930371/522444
 * @author Pete
 *
 */
public class LangtonsAnt {

    private static final int TIMER_DELAY = 30;

    private static void createAndShowGui() {
        Model model = new Model(800);
        View view = new View(800);
        Controller controller = new Controller(model, view);

        JFrame frame = new JFrame("Langtons Ant");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(view);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

        controller.startTimer(TIMER_DELAY);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }

    private static class Model {
        public static final String POINT = "point";
        private SwingPropertyChangeSupport support = new SwingPropertyChangeSupport(this);
        private int gridSize;
        private boolean[][] grid; // false is white. Better to use enums
        private Point oldValue;
        private Point point; // ant location

        public Model(int gridSize) {
            this.gridSize = gridSize;
            grid = new boolean[gridSize][gridSize];
            int x = gridSize / 2;
            int y = gridSize / 2;
            setPoint(new Point(x, y));
        }

        public void setPoint(Point point) {
            this.oldValue = this.point;
            Point newValue = point;
            this.point = point;
            support.firePropertyChange(POINT, oldValue, newValue);
        }

        public Point getPoint() {
            return point;
        }

        public boolean[][] getGrid() {
            return grid;
        }

        public int getGridSize() {
            return gridSize;
        }

        public void step() {
            // first will hold relative new positions
            int newX = 0;
            int newY = 0;
            boolean gridPoint = getGridPoint(point);
            if (oldValue == null) {
                newX = point.x;
                newY = point.y - 1;
            } else {
                int dX = point.x - oldValue.x;
                int dY = point.y - oldValue.y;
                if (dX != 0) {
                    // from left or right
                    newY = dX > 0 ? 1 : -1;  // assume "white" or false
                    newY = gridPoint ? -newY : newY;  // if "black" then reverse
                } else {
                    // from up or down
                    newX = dY > 0 ? -1 : 1; // assume "white" or false
                    newX = gridPoint ? -newX : newX; // if "black" then reverse
                }

                // convert from relative to absolute new positions
                newX = point.x + newX;
                newY = point.y + newY;
            }
            setGridPoint(point, !gridPoint);
            setPoint(new Point(newX, newY));
        }

        public boolean getGridPoint(int x, int y) {
            return grid[x][y];
        }

        public boolean getGridPoint(Point p) {
            return getGridPoint(p.x, p.y);
        }

        public void setGridPoint(int x, int y, boolean b) {
            grid[x][y] = b;
        }

        public void setGridPoint(Point p, boolean b) {
            setGridPoint(p.x, p.y, b);
        }

        public void addPropertyChangeListener(String propertyName, PropertyChangeListener l) {
            support.addPropertyChangeListener(propertyName, l);
        }
    }

    private static class Controller {

        private Model model;
        private View view;
        private Timer timer;

        public Controller(Model model, View view) {
            this.model = model;
            this.view = view;
            view.setAntImg(createAntImg());
            model.addPropertyChangeListener(Model.POINT, new ModelListener());
        }

        private BufferedImage createAntImg() {
            // trivial image for now
            BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
            Graphics g = img.getGraphics();
            g.setColor(Color.RED);
            g.fillRect(0, 0, 1, 1);
            g.dispose();
            return img;
        }

        public void startTimer(int delay) {
            timer = new Timer(delay, new TimerListener());
        }

        private class TimerListener implements ActionListener {
            @Override
            public void actionPerformed(ActionEvent e) {
                model.step();
            }
        }

        private class ModelListener implements PropertyChangeListener {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                // TODO Finish this.
                // get the new point and old point
                // translate model coord to view coord
                // Change the state of the view's buffered image
                // repaint the limited region that was changed

            }
        }

    }

    private static class View extends JPanel {
        private static final Color BACKGROUND = Color.WHITE;
        private BufferedImage gridImg;
        private BufferedImage antImg;
        private Point guiAntLocation;
        private int pixelWidth;

        public View(int pixelWidth) {
            this.pixelWidth = pixelWidth;
            gridImg = new BufferedImage(pixelWidth, pixelWidth, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2 = gridImg.createGraphics();
            g2.setColor(BACKGROUND);
            g2.fillRect(0, 0, pixelWidth, pixelWidth);
            g2.dispose();
        }

        public int getPixelWidth() {
            return pixelWidth;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (getGridImg() != null) {
                g.drawImage(getGridImg(), 0, 0, this);
            }
            if (guiAntLocation != null && antImg != null) {
                int x = guiAntLocation.x;
                int y = guiAntLocation.y;
                g.drawImage(antImg, x, y, this);
            }
        }

        public void setGuiAntLocation(Point guiAntLocation) {
            this.guiAntLocation = guiAntLocation;
        }

        public Point getGuiAntLocation() {
            return guiAntLocation;
        }

        @Override
        public Dimension getPreferredSize() {
            if (isPreferredSizeSet() || getGridImg() == null) {
                return super.getPreferredSize();
            }
            return new Dimension(getGridImg().getWidth(), getGridImg().getHeight());
        }

        public BufferedImage getGridImg() {
            return gridImg;
        }

        public void setGridImg(BufferedImage gridImg) {
            this.gridImg = gridImg;
        }

        public void setAntImg(BufferedImage antImg) {
            this.antImg = antImg;
        }
    }
}


问:
React dynamic forms that are nested
I'm soooo close to getting this to work but just can't seem to wrap my head around this.

I have a form that's supposed to submit to a json file with the following structure:

```<code>    {
      title: '',
      content: [
        {className: '', body: ''}
      ]
    }
</code>```

I'm able to set the state for the title no problem, as well as the first object in the content array. I think I need to create a loop or something? Below is my full component.

```<code>import React, { Component } from 'react';

class AddEditPage extends Component {
  constructor(props) {
    super(props)
    this.state = {
      title: '',
      content: [
        {className: '', body: ''}
      ]
    }
    this.addInput = this.addInput.bind(this);
    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
    this.handleNestedChange = this.handleNestedChange.bind(this);
  }

  handleChange(e) {
    const value = e.target.value
    this.setState({
      [e.target.name]: value
    })
  }

  handleNestedChange(e) {
    const value = e.target.value
    console.log(e.target.id)
    this.setState({

    })

  }

  handleSubmit(e) {
    e.preventDefault();
    console.log(this.state)
  }

  addInput() {
    const newInput = { className: '', body: ''}
    this.setState({content: this.state.content.concat(newInput)});
  }

  render() {
    const contentInputs = this.state.content.map((content, i)=> {
     return (
        <div key={i}>
          <input
            type="text"
            name="className"
            id={`${i}`}
            placeholder="Class name"
            onChange={this.handleNestedChange}
          />
          <input
            type="text"
            name="body"
            placeholder="Body"
            id={`${i}`}
            onChange={this.handleNestedChange}
          />
        </div>
      )
    })

    return (
      <div>
        <h2>New Page</h2>
        <form onSubmit={this.handleSubmit}>
            <input
            type="text"
            name="title"
            placeholder={this.state.title || `Enter the title`}
            onChange={this.handleChange}
            />
          <h3>Content</h3>
            {contentInputs}
            <button onClick={this.addInput}>Add</button>
          <input type="submit" />
        </form>
      </div>
    );
  }
}

export default AddEditPage;
</code>```

 & praise for the answer haha

答:
Although it's not a very robust solution, assuming the input 'name' attributes always match exactly to the object keys in your state, you can do this:

```<code>handleNestedChange(e) {
    const newStateContent = this.state.content;
    newStateContent[e.target.id][e.target.name] = e.target.value;
    this.setState({
      content: newStateContent
    });
}
</code>```

Title: React dynamic forms that are nested

Body:
I'm soooo close to getting this to work but just can't seem to wrap my head around this.

I have a form that's supposed to submit to a json file with the following structure:

    {
      title: '',
      content: [
        {className: '', body: ''}
      ]
    }

I'm able to set the state for the title no problem, as well as the first object in the content array. I think I need to create a loop or something? Below is my full component.

import React, { Component } from 'react';

class AddEditPage extends Component {
  constructor(props) {
    super(props)
    this.state = {
      title: '',
      content: [
        {className: '', body: ''}
      ]
    }
    this.addInput = this.addInput.bind(this);
    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
    this.handleNestedChange = this.handleNestedChange.bind(this);
  }

  handleChange(e) {
    const value = e.target.value
    this.setState({
      [e.target.name]: value
    })
  }

  handleNestedChange(e) {
    const value = e.target.value
    console.log(e.target.id)
    this.setState({

    })

  }

  handleSubmit(e) {
    e.preventDefault();
    console.log(this.state)
  }

  addInput() {
    const newInput = { className: '', body: ''}
    this.setState({content: this.state.content.concat(newInput)});
  }

  render() {
    const contentInputs = this.state.content.map((content, i)=> {
     return (

          <input
            type="text"
            name="className"
            id={`${i}`}
            placeholder="Class name"
            onChange={this.handleNestedChange}
          />
          <input
            type="text"
            name="body"
            placeholder="Body"
            id={`${i}`}
            onChange={this.handleNestedChange}
          />

      )
    })

    return (

New Page

        <form onSubmit={this.handleSubmit}>
            <input
            type="text"
            name="title"
            placeholder={this.state.title || `Enter the title`}
            onChange={this.handleChange}
            />

Content

            {contentInputs}
            <button onClick={this.addInput}>Add</button>
          <input type="submit" />
        </form>

    );
  }
}

export default AddEditPage;

 & praise for the answer haha

Body:
Although it's not a very robust solution, assuming the input 'name' attributes always match exactly to the object keys in your state, you can do this:

handleNestedChange(e) {
    const newStateContent = this.state.content;
    newStateContent[e.target.id][e.target.name] = e.target.value;
    this.setState({
      content: newStateContent
    });
}


问:
Wireshark installed but not working on Amazon linux
I have installed the wireshark on amazon linux through the following command:

```<code>sudo yum install wireshark
</code>```

The following commands gives me this output:

```<code>Package wireshark-1.8.10-25.22.amzn1.x86_64 already installed and latest version
</code>```

But when i try to run wireshark command it gives the following error:

```<code>bash: wireshark: command not found
</code>```

Am i missing something. Please note that i have access as root user. Any help is appreciated.

答:
The wireshark command does not work. I resolved the issue by using the command below:

```<code>tshark -i eth0 -f "udp port 8080" -w captureFile.pcap
</code>```

The following command captures the packets on eth0(interface name) with the filter on udp port number 8080 and then saves it to the file captureFile.pcap

Body:
I have installed the wireshark on amazon linux through the following command:

sudo yum install wireshark

The following commands gives me this output:

Package wireshark-1.8.10-25.22.amzn1.x86_64 already installed and latest version

But when i try to run wireshark command it gives the following error:

bash: wireshark: command not found

Am i missing something. Please note that i have access as root user. Any help is appreciated.

Body:
The wireshark command does not work. I resolved the issue by using the command below:

tshark -i eth0 -f "udp port 8080" -w captureFile.pcap

The following command captures the packets on eth0(interface name) with the filter on udp port number 8080 and then saves it to the file captureFile.pcap


问:
How to allow protractor test to register custom protocol handler in chrome
When I register a custom protocol handler by executing script with browser.executeScript(navigator.registerProtocolHandler(protocol, url, title)); a little icon appears in the address bar that has to be clicked and I have to choose option "allow" (ignore is by default);
but how to do that with protractor ?
I know that chrome options can be set through chromeOptions object in conf file

```<code>capabilities: {
  'browserName': 'chrome',
  'chromeOptions': {
    'args': ['']
  }
}
</code>```

but which option from this list is suitable for my problem
https://peter.sh/experiments/chromium-command-line-switches/

or maybe there is other solution?

答:
I think I figured it out; try this:

```<code>capabilities: {
    'browserName' : 'chrome',
    'chromeOptions' : {
        args: [],
        prefs : {
            custom_handlers : {
                'enabled' : true,
                'registered_protocol_handlers' : [
                    {
                        'default' : true,
                        'protocol' : '',
                        'title' : '',
                        'url' : ''
                    }
                ]
            }
        }
    }
}
</code>```

Obviously fill in the protocol, url and title as applicable.

Body:
When I register a custom protocol handler by executing script with browser.executeScript(navigator.registerProtocolHandler(protocol, url, title)); a little icon appears in the address bar that has to be clicked and I have to choose option "allow" (ignore is by default);
but how to do that with protractor ?
I know that chrome options can be set through chromeOptions object in conf file

capabilities: {
  'browserName': 'chrome',
  'chromeOptions': {
    'args': ['']
  }
}

but which option from this list is suitable for my problem
https://peter.sh/experiments/chromium-command-line-switches/

or maybe there is other solution?

Body:
I think I figured it out; try this:

capabilities: {
    'browserName' : 'chrome',
    'chromeOptions' : {
        args: [],
        prefs : {
            custom_handlers : {
                'enabled' : true,
                'registered_protocol_handlers' : [
                    {
                        'default' : true,
                        'protocol' : '',
                        'title' : '',
                        'url' : ''
                    }
                ]
            }
        }
    }
}

Obviously fill in the protocol, url and title as applicable.


问:
How to Make an edge between two nodes of two different graphs in DSE?
I am using Datastack(DSE) i'm not able to find out how to make an Edge between two nodes of two different graphs(notebook)</p>

答:
It is not possible to create edges between two different graphs. Chances are, if you want to do that then you don't actually have 2 graphs.

You can use the same graph from multiple notebooks, if that helps.


问:
Parsing and storing xml into MSSQL database table
I am parsing xml and creating Java object out of it.
Now, how can i serialize that object and store it into a database

I am parsing xml object as follows

```<code>    outputStr = IOUtils.toString(xmlfile.getInputStream(),"UTF-8");
    Report = XMLUtil.toObject(outputStr, Customer.class);
</code>```

I want to store Report object into database

答:
There is no magical way of mapping an arbitrary java object into an SQL database. If there was, the inventor would be a millionaire. This is because java objects can be flat, trees, acyclic directed graphs, or graphs while SQL databases have an entirely different structure altogether.

If you want to put your object onto a MSSQL database you will either have to use an ORM such as hibernate (easier, but less control) or write your own serialization logic (requires knowledge of SQL, but more control).

Alternatively, if your business requirements are flexible, you could use a persistence layer that is better suited to object hierarchies. Popular examples include document databases such as MongoDB or CouchDB. You could even serialize to a file format such as JSON and store it on the filesystem. Whether that is a good idea or not depends on your specific problem.

Body:
I am parsing xml and creating Java object out of it.
Now, how can i serialize that object and store it into a database

I am parsing xml object as follows

    outputStr = IOUtils.toString(xmlfile.getInputStream(),"UTF-8");
    Report = XMLUtil.toObject(outputStr, Customer.class);

I want to store Report object into database


问:
How to set busybox vi auto wrap when a line too long?
I use command line in docker,the os is alpine linux, when use vi command,if a line is too long,it can't auto wrap, so the end of the line cannot be displayed.

I tried several settings, such as: set columns=,set wrap,stty columns... all settings are not in effect.

Does anyone know how to set it up? Thanks a lot.

答:
busyBox is not support Wrapping line .

see: https://en.wikibooks.org/wiki/Learning_the_vi_Editor/BusyBox_vi
"No wrapping of long lines. Long lines are displayed via side-scrolling."