text:
package org.apache.helix.integration;

import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.CountDownLatch;

import org.apache.helix.Criteria;
import org.apache.helix.HelixDataAccessor;
import org.apache.helix.HelixManager;
import org.apache.helix.InstanceType;
import org.apache.helix.NotificationContext;
import org.apache.helix.PropertyKey;
import org.apache.helix.PropertyKey.Builder;
import org.apache.helix.PropertyType;
import org.apache.helix.ZNRecord;
import org.apache.helix.manager.zk.DefaultSchedulerMessageHandlerFactory;
import org.apache.helix.messaging.AsyncCallback;
import org.apache.helix.messaging.handling.HelixTaskResult;
import org.apache.helix.messaging.handling.MessageHandler;
import org.apache.helix.messaging.handling.MessageHandlerFactory;
import org.apache.helix.model.ClusterConstraints.ConstraintType;
import org.apache.helix.model.ConstraintItem;
import org.apache.helix.model.Message;
import org.apache.helix.model.Message.MessageState;
import org.apache.helix.model.Message.MessageType;
import org.apache.helix.model.StatusUpdate;
import org.apache.helix.monitoring.ZKPathDataDumpTask;
import org.apache.helix.util.HelixUtil;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.testng.Assert;
import org.testng.annotations.Test;

public class TestSchedulerMessage extends ZkStandAloneCMTestBaseWithPropertyServerCheck {

  class MockAsyncCallback extends AsyncCallback {
    Message _message;

    public MockAsyncCallback() {
    }

    @Override
    public void onTimeOut() {
      // TODO Auto-generated method stub

    }

    @Override
    public void onReplyMessage(Message message) {
      _message = message;
    }
  }

  TestMessagingHandlerFactory _factory = new TestMessagingHandlerFactory();

  public static class TestMessagingHandlerFactory implements MessageHandlerFactory {
    public Map<String, Set<String>> _results = new ConcurrentHashMap<String, Set<String>>();

    @Override
    public MessageHandler createHandler(Message message, NotificationContext context) {
      return new TestMessagingHandler(message, context);
    }

    @Override
    public String getMessageType() {
      return "TestParticipant";
    }

    @Override
    public void reset() {
      // TODO Auto-generated method stub

    }

    public class TestMessagingHandler extends MessageHandler {
      public TestMessagingHandler(Message message, NotificationContext context) {
        super(message, context);
        // TODO Auto-generated constructor stub
      }

      @Override
      public HelixTaskResult handleMessage() throws InterruptedException {
        HelixTaskResult result = new HelixTaskResult();
        result.setSuccess(true);
        String destName = _message.getTgtName();
        result.getTaskResultMap().put("Message", _message.getMsgId());
        synchronized (_results) {
          if (!_results.containsKey(_message.getPartitionName())) {
            _results.put(_message.getPartitionName(), new ConcurrentSkipListSet<String>());
          }
        }
        _results.get(_message.getPartitionName()).add(_message.getMsgId());
        // System.err.println("Message " + _message.getMsgId() + " executed");
        return result;
      }

      @Override
      public void onError(Exception e, ErrorCode code, ErrorType type) {
        // TODO Auto-generated method stub
      }
    }
  }

  public static class TestMessagingHandlerFactoryLatch implements MessageHandlerFactory {
    public volatile CountDownLatch _latch = new CountDownLatch(1);
    public int _messageCount = 0;
    public Map<String, Set<String>> _results = new ConcurrentHashMap<String, Set<String>>();

    @Override
    public synchronized MessageHandler createHandler(Message message, NotificationContext context) {
      _messageCount++;
      return new TestMessagingHandlerLatch(message, context);
    }

    public synchronized void signal() {
      _latch.countDown();
      _latch = new CountDownLatch(1);
    }

    @Override
    public String getMessageType() {
      return "TestMessagingHandlerLatch";
    }

    @Override
    public void reset() {
      // TODO Auto-generated method stub
    }

    public class TestMessagingHandlerLatch extends MessageHandler {
      public TestMessagingHandlerLatch(Message message, NotificationContext context) {
        super(message, context);
        // TODO Auto-generated constructor stub
      }

      @Override
      public HelixTaskResult handleMessage() throws InterruptedException {
        _latch.await();
        HelixTaskResult result = new HelixTaskResult();
        result.setSuccess(true);
        result.getTaskResultMap().put("Message", _message.getMsgId());
        String destName = _message.getTgtName();
        synchronized (_results) {
          if (!_results.containsKey(_message.getPartitionName())) {
            _results.put(_message.getPartitionName(), new ConcurrentSkipListSet<String>());
          }
        }
        _results.get(_message.getPartitionName()).add(destName);
        // System.err.println("Message " + _message.getMsgId() + " executed");
        return result;
      }

      @Override
      public void onError(Exception e, ErrorCode code, ErrorType type) {
        // TODO Auto-generated method stub
      }
    }
  }

  @Test()
  public void TestSchedulerMsgUsingQueue() throws Exception {
    Logger.getRootLogger().setLevel(Level.INFO);
    _factory._results.clear();
    Thread.sleep(2000);
    HelixManager manager = null;
    for (int i = 0; i < NODE_NR; i++) {
      _participants[i].getMessagingService().registerMessageHandlerFactory(
          _factory.getMessageType(), _factory);

      manager = _participants[i]; // _startCMResultMap.get(hostDest)._manager;
    }

    Message schedulerMessage =
        new Message(MessageType.SCHEDULER_MSG + "", UUID.randomUUID().toString());
    schedulerMessage.setTgtSessionId("*");
    schedulerMessage.setTgtName("CONTROLLER");
    // TODO: change it to "ADMIN" ?
    schedulerMessage.setSrcName("CONTROLLER");
    schedulerMessage.getRecord().setSimpleField(
        DefaultSchedulerMessageHandlerFactory.SCHEDULER_TASK_QUEUE, "TestSchedulerMsg");
    // Template for the individual message sent to each participant
    Message msg = new Message(_factory.getMessageType(), "Template");
    msg.setTgtSessionId("*");
    msg.setMsgState(MessageState.NEW);

    // Criteria to send individual messages
    Criteria cr = new Criteria();
    cr.setInstanceName("localhost_%");
    cr.setRecipientInstanceType(InstanceType.PARTICIPANT);
    cr.setSessionSpecific(false);
    cr.setResource("%");
    cr.setPartition("%");

    ObjectMapper mapper = new ObjectMapper();
    SerializationConfig serializationConfig = mapper.getSerializationConfig();
    serializationConfig.set(SerializationConfig.Feature.INDENT_OUTPUT, true);

    StringWriter sw = new StringWriter();
    mapper.writeValue(sw, cr);

    String crString = sw.toString();

    schedulerMessage.getRecord().setSimpleField("Criteria", crString);
    schedulerMessage.getRecord().setMapField("MessageTemplate", msg.getRecord().getSimpleFields());
    schedulerMessage.getRecord().setSimpleField("TIMEOUT", "-1");

    HelixDataAccessor helixDataAccessor = manager.getHelixDataAccessor();
    Builder keyBuilder = helixDataAccessor.keyBuilder();
    helixDataAccessor.createProperty(keyBuilder.controllerMessage(schedulerMessage.getMsgId()),
        schedulerMessage);

    for (int i = 0; i < 30; i++) {
      Thread.sleep(2000);
      if (_PARTITIONS == _factory._results.size()) {
        break;
      }
    }

    Assert.assertEquals(_PARTITIONS, _factory._results.size());
    PropertyKey controllerTaskStatus =
        keyBuilder.controllerTaskStatus(MessageType.SCHEDULER_MSG.toString(),
            schedulerMessage.getMsgId());

    int messageResultCount = 0;
    for (int i = 0; i < 10; i++) {
      ZNRecord statusUpdate = helixDataAccessor.getProperty(controllerTaskStatus).getRecord();
      Assert.assertTrue(statusUpdate.getMapField("SentMessageCount").get("MessageCount")
          .equals("" + (_PARTITIONS * 3)));
      for (String key : statusUpdate.getMapFields().keySet()) {
        if (key.startsWith("MessageResult ")) {
          messageResultCount++;
        }
      }
      if (messageResultCount == _PARTITIONS * 3) {
        break;
      } else {
        Thread.sleep(2000);
      }
    }
    Assert.assertEquals(messageResultCount, _PARTITIONS * 3);
    int count = 0;
    for (Set<String> val : _factory._results.values()) {
      count += val.size();
    }
    Assert.assertEquals(count, _PARTITIONS * 3);

  }

  @Test()
  public void TestSchedulerMsg() throws Exception {
    Logger.getRootLogger().setLevel(Level.INFO);
    _factory._results.clear();
    HelixManager manager = null;
    for (int i = 0; i < NODE_NR; i++) {
      _participants[i].getMessagingService().registerMessageHandlerFactory(
          _factory.getMessageType(), _factory);

      manager = _participants[i]; // _startCMResultMap.get(hostDest)._manager;
    }

    Message schedulerMessage =
        new Message(MessageType.SCHEDULER_MSG + "", UUID.randomUUID().toString());
    schedulerMessage.setTgtSessionId("*");
    schedulerMessage.setTgtName("CONTROLLER");
    // TODO: change it to "ADMIN" ?
    schedulerMessage.setSrcName("CONTROLLER");
    // schedulerMessage.getRecord().setSimpleField(DefaultSchedulerMessageHandlerFactory.SCHEDULER_TASK_QUEUE,
    // "TestSchedulerMsg");
    // Template for the individual message sent to each participant
    Message msg = new Message(_factory.getMessageType(), "Template");
    msg.setTgtSessionId("*");
    msg.setMsgState(MessageState.NEW);

    // Criteria to send individual messages
    Criteria cr = new Criteria();
    cr.setInstanceName("localhost_%");
    cr.setRecipientInstanceType(InstanceType.PARTICIPANT);
    cr.setSessionSpecific(false);
    cr.setResource("%");
    cr.setPartition("%");

    ObjectMapper mapper = new ObjectMapper();
    SerializationConfig serializationConfig = mapper.getSerializationConfig();
    serializationConfig.set(SerializationConfig.Feature.INDENT_OUTPUT, true);

    StringWriter sw = new StringWriter();
    mapper.writeValue(sw, cr);

    String crString = sw.toString();

    schedulerMessage.getRecord().setSimpleField("Criteria", crString);
    schedulerMessage.getRecord().setMapField("MessageTemplate", msg.getRecord().getSimpleFields());
    schedulerMessage.getRecord().setSimpleField("TIMEOUT", "-1");

    HelixDataAccessor helixDataAccessor = manager.getHelixDataAccessor();
    Builder keyBuilder = helixDataAccessor.keyBuilder();
    helixDataAccessor.createProperty(keyBuilder.controllerMessage(schedulerMessage.getMsgId()),
        schedulerMessage);

    for (int i = 0; i < 30; i++) {
      Thread.sleep(2000);
      if (_PARTITIONS == _factory._results.size()) {
        break;
      }
    }

    Assert.assertEquals(_PARTITIONS, _factory._results.size());
    PropertyKey controllerTaskStatus =
        keyBuilder.controllerTaskStatus(MessageType.SCHEDULER_MSG.toString(),
            schedulerMessage.getMsgId());

    int messageResultCount = 0;
    for (int i = 0; i < 10; i++) {
      Thread.sleep(1000);
      ZNRecord statusUpdate = helixDataAccessor.getProperty(controllerTaskStatus).getRecord();
      Assert.assertTrue(statusUpdate.getMapField("SentMessageCount").get("MessageCount")
          .equals("" + (_PARTITIONS * 3)));
      for (String key : statusUpdate.getMapFields().keySet()) {
        if (key.startsWith("MessageResult ")) {
          messageResultCount++;
          Assert.assertTrue(statusUpdate.getMapField(key).size() > 1);
        }
      }
      if (messageResultCount == _PARTITIONS * 3) {
        break;
      } else {
        Thread.sleep(2000);
      }
    }
    Assert.assertEquals(messageResultCount, _PARTITIONS * 3);
    int count = 0;
    for (Set<String> val : _factory._results.values()) {
      count += val.size();
    }
    Assert.assertEquals(count, _PARTITIONS * 3);

    // test the ZkPathDataDumpTask
    String controllerStatusPath =
        HelixUtil.getControllerPropertyPath(manager.getClusterName(),
            PropertyType.STATUSUPDATES_CONTROLLER);
    List<String> subPaths = _gZkClient.getChildren(controllerStatusPath);
    Assert.assertTrue(subPaths.size() > 0);
    for (String subPath : subPaths) {
      String nextPath = controllerStatusPath + "/" + subPath;
      List<String> subsubPaths = _gZkClient.getChildren(nextPath);
      Assert.assertTrue(subsubPaths.size() > 0);
    }

    String instanceStatusPath =
        HelixUtil.getInstancePropertyPath(manager.getClusterName(), "localhost_" + (START_PORT),
            PropertyType.STATUSUPDATES);

    subPaths = _gZkClient.getChildren(instanceStatusPath);
    Assert.assertTrue(subPaths.size() > 0);
    for (String subPath : subPaths) {
      String nextPath = instanceStatusPath + "/" + subPath;
      List<String> subsubPaths = _gZkClient.getChildren(nextPath);
      Assert.assertTrue(subsubPaths.size() > 0);
      for (String subsubPath : subsubPaths) {
        String nextnextPath = nextPath + "/" + subsubPath;
        Assert.assertTrue(_gZkClient.getChildren(nextnextPath).size() > 0);
      }
    }
    Thread.sleep(3000);
    ZKPathDataDumpTask dumpTask = new ZKPathDataDumpTask(manager, _gZkClient, 0);
    dumpTask.run();

    subPaths = _gZkClient.getChildren(controllerStatusPath);
    Assert.assertTrue(subPaths.size() > 0);
    for (String subPath : subPaths) {
      String nextPath = controllerStatusPath + "/" + subPath;
      List<String> subsubPaths = _gZkClient.getChildren(nextPath);
      Assert.assertTrue(subsubPaths.size() == 0);
    }

    subPaths = _gZkClient.getChildren(instanceStatusPath);
    Assert.assertTrue(subPaths.size() > 0);
    for (String subPath : subPaths) {
      String nextPath = instanceStatusPath + "/" + subPath;
      List<String> subsubPaths = _gZkClient.getChildren(nextPath);
      Assert.assertTrue(subsubPaths.size() > 0);
      for (String subsubPath : subsubPaths) {
        String nextnextPath = nextPath + "/" + subsubPath;
        Assert.assertTrue(_gZkClient.getChildren(nextnextPath).size() == 0);
      }
    }
  }

  @Test()
  public void TestSchedulerMsg2() throws Exception {
    _factory._results.clear();
    Thread.sleep(2000);
    HelixManager manager = null;
    for (int i = 0; i < NODE_NR; i++) {
      _participants[i].getMessagingService().registerMessageHandlerFactory(
          _factory.getMessageType(), _factory);

      manager = _participants[i]; // _startCMResultMap.get(hostDest)._manager;
    }

    Message schedulerMessage =
        new Message(MessageType.SCHEDULER_MSG + "", UUID.randomUUID().toString());
    schedulerMessage.setTgtSessionId("*");
    schedulerMessage.setTgtName("CONTROLLER");
    // TODO: change it to "ADMIN" ?
    schedulerMessage.setSrcName("CONTROLLER");

    // Template for the individual message sent to each participant
    Message msg = new Message(_factory.getMessageType(), "Template");
    msg.setTgtSessionId("*");
    msg.setMsgState(MessageState.NEW);

    // Criteria to send individual messages
    Criteria cr = new Criteria();
    cr.setInstanceName("localhost_%");
    cr.setRecipientInstanceType(InstanceType.PARTICIPANT);
    cr.setSessionSpecific(false);
    cr.setResource("%");
    cr.setPartition("%");

    ObjectMapper mapper = new ObjectMapper();
    SerializationConfig serializationConfig = mapper.getSerializationConfig();
    serializationConfig.set(SerializationConfig.Feature.INDENT_OUTPUT, true);

    StringWriter sw = new StringWriter();
    mapper.writeValue(sw, cr);

    String crString = sw.toString();

    schedulerMessage.getRecord().setSimpleField("Criteria", crString);
    schedulerMessage.getRecord().setMapField("MessageTemplate", msg.getRecord().getSimpleFields());
    schedulerMessage.getRecord().setSimpleField("TIMEOUT", "-1");
    schedulerMessage.getRecord().setSimpleField("WAIT_ALL", "true");

    Criteria cr2 = new Criteria();
    cr2.setRecipientInstanceType(InstanceType.CONTROLLER);
    cr2.setInstanceName("*");
    cr2.setSessionSpecific(false);

    schedulerMessage.getRecord().setSimpleField(
        DefaultSchedulerMessageHandlerFactory.SCHEDULER_TASK_QUEUE, "TestSchedulerMsg2");
    MockAsyncCallback callback = new MockAsyncCallback();
    manager.getMessagingService().sendAndWait(cr2, schedulerMessage, callback, -1);
    String msgId =
        callback._message.getResultMap()
            .get(DefaultSchedulerMessageHandlerFactory.SCHEDULER_MSG_ID);

    HelixDataAccessor helixDataAccessor = manager.getHelixDataAccessor();
    Builder keyBuilder = helixDataAccessor.keyBuilder();
    for (int i = 0; i < 10; i++) {
      Thread.sleep(200);
      PropertyKey controllerTaskStatus =
          keyBuilder.controllerTaskStatus(MessageType.SCHEDULER_MSG.toString(), msgId);
      ZNRecord statusUpdate = helixDataAccessor.getProperty(controllerTaskStatus).getRecord();
      if (statusUpdate.getMapFields().containsKey("Summary")) {
        break;
      }
    }

    Assert.assertEquals(_PARTITIONS, _factory._results.size());
    PropertyKey controllerTaskStatus =
        keyBuilder.controllerTaskStatus(MessageType.SCHEDULER_MSG.toString(), msgId);
    ZNRecord statusUpdate = helixDataAccessor.getProperty(controllerTaskStatus).getRecord();
    Assert.assertTrue(statusUpdate.getMapField("SentMessageCount").get("MessageCount")
        .equals("" + (_PARTITIONS * 3)));
    int messageResultCount = 0;
    for (String key : statusUpdate.getMapFields().keySet()) {
      if (key.startsWith("MessageResult ")) {
        messageResultCount++;
      }
    }
    Assert.assertEquals(messageResultCount, _PARTITIONS * 3);

    int count = 0;
    for (Set<String> val : _factory._results.values()) {
      count += val.size();
    }
    Assert.assertEquals(count, _PARTITIONS * 3);
  }

  @Test()
  public void TestSchedulerZeroMsg() throws Exception {
    TestMessagingHandlerFactory factory = new TestMessagingHandlerFactory();
    HelixManager manager = null;
    for (int i = 0; i < NODE_NR; i++) {
      _participants[i].getMessagingService().registerMessageHandlerFactory(
          factory.getMessageType(), factory);

      manager = _participants[i]; // _startCMResultMap.get(hostDest)._manager;
    }

    Message schedulerMessage =
        new Message(MessageType.SCHEDULER_MSG + "", UUID.randomUUID().toString());
    schedulerMessage.setTgtSessionId("*");
    schedulerMessage.setTgtName("CONTROLLER");
    // TODO: change it to "ADMIN" ?
    schedulerMessage.setSrcName("CONTROLLER");

    // Template for the individual message sent to each participant
    Message msg = new Message(factory.getMessageType(), "Template");
    msg.setTgtSessionId("*");
    msg.setMsgState(MessageState.NEW);

    // Criteria to send individual messages
    Criteria cr = new Criteria();
    cr.setInstanceName("localhost_DOESNOTEXIST");
    cr.setRecipientInstanceType(InstanceType.PARTICIPANT);
    cr.setSessionSpecific(false);
    cr.setResource("%");
    cr.setPartition("%");

    ObjectMapper mapper = new ObjectMapper();
    SerializationConfig serializationConfig = mapper.getSerializationConfig();
    serializationConfig.set(SerializationConfig.Feature.INDENT_OUTPUT, true);

    StringWriter sw = new StringWriter();
    mapper.writeValue(sw, cr);

    String crString = sw.toString();

    schedulerMessage.getRecord().setSimpleField("Criteria", crString);
    schedulerMessage.getRecord().setMapField("MessageTemplate", msg.getRecord().getSimpleFields());
    schedulerMessage.getRecord().setSimpleField("TIMEOUT", "-1");

    HelixDataAccessor helixDataAccessor = manager.getHelixDataAccessor();
    Builder keyBuilder = helixDataAccessor.keyBuilder();
    PropertyKey controllerMessageKey = keyBuilder.controllerMessage(schedulerMessage.getMsgId());
    helixDataAccessor.setProperty(controllerMessageKey, schedulerMessage);

    Thread.sleep(3000);

    Assert.assertEquals(0, factory._results.size());
    PropertyKey controllerTaskStatus =
        keyBuilder.controllerTaskStatus(MessageType.SCHEDULER_MSG.toString(),
            schedulerMessage.getMsgId());
    for (int i = 0; i < 10; i++) {
      StatusUpdate update = helixDataAccessor.getProperty(controllerTaskStatus);
      if (update == null || update.getRecord().getMapField("SentMessageCount") == null) {
        Thread.sleep(1000);
      }
    }
    ZNRecord statusUpdate = helixDataAccessor.getProperty(controllerTaskStatus).getRecord();
    Assert.assertTrue(statusUpdate.getMapField("SentMessageCount").get("MessageCount").equals("0"));
    int count = 0;
    for (Set<String> val : factory._results.values()) {
      count += val.size();
    }
    Assert.assertEquals(count, 0);
  }

  @Test()
  public void TestSchedulerMsg3() throws Exception {
    _factory._results.clear();
    Thread.sleep(2000);
    HelixManager manager = null;
    for (int i = 0; i < NODE_NR; i++) {
      _participants[i].getMessagingService().registerMessageHandlerFactory(
          _factory.getMessageType(), _factory);

      _participants[i].getMessagingService().registerMessageHandlerFactory(
          _factory.getMessageType(), _factory);

      manager = _participants[i]; // _startCMResultMap.get(hostDest)._manager;
    }

    Message schedulerMessage =
        new Message(MessageType.SCHEDULER_MSG + "", UUID.randomUUID().toString());
    schedulerMessage.setTgtSessionId("*");
    schedulerMessage.setTgtName("CONTROLLER");
    // TODO: change it to "ADMIN" ?
    schedulerMessage.setSrcName("CONTROLLER");

    // Template for the individual message sent to each participant
    Message msg = new Message(_factory.getMessageType(), "Template");
    msg.setTgtSessionId("*");
    msg.setMsgState(MessageState.NEW);

    // Criteria to send individual messages
    Criteria cr = new Criteria();
    cr.setInstanceName("localhost_%");
    cr.setRecipientInstanceType(InstanceType.PARTICIPANT);
    cr.setSessionSpecific(false);
    cr.setResource("%");
    cr.setPartition("%");

    ObjectMapper mapper = new ObjectMapper();
    SerializationConfig serializationConfig = mapper.getSerializationConfig();
    serializationConfig.set(SerializationConfig.Feature.INDENT_OUTPUT, true);

    StringWriter sw = new StringWriter();
    mapper.writeValue(sw, cr);

    String crString = sw.toString();

    schedulerMessage.getRecord().setSimpleField("Criteria", crString);
    schedulerMessage.getRecord().setMapField("MessageTemplate", msg.getRecord().getSimpleFields());
    schedulerMessage.getRecord().setSimpleField("TIMEOUT", "-1");
    schedulerMessage.getRecord().setSimpleField("WAIT_ALL", "true");

    schedulerMessage.getRecord().setSimpleField(
        DefaultSchedulerMessageHandlerFactory.SCHEDULER_TASK_QUEUE, "TestSchedulerMsg3");
    Criteria cr2 = new Criteria();
    cr2.setRecipientInstanceType(InstanceType.CONTROLLER);
    cr2.setInstanceName("*");
    cr2.setSessionSpecific(false);

    MockAsyncCallback callback = new MockAsyncCallback();
    cr.setInstanceName("localhost_%");
    mapper = new ObjectMapper();
    serializationConfig = mapper.getSerializationConfig();
    serializationConfig.set(SerializationConfig.Feature.INDENT_OUTPUT, true);

    sw = new StringWriter();
    mapper.writeValue(sw, cr);

    crString = sw.toString();
    schedulerMessage.getRecord().setSimpleField("Criteria", crString);

    for (int i = 0; i < 4; i++) {
      callback = new MockAsyncCallback();
      cr.setInstanceName("localhost_" + (START_PORT + i));
      mapper = new ObjectMapper();
      serializationConfig = mapper.getSerializationConfig();
      serializationConfig.set(SerializationConfig.Feature.INDENT_OUTPUT, true);

      sw = new StringWriter();
      mapper.writeValue(sw, cr);
      schedulerMessage.setMsgId(UUID.randomUUID().toString());
      crString = sw.toString();
      schedulerMessage.getRecord().setSimpleField("Criteria", crString);
      manager.getMessagingService().sendAndWait(cr2, schedulerMessage, callback, -1);
      String msgId =
          callback._message.getResultMap().get(
              DefaultSchedulerMessageHandlerFactory.SCHEDULER_MSG_ID);

      HelixDataAccessor helixDataAccessor = manager.getHelixDataAccessor();
      Builder keyBuilder = helixDataAccessor.keyBuilder();

      for (int j = 0; j < 100; j++) {
        Thread.sleep(200);
        PropertyKey controllerTaskStatus =
            keyBuilder.controllerTaskStatus(MessageType.SCHEDULER_MSG.toString(), msgId);
        ZNRecord statusUpdate = helixDataAccessor.getProperty(controllerTaskStatus).getRecord();
        if (statusUpdate.getMapFields().containsKey("Summary")) {
          break;
        }
      }

      PropertyKey controllerTaskStatus =
          keyBuilder.controllerTaskStatus(MessageType.SCHEDULER_MSG.toString(), msgId);
      ZNRecord statusUpdate = helixDataAccessor.getProperty(controllerTaskStatus).getRecord();
      Assert.assertTrue(statusUpdate.getMapField("SentMessageCount").get("MessageCount")
          .equals("" + (_PARTITIONS * 3 / 5)));
      int messageResultCount = 0;
      for (String key : statusUpdate.getMapFields().keySet()) {
        if (key.startsWith("MessageResult")) {
          messageResultCount++;
        }
      }
      Assert.assertEquals(messageResultCount, _PARTITIONS * 3 / 5);

      int count = 0;
      // System.out.println(i);
      for (Set<String> val : _factory._results.values()) {
        // System.out.println(val);
        count += val.size();
      }
      // System.out.println(count);
      Assert.assertEquals(count, _PARTITIONS * 3 / 5 * (i + 1));
    }
  }

  @Test()
  public void TestSchedulerMsg4() throws Exception {
    _factory._results.clear();
    HelixManager manager = null;
    for (int i = 0; i < NODE_NR; i++) {
      _participants[i].getMessagingService().registerMessageHandlerFactory(
          _factory.getMessageType(), _factory);

      _participants[i].getMessagingService().registerMessageHandlerFactory(
          _factory.getMessageType(), _factory);

      manager = _participants[i]; // _startCMResultMap.get(hostDest)._manager;
    }

    Message schedulerMessage =
        new Message(MessageType.SCHEDULER_MSG + "", UUID.randomUUID().toString());
    schedulerMessage.setTgtSessionId("*");
    schedulerMessage.setTgtName("CONTROLLER");
    // TODO: change it to "ADMIN" ?
    schedulerMessage.setSrcName("CONTROLLER");

    // Template for the individual message sent to each participant
    Message msg = new Message(_factory.getMessageType(), "Template");
    msg.setTgtSessionId("*");
    msg.setMsgState(MessageState.NEW);

    // Criteria to send individual messages
    Criteria cr = new Criteria();
    cr.setInstanceName("localhost_%");
    cr.setRecipientInstanceType(InstanceType.PARTICIPANT);
    cr.setSessionSpecific(false);
    cr.setResource("TestDB");
    cr.setPartition("%");

    ObjectMapper mapper = new ObjectMapper();
    SerializationConfig serializationConfig = mapper.getSerializationConfig();
    serializationConfig.set(SerializationConfig.Feature.INDENT_OUTPUT, true);

    StringWriter sw = new StringWriter();
    mapper.writeValue(sw, cr);

    String crString = sw.toString();

    schedulerMessage.getRecord().setSimpleField("Criteria", crString);
    schedulerMessage.getRecord().setMapField("MessageTemplate", msg.getRecord().getSimpleFields());
    schedulerMessage.getRecord().setSimpleField("TIMEOUT", "-1");
    schedulerMessage.getRecord().setSimpleField("WAIT_ALL", "true");

    schedulerMessage.getRecord().setSimpleField(
        DefaultSchedulerMessageHandlerFactory.SCHEDULER_TASK_QUEUE, "TestSchedulerMsg4");
    Criteria cr2 = new Criteria();
    cr2.setRecipientInstanceType(InstanceType.CONTROLLER);
    cr2.setInstanceName("*");
    cr2.setSessionSpecific(false);

    Map<String, String> constraints = new TreeMap<String, String>();
    constraints.put("MESSAGE_TYPE", "STATE_TRANSITION");
    constraints.put("TRANSITION", "OFFLINE-COMPLETED");
    constraints.put("CONSTRAINT_VALUE", "1");
    constraints.put("INSTANCE", ".*");
    manager.getClusterManagmentTool().setConstraint(manager.getClusterName(),
        ConstraintType.MESSAGE_CONSTRAINT, "constraint1", new ConstraintItem(constraints));

    MockAsyncCallback callback = new MockAsyncCallback();
    cr.setInstanceName("localhost_%");
    mapper = new ObjectMapper();
    serializationConfig = mapper.getSerializationConfig();
    serializationConfig.set(SerializationConfig.Feature.INDENT_OUTPUT, true);

    sw = new StringWriter();
    mapper.writeValue(sw, cr);

    crString = sw.toString();
    schedulerMessage.getRecord().setSimpleField("Criteria", crString);
    manager.getMessagingService().sendAndWait(cr2, schedulerMessage, callback, -1);
    String msgIdPrime =
        callback._message.getResultMap()
            .get(DefaultSchedulerMessageHandlerFactory.SCHEDULER_MSG_ID);

    HelixDataAccessor helixDataAccessor = manager.getHelixDataAccessor();
    Builder keyBuilder = helixDataAccessor.keyBuilder();
    ArrayList<String> msgIds = new ArrayList<String>();
    for (int i = 0; i < NODE_NR; i++) {
      callback = new MockAsyncCallback();
      cr.setInstanceName("localhost_" + (START_PORT + i));
      mapper = new ObjectMapper();
      serializationConfig = mapper.getSerializationConfig();
      serializationConfig.set(SerializationConfig.Feature.INDENT_OUTPUT, true);

      sw = new StringWriter();
      mapper.writeValue(sw, cr);
      schedulerMessage.setMsgId(UUID.randomUUID().toString());
      crString = sw.toString();
      schedulerMessage.getRecord().setSimpleField("Criteria", crString);
      manager.getMessagingService().sendAndWait(cr2, schedulerMessage, callback, -1);
      String msgId =
          callback._message.getResultMap().get(
              DefaultSchedulerMessageHandlerFactory.SCHEDULER_MSG_ID);
      msgIds.add(msgId);
    }
    for (int i = 0; i < NODE_NR; i++) {
      String msgId = msgIds.get(i);
      for (int j = 0; j < 100; j++) {
        Thread.sleep(200);
        PropertyKey controllerTaskStatus =
            keyBuilder.controllerTaskStatus(MessageType.SCHEDULER_MSG.toString(), msgId);
        ZNRecord statusUpdate = helixDataAccessor.getProperty(controllerTaskStatus).getRecord();
        if (statusUpdate.getMapFields().containsKey("Summary")) {
          // System.err.println(msgId+" done");
          break;
        }
      }

      PropertyKey controllerTaskStatus =
          keyBuilder.controllerTaskStatus(MessageType.SCHEDULER_MSG.toString(), msgId);
      ZNRecord statusUpdate = helixDataAccessor.getProperty(controllerTaskStatus).getRecord();
      Assert.assertTrue(statusUpdate.getMapField("SentMessageCount").get("MessageCount")
          .equals("" + (_PARTITIONS * 3 / 5)));
      int messageResultCount = 0;
      for (String key : statusUpdate.getMapFields().keySet()) {
        if (key.startsWith("MessageResult")) {
          messageResultCount++;
        }
      }
      if (messageResultCount != _PARTITIONS * 3 / 5) {
        int x = 10;
        x = x + messageResultCount;
      }
      Assert.assertEquals(messageResultCount, _PARTITIONS * 3 / 5);
    }

    for (int j = 0; j < 100; j++) {
      Thread.sleep(200);
      PropertyKey controllerTaskStatus =
          keyBuilder.controllerTaskStatus(MessageType.SCHEDULER_MSG.toString(), msgIdPrime);
      ZNRecord statusUpdate = helixDataAccessor.getProperty(controllerTaskStatus).getRecord();
      if (statusUpdate.getMapFields().containsKey("Summary")) {
        break;
      }
    }
    int count = 0;
    for (Set<String> val : _factory._results.values()) {
      // System.out.println(val);
      count += val.size();
    }
    // System.out.println(count);
    Assert.assertEquals(count, _PARTITIONS * 3 * 2);
  }

  @Test
  public void TestSchedulerMsgContraints() throws JsonGenerationException, JsonMappingException,
      IOException, InterruptedException {
    TestMessagingHandlerFactoryLatch factory = new TestMessagingHandlerFactoryLatch();
    HelixManager manager = null;
    for (int i = 0; i < NODE_NR; i++) {
      _participants[i].getMessagingService().registerMessageHandlerFactory(
          factory.getMessageType(), factory);

      _participants[i].getMessagingService().registerMessageHandlerFactory(
          factory.getMessageType(), factory);

      manager = _participants[i]; // _startCMResultMap.get(hostDest)._manager;
    }

    Message schedulerMessage =
        new Message(MessageType.SCHEDULER_MSG + "", UUID.randomUUID().toString());
    schedulerMessage.setTgtSessionId("*");
    schedulerMessage.setTgtName("CONTROLLER");
    // TODO: change it to "ADMIN" ?
    schedulerMessage.setSrcName("CONTROLLER");

    // Template for the individual message sent to each participant
    Message msg = new Message(factory.getMessageType(), "Template");
    msg.setTgtSessionId("*");
    msg.setMsgState(MessageState.NEW);

    // Criteria to send individual messages
    Criteria cr = new Criteria();
    cr.setInstanceName("localhost_%");
    cr.setRecipientInstanceType(InstanceType.PARTICIPANT);
    cr.setSessionSpecific(false);
    cr.setResource("%");
    cr.setPartition("%");

    ObjectMapper mapper = new ObjectMapper();
    SerializationConfig serializationConfig = mapper.getSerializationConfig();
    serializationConfig.set(SerializationConfig.Feature.INDENT_OUTPUT, true);

    StringWriter sw = new StringWriter();
    mapper.writeValue(sw, cr);

    String crString = sw.toString();

    schedulerMessage.getRecord().setSimpleField("Criteria", crString);
    schedulerMessage.getRecord().setMapField("MessageTemplate", msg.getRecord().getSimpleFields());
    schedulerMessage.getRecord().setSimpleField("TIMEOUT", "-1");
    schedulerMessage.getRecord().setSimpleField("WAIT_ALL", "true");
    schedulerMessage.getRecord().setSimpleField(
        DefaultSchedulerMessageHandlerFactory.SCHEDULER_TASK_QUEUE, "TestSchedulerMsgContraints");

    Criteria cr2 = new Criteria();
    cr2.setRecipientInstanceType(InstanceType.CONTROLLER);
    cr2.setInstanceName("*");
    cr2.setSessionSpecific(false);

    MockAsyncCallback callback = new MockAsyncCallback();
    mapper = new ObjectMapper();
    serializationConfig = mapper.getSerializationConfig();
    serializationConfig.set(SerializationConfig.Feature.INDENT_OUTPUT, true);

    sw = new StringWriter();
    mapper.writeValue(sw, cr);

    HelixDataAccessor helixDataAccessor = manager.getHelixDataAccessor();
    Builder keyBuilder = helixDataAccessor.keyBuilder();

    // Set contraints that only 1 msg per participant
    Map<String, String> constraints = new TreeMap<String, String>();
    constraints.put("MESSAGE_TYPE", "STATE_TRANSITION");
    constraints.put("TRANSITION", "OFFLINE-COMPLETED");
    constraints.put("CONSTRAINT_VALUE", "1");
    constraints.put("INSTANCE", ".*");
    manager.getClusterManagmentTool().setConstraint(manager.getClusterName(),
        ConstraintType.MESSAGE_CONSTRAINT, "constraint1", new ConstraintItem(constraints));

    // Send scheduler message
    crString = sw.toString();
    schedulerMessage.getRecord().setSimpleField("Criteria", crString);
    manager.getMessagingService().sendAndWait(cr2, schedulerMessage, callback, -1);
    String msgId =
        callback._message.getResultMap()
            .get(DefaultSchedulerMessageHandlerFactory.SCHEDULER_MSG_ID);

    for (int j = 0; j < 10; j++) {
      Thread.sleep(200);
      PropertyKey controllerTaskStatus =
          keyBuilder.controllerTaskStatus(MessageType.SCHEDULER_MSG.toString(), msgId);
      ZNRecord statusUpdate = helixDataAccessor.getProperty(controllerTaskStatus).getRecord();
      if (statusUpdate.getMapFields().containsKey("SentMessageCount")) {
        Assert.assertEquals(
            statusUpdate.getMapFields().get("SentMessageCount").get("MessageCount"), ""
                + (_PARTITIONS * 3));
        break;
      }
    }

    for (int i = 0; i < _PARTITIONS * 3 / 5; i++) {
      for (int j = 0; j < 10; j++) {
        Thread.sleep(300);
        if (factory._messageCount == 5 * (i + 1))
          break;
      }
      Thread.sleep(300);
      Assert.assertEquals(factory._messageCount, 5 * (i + 1));
      factory.signal();
      // System.err.println(i);
    }

    for (int j = 0; j < 10; j++) {
      Thread.sleep(200);
      PropertyKey controllerTaskStatus =
          keyBuilder.controllerTaskStatus(MessageType.SCHEDULER_MSG.toString(), msgId);
      ZNRecord statusUpdate = helixDataAccessor.getProperty(controllerTaskStatus).getRecord();
      if (statusUpdate.getMapFields().containsKey("Summary")) {
        break;
      }
    }

    Assert.assertEquals(_PARTITIONS, factory._results.size());
    PropertyKey controllerTaskStatus =
        keyBuilder.controllerTaskStatus(MessageType.SCHEDULER_MSG.toString(), msgId);
    ZNRecord statusUpdate = helixDataAccessor.getProperty(controllerTaskStatus).getRecord();
    Assert.assertTrue(statusUpdate.getMapField("SentMessageCount").get("MessageCount")
        .equals("" + (_PARTITIONS * 3)));
    int messageResultCount = 0;
    for (String key : statusUpdate.getMapFields().keySet()) {
      if (key.startsWith("MessageResult ")) {
        messageResultCount++;
      }
    }
    Assert.assertEquals(messageResultCount, _PARTITIONS * 3);

    int count = 0;
    for (Set<String> val : factory._results.values()) {
      count += val.size();
    }
    Assert.assertEquals(count, _PARTITIONS * 3);

    manager.getClusterManagmentTool().removeConstraint(manager.getClusterName(),
        ConstraintType.MESSAGE_CONSTRAINT, "constraint1");

  }
}


text:
<?php namespace Fisharebest\Localization\Territory;

class TerritoryLr extends AbstractTerritory implements TerritoryInterface {
	public function code() {
		return 'LR';
	}

	public function measurementSystem() {
		return 'US';
	}
}

redpajama_set_name: RedPajamaGithub


text:
require 'sinatra/base'
require 'oauth2'
require 'slim'

class App < Sinatra::Base

  # Single Sign On service configuration
  SSO_HOST = ENV['SSO_HOST']
  SSO_TOKEN_PATH = ENV['SSO_TOKEN_PATH']
  SSO_AUTHORIZE_PATH = ENV['SSO_AUTHORIZE_PATH']
  PROFILE_PATH = ENV['PROFILE_PATH']

  SSO_LOGOUT_PATH = ENV['SSO_LOGOUT_PATH']

  # Setting from Single Sign On Client Configuration page
  CLIENT_ID = ENV['CLIENT_ID']
  CLIENT_SECRET = ENV['CLIENT_SECRET']

  # where SSO calls us back after authenticated
  AUTH_CALLBACK_PATH = '/auth/oauth2/callback'

  configure do
    set :client, OAuth2::Client.new(CLIENT_ID, CLIENT_SECRET, site: SSO_HOST, authorize_url: SSO_AUTHORIZE_PATH, token_url: SSO_TOKEN_PATH)
    set :root, File.dirname(__FILE__)
  end

  get '/' do
    # render the index.slim page
    slim :index
  end

  get '/profile' do
    # this will redirect to the sso authorize service requesting access to the profile service
    redirect App.client.auth_code.authorize_url(redirect_uri: redirect_uri(request), scope: 'profile')
  end

  get AUTH_CALLBACK_PATH do

    # first exchange the code for a bearer token. this returns a instance of a OAuth2::AccessToken
    token = App.client.auth_code.get_token(params[:code], redirect_uri: redirect_uri(request))

    # next use the token to make a request to the profile service
    properties = JSON.parse(token.post("#{SSO_HOST}/#{PROFILE_PATH}").response.body)

    # alternatively you can fetch the actual bearer token from the AccessToken (possibly store it in session for later use)
    # and use it with a REST client of your choice like this:
    # RestClient.post 'https://idaas.ng.bluemix.net/idaas/resources/profile.jsp', { 'access_token' => token.token }

    # now render the profile.slim page with the user profile properties
    slim :profile, locals: { properties: properties }

  end

  def redirect_uri(request)
    "#{request.scheme}://#{request.host}#{AUTH_CALLBACK_PATH}"
  end

end


text:
function isLeaf{K,V}(x::_Node{K,V})
    typeof(x) == Leaf{K,V}
end

function isEmpty(tree::BinaryTree)
    isLeaf(tree.root)
end

function insert{K,V}( tree::BinaryTree{K,V}, key::K, value::V )
    if isEmpty(tree)
        tree.root = Node(key, value)
    else
        iter = BinaryTreeIterator(tree)
        done = false
        while !done
            if key <= currentNode(iter).key
                if isLeaf(currentNode(iter).left)
                    currentNode(iter).left = Node( key, value )
                    done = true
                else
                    goLeft(iter)
                end
            else
                if isLeaf(currentNode(iter).right)
                    currentNode(iter).right = Node( key, value )
                    done = true
                else
                    goRight(iter)
                end
            end
        end
        rebalance( iter )
    end
end

function Base.find{K,V}( tree::BinaryTree{K,V}, key::K )
    iter = BinaryTreeIterator(tree)
    found = false
    if isEmpty(tree)
        return((iter,false))
    else
        while !found
            if key < currentNode(iter).key
                if !goLeft(iter)
                    break
                end
            elseif key > currentNode(iter).key
                if !goRight(iter)
                    break
                end
            else
                found = true
            end
        end
        return((iter, found))
    end
end

function goTo{K,V}( tree::BinaryTree{K,V}, key::K )
    iter, found = find(tree, key)
    iter.nodeStack = iter.nodeStack[map(x -> x.key >= key, iter.nodeStack)]
    return((iter, found))
end

function Base.get{K,V}(tree::BinaryTree{K,V}, key::K)
    iter, found = find( tree, key )
    if found
        return( currentNode(iter).value )
    else
        return( nothing )
    end
end

function hasKey{K,V}( tree::BinaryTree{K,V}, key::K )
    return(find(tree, key)[2])
end

function Base.delete!{K,V}( tree::BinaryTree{K,V}, key::K )
    iter, found = find( tree, key )
    if !found
        warn("Attempted to delete unmapped key " * string(key))
        return(false)
    end
    deletee = currentNode(iter)
    while goRight(iter)
    end
    deletee.key = currentNode(iter).key
    deletee.value = currentNode(iter).value
    goUp(iter)
    currentNode(iter).right = currentNode(iter).right.left #Do we have to delete explicitly? GC?
    rebalance(iter)
end

function Base.string(x::Node)
    return "Node(" * string(x.key) * ":" * string(x.value) * " - " * string(height(x)) * ")"
end
Base.print(io::IO, x::Node) = print(io, string(x))
Base.show(io::IO, x::Node) = print(io, string(x))

function Base.string(x::BinaryTreeIterator)
    return "BinaryTreeIterator(" * string(currentNode(x)) * " - " * string(length(x.nodeStack)) * ")"
end
Base.print(io::IO, x::BinaryTreeIterator) = print(io, string(x))
Base.show(io::IO, x::BinaryTreeIterator) = print(io, string(x))

function height( node::Leaf )
    return 0
end

function height{K,V}( node::Node{K,V} )
    return( max( height(node.left), height(node.right)) + 1 )
end

function balanceFactor{K,V}(node::Node{K,V})
    return(height(node.left) - height(node.right))
end

function balanceFactor(node::Leaf)
    return 0
end


text:
A Ruby library for retrieving and parsing [bulk data downloads](http://classic.fec.gov/finance/disclosure/ftp_download.shtml) from the Federal Election Commission. While fech-ftp provides an API to some transaction data (contributions from a committee to a candidate and contributions between two committees), its main purpose is to provide a simple interface to the "[committee master](http://classic.fec.gov/finance/disclosure/metadata/DataDictionaryCommitteeMaster.shtml)" and "[candidate master](http://classic.fec.gov/finance/disclosure/metadata/DataDictionaryCandidateMaster.shtml)" files, with the ultimate goal of providing a way to connect individual transactions parsed by [Fech](https://github.com/NYTimes/Fech) with their canonical recipients.

fech-ftp is tested under Ruby 2.0.0, 2.1.X, 2.2.X, and 2.3.X.

Ironically, the FEC announced in late 2017 that it would be moving its bulk data files from an FTP server to S3. This library has been updated to work with that setup, so it performs exactly zero FTP requests.

## Installation

Add this line to your application's Gemfile:

    gem 'fech-ftp'

And then execute:

    $ bundle

Or install it yourself as:

    $ gem install fech-ftp

## Usage

Fech-FTP can be used by itself or in combination with Fech. To retrieve canonical details about candidates for an election cycle, pass the cycle into the following constructor:

```ruby
require 'fech-ftp'
cands = Fech::Candidate.detail(2018)
cands.first # => {:candidate_id=>"H0AL02087", :candidate_name=>"ROBY, MARTHA", :party=>"REP", :election_year=>"2018", :office_state=>"AL", :office=>"H", :district=>"02", :incumbent_challenger_status=>"I", :candidate_status=>"C", :committee_id=>"C00462143", :street_one=>"3260 BANKHEAD AVE", :street_two=>"", :city=>"MONTGOMERY", :state=>"AL", :zipcode=>"361062448"}
```

If you want to have the data transferred into an csv, add the property `format: :csv`, like so:

```ruby
Fech::Candidate.detail(2018, format: :csv)
```

You can specify the location that the FEC zip files opened by fech-ftp are downloaded by adding the property `location`, with an absolute path to an _existing_ directory that must include a trailing slash, like so:

```ruby
Fech::Candidate.detail(2018, location: "/tmp/fec/")
```

If you are using the [Sequel Gem](https://github.com/jeremyevans/sequel), you can pass in the DB table object as the `connection` property:

```ruby
Fech::Candidate.detail(2018, format: :db, connection: DB[:candidates])
```

Please note that it assumes the table object's columns == header properties for the data that gets passed in. Otherwise, an exception will be thrown.
To get around this, you can provide the `connection` property as an array, with the traditional `DB` constant value being the in the first element, followed by the table name:

```ruby
Fech::Candidate.detail(2018, format: :db, connection: [<DATABASE OBJECT>, :candidates])
```

The table will automatically be created, and then will be populated with the selected dataset. Also please note that it assumes there are no foreign keys. To add them, please follow the Sequel documentation guidelines for adding/altering foreign keys.

`Fech::Candidate` and `Fech::Committee` each have multiple datasets available and can be accessed using the corresponding method:

`Candidate` responds to `summary_current, summary_all, detail`
`Committee` responds to `linkage, summary_all, detail`

The following have only a single dataset but will respond to any of the above methods:

```ruby
Fech::CandidateContribution
Fech::IndividualContribution
Fech::CommitteeContribution
```

There are additional classes representing [PAC contributions to candidates](http://classic.fec.gov/finance/disclosure/metadata/DataDictionaryContributionstoCandidates.shtml) (`CandidateContribution`) and [transactions involving two committees](http://classic.fec.gov/finance/disclosure/metadata/DataDictionaryCommitteetoCommittee.shtml) (`CommitteeContribution`). Be advised that both of the FTP files loaded by these classes are large and can take minutes to parse. They are appropriately used for background processing or data loading purposes, not for providing a live API. Individual Contributions in particular runs in excess of 1-2 million rows of data (~ 200mb)

## Authors

* [Derek Willis](https://github.com/dwillis)
* [Matt Long](https://github.com/wismer)

## Contributing

1. Fork it ( http://github.com/dwillis/fech-ftp/fork )
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request


text:
namespace Stankins.AzureDevOps
{
    public class Bash : MultipleCommands
    {
        public Bash(string value)
        {
            Name = "bash";
            Value = value;
        }
    }

}


text:
{% extends "base.html" %}
{% block content-title %}Calendar{% endblock %}
{% block content %}

{{title}}

          Basic Elements

			  <form class="form form-horizontal" action="" method="POST">
          {% csrf_token %}

            {{ password_form.old_password.label }}

              {{ password_form.old_password }}
              {{ password_form.old_password.errors }}

           {{ password_form.new_password1.label }}

              {{ password_form.new_password1 }}
              {{ password_form.new_password1.errors }}

           {{ password_form.new_password2.label }}

              {{ password_form.new_password2 }}
              {{ password_form.new_password2.errors }}

                <button type="submit" class="btn btn-primary">Save</button>
                <button type="button" class="btn btn-default">Cancel</button>

        </form>

{% endblock %}


text:
import {IDBKeyRange} from './database'

export class Index {
  constructor(db, name, indexName) {
    this.db = db
    this.name = name
    this.indexName = indexName
  }

  make(keyRange) {
    return {
      query: () => {
        return this.query(keyRange)
      },
      remove: () => {
        return this.remove(keyRange)
      }
    }
  }

  // keyRange
  only(value) {
    var keyRange = IDBKeyRange.only(value)
    return this.make(keyRange)
  }

  between(start, end, startedOpened, endOpened) {
    var keyRange = IDBKeyRange.bound(start, end, startedOpened, endOpened)
    return this.make(keyRange)
  }

  lt(end, endOpened) {
    var keyRange = IDBKeyRange.upperBound(end, endOpened)
    return this.make(keyRange)
  }

  gt(start, startOpened) {
    var keyRange = IDBKeyRange.lowerBound(start, startOpened)
    return this.make(keyRange)
  }

  // opt
  query(keyRange) {
    return this.db.getByIndex(this.name, this.indexName, keyRange)
  }

  remove(keyRange) {
    return this.db.removeByIndex(this.name, this.indexName, keyRange)
  }
}


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<title>Uses of Class com.mygdx.game.GameTimer</title>
<meta name="date" content="2017-05-01">
<link rel="stylesheet" type="text/css" href="../../../../stylesheet.css" title="Style">

JavaScript is disabled on your browser.

Skip navigation links

Overview

Package

Class

Use

Tree

Deprecated

Index

Help

Prev

Next

Frames

No Frames

All Classes

Uses of Class
com.mygdx.game.GameTimer

Packages that use GameTimer

Package
Description

com.mygdx.game

Uses of GameTimer in com.mygdx.game

Fields in com.mygdx.game declared as GameTimer

Modifier and Type
Field and Description

private GameTimer
GameEngine.timer

Timer used to dictate the pace and flow of the game
 This has a visual interface which will be displayed in the top-left corner of the game-screen

Methods in com.mygdx.game that return GameTimer

Modifier and Type
Method and Description

GameTimer
GameEngine.timer()

Returns the GameTimer declared and managed by the engine

Skip navigation links

Overview

Package

Class

Use

Tree

Deprecated

Index

Help

Prev

Next

Frames

No Frames

All Classes


text:
package com.sf.openapi.express.sample.wms.salesOrder.dto;

import com.sf.openapi.express.sample.wms.common.dto.LscmRequestDto;

public class SailOrderCancelReqDto extends LscmRequestDto
{

    public SailOrderCancelReqDto()
    {
    }

    public String getCompany()
    {
        return company;
    }

    public void setCompany(String company)
    {
        this.company = company;
    }

    public String getOrderid()
    {
        return orderid;
    }

    public void setOrderid(String orderid)
    {
        this.orderid = orderid;
    }

    private String company;
    private String orderid;
}


text:
package com.founder.fix.fixflow.core.impl.interceptor;

/**
 * @author kenshin
 */
public interface Session {

  void flush();

  void close();
}


text:
package suggestion

import (
	"go/token"
	"testing"

	"golang.org/x/lint"
)

func TestLintNamesUnderscore(t *testing.T) {
	var testcases = []struct {
		problem            lint.Problem
		expectedSuggestion string
	}{
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "don't use underscores in Go names; func Qux_1 should be Qux1",
				Link:       "http://golang.org/doc/effective_go.html#mixed-caps",
				Category:   "naming",
				LineText:   "func Qux_1() error {",
				Confidence: 100.00,
			},
			expectedSuggestion: "```suggestion\nfunc Qux1() error {```\n",
		},
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "don't use underscores in Go names; func Qux_Foo_Func should be QuxFooFunc",
				Link:       "http://golang.org/doc/effective_go.html#mixed-caps",
				Category:   "naming",
				LineText:   "func Qux_Foo_Func() error {",
				Confidence: 100.00,
			},
			expectedSuggestion: "```suggestion\nfunc QuxFooFunc() error {```\n",
		},
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "don't use underscores in Go names; func Qux_Foo_Func should be QuxFooFunc",
				Link:       "http://golang.org/doc/effective_go.html#mixed-caps",
				Category:   "naming",
				LineText:   "func QuxCorrectFunc() error {",
				Confidence: 100.00,
			},
			expectedSuggestion: "",
		},
	}
	for _, test := range testcases {
		suggestion := SuggestCodeChange(test.problem)
		if suggestion != test.expectedSuggestion {
			t.Errorf("Excepted code suggestion %s but got %s for LineText %s", test.expectedSuggestion, suggestion, test.problem.LineText)
		}
	}
}

func TestLintNamesAllCaps(t *testing.T) {
	var testcases = []struct {
		problem            lint.Problem
		expectedSuggestion string
	}{
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "don't use ALL_CAPS in Go names; use CamelCase",
				Link:       "",
				Category:   "naming",
				LineText:   "func QUX_FUNC() error {",
				Confidence: 100.00,
			},
			expectedSuggestion: "```suggestion\nfunc QuxFunc() error {```\n",
		},
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "don't use ALL_CAPS in Go names; use CamelCase",
				Link:       "http://golang.org/doc/effective_go.html#mixed-caps",
				Category:   "naming",
				LineText:   "func QUX() error {",
				Confidence: 100.00,
			},
			expectedSuggestion: "```suggestion\nfunc Qux() error {```\n",
		},
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "don't use ALL_CAPS in Go names; use CamelCase",
				Link:       "http://golang.org/doc/effective_go.html#mixed-caps",
				Category:   "naming",
				LineText:   "func QUX_FOO_FUNC() error {",
				Confidence: 100.00,
			},
			expectedSuggestion: "```suggestion\nfunc QuxFooFunc() error {```\n",
		},
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "don't use ALL_CAPS in Go names; use CamelCase",
				Link:       "http://golang.org/doc/effective_go.html#mixed-caps",
				Category:   "naming",
				LineText:   "func QUX_FOO_FUNC_1() error {",
				Confidence: 100.00,
			},
			expectedSuggestion: "```suggestion\nfunc QuxFooFunc1() error {```\n",
		},
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "don't use ALL_CAPS in Go names; use CamelCase",
				Link:       "http://golang.org/doc/effective_go.html#mixed-caps",
				Category:   "naming",
				LineText:   "func QuxCorrectFunc() error {",
				Confidence: 100.00,
			},
			expectedSuggestion: "",
		},
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "don't use ALL_CAPS in Go names; use CamelCase",
				Link:       "http://golang.org/doc/effective_go.html#mixed-caps",
				Category:   "naming",
				LineText:   "func Qux() error {",
				Confidence: 100.00,
			},
			expectedSuggestion: "",
		},
	}
	for _, test := range testcases {
		suggestion := SuggestCodeChange(test.problem)
		if suggestion != test.expectedSuggestion {
			t.Errorf("Excepted code suggestion %s but got %s for LineText %s", test.expectedSuggestion, suggestion, test.problem.LineText)
		}
	}
}

func TestLintStutter(t *testing.T) {
	var testcases = []struct {
		problem            lint.Problem
		expectedSuggestion string
	}{
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "func name will be used as bar.BarFunc by other packages, and that stutters; consider calling this Func",
				Link:       "https://golang.org/wiki/CodeReviewComments#package-names",
				Category:   "naming",
				LineText:   "func BarFunc() error {",
				Confidence: 100.00,
			},
			expectedSuggestion: "```suggestion\nfunc Func() error {```\n",
		},
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "type name will be used as bar.BarMaker by other packages, and that stutters; consider calling this Maker",
				Link:       "https://golang.org/wiki/CodeReviewComments#package-names",
				Category:   "naming",
				LineText:   "type BarMaker struct{}",
				Confidence: 100.00,
			},
			expectedSuggestion: "```suggestion\ntype Maker struct{}```\n",
		},
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "type name will be used as bar.Bar by other packages, and that stutters; consider calling this Bar",
				Link:       "https://golang.org/wiki/CodeReviewComments#package-names",
				Category:   "naming",
				LineText:   "type Bar struct{}",
				Confidence: 100.00,
			},
			expectedSuggestion: "",
		},
	}
	for _, test := range testcases {
		suggestion := SuggestCodeChange(test.problem)
		if suggestion != test.expectedSuggestion {
			t.Errorf("Excepted code suggestion %s but got %s for LineText %s", test.expectedSuggestion, suggestion, test.problem.LineText)
		}
	}
}

func TestLintErrorf(t *testing.T) {
	var testcases = []struct {
		problem            lint.Problem
		expectedSuggestion string
	}{
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "should replace errors.New(fmt.Sprintf(...)) with fmt.Errorf(...)",
				Link:       "",
				Category:   "error",
				LineText:   "        return errors.New(fmt.Sprintf(\"something %d\", x))",
				Confidence: 100.00,
			},
			expectedSuggestion: "```suggestion\n        return fmt.Errorf(\"something %d\", x)```\n",
		},
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "should replace errors.New(fmt.Sprintf(...)) with fmt.Errorf(...)",
				Link:       "",
				Category:   "error",
				LineText:   "        return errors.New(fmt.Sprintf(\"something %s %d\", fooFunc(foo), bar))",
				Confidence: 100.00,
			},
			expectedSuggestion: "```suggestion\n        return fmt.Errorf(\"something %s %d\", fooFunc(foo), bar)```\n",
		},
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "should replace errors.New(fmt.Sprintf(...)) with fmt.Errorf(...)",
				Link:       "",
				Category:   "error",
				LineText:   "        return errors.New(fmt.Sprintf(\"something %s %d\", fooFunc(barFunc(foo), string(x)), bar))",
				Confidence: 100.00,
			},
			expectedSuggestion: "```suggestion\n        return fmt.Errorf(\"something %s %d\", fooFunc(barFunc(foo), string(x)), bar)```\n",
		},
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "should replace errors.New(fmt.Sprintf(...)) with fmt.Errorf(...)",
				Link:       "",
				Category:   "error",
				LineText:   "        return fmt.Errorf(\"something %d\", x)",
				Confidence: 100.00,
			},
			expectedSuggestion: "",
		},
	}
	for _, test := range testcases {
		suggestion := SuggestCodeChange(test.problem)
		if suggestion != test.expectedSuggestion {
			t.Errorf("Excepted code suggestion %s but got %s for LineText %s", test.expectedSuggestion, suggestion, test.problem.LineText)
		}
	}
}

func TestLintLoopRanges(t *testing.T) {
	var testcases = []struct {
		problem            lint.Problem
		expectedSuggestion string
	}{
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "should omit values from range; this loop is equivalent to `for range ...`",
				Link:       "",
				Category:   "range-loop",
				LineText:   "for _ = range m {",
				Confidence: 100.00,
			},
			expectedSuggestion: "```suggestion\nfor range m {```\n",
		},
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "should omit values from range; this loop is equivalent to `for range ...`",
				Link:       "",
				Category:   "range-loop",
				LineText:   "for _, _ = range m {",
				Confidence: 100.00,
			},
			expectedSuggestion: "```suggestion\nfor range m {```\n",
		},
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "should omit 2nd value from range; this loop is equivalent to `for y = range ...`",
				Link:       "",
				Category:   "range-loop",
				LineText:   "for y, _ = range m {",
				Confidence: 100.00,
			},
			expectedSuggestion: "```suggestion\nfor y = range m {```\n",
		},
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "should omit 2nd value from range; this loop is equivalent to `for yVar1 = range ...`",
				Link:       "",
				Category:   "range-loop",
				LineText:   "for yVar1, _ = range m {",
				Confidence: 100.00,
			},
			expectedSuggestion: "```suggestion\nfor yVar1 = range m {```\n",
		},
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "should omit 2nd value from range; this loop is equivalent to `for y := range ...`",
				Link:       "",
				Category:   "range-loop",
				LineText:   "for y, _ := range m {",
				Confidence: 100.00,
			},
			expectedSuggestion: "```suggestion\nfor y := range m {```\n",
		},
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "should omit values from range; this loop is equivalent to `for range ...`",
				Link:       "",
				Category:   "range-loop",
				LineText:   "for range m {",
				Confidence: 100.00,
			},
			expectedSuggestion: "",
		},
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "should omit 2nd value from range; this loop is equivalent to `for y = range ...`",
				Link:       "",
				Category:   "range-loop",
				LineText:   "for y = range m {",
				Confidence: 100.00,
			},
			expectedSuggestion: "",
		},
	}
	for _, test := range testcases {
		suggestion := SuggestCodeChange(test.problem)
		if suggestion != test.expectedSuggestion {
			t.Errorf("Excepted code suggestion %s but got %s for LineText %s", test.expectedSuggestion, suggestion, test.problem.LineText)
		}
	}
}

func TestLintVarDecl(t *testing.T) {
	var testcases = []struct {
		problem            lint.Problem
		expectedSuggestion string
	}{
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "should omit type int from declaration of var myInt; it will be inferred from the right-hand side",
				Link:       "",
				Category:   "type-inference",
				LineText:   "var myInt int = 7",
				Confidence: 100.00,
			},
			expectedSuggestion: "```suggestion\nvar myInt = 7```\n",
		},
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "should drop = 0 from declaration of var myZeroInt; it is the zero value",
				Link:       "",
				Category:   "zero-value",
				LineText:   "var myZeroInt int = 0",
				Confidence: 100.00,
			},
			expectedSuggestion: "```suggestion\nvar myZeroInt int```\n",
		},
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "should drop = 0. from declaration of var myZeroFlt; it is the zero value",
				Link:       "",
				Category:   "zero-value",
				LineText:   "var myZeroFlt float32 = 0.",
				Confidence: 100.00,
			},
			expectedSuggestion: "```suggestion\nvar myZeroFlt float32```\n",
		},
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "should drop = 0.0 from declaration of var myZeroF64; it is the zero value",
				Link:       "",
				Category:   "zero-value",
				LineText:   "var myZeroF64 float64 = 0.0",
				Confidence: 100.00,
			},
			expectedSuggestion: "```suggestion\nvar myZeroF64 float64```\n",
		},
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "should drop = 0i from declaration of var myZeroImg; it is the zero value",
				Link:       "",
				Category:   "zero-value",
				LineText:   "var myZeroImg complex64 = 0i",
				Confidence: 100.00,
			},
			expectedSuggestion: "```suggestion\nvar myZeroImg complex64```\n",
		},
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "should drop = \"\" from declaration of var myZeroStr; it is the zero value",
				Link:       "",
				Category:   "zero-value",
				LineText:   "var myZeroStr string = \"\"",
				Confidence: 100.00,
			},
			expectedSuggestion: "```suggestion\nvar myZeroStr string```\n",
		},
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "should drop = `` from declaration of var myZeroStr; it is the zero value",
				Link:       "",
				Category:   "zero-value",
				LineText:   "var myZeroStr string = ``",
				Confidence: 100.00,
			},
			expectedSuggestion: "```suggestion\nvar myZeroStr string```\n",
		},
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "should drop = nil from declaration of var myZeroPtr; it is the zero value",
				Link:       "",
				Category:   "zero-value",
				LineText:   "var myZeroPtr *Q = nil",
				Confidence: 100.00,
			},
			expectedSuggestion: "```suggestion\nvar myZeroPtr *Q```\n",
		},
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "should drop = '\\x00' from declaration of var myZeroRune; it is the zero value",
				Link:       "",
				Category:   "zero-value",
				LineText:   "var myZeroRune rune = '\\x00'",
				Confidence: 100.00,
			},
			expectedSuggestion: "```suggestion\nvar myZeroRune rune```\n",
		},
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "should drop = '\\000' from declaration of var myZeroRune2; it is the zero value",
				Link:       "",
				Category:   "zero-value",
				LineText:   "var myZeroRune2 rune = '\\000'",
				Confidence: 100.00,
			},
			expectedSuggestion: "```suggestion\nvar myZeroRune2 rune```\n",
		},
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "should drop = `` from declaration of var myZeroStr; it is the zero value",
				Link:       "",
				Category:   "zero-value",
				LineText:   "var myZeroStr string",
				Confidence: 100.00,
			},
			expectedSuggestion: "",
		},
		{
			problem: lint.Problem{
				Position: token.Position{
					Filename: "qux.go",
				},
				Text:       "should omit type int from declaration of var myInt; it will be inferred from the right-hand side",
				Link:       "",
				Category:   "type-inference",
				LineText:   "var myInt = 7",
				Confidence: 100.00,
			},
			expectedSuggestion: "",
		},
	}
	for _, test := range testcases {
		suggestion := SuggestCodeChange(test.problem)
		if suggestion != test.expectedSuggestion {
			t.Errorf("Excepted code suggestion %s but got %s for LineText %s", test.expectedSuggestion, suggestion, test.problem.LineText)
		}
	}
}


text:
maintainer       'Cory Roloff'
license          'Apache 2.0'
description      'Installs and configures an NPM registry'
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
name             'npm_registry'
version          '0.2.0'

recipe           'npm_registry', 'Installs and configures an NPM registry'

%w{git couchdb nodejs}.each do |cookbook|
  depends cookbook
end

%w{cron}.each do |cookbook|
  suggests cookbook
end

%w{ubuntu}.each do |os|
  supports os
end


text:
/*---------------------------------------------------------------------------------
/*
/* Main JS
/*
-----------------------------------------------------------------------------------*/

(function($) {

	"use strict";

	/*---------------------------------------------------- */
	/* Preloader
	------------------------------------------------------ */
   $(window).load(function() {

      // will first fade out the loading animation
    	$("#loader").fadeOut("slow", function(){

        // will fade out the whole DIV that covers the website.
        $("#preloader").delay(300).fadeOut("slow");

      });

  	})

  	/*----------------------------------------------------*/
  	/* Flexslider
  	/*----------------------------------------------------*/
  	$(window).load(function() {

	  	$('#hero-slider').flexslider({
	   	namespace: "flex-",
	      controlsContainer: ".hero-container",
	      animation: 'fade',
	      controlNav: true,
	      directionNav: false,
	      smoothHeight: true,
	      slideshowSpeed: 7000,
	      animationSpeed: 600,
	      randomize: false,
	      before: function(slider){
			   $(slider).find(".animated").each(function(){
			   	$(this).removeAttr("class");
			  	});
			},
			start: function(slider){
			   $(slider).find(".flex-active-slide")
			           	.find("h1").addClass("animated fadeInDown show")
			           	.next().addClass("animated fadeInUp show");

			   $(window).trigger('resize');
			},
			after: function(slider){
			 	$(slider).find(".flex-active-slide")
			           	.find("h1").addClass("animated fadeInDown show")
			           	.next().addClass("animated fadeInUp show");
			}
	   });

	   $('#testimonial-slider').flexslider({
	   	namespace: "flex-",
	      controlsContainer: "",
	      animation: 'slide',
	      controlNav: true,
	      directionNav: false,
	      smoothHeight: true,
	      slideshowSpeed: 7000,
	      animationSpeed: 600,
	      randomize: false,
	   });

   });

   /*----------------------------------------------------*/
	/* Adjust Primary Navigation Background Opacity
	------------------------------------------------------*/
   $(window).on('scroll', function() {

		var h = $('header').height();
		var y = $(window).scrollTop();
      var header = $('#main-header');

	   if ((y > h + 30 ) && ($(window).outerWidth() > 768 ) ) {
	      header.addClass('opaque');
	   }
      else {
         if (y < h + 30) {
            header.removeClass('opaque');
         }
         else {
            header.addClass('opaque');
         }
      }

	});

   /*----------------------------------------------------*/
  	/* Highlight the current section in the navigation bar
  	------------------------------------------------------*/
	var sections = $("section"),
	navigation_links = $("#nav-wrap a");

	sections.waypoint( {

       handler: function(direction) {

		   var active_section;

			active_section = $('section#' + this.element.id);

			if (direction === "up") active_section = active_section.prev();

			var active_link = $('#nav-wrap a[href="#' + active_section.attr("id") + '"]');

         navigation_links.parent().removeClass("current");
			active_link.parent().addClass("current");

		},

		offset: '25%'

	});

   /*----------------------------------------------------*/
  	/* FitText Settings
  	------------------------------------------------------ */
  	setTimeout(function() {

   	$('#hero-slider h1').fitText(1, { minFontSize: '30px', maxFontSize: '49px' });

  	}, 100);

  	/*-----------------------------------------------------*/
  	/* Mobile Menu
   ------------------------------------------------------ */
   var menu_icon = $("Menu");
  	var toggle_button = $("", {
                        id: "toggle-btn",
                        html : "",
                        title: "Menu",
                        href : "#" }
                        );
  	var nav_wrap = $('nav#nav-wrap')
  	var nav = $("ul#nav");

   /* if JS is enabled, remove the two a.mobile-btns
  	and dynamically prepend a.toggle-btn to #nav-wrap */
  	nav_wrap.find('a.mobile-btn').remove();
  	toggle_button.append(menu_icon);
   nav_wrap.prepend(toggle_button);

  	toggle_button.on("click", function(e) {
   	e.preventDefault();
    	nav.slideToggle("fast");
  	});

  	if (toggle_button.is(':visible')) nav.addClass('mobile');
  	$(window).resize(function() {
   	if (toggle_button.is(':visible')) nav.addClass('mobile');
    	else nav.removeClass('mobile');
  	});

  	$('ul#nav li a').on("click", function() {
   	if (nav.hasClass('mobile')) nav.fadeOut('fast');
  	});

  	/*----------------------------------------------------*/
  	/* Smooth Scrolling
  	------------------------------------------------------ */
  	$('.smoothscroll').on('click', function (e) {

	 	e.preventDefault();

   	var target = this.hash,
    	$target = $(target);

    	$('html, body').stop().animate({
       	'scrollTop': $target.offset().top
      }, 800, 'swing', function () {
      	window.location.hash = target;
      });

  	});

   /*----------------------------------------------------*/
	/*	Modal Popup
	------------------------------------------------------*/
    $('.item-wrap a').magnificPopup({

       type:'inline',
       fixedContentPos: false,
       removalDelay: 300,
       showCloseBtn: false,
       mainClass: 'mfp-fade'

    });

    $(document).on('click', '.popup-modal-dismiss', function (e) {
    		e.preventDefault();
    		$.magnificPopup.close();
    });

   /*----------------------------------------------------*/
	/*  Placeholder Plugin Settings
	------------------------------------------------------ */
	$('input, textarea').placeholder()

	/*----------------------------------------------------*/
	/*	contact form
	------------------------------------------------------*/

	/* local validation */
	$('#contactForm').validate({

		/* submit via ajax */
		submitHandler: function(form) {

			var sLoader = $('#submit-loader');

			$.ajax({

		      type: "POST",
		      url: "inc/sendEmail.php",
		      data: $(form).serialize(),
		      beforeSend: function() {

		      	sLoader.fadeIn();

		      },
		      success: function(msg) {

	            // Message was sent
	            if (msg == 'OK') {
	            	sLoader.fadeOut();
	               $('#message-warning').hide();
	               $('#contactForm').fadeOut();
	               $('#message-success').fadeIn();
	            }
	            // There was an error
	            else {
	            	sLoader.fadeOut();
	               $('#message-warning').html(msg);
		            $('#message-warning').fadeIn();
	            }

		      },
		      error: function() {

		      	sLoader.fadeOut();
		      	$('#message-warning').html("Something went wrong. Please try again.");
		         $('#message-warning').fadeIn();

		      }

	      });
  		}

	});

})(jQuery);


text:
import Adapter from '@wojtekmaj/enzyme-adapter-react-17';
import Enzyme, { mount } from 'enzyme';
import Input from '../input';

// Temporary use of adapter until Enzyme is compatible with React 17.
Enzyme.configure({ adapter: new Adapter() });

describe('Gene search input', () => {
    test('Input renders, contains text and ref', () => {
        const func = jest.fn();
        let inputRef = null;
        const inputBox = mount(
            <Input
                input="ep300"
                onChange={func}
                ref={(current) => { inputRef = current; }}
            />
        );
        expect(
            inputBox.find('input').props().value
        ).toEqual('ep300');
        expect(
            inputBox.find('input').props().placeholder
        ).toEqual('Enter gene name here');
        expect(
            inputRef.value
        ).toEqual('ep300');
        inputRef.value = 'new value';
        expect(
            inputRef.value
        ).toEqual('new value');
    });
    test('Input fires function on change', () => {
        const func = jest.fn();
        const inputBox = mount(
            <Input
                input="hello"
                onChange={func}
            />
        );
        expect(func).toHaveBeenCalledTimes(0);
        inputBox.simulate('change');
        expect(func).toHaveBeenCalledTimes(1);
    });
});


text:
<?php
/**
 * jqGrid widget
 */
use Sfcms\JqGrid\Provider;

function smarty_function_jqgrid($params, $smarty)
{
    if (!isset($params['provider']) || !$params['provider'] instanceof Provider) {
        return 'Provider not defined';
    }
    /** @var $provider Provider */
    $provider = $params['provider'];
    $name     = isset($params['name']) ? $params['name'] : 'jqgrid';

    $config = $provider->getConfig($name, $params);

    return sprintf(
        '
'
            . '

',
        $name,
        json_encode($config),
        $name
    );
}


text:
layout: doc
title: OsmAnd 2.0+
permalink: /it/mobile-mapping/osmand2/
lang: it
category: mobile-mapping
---

OsmAnd 2.x
==========

OsmAnd (OSM Automated Navigation Directions) è un'applicazione open source per vedere le mappe, modificarle, registrare tracce e andare in giro che utilizza il database OpenStreetMap (OSM) per uso sia online che offline. Comprende anche una funzionalità di instradamento e navigazione, con guida visuale e vocale, che è disponibile sia online che offline. OsmAnd consente agli utenti di contribuire direttamente a OpenStreetMap riportando errori, caricando tracce GPX, e aggiungendo (o modificando) Punti di Interesse (PDI).

La versione iOS è disponibile su iTunes.

>Alcune delle caratteristiche di OsmAnd sulla piattaforma Android possono essere non ancora disponibili sull'edizione iOS. Guarda sul [sito blog](http://osmand.net/blog) degli sviluppatori per dettagli.

Oltre alle fonti precedenti, una versione mantenuta dalla comunità è disponibile su [F-Droid](https://f-droid.org/app/net.osmand.plus), o attraverso software di terze parti come [Amazon](http://www.amazon.com/OsmAnd-Maps-Navigation/dp/B00D0SA8I8).

Iniziare
---------------

OsmAnd consente di usare mappe online dinamiche, come pure database fuori-linea da OpenStreetMap che non richiedono una connessione internet. La seconda modalità richiede che siano stati eseguiti i passi necessari per scaricare e memorizzare il database offline sul proprio dispositivo.

La funzionalità fuori-linea (offline, senza necessità di connessione internet) di OsmAnd è uno dei suoi molti punti di forza. Perciò, una delle prime cose che un nuovo utente può voler fare è scaricare il/i database. E, se vi interessa la navigazione assistita vocale, dovrete scaricare anche i file vocali.

+ Premi l'icona **Opzioni** e seleziona **Gestione mappe**. Le varie voci della *Interfaccia Utente* sono descritte nella prossima sezione. Se si sta usando la versione gratuita dal Google Play Store, potrebbe comparire un finestra di dialogo. Se compare, semplicemente selezionate "Ok". La versione f-Droid mantenuta dalla comunità non presenta questa finestra di dialogo.

Dalla finestra che viene mostrata, si possono gestire tutti i file online raster, i database offline vettoriali, ed i file vocali usati dalla app OsmAnd.

+ Sotto la linguetta *TUTTI I DOWNLOAD* sono visualizzati tutti i file disponibili sul server OsmAnd.
+ Dalla linguetta *NEL DISPOSITIVO* sono elencate le mappe, messaggi vocali e registrazioni audio/video nel vostro dispositivo.
+ Dalla linguetta "AGGIORNABILI" sono mostrati i file locali che sono obsoleti e devono essere aggiornati dal server OsmAnd.

![Download][]

Per scaricare il database di un'area geografica, selezionate la linguetta *TUTTI I DOWNLOAD* e scrivete un nome o la zona geografica che vi interessa.

![Download db][]

Dopo aver selezionato i file, premete il pulsante download dal pulsante opzioni. A seconda della vostra connessione internet o del numero di file selezionati, possono essere necessari svariati minuti. Una volta scaricati i file, siete pronti ad usare la modalità offline di OsmAnd.

Una delle caratteristiche uniche della versione F-Droid della comunità, è la frequenza illimitata di download che potete fare dalla app stessa. La versione gratuita del Play store è limitata a solo dieci download. Una soluzione a questo limite è di scaricare  sul vostro pc il database da [http://download.osmand.net/rawindexes/](http://download.osmand.net/rawindexes/), e poi trasferirli manualmente sul vostro dispositivo.

I database predisposti che sono stati appena scaricati sono anche chiamati "Mappe Vettoriali", e sono memorizzate nel formato .obf. Sono compatte, e consentono agli utenti offline di zoomare fino ad un grande livello di dettaglio.

Interfaccia utente
--------------------------

![Canvass Elements][]

Il recente aggiornamento di OsmAnd per Android alla versione 2.x (e OsmAnd DVR su iOS alla 3.x) migliora l'interfaccia con lo stile Material Design, e ora include un cruscotto con diverse schede, uno stile più amichevole, e modifiche semplificate per i Punti-di-Interesse (PDI) e per le Note di OpenStreetMap.

La mappa mostrerà vie, strade, uso del terreno, PDI, corsi d'acqua, e molti altri dati geografici.

In più, usando i pulsanti dell'interfaccia:

- Il pulsante "Configura la Mappa" presenta un menu per selezionare il profilo da usare. Potete scegliere tra: Naviga Mappa, Auto, Bicicletta, Pedoni per specificare quanti più o meno dettagli saranno mostrati. E' anche mostrato
come i PDI, le Etichette, i percorsi GPX, le Note OSM e i Preferiti sono visualizzati.
- "Orientamento" cambia l'orientamento della mappa, e mostrerà una diversa icona del compasso a seconda del metodo di orientamento scelto.

Nel pannello in alto a destra della schermata potete notare **Informazione GPS**, che visualizza il numero di satelliti a cui il vostro dispositivo è connesso, ed il numero di satelliti visibili sull'orizzonte. **Registra Traccia** è visibile quando il componente aggiuntivo *Registrazione Tracce* è abilitato. Lo stesso vale per lo **Strumento Righello**, se il componente aggiuntivo *Calcolatore Distanze e Strumento Pianificazione* è abilitato. Ulteriori pulsanti possono o meno essere visibili a seconda di come sono stati impostati o di come certi plugin sono stati abilitati.

Quando sul vostro dispositivo è abilitato il GPS o il posizionamento tramite rete, un **Indicatore Posizione** (le vostre coordinate sono in qualche punto del cerchio blu) visualizza la vostra posizione approssimativa sulla mappa. Premendo il pulsante **Dove Sono** centra la mappa sulla locazione GPS corrente o l'ultima conosciuta. Il contorno dell'icona è blu quando l'informazione di posizione è disponibile, e grigio quando la posizione non è ancora nota.

Il **Pannello di controllo** (prima voce del menu Opzioni) mostra diverse schede informative, tra cui le opzioni *Cerca*, *Cronologia*, *Le mie Tracce*, e *Componenti aggiuntivi*.

**Scala e zoom** indica il livello di zoom attualmente usato nella schermata. Le unità di misura possono essere impostate a Metriche o a Inglesi (in piedi e yard), da *Opzioni\>Impostazioni\>Impostazioni Generali\>Unità di Misura.*

Il pulsante **Navigazione** apre una finestra di dialogo per fissare le rotte di navigazione Da e A che sono appropriate per la modalità di trasporto scelta (per es. auto, bici, o a piedi).

I pulsanti **Zoom** consentono di zoomare più o meno sulla mappa. Toccando due volte su un'area che vi interessa farà posizionare quel punto al centro della mappa e lo zoomerà, per mostrare maggiori dettagli.

Quando premete il pulsante **Dove sono**, la mappa è centrata nella locazione GPS corrente o nell'ultima conosciuta.

> Se le tue schermate sono un po' diverse, probabilmente dovrai abilitare o scaricare qualche plugin.

Navigazione
--------------------------

Trascina un dito sullo schermo per spostarti su altre aree della mappa. Una pressione più lunga sullo schermo mostrerà una finestrella con un segnaposto sul punto specificato.

![Long Press Pop-up][]

Premi su questa finestrella per visualizzare un **Menu Contestuale** per il punto specificato.

![Long Press Menu][]

#### Menu contestuale

Il Menu Contestuale visualizza opzioni aggiuntive relative alla selezione del punto specificato.

+ **Indicazioni da, Aggiungi un punto intermedio GPX** sono opzioni relative ai percorsi di navigazione.
+ **Cerca nelle vicinanze** fornisce una ricerca localizzata, limitata ai PDI disponibili nel database installato.

Se il plugin *Note audio/video* è installato, sono anche mostrate ulteriori opzioni relative all'acquisizione multimediale: **Prendi una nota audio**, **Prendi una nota video**, e **Scatta una foto**.

Per aggiungere un nuovo PDI direttamente ad OpenStreetMap usando le coordinate specificate, selezionare **Crea PDI**. Usare **Apri una nota di OSM** per segnalazioni tipo errori, o per lasciare dei commenti ad altri mappatori che operano nella stessa zona.

L'opzione **Crea PDI** è disponibile solo quando è abilitato il plugin *Modifiche OSM*. Imposta questa opzione da *Opzioni\>Componenti aggiuntivi*.

Modifiche OSM
--------------------------------

### Setup
Per abilitare la possibilità di aggiungere o modificare dati a OpenStreetMap, OsmAnd deve essere configurato con le vostre credenziali OpenStreetMap. Premi il pulsante **Opzioni** e scorri fino alla voce *Componenti aggiuntivi*; selezionalo e poi alla voce "Modifiche OSM",  seleziona *altre azioni* (i tre puntini verticali) e quindi *Impostazioni*.

![osm plugin][]

Per impostare le vostre credenziali per modificare OSM devi già avere preimpostato un nome utente e una password OpenStreetMap.

![osm creds][]

### Aggiungere PDI

Metodo 1: Indica una locazione tenendo premuto sul punto che interessa della mappa e poi cliccando sulla finestrella che compare per visualizzare il **menu Contestuale**.

Metodo 2: Usa le coordinate ricavate dal GPS premendo il pulsante **Dove sono** e poi premendo **Opzioni** e selezionando **Usa la posizione**. Ora seleziona **Crea PDI** dal **menu Contestuale** per aggiungere un nuovo elemento, con associate le opportune etichette. Aggiungi le informazioni del PDI: nome, tipo di elemento, ed un commento che spiega l'elemento che state aggiungendo.

![poi basic][]

In modo "ESTESO" si possono aggiungere più etichette.

![poi advanced][]

Quando hai terminato, seleziona **Salva**.

### Modificare i PDI

#### Mostrare o visualizzare i PDI

Per poter modificare i PDI, assicurati che siano abilitati alla loro visualizzazione su schermo selezionando **Configura la mappa** dalle **Opzioni** e abilitando quindi la voce PDI e selezionando la categoria di PDI che vi interessa.

![poi show][]

![poi show eats][]

Dall'elenco delle categorie di PDI, volendo visualizzare più categorie, seleziona *Cerca* e poi *RICERCA PERSONALIZZATA* (in fondo all'elenco). Viene così ripresentato l'elenco delle categorie consentendo di selezionarle ad una ad una; quando una categoria è selezionata viene visualizzato l'elenco delle sue sottocategorie, e anche qui possono essere selezionate singolarmente quelle che interessano.

Nello schermata successiva, questo filtro personalizzato può essere salvato per essere riutilizzato premendo **MOSTRA** (in basso a destra) e quindi il pulsante blu di salvataggio (verrà richiesto di assegnare un nome al filtro personalizzato).

![poi custom][]

Il filtro personalizzato "All" è ora mostrato nella lista di selezione quando si filtrano i PDI.

![poi custom2][]

#### Modifiche

Ora che i PDI sono visualizzati sulla mappa come pallini arancioni, tenendo premuto su uno di questi sarà visualizzato il nome dell'elemento. Premere sulla finestrella per visualizzare il **menu Contestuale**. Sono disponibili due ulteriori opzioni:

- **Modifica PDI** per modificarlo, e
- **Cancella PDI**.

Sarà visualizzata una finestra dove si possono modificare a piacere i campi dei PDI. E' buona pratica aggiungere un commento o delle note quando si modificano i PDI. L'editor dei PDI è la stessa schermata usata per aggiungere PDI.

![poi edit1][]

Si è limitati a poter modificare solo PDI e elementi-punto. Poligoni ed aree saranno visualizzati sempre con punti arancione, ma sarà visualizzato solo il nome dell'elemento, non essendo disponibile il **menu Contestuale**.

### Aggiungere Note e Commenti, Segnalare Errori, Chiudere Errori

Un altro modo di contribuire ad OpenStreetMap è lasciando delle Note, con lo scopo di segnalazione generica, o segnalando errori o resoconti che saranno utilizzabili da altri mappatori attivi nella zona. Per visualizzare le Note sulla mappa, selezionare **Configura la mappa** e verifica che le **Note OSM** siano selezionate. Devi anche essere online tramite una connessione WiFi, o un piano dati telefonico del cellulare.

#### Aggiungere Note e riportare Errori

Per aggiungere una Nota o riportare un errore, attivare **Usa posizione** dal menu o selezionare una locazione sulla mappa (vedi Aggiungere PDI nella sezione precedemte).

![note][]

Quando una locazione è stata impostata o specificata, seleziona **Apri una Nota di OSM** dal menu Altre Azioni ed una nuova finestra modale comparirà sul video. Scrivete la nota o la segnalazione di errore. Se è la prima volta che usate il modulo aggiuntivo, tenete pronte le vostre credenziali OpenStreetMap. Potete anche lasciare dei commenti anonimi non inserendo le vostre credenziali.

![note2][]

A seconda delle impostazioni del dispositivo, e della connettività internet, le modifiche e le note sono mandate direttamente al server OpenStreetMap o memorizzate localmente sul dispositivo finché non sarà disponibile una connessione internet. Vedi il prossimo capitolo *Modifiche online ed offline* per ulteriori dettagli.

Gli errori sono visualizati sulla mappa in diversi colori:

- giallo (locali, ancora sul dispositivo).
- rosso (nota/errore aperto, riportato al server) oppure
- verde (nota risolta/chiusa sul server).

![note1][]

Configurazione
--------------------------------

### Modifiche Online ed Offline

Se avete un piano dati telefonico non limitato, potete lasciare disabilitata / non contrassegnata l'opzione *Modifiche offline* nelle *impostazioni del componente aggiuntivo Modifiche OSM*. Questo farà inviare le vostre modifiche e contributi a OpenStreetMap non appena le avete salvate. Nel caso non sia disponibile la connettività internet, i dati sono temporaneamente memorizzati sul dispositivo, ed inviati non appena la connessione internet è ripristinata.

Se vuoi limitare il traffico internet sul dispositivo, abilita *Modifiche offline* ed invia manualmente le tue modifiche e note quando hai possibilità di connetterti ad internet. Le modifiche che hai fatto offline rimarranno sul dispositivo finché non ti connetterai ad internet.

Puoi gestire i dati parcheggiati sul dispositivo da **Opzioni \> Componenti aggiuntivi \> Modifiche OSM \> Impostazioni** e selezionare l'opzione **PDI/Note OSM salvati in locale**. I dati elencati in questa finestra sono codificati per colore: verde è per PDI nuovo o modificato, e rosso per PDI che hai contrassegnato per la cancellazione.

![locally saved bugs][]

A questo punto, hai l'alternativa se caricare i dati su OSM o esportarli al tuo PC.

Raccogliere tracce GPX
---------------------

Prima di registrare tracce GPX, verifica che il componente aggiuntivo **Registrazione viaggio** sia abilitato in **Opzioni \> Componenti aggiuntivi**. Se il componente non è elencato, seleziona *Mostra tutti* e trovalo nella lista.

![Enable Trip recording][]

Per registrare opportunamente note audio o video dalla videata principale, abilita il componente **Note audio/video** da **Opzioni \> Componenti aggiuntivi**. Se scatti sovente delle foto, invece di note audio o video, cambia l'azione predefinita per il widget Audio/Video. Vai a **Opzioni \> Componenti aggiuntivi \> Note audio/video \> Impostazioni \> Azione predefinita del widget** ed imposta **Scatta una foto** come azione predefinita.

![Right panel gpx photo][]

Raccogliere Foto, note Video o Audio.
-------------------------------------------

Per registrare una foto (o video, o nota audio) di un certo elemento, tieni premuto sulla sua locazione nella mappa, quindi seleziona la finestra di dialogo che compare e scegli un'azione: prendi una nota audio, prendi una nota video, scatta una foto, o seleziona un'altra scelta dal menu contestuale.

![Taking audio, photo or notes][]

Visualizzare tracce GPX
--------------------------------------------

Per visualizzare le tracce GPX, seleziona **Opzioni \> Configura la mappa** ed abilita l'opzione **Percorso GPX..**. Sarà visualizzata un lista di opzioni compresa la traccia corrente che potresti star registrando, o altre tracce GPX registrate o memorizzate in precedenza nella cartella OsmAnd del tuo dispositivo.

Mostrare le tracce GPX sulla mappa è utile per tenere traccia dell'avanzamento mentre stai procedendo, e per controllare se hai dimenticato qualcosa lungo il percorso.

![Display GPS tracks][]

Qui sotto è riportato un esempio di come le tracce ed i waypoint sono riportati sulla mappa. La traccia è visualizzata con una linea azzurra, ed i waypoint sono delle stelle bianche dentro un cerchio rosso.

![Show GPS tracks and waypoints][]

Esportare le tracce GPX all'editor OpenStreetMap
--------------------------------------------

Quando hai finito di raccogliere dati sul campo, puoi importare le tracce GPX per usarle in JOSM, iD, o in un altro editor OpenStreetMap.

Connetti il tuo dispositivo ad un computer (usando un cavo dati, Bluetooth o una connessione internet) e copia le tracce GPX e (se ci sono) i file multimedali che hai registrato. Nella memoria del tuo dispositivo, cerca le tracce GPX nella cartella /osmand/tracks, e i file multimediali in /osmand/avnotes/.

Usare le tracce GPX negli editor JOSM e iD è facile, basta trascinare i file e rilasciarli nell'applicazione (o nella finestra del browser, per iD).

- altre informazioni su iD in [Configurare il livello di sfondo](/it/beginner/id-editor/#configuring-the-background-layer).
- altre informazioni su JOSM in [Apri in JOSM](/it/mobile-mapping/using-gps/#open-in-josm)
- Per altri editor OpenStreetMap, riferitevi alla vostra documentazione dei programmi.

Usare OsmAnd con FieldPapers e JOSM
--------------------------------------

[FieldPapers](http://fieldpapers.org) è uno degli strumenti "a bassa tecnologia" favoriti, usato da molti mappatori. [Qui c'è materiale informativo su FieldPapers](/it/mobile-mapping/field-papers/).

> Il seguente protocollo è stato sviluppato durante un'attività di mappatura sul campo in Bangladesh. Leggi il post originale [qui](https://wiki.openstreetmap.org/wiki/Field_Papers#How_to_use_with_OsmAnd).

* Esporta Field Papers normalmente come PDF, e scarica lo shapefile sul tuo PC
* Verifica che il plugin OpenData sia installato in JOSM, quindi apri lo shapefile che hai appena scaricato.
* Usa le linee per scrivere i numeri di griglia in ciascuna cella
* Esportalo come GPX
* Caricalo nel dispositivo nella cartella */osmand/tracks*
* Su OsmAnd, verifica che sia abilitato in **Configura la mappa \> Percorso GPX...**, seleziona la traccia che hai appena fatto e premi *OK*. Vedi il capitolo precedente di questa guida *visualizzare le tracce GPX*

La traccia GPX è ora visibile sulla mappa OsmAnd.

Sommario
-------------------

Eccellente! Ora puoi usare lo smartphone per raccogliere dati sul campo che poi puoi aggiungere al database OpenStreetMap, come alternativa ai ricevitori GPS dedicati. L'ampia disponibilità di smartphone con il GPS (e/o GLONASS) apre nuove opportunità per raccogliere ed aggiornare i dati OpenStreetMap da parte di mappatori occasionali.

Prenditi del tempo per impratichirti e famigliarizzare con la app prima di operare con dati dal vivo.

Questo capitolo introduce il concetto di uso di OsmAnd per raccogliere tracce GPX, modifcare o cancellare PDI, oltre ad aggiungere, commentare o chiudere Note/Errori e come trasferire questi file su PC.

Documentazione ufficiale di OsmAnd
-------------------

Ulteriore materiale di riferimento è disponibile nella sezione [help](http://osmand.net/help/) del sito web di OsmAnd.

I dettagli relativi alla legenda in uso nello stile predefinito della mappa sono nella loro [pagina apposita](http://osmand.net/help-online/map-legend).

[Canvass Elements]: /images/mobile-mapping/osmand2_000_it.png
[Long Press Pop-up]: /images/mobile-mapping/osmand2_001a_it.png
[Long Press Menu]: /images/mobile-mapping/osmand2_001b_it.png
[Download]: /images/mobile-mapping/osmand2_002a_it.png
[Download db]: /images/mobile-mapping/osmand2_002b_it.png
[osm plugin]: /images/mobile-mapping/osmand2_003_it.png
[osm creds]: /images/mobile-mapping/osmand2_003b_it.png
[poi basic]: /images/mobile-mapping/osmand2_004a_it.png
[poi advanced]: /images/mobile-mapping/osmand2_004b_it.png
[poi show]: /images/mobile-mapping/osmand2_005a_it.png
[poi show eats]: /images/mobile-mapping/osmand2_005b_it.png
[poi custom]: /images/mobile-mapping/osmand2_005c_it.png
[poi custom2]: /images/mobile-mapping/osmand2_005d_it.png
[poi edit1]: /images/mobile-mapping/osmand2_006a_it.png
[note]: /images/mobile-mapping/osmand2_007a_it.png
[note0]: /images/mobile-mapping/osmand2_007b_it.png
[note1]: /images/mobile-mapping/osmand2_008b_it.png
[note2]: /images/mobile-mapping/osmand2_007c_it.png
[locally saved bugs]: /images/mobile-mapping/osmand2_008a_it.png
[Enable Trip Recording]: /images/mobile-mapping/osmand2_009a_it.png
[Right panel gpx photo]: /images/mobile-mapping/osmand2_009b_it.png
[Taking audio, photo or notes]: /images/mobile-mapping/osmand2_009c_it.png
[Display GPS tracks]: /images/mobile-mapping/osmand2_009d_it.png
[Show GPS tracks and waypoints]: /images/mobile-mapping/osmand2_010a_it.png