text:
#pragma once

#include <fcntl.h>
#include <unistd.h>

#include <folly/io/PortableSpinLock.h>
#include <folly/io/async/EventBase.h>
#include <folly/io/async/EventHandler.h>
#include <folly/io/async/Request.h>
#include <folly/Likely.h>
#include <folly/ScopeGuard.h>

#include <glog/logging.h>
#include <deque>

#if __linux__ && !__ANDROID__
#define FOLLY_HAVE_EVENTFD
#include <folly/io/async/EventFDWrapper.h>
#endif

namespace folly {

/**
 * A producer-consumer queue for passing messages between EventBase threads.
 *
 * Messages can be added to the queue from any thread.  Multiple consumers may
 * listen to the queue from multiple EventBase threads.
 *
 * A NotificationQueue may not be destroyed while there are still consumers
 * registered to receive events from the queue.  It is the user's
 * responsibility to ensure that all consumers are unregistered before the
 * queue is destroyed.
 *
 * MessageT should be MoveConstructible (i.e., must support either a move
 * constructor or a copy constructor, or both).  Ideally it's move constructor
 * (or copy constructor if no move constructor is provided) should never throw
 * exceptions.  If the constructor may throw, the consumers could end up
 * spinning trying to move a message off the queue and failing, and then
 * retrying.
 */
template<typename MessageT>
class NotificationQueue {
 public:
  /**
   * A callback interface for consuming messages from the queue as they arrive.
   */
  class Consumer : private EventHandler {
   public:
    enum : uint16_t { kDefaultMaxReadAtOnce = 10 };

    Consumer()
      : queue_(nullptr),
        destroyedFlagPtr_(nullptr),
        maxReadAtOnce_(kDefaultMaxReadAtOnce) {}

    virtual ~Consumer();

    /**
     * messageAvailable() will be invoked whenever a new
     * message is available from the pipe.
     */
    virtual void messageAvailable(MessageT&& message) = 0;

    /**
     * Begin consuming messages from the specified queue.
     *
     * messageAvailable() will be called whenever a message is available.  This
     * consumer will continue to consume messages until stopConsuming() is
     * called.
     *
     * A Consumer may only consume messages from a single NotificationQueue at
     * a time.  startConsuming() should not be called if this consumer is
     * already consuming.
     */
    void startConsuming(EventBase* eventBase, NotificationQueue* queue) {
      init(eventBase, queue);
      registerHandler(READ | PERSIST);
    }

    /**
     * Same as above but registers this event handler as internal so that it
     * doesn't count towards the pending reader count for the IOLoop.
     */
    void startConsumingInternal(
        EventBase* eventBase, NotificationQueue* queue) {
      init(eventBase, queue);
      registerInternalHandler(READ | PERSIST);
    }

    /**
     * Stop consuming messages.
     *
     * startConsuming() may be called again to resume consumption of messages
     * at a later point in time.
     */
    void stopConsuming();

    /**
     * Get the NotificationQueue that this consumer is currently consuming
     * messages from.  Returns nullptr if the consumer is not currently
     * consuming events from any queue.
     */
    NotificationQueue* getCurrentQueue() const {
      return queue_;
    }

    /**
     * Set a limit on how many messages this consumer will read each iteration
     * around the event loop.
     *
     * This helps rate-limit how much work the Consumer will do each event loop
     * iteration, to prevent it from starving other event handlers.
     *
     * A limit of 0 means no limit will be enforced.  If unset, the limit
     * defaults to kDefaultMaxReadAtOnce (defined to 10 above).
     */
    void setMaxReadAtOnce(uint32_t maxAtOnce) {
      maxReadAtOnce_ = maxAtOnce;
    }
    uint32_t getMaxReadAtOnce() const {
      return maxReadAtOnce_;
    }

    EventBase* getEventBase() {
      return base_;
    }

    virtual void handlerReady(uint16_t events) noexcept;

   private:

    void setActive(bool active, bool shouldLock = false) {
      if (!queue_) {
        active_ = active;
        return;
      }
      if (shouldLock) {
        queue_->spinlock_.lock();
      }
      if (!active_ && active) {
        ++queue_->numActiveConsumers_;
      } else if (active_ && !active) {
        --queue_->numActiveConsumers_;
      }
      active_ = active;
      if (shouldLock) {
        queue_->spinlock_.unlock();
      }
    }
    void init(EventBase* eventBase, NotificationQueue* queue);

    NotificationQueue* queue_;
    bool* destroyedFlagPtr_;
    uint32_t maxReadAtOnce_;
    EventBase* base_;
    bool active_{false};
  };

  enum class FdType {
    PIPE,
#ifdef FOLLY_HAVE_EVENTFD
    EVENTFD,
#endif
  };

  /**
   * Create a new NotificationQueue.
   *
   * If the maxSize parameter is specified, this sets the maximum queue size
   * that will be enforced by tryPutMessage().  (This size is advisory, and may
   * be exceeded if producers explicitly use putMessage() instead of
   * tryPutMessage().)
   *
   * The fdType parameter determines the type of file descriptor used
   * internally to signal message availability.  The default (eventfd) is
   * preferable for performance and because it won't fail when the queue gets
   * too long.  It is not available on on older and non-linux kernels, however.
   * In this case the code will fall back to using a pipe, the parameter is
   * mostly for testing purposes.
   */
  explicit NotificationQueue(uint32_t maxSize = 0,
#ifdef FOLLY_HAVE_EVENTFD
                             FdType fdType = FdType::EVENTFD)
#else
                             FdType fdType = FdType::PIPE)
#endif
    : eventfd_(-1),
      pipeFds_{-1, -1},
      advisoryMaxQueueSize_(maxSize),
      pid_(getpid()),
      queue_() {

    RequestContext::getStaticContext();

#ifdef FOLLY_HAVE_EVENTFD
    if (fdType == FdType::EVENTFD) {
      eventfd_ = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK | EFD_SEMAPHORE);
      if (eventfd_ == -1) {
        if (errno == ENOSYS || errno == EINVAL) {
          // eventfd not availalble
          LOG(ERROR) << "failed to create eventfd for NotificationQueue: "
                     << errno << ", falling back to pipe mode (is your kernel "
                     << "> 2.6.30?)";
          fdType = FdType::PIPE;
        } else {
          // some other error
          folly::throwSystemError("Failed to create eventfd for "
                                  "NotificationQueue", errno);
        }
      }
    }
#endif
    if (fdType == FdType::PIPE) {
      if (pipe(pipeFds_)) {
        folly::throwSystemError("Failed to create pipe for NotificationQueue",
                                errno);
      }
      try {
        // put both ends of the pipe into non-blocking mode
        if (fcntl(pipeFds_[0], F_SETFL, O_RDONLY | O_NONBLOCK) != 0) {
          folly::throwSystemError("failed to put NotificationQueue pipe read "
                                  "endpoint into non-blocking mode", errno);
        }
        if (fcntl(pipeFds_[1], F_SETFL, O_WRONLY | O_NONBLOCK) != 0) {
          folly::throwSystemError("failed to put NotificationQueue pipe write "
                                  "endpoint into non-blocking mode", errno);
        }
      } catch (...) {
        ::close(pipeFds_[0]);
        ::close(pipeFds_[1]);
        throw;
      }
    }
  }

  ~NotificationQueue() {
    if (eventfd_ >= 0) {
      ::close(eventfd_);
      eventfd_ = -1;
    }
    if (pipeFds_[0] >= 0) {
      ::close(pipeFds_[0]);
      pipeFds_[0] = -1;
    }
    if (pipeFds_[1] >= 0) {
      ::close(pipeFds_[1]);
      pipeFds_[1] = -1;
    }
  }

  /**
   * Set the advisory maximum queue size.
   *
   * This maximum queue size affects calls to tryPutMessage().  Message
   * producers can still use the putMessage() call to unconditionally put a
   * message on the queue, ignoring the configured maximum queue size.  This
   * can cause the queue size to exceed the configured maximum.
   */
  void setMaxQueueSize(uint32_t max) {
    advisoryMaxQueueSize_ = max;
  }

  /**
   * Attempt to put a message on the queue if the queue is not already full.
   *
   * If the queue is full, a std::overflow_error will be thrown.  The
   * setMaxQueueSize() function controls the maximum queue size.
   *
   * This method may contend briefly on a spinlock if many threads are
   * concurrently accessing the queue, but for all intents and purposes it will
   * immediately place the message on the queue and return.
   *
   * tryPutMessage() may throw std::bad_alloc if memory allocation fails, and
   * may throw any other exception thrown by the MessageT move/copy
   * constructor.
   */
  void tryPutMessage(MessageT&& message) {
    putMessageImpl(std::move(message), advisoryMaxQueueSize_);
  }
  void tryPutMessage(const MessageT& message) {
    putMessageImpl(message, advisoryMaxQueueSize_);
  }

  /**
   * No-throw versions of the above.  Instead returns true on success, false on
   * failure.
   *
   * Only std::overflow_error is prevented from being thrown (since this is the
   * common exception case), user code must still catch std::bad_alloc errors.
   */
  bool tryPutMessageNoThrow(MessageT&& message) {
    return putMessageImpl(std::move(message), advisoryMaxQueueSize_, false);
  }
  bool tryPutMessageNoThrow(const MessageT& message) {
    return putMessageImpl(message, advisoryMaxQueueSize_, false);
  }

  /**
   * Unconditionally put a message on the queue.
   *
   * This method is like tryPutMessage(), but ignores the maximum queue size
   * and always puts the message on the queue, even if the maximum queue size
   * would be exceeded.
   *
   * putMessage() may throw std::bad_alloc if memory allocation fails, and may
   * throw any other exception thrown by the MessageT move/copy constructor.
   */
  void putMessage(MessageT&& message) {
    putMessageImpl(std::move(message), 0);
  }
  void putMessage(const MessageT& message) {
    putMessageImpl(message, 0);
  }

  /**
   * Put several messages on the queue.
   */
  template<typename InputIteratorT>
  void putMessages(InputIteratorT first, InputIteratorT last) {
    typedef typename std::iterator_traits<InputIteratorT>::iterator_category
      IterCategory;
    putMessagesImpl(first, last, IterCategory());
  }

  /**
   * Try to immediately pull a message off of the queue, without blocking.
   *
   * If a message is immediately available, the result parameter will be
   * updated to contain the message contents and true will be returned.
   *
   * If no message is available, false will be returned and result will be left
   * unmodified.
   */
  bool tryConsume(MessageT& result) {
    checkPid();

    try {

      folly::io::PortableSpinLockGuard g(spinlock_);

      if (UNLIKELY(queue_.empty())) {
        return false;
      }

      auto data = std::move(queue_.front());
      result = data.first;
      RequestContext::setContext(data.second);

      queue_.pop_front();
    } catch (...) {
      // Handle an exception if the assignment operator happens to throw.
      // We consumed an event but weren't able to pop the message off the
      // queue.  Signal the event again since the message is still in the
      // queue.
      signalEvent(1);
      throw;
    }

    return true;
  }

  int size() {
    folly::io::PortableSpinLockGuard g(spinlock_);
    return queue_.size();
  }

  /**
   * Check that the NotificationQueue is being used from the correct process.
   *
   * If you create a NotificationQueue in one process, then fork, and try to
   * send messages to the queue from the child process, you're going to have a
   * bad time.  Unfortunately users have (accidentally) run into this.
   *
   * Because we use an eventfd/pipe, the child process can actually signal the
   * parent process that an event is ready.  However, it can't put anything on
   * the parent's queue, so the parent wakes up and finds an empty queue.  This
   * check ensures that we catch the problem in the misbehaving child process
   * code, and crash before signalling the parent process.
   */
  void checkPid() const {
    CHECK_EQ(pid_, getpid());
  }

 private:
  // Forbidden copy constructor and assignment operator
  NotificationQueue(NotificationQueue const &) = delete;
  NotificationQueue& operator=(NotificationQueue const &) = delete;

  inline bool checkQueueSize(size_t maxSize, bool throws=true) const {
    DCHECK(0 == spinlock_.trylock());
    if (maxSize > 0 && queue_.size() >= maxSize) {
      if (throws) {
        throw std::overflow_error("unable to add message to NotificationQueue: "
                                  "queue is full");
      }
      return false;
    }
    return true;
  }

  inline void signalEvent(size_t numAdded = 1) const {
    static const uint8_t kPipeMessage[] = {
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
    };

    ssize_t bytes_written = 0;
    ssize_t bytes_expected = 0;
    if (eventfd_ >= 0) {
      // eventfd(2) dictates that we must write a 64-bit integer
      uint64_t numAdded64(numAdded);
      bytes_expected = static_cast<ssize_t>(sizeof(numAdded64));
      bytes_written = ::write(eventfd_, &numAdded64, sizeof(numAdded64));
    } else {
      // pipe semantics, add one message for each numAdded
      bytes_expected = numAdded;
      do {
        size_t messageSize = std::min(numAdded, sizeof(kPipeMessage));
        ssize_t rc = ::write(pipeFds_[1], kPipeMessage, messageSize);
        if (rc < 0) {
          // TODO: if the pipe is full, write will fail with EAGAIN.
          // See task #1044651 for how this could be handled
          break;
        }
        numAdded -= rc;
        bytes_written += rc;
      } while (numAdded > 0);
    }
    if (bytes_written != bytes_expected) {
      folly::throwSystemError("failed to signal NotificationQueue after "
                              "write", errno);
    }
  }

  bool tryConsumeEvent() {
    uint64_t value = 0;
    ssize_t rc = -1;
    if (eventfd_ >= 0) {
      rc = ::read(eventfd_, &value, sizeof(value));
    } else {
      uint8_t value8;
      rc = ::read(pipeFds_[0], &value8, sizeof(value8));
      value = value8;
    }
    if (rc < 0) {
      // EAGAIN should pretty much be the only error we can ever get.
      // This means someone else already processed the only available message.
      assert(errno == EAGAIN);
      return false;
    }
    assert(value == 1);
    return true;
  }

  bool putMessageImpl(MessageT&& message, size_t maxSize, bool throws=true) {
    checkPid();
    bool signal = false;
    {
      folly::io::PortableSpinLockGuard g(spinlock_);
      if (!checkQueueSize(maxSize, throws)) {
        return false;
      }
      // We only need to signal an event if not all consumers are
      // awake.
      if (numActiveConsumers_ < numConsumers_) {
        signal = true;
      }
      queue_.push_back(
        std::make_pair(std::move(message),
                       RequestContext::saveContext()));
    }
    if (signal) {
      signalEvent();
    }
    return true;
  }

  bool putMessageImpl(
    const MessageT& message, size_t maxSize, bool throws=true) {
    checkPid();
    bool signal = false;
    {
      folly::io::PortableSpinLockGuard g(spinlock_);
      if (!checkQueueSize(maxSize, throws)) {
        return false;
      }
      if (numActiveConsumers_ < numConsumers_) {
        signal = true;
      }
      queue_.push_back(std::make_pair(message, RequestContext::saveContext()));
    }
    if (signal) {
      signalEvent();
    }
    return true;
  }

  template<typename InputIteratorT>
  void putMessagesImpl(InputIteratorT first, InputIteratorT last,
                       std::input_iterator_tag) {
    checkPid();
    bool signal = false;
    size_t numAdded = 0;
    {
      folly::io::PortableSpinLockGuard g(spinlock_);
      while (first != last) {
        queue_.push_back(std::make_pair(*first, RequestContext::saveContext()));
        ++first;
        ++numAdded;
      }
      if (numActiveConsumers_ < numConsumers_) {
        signal = true;
      }
    }
    if (signal) {
      signalEvent();
    }
  }

  mutable folly::io::PortableSpinLock spinlock_;
  int eventfd_;
  int pipeFds_[2]; // to fallback to on older/non-linux systems
  uint32_t advisoryMaxQueueSize_;
  pid_t pid_;
  std::deque<std::pair<MessageT, std::shared_ptr<RequestContext>>> queue_;
  int numConsumers_{0};
  std::atomic<int> numActiveConsumers_{0};
};

template<typename MessageT>
NotificationQueue<MessageT>::Consumer::~Consumer() {
  // If we are in the middle of a call to handlerReady(), destroyedFlagPtr_
  // will be non-nullptr.  Mark the value that it points to, so that
  // handlerReady() will know the callback is destroyed, and that it cannot
  // access any member variables anymore.
  if (destroyedFlagPtr_) {
    *destroyedFlagPtr_ = true;
  }
}

template<typename MessageT>
void NotificationQueue<MessageT>::Consumer::handlerReady(uint16_t events)
    noexcept {
  uint32_t numProcessed = 0;
  bool firstRun = true;
  setActive(true);
  SCOPE_EXIT { setActive(false, /* shouldLock = */ true); };
  while (true) {
    // Try to decrement the eventfd.
    //
    // The eventfd is only used to wake up the consumer - there may or
    // may not actually be an event available (another consumer may
    // have read it).  We don't really care, we only care about
    // emptying the queue.
    if (firstRun) {
      queue_->tryConsumeEvent();
      firstRun = false;
    }

    // Now pop the message off of the queue.
    //
    // We have to manually acquire and release the spinlock here, rather than
    // using SpinLockHolder since the MessageT has to be constructed while
    // holding the spinlock and available after we release it.  SpinLockHolder
    // unfortunately doesn't provide a release() method.  (We can't construct
    // MessageT first since we have no guarantee that MessageT has a default
    // constructor.
    queue_->spinlock_.lock();
    bool locked = true;

    try {
      if (UNLIKELY(queue_->queue_.empty())) {
        // If there is no message, we've reached the end of the queue, return.
        setActive(false);
        queue_->spinlock_.unlock();
        return;
      }

      // Pull a message off the queue.
      auto& data = queue_->queue_.front();

      MessageT msg(std::move(data.first));
      auto old_ctx =
        RequestContext::setContext(data.second);
      queue_->queue_.pop_front();

      // Check to see if the queue is empty now.
      // We use this as an optimization to see if we should bother trying to
      // loop again and read another message after invoking this callback.
      bool wasEmpty = queue_->queue_.empty();
      if (wasEmpty) {
        setActive(false);
      }

      // Now unlock the spinlock before we invoke the callback.
      queue_->spinlock_.unlock();
      locked = false;

      // Call the callback
      bool callbackDestroyed = false;
      CHECK(destroyedFlagPtr_ == nullptr);
      destroyedFlagPtr_ = &callbackDestroyed;
      messageAvailable(std::move(msg));

      RequestContext::setContext(old_ctx);

      // If the callback was destroyed before it returned, we are done
      if (callbackDestroyed) {
        return;
      }
      destroyedFlagPtr_ = nullptr;

      // If the callback is no longer installed, we are done.
      if (queue_ == nullptr) {
        return;
      }

      // If we have hit maxReadAtOnce_, we are done.
      ++numProcessed;
      if (maxReadAtOnce_ > 0 && numProcessed >= maxReadAtOnce_) {
        queue_->signalEvent(1);
        return;
      }

      // If the queue was empty before we invoked the callback, it's probable
      // that it is still empty now.  Just go ahead and return, rather than
      // looping again and trying to re-read from the eventfd.  (If a new
      // message had in fact arrived while we were invoking the callback, we
      // will simply be woken up the next time around the event loop and will
      // process the message then.)
      if (wasEmpty) {
        return;
      }
    } catch (const std::exception& ex) {
      // This catch block is really just to handle the case where the MessageT
      // constructor throws.  The messageAvailable() callback itself is
      // declared as noexcept and should never throw.
      //
      // If the MessageT constructor does throw we try to handle it as best as
      // we can, but we can't work miracles.  We will just ignore the error for
      // now and return.  The next time around the event loop we will end up
      // trying to read the message again.  If MessageT continues to throw we
      // will never make forward progress and will keep trying each time around
      // the event loop.
      if (locked) {
        // Unlock the spinlock.
        queue_->spinlock_.unlock();

        // Push a notification back on the eventfd since we didn't actually
        // read the message off of the queue.
        queue_->signalEvent(1);
      }

      return;
    }
  }
}

template<typename MessageT>
void NotificationQueue<MessageT>::Consumer::init(
    EventBase* eventBase,
    NotificationQueue* queue) {
  assert(eventBase->isInEventBaseThread());
  assert(queue_ == nullptr);
  assert(!isHandlerRegistered());
  queue->checkPid();

  base_ = eventBase;

  queue_ = queue;

  {
    folly::io::PortableSpinLockGuard g(queue_->spinlock_);
    queue_->numConsumers_++;
  }
  queue_->signalEvent();

  if (queue_->eventfd_ >= 0) {
    initHandler(eventBase, queue_->eventfd_);
  } else {
    initHandler(eventBase, queue_->pipeFds_[0]);
  }
}

template<typename MessageT>
void NotificationQueue<MessageT>::Consumer::stopConsuming() {
  if (queue_ == nullptr) {
    assert(!isHandlerRegistered());
    return;
  }

  {
    folly::io::PortableSpinLockGuard g(queue_->spinlock_);
    queue_->numConsumers_--;
    setActive(false);
  }

  assert(isHandlerRegistered());
  unregisterHandler();
  detachEventBase();
  queue_ = nullptr;
}

} // folly


text:
/**
 * @license Angulartics v0.15.18
 * (c) 2013 Luis Farzati http://luisfarzati.github.io/angulartics
 * Google Tag Manager Plugin Contributed by http://github.com/danrowe49
 * License: MIT
 */

(function(angular){
'use strict';

/**
 * @ngdoc overview
 * @name angulartics.google.analytics
 * Enables analytics support for Google Tag Manager (http://google.com/tagmanager)
 */

angular.module('angulartics.google.tagmanager', ['angulartics'])
.config(['$analyticsProvider', function($analyticsProvider){

	/**
	* Send content views to the dataLayer
	*
	* @param {string} path Required 'content name' (string) describes the content loaded
	*/

	$analyticsProvider.registerPageTrack(function(path){
		var dataLayer = window.dataLayer = window.dataLayer || [];
		dataLayer.push({
			'event': 'content-view',
			'content-name': path
		});
	});

	/**
   * Send interactions to the dataLayer, i.e. for event tracking in Google Analytics
   * @name eventTrack
   *
   * @param {string} action Required 'action' (string) associated with the event
   * @param {object} properties Comprised of the mandatory field 'category' (string) and optional  fields 'label' (string), 'value' (integer) and 'noninteraction' (boolean)
   */

	$analyticsProvider.registerEventTrack(function(action, properties){
		var dataLayer = window.dataLayer = window.dataLayer || [];
		dataLayer.push({
			'event': 'interaction',
			'target': properties.category,
			'action': action,
			'target-properties': properties.label,
			'value': properties.value,
			'interaction-type': properties.noninteraction
		});

	});
}]);

})(angular);

redpajama_set_name: RedPajamaGithub


text:
#ifndef _TEXTCAT_H_
#define _TEXTCAT_H_

#include <stdio.h>

#define _TEXTCAT_RESULT_UNKOWN        "UNKNOWN"
#define _TEXTCAT_RESULT_SHORT         "SHORT"

/**
 * textcat_Init() - Initialize the text classifier. The textfile
 * conffile should contain a list of fingerprint filenames and
 * identification strings for the categories.  The filenames should be
 * reachable from the current working directory. The identification
 * strings will are used in the classification output.
 *
 * Returns: handle on success, NULL on error. (At the moment, the
 * only way errors can occur, is when the library cannot read the
 * conffile, or one of the fingerprint files listed in it.)
 */
extern void *textcat_Init( const char *conffile );

/**
 * textcat_Done() - Free up resources for handle
 */
extern void textcat_Done( void *handle );

/**
 * textcat_Classify() - Give the most likely categories for buffer
 * with length size.
 *
 * Returns: string containing a list of category id's, each one
 * between square brackets, "UNKNOWN" when not recognized, "SHORT" if the
 * document was too short to make a reliable assessment.
 *
 * Performace note: longer buffers take longer to process. However,
 * for many uses it is not necessary to categorize the whole buffer.
 * For language classification, a few hundred bytes will suffice.
 */
extern char *textcat_Classify( void *handle, const char *buffer, size_t size );

/**
 * textcat_Version() - Returns a string describing the version of this classifier.
 */
extern char *textcat_Version();
#endif


text:
package com.evolveum.midpoint.prism.query;

import com.evolveum.midpoint.prism.*;
import com.evolveum.midpoint.prism.foo.AssignmentType;
import com.evolveum.midpoint.prism.foo.UserType;
import com.evolveum.midpoint.prism.match.MatchingRuleRegistry;
import com.evolveum.midpoint.prism.match.MatchingRuleRegistryFactory;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.query.builder.QueryBuilder;
import com.evolveum.midpoint.prism.util.PrismTestUtil;
import com.evolveum.midpoint.util.PrettyPrinter;
import com.evolveum.midpoint.util.exception.SchemaException;
import org.testng.AssertJUnit;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test;
import org.xml.sax.SAXException;

import javax.xml.namespace.QName;
import java.io.IOException;
import java.lang.reflect.Method;

import static com.evolveum.midpoint.prism.PrismInternalTestUtil.DEFAULT_NAMESPACE_PREFIX;
import static com.evolveum.midpoint.prism.PrismInternalTestUtil.NS_FOO;
import static com.evolveum.midpoint.prism.util.PrismTestUtil.getPrismContext;
import static com.evolveum.midpoint.prism.util.PrismTestUtil.getSchemaRegistry;

/**
 * Here are the most simple tests for Query Builder.
 * More advanced tests are part of QueryInterpreterTest in repo-sql-impl-test.
 *
 * These tests are strict in the sense they check the exact structure of created queries.
 * Repo tests check just the HQL outcome.
 */
public class TestQueryBuilder {

    public static final QName USER_TYPE_QNAME = new QName(NS_FOO, "UserType");
    public static final QName ASSIGNMENT_TYPE_QNAME = new QName(NS_FOO, "AssignmentType");
    private static MatchingRuleRegistry matchingRuleRegistry;

	@BeforeSuite
	public void setupDebug() throws SchemaException, SAXException, IOException {
		PrettyPrinter.setDefaultNamespacePrefix(DEFAULT_NAMESPACE_PREFIX);
		PrismTestUtil.resetPrismContext(new PrismInternalTestUtil());

		matchingRuleRegistry = MatchingRuleRegistryFactory.createRegistry();
	}

    @BeforeMethod
    public void beforeMethod(Method method) throws Exception {
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>> START TEST" + getClass().getName() + "." + method.getName() + "<<<<<<<<<<<<<<<<<<<<<<<<");
    }

	@Test
	public void test100EmptyFilter() throws Exception{
		ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()).build();
		ObjectQuery expected = ObjectQuery.createObjectQuery((ObjectFilter) null);
        compare(actual, expected);
    }

    @Test
    public void test110EmptyBlock() throws Exception{
        ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()).block().endBlock().build();
        ObjectQuery expected = ObjectQuery.createObjectQuery((ObjectFilter) null);
        compare(actual, expected);
    }

    @Test
    public void test112EmptyBlocks() throws Exception{
        ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext())
                .block()
                    .block()
                        .block()
                        .endBlock()
                    .endBlock()
                .endBlock()
                .build();
        ObjectQuery expected = ObjectQuery.createObjectQuery((ObjectFilter) null);
        compare(actual, expected);
    }

    @Test(expectedExceptions = IllegalStateException.class)
    public void test113BlocksLeftOpen() throws Exception{
        QueryBuilder.queryFor(UserType.class, getPrismContext())
                .block()
                .block()
                .block()
                .endBlock()
                .endBlock()
                .build();
    }

    @Test(expectedExceptions = IllegalStateException.class)
    public void test114NoOpenBlocks() throws Exception{
        QueryBuilder.queryFor(UserType.class, getPrismContext())
                .block()
                .block()
                .endBlock()
                .endBlock()
                .endBlock()
                .build();
    }

    @Test
    public void test120All() throws Exception{
        ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()).all().build();
        ObjectQuery expected = ObjectQuery.createObjectQuery(AllFilter.createAll());
        compare(actual, expected);
    }

    @Test
    public void test122AllInBlock() throws Exception{
        ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()).block().all().endBlock().build();
        ObjectQuery expected = ObjectQuery.createObjectQuery(AllFilter.createAll());
        compare(actual, expected);
    }

    @Test
    public void test130SingleEquals() throws Exception{
        ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()).item(UserType.F_LOCALITY).eq("Caribbean").build();
        ObjectQuery expected = ObjectQuery.createObjectQuery(createEqual(UserType.F_LOCALITY, UserType.class, null, "Caribbean"));
        compare(actual, expected);
    }

    @Test
    public void test132SingleAnd() throws Exception{
        ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext())
                .item(UserType.F_LOCALITY).eq("Caribbean")
                .and().item(UserType.F_DESCRIPTION).eq("desc")
                .build();
        ObjectQuery expected = ObjectQuery.createObjectQuery(
                AndFilter.createAnd(
                        createEqual(UserType.F_LOCALITY, UserType.class, null, "Caribbean"),
                        createEqual(UserType.F_DESCRIPTION, UserType.class, null, "desc")
                )
        );
        compare(actual, expected);
    }

    @Test
    public void test134SingleOrWithNot() throws Exception{
        ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext())
                .item(UserType.F_LOCALITY).eq("Caribbean")
                .or().not().item(UserType.F_DESCRIPTION).eq("desc")
                .build();
        ObjectQuery expected = ObjectQuery.createObjectQuery(
                OrFilter.createOr(
                        createEqual(UserType.F_LOCALITY, UserType.class, null, "Caribbean"),
                        NotFilter.createNot(
                                createEqual(UserType.F_DESCRIPTION, UserType.class, null, "desc")
                        )
                )
        );
        compare(actual, expected);
    }

    @Test
    public void test136AndOrNotSequence() throws Exception{
        ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext())
                .item(UserType.F_LOCALITY).eq("Caribbean")
                .or()
                        .not().item(UserType.F_DESCRIPTION).eq("desc")
                        .and().all()
                        .and().none()
                .or()
                        .undefined()
                        .and().not().none()
                .build();
        ObjectQuery expected = ObjectQuery.createObjectQuery(
                OrFilter.createOr(
                        createEqual(UserType.F_LOCALITY, UserType.class, null, "Caribbean"),
                        AndFilter.createAnd(
                                NotFilter.createNot(
                                        createEqual(UserType.F_DESCRIPTION, UserType.class, null, "desc")
                                ),
                                AllFilter.createAll(),
                                NoneFilter.createNone()
                        ),
                        AndFilter.createAnd(
                                UndefinedFilter.createUndefined(),
                                NotFilter.createNot(
                                        NoneFilter.createNone()
                                )
                        )
                )
        );
        compare(actual, expected);
    }

    @Test
    public void test140TypeWithEquals() throws Exception{
        ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext())
                .type(UserType.class)
                .item(UserType.F_LOCALITY).eq("Caribbean")
                .build();
        ObjectQuery expected = ObjectQuery.createObjectQuery(
                TypeFilter.createType(
                        USER_TYPE_QNAME,
                        createEqual(UserType.F_LOCALITY, UserType.class, null, "Caribbean")
                )
        );
        compare(actual, expected);
    }

    @Test
    public void test142TypeWithEqualsInBlock() throws Exception{
        ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext())
                .type(UserType.class)
                .block()
                .item(UserType.F_LOCALITY).eq("Caribbean")
                .endBlock()
                .build();
        ObjectQuery expected = ObjectQuery.createObjectQuery(
                TypeFilter.createType(
                        USER_TYPE_QNAME,
                        createEqual(UserType.F_LOCALITY, UserType.class, null, "Caribbean")
                )
        );
        compare(actual, expected);
    }

    @Test
    public void test144TypeWithEqualsAndAllInBlock() throws Exception{
        ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext())
                .type(UserType.class)
                .block()
                .item(UserType.F_LOCALITY).eq("Caribbean")
                .and().all()
                .endBlock()
                .build();
        ObjectQuery expected = ObjectQuery.createObjectQuery(
                TypeFilter.createType(
                        USER_TYPE_QNAME,
                        AndFilter.createAnd(
                                createEqual(UserType.F_LOCALITY, UserType.class, null, "Caribbean"),
                                AllFilter.createAll()
                        )
                )
        );
        compare(actual, expected);
    }

    @Test
    public void test144TypeInTypeInType() throws Exception{
        ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext())
                .type(UserType.class)
                .type(AssignmentType.class)
                .type(UserType.class)
                .all()
                .build();
        ObjectQuery expected = ObjectQuery.createObjectQuery(
                TypeFilter.createType(
                        USER_TYPE_QNAME,
                        TypeFilter.createType(
                                ASSIGNMENT_TYPE_QNAME,
                                TypeFilter.createType(
                                        USER_TYPE_QNAME,
                                        AllFilter.createAll()
                                )
                        )
                )
        );
        compare(actual, expected);
    }

    @Test
    public void test146TypeAndSomething() throws Exception{
        ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext())
                .type(UserType.class)
                .none()
                .and().all()
                .build();
        ObjectQuery expected = ObjectQuery.createObjectQuery(
                AndFilter.createAnd(
                        TypeFilter.createType(
                                USER_TYPE_QNAME,
                                NoneFilter.createNone()
                        ),
                        AllFilter.createAll()
                )
        );
        compare(actual, expected);
    }

    @Test
    public void test148TypeEmpty() throws Exception{
        ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext())
                .type(UserType.class)
                .block().endBlock()
                .build();
        ObjectQuery expected = ObjectQuery.createObjectQuery(
                TypeFilter.createType(
                        USER_TYPE_QNAME,
                        null
                )
        );
        compare(actual, expected);
    }

    @Test
    public void test149TypeEmptyAndAll() throws Exception{
        ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext())
                .type(UserType.class)
                .block().endBlock()
                .and().all()
                .build();
        ObjectQuery expected = ObjectQuery.createObjectQuery(
                AndFilter.createAnd(
                        TypeFilter.createType(
                                USER_TYPE_QNAME,
                                null
                        ),
                        AllFilter.createAll()
                )
        );
        compare(actual, expected);
    }

    @Test
    public void test150ExistsWithEquals() throws Exception{
        ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext())
                .exists(UserType.F_ASSIGNMENT)
                .item(AssignmentType.F_DESCRIPTION).startsWith("desc1")
                .build();
        ComplexTypeDefinition assCtd = getPrismContext().getSchemaRegistry().findComplexTypeDefinitionByCompileTimeClass(AssignmentType.class);
        PrismContainerDefinition userPcd = getPrismContext().getSchemaRegistry().findContainerDefinitionByCompileTimeClass(UserType.class);
        ObjectQuery expected = ObjectQuery.createObjectQuery(
                ExistsFilter.createExists(
                        new ItemPath(UserType.F_ASSIGNMENT),
                        userPcd,
                        SubstringFilter.createSubstring(
                                new ItemPath(AssignmentType.F_DESCRIPTION),
                                assCtd.findPropertyDefinition(AssignmentType.F_DESCRIPTION),
                                getPrismContext(),
                                null, "desc1", true, false)
                )
                );
        compare(actual, expected);
    }

    @Test
    public void test151ExistsWithEquals2() throws Exception{
        ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext())
                .exists(UserType.F_ASSIGNMENT)
                .item(AssignmentType.F_NOTE).endsWith("DONE.")
                .build();
        ComplexTypeDefinition assCtd = getPrismContext().getSchemaRegistry().findComplexTypeDefinitionByCompileTimeClass(AssignmentType.class);
        PrismContainerDefinition userPcd = getPrismContext().getSchemaRegistry().findContainerDefinitionByCompileTimeClass(UserType.class);
        ObjectQuery expected = ObjectQuery.createObjectQuery(
                ExistsFilter.createExists(
                        new ItemPath(UserType.F_ASSIGNMENT),
                        userPcd,
                        SubstringFilter.createSubstring(
                                new ItemPath(AssignmentType.F_NOTE),
                                assCtd.findPropertyDefinition(AssignmentType.F_NOTE),
                                getPrismContext(),
                                null, "DONE.", false, true)
                )
        );
        compare(actual, expected);
    }

    @Test
    public void test152ExistsWithEqualsInBlock() throws Exception{
        ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext())
                .exists(UserType.F_ASSIGNMENT)
                .block()
                    .item(AssignmentType.F_NOTE).endsWith("DONE.")
                .endBlock()
                .build();
        ComplexTypeDefinition assCtd = getPrismContext().getSchemaRegistry().findComplexTypeDefinitionByCompileTimeClass(AssignmentType.class);
        PrismContainerDefinition userPcd = getPrismContext().getSchemaRegistry().findContainerDefinitionByCompileTimeClass(UserType.class);
        ObjectQuery expected = ObjectQuery.createObjectQuery(
                ExistsFilter.createExists(
                        new ItemPath(UserType.F_ASSIGNMENT),
                        userPcd,
                        SubstringFilter.createSubstring(
                                new ItemPath(AssignmentType.F_NOTE),
                                assCtd.findPropertyDefinition(AssignmentType.F_NOTE),
                                getPrismContext(),
                                null, "DONE.", false, true)
                )
        );
        compare(actual, expected);
    }

    @Test
    public void test154ExistsWithEqualsAndAllInBlock() throws Exception{
        ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext())
                .exists(UserType.F_ASSIGNMENT)
                .block()
                .item(AssignmentType.F_NOTE).endsWith("DONE.")
                    .and().all()
                .endBlock()
                .build();
        ComplexTypeDefinition assCtd = getPrismContext().getSchemaRegistry().findComplexTypeDefinitionByCompileTimeClass(AssignmentType.class);
        PrismContainerDefinition userPcd = getPrismContext().getSchemaRegistry().findContainerDefinitionByCompileTimeClass(UserType.class);
        ObjectQuery expected = ObjectQuery.createObjectQuery(
                ExistsFilter.createExists(
                        new ItemPath(UserType.F_ASSIGNMENT),
                        userPcd,
                        AndFilter.createAnd(
                                SubstringFilter.createSubstring(
                                        new ItemPath(AssignmentType.F_NOTE),
                                        assCtd.findPropertyDefinition(AssignmentType.F_NOTE),
                                        getPrismContext(),
                                        null, "DONE.", false, true
                                ),
                                AllFilter.createAll()
                        )
                )
        );
        compare(actual, expected);
    }

    @Test
    public void test156ExistsAndSomething() throws Exception{
        ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext())
                .exists(UserType.F_ASSIGNMENT)
                    .none()
                .and().all()
                .build();

        ComplexTypeDefinition assCtd = getPrismContext().getSchemaRegistry().findComplexTypeDefinitionByCompileTimeClass(AssignmentType.class);
        PrismContainerDefinition userPcd = getPrismContext().getSchemaRegistry().findContainerDefinitionByCompileTimeClass(UserType.class);
        ObjectQuery expected = ObjectQuery.createObjectQuery(
                AndFilter.createAnd(
                        ExistsFilter.createExists(
                                new ItemPath(UserType.F_ASSIGNMENT),
                                userPcd,
                                NoneFilter.createNone()
                        ),
                        AllFilter.createAll()
                )
        );
        compare(actual, expected);
    }

    @Test
    public void test200OrderByName() throws Exception{
        ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext())
                .asc(UserType.F_NAME)
                .build();
        ObjectQuery expected = ObjectQuery.createObjectQuery(
                ObjectPaging.createPaging(UserType.F_NAME, OrderDirection.ASCENDING)
        );
        compare(actual, expected);
    }

    @Test
    public void test210OrderByNameAndId() throws Exception{
        ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext())
                .item(UserType.F_LOCALITY).eq("Caribbean")
                .asc(UserType.F_NAME)
                .desc(PrismConstants.T_ID)
                .build();
        ObjectPaging paging = ObjectPaging.createEmptyPaging();
        paging.addOrderingInstruction(UserType.F_NAME, OrderDirection.ASCENDING);
        paging.addOrderingInstruction(PrismConstants.T_ID, OrderDirection.DESCENDING);
        ObjectQuery expected = ObjectQuery.createObjectQuery(
                createEqual(UserType.F_LOCALITY, UserType.class, null, "Caribbean"),
                paging);
        compare(actual, expected);
    }

    @Test
    public void test300EqualItem() throws Exception {
        ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext())
                .item(UserType.F_LOCALITY).eq().item(UserType.F_NAME)
                .build();
        PrismContainerDefinition userPcd = getPrismContext().getSchemaRegistry().findContainerDefinitionByCompileTimeClass(UserType.class);
        ObjectQuery expected = ObjectQuery.createObjectQuery(
                EqualFilter.createEqual(
                        new ItemPath(UserType.F_LOCALITY),
                        userPcd.findPropertyDefinition(UserType.F_LOCALITY),
                        null,
                        new ItemPath(UserType.F_NAME),
                        null
                )
        );
        compare(actual, expected);
    }

    @Test
    public void test310LessThanItem() throws Exception {
        PrismObjectDefinition userDef = getSchemaRegistry().findObjectDefinitionByCompileTimeClass(UserType.class);
        PrismPropertyDefinition nameDef = userDef.findPropertyDefinition(UserType.F_NAME);
        PrismPropertyDefinition localityDef = userDef.findPropertyDefinition(UserType.F_LOCALITY);
        ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext())
                .item(new ItemPath(UserType.F_LOCALITY), localityDef)
                    .le()
                        .item(new ItemPath(UserType.F_NAME), nameDef)
                .build();
        ObjectQuery expected = ObjectQuery.createObjectQuery(
                LessFilter.createLess(new ItemPath(UserType.F_LOCALITY), localityDef, null,
		                new ItemPath(UserType.F_NAME), nameDef, true)
        );
        compare(actual, expected);
    }

    protected void compare(ObjectQuery actual, ObjectQuery expected) {
        String exp = expected.debugDump();
        String act = actual.debugDump();
        System.out.println("Generated query:\n" + act);
        AssertJUnit.assertEquals("queries do not match", exp, act);
    }

    private <C extends Containerable, T> EqualFilter<T> createEqual(QName propertyName, Class<C> type, QName matchingRule, T realValue) {
        return createEqual(new ItemPath(propertyName), type, matchingRule, realValue);
    }

    private <C extends Containerable, T> EqualFilter<T> createEqual(ItemPath propertyPath, Class<C> type, QName matchingRule, T realValue) {
        PrismPropertyDefinition<T> propertyDefinition = (PrismPropertyDefinition) FilterUtils.findItemDefinition(propertyPath, type, getPrismContext());
        return EqualFilter.createEqual(propertyPath, propertyDefinition, matchingRule, getPrismContext(), realValue);
    }
}


text:
/**
 * Created by chief on 16/7/16.
 */

define('widget',[],function(){
    var init = function (el,name,jswidget){

        if(typeof name=='undefined'){
            return false;
        }

        var widgetViewModel = require('./viewModel/'+name+'Model.js');

        var widgetViewModelClone = widgetViewModel;

        $(el).data("model",widgetViewModelClone);

        ko.applyBindings(widgetViewModelClone,el);

        //ko.applyBindings(widgetViewModel,el);

        // 导航条 当手机屏幕 icon触发导航条显示
        $(".nav-toggle").unbind("click").bind("click",function(){
            $(".xs-hide").toggleClass("xs-show");
        })
        if(name=="checkbox" || name=="radio"){
            u.compMgr.updateComp();
        }

        if(name == "widget7"){
            setTimeout(function(){
                $('#carousel-example-generic').carousel();
            }, 5000 );
        }

    };

    return {
        init:init
    }
});


text:
![1 stars](../../images/ic_star_black_18dp_1x.png)![1 stars](../../images/ic_star_border_black_18dp_1x.png)![1 stars](../../images/ic_star_border_black_18dp_1x.png)![1 stars](../../images/ic_star_border_black_18dp_1x.png)![1 stars](../../images/ic_star_border_black_18dp_1x.png) 1

To use the Food Bot skill, try saying...

* *Alexa ask food bot what is the protein content of peanut butter*

* *Alexa ask food bot how much selenium is in eggnog*

* *Alexa ask food bot what is the energy content of cottage cheese*

Food bot gives you with the nutrient value of many common food items per 100 grams (3.5 oz). Data is provided by the USDA Nutritional Database. You can use one or two words to ask about a specific food and Food Bot will let you know the nutrient content of the specified food item and nutrient. All nutrient content currently provided is per 100 grams. Food Bot will also tell you the full name of the food item that was matched in the USDA Nutritional Database. If the food item can't be found when you use the plural form of the food item, try searching for the item in singular for or vice versa. Please feel free to send any feedback or questions about the app to matej.marjanovich+foodbot@gmail.com.

***

### Skill Details

* **Invocation Name:** food bot
* **Category:** null
* **ID:** amzn1.echo-sdk-ams.app.94cacaa5-d0cc-4dcd-b141-e76c935fd370
* **ASIN:** B01G788GNG
* **Author:** Matej Marjanovic
* **Release Date:** May 31, 2016 @ 07:38:41
* **In-App Purchasing:** No


text:
#ifndef QT3DEXTRAS_QNORMALDIFFUSEMAPMATERIAL_H
#define QT3DEXTRAS_QNORMALDIFFUSEMAPMATERIAL_H

#include <Qt3DExtras/qt3dextras_global.h>
#include <Qt3DRender/qmaterial.h>
#include <QColor>

QT_BEGIN_NAMESPACE

namespace Qt3DRender {

class QAbstractTexture;

} // namespace Qt3DRender

namespace Qt3DExtras {

class QNormalDiffuseMapMaterialPrivate;

class QT3DEXTRASSHARED_EXPORT QNormalDiffuseMapMaterial : public Qt3DRender::QMaterial
{
    Q_OBJECT
    Q_PROPERTY(QColor ambient READ ambient WRITE setAmbient NOTIFY ambientChanged)
    Q_PROPERTY(QColor specular READ specular WRITE setSpecular NOTIFY specularChanged)
    Q_PROPERTY(Qt3DRender::QAbstractTexture *diffuse READ diffuse WRITE setDiffuse NOTIFY diffuseChanged)
    Q_PROPERTY(Qt3DRender::QAbstractTexture *normal READ normal WRITE setNormal NOTIFY normalChanged)
    Q_PROPERTY(float shininess READ shininess WRITE setShininess NOTIFY shininessChanged)
    Q_PROPERTY(float textureScale READ textureScale WRITE setTextureScale NOTIFY textureScaleChanged)

public:
    explicit QNormalDiffuseMapMaterial(Qt3DCore::QNode *parent = nullptr);
    ~QNormalDiffuseMapMaterial();

    QColor ambient() const;
    QColor specular() const;
    Qt3DRender::QAbstractTexture *diffuse() const;
    Qt3DRender::QAbstractTexture *normal() const;
    float shininess() const;
    float textureScale() const;

public Q_SLOTS:
    void setAmbient(const QColor &ambient);
    void setSpecular(const QColor &specular);
    void setDiffuse(Qt3DRender::QAbstractTexture *diffuse);
    void setNormal(Qt3DRender::QAbstractTexture *normal);
    void setShininess(float shininess);
    void setTextureScale(float textureScale);

Q_SIGNALS:
    void ambientChanged(const QColor &ambient);
    void diffuseChanged(Qt3DRender::QAbstractTexture *diffuse);
    void normalChanged(Qt3DRender::QAbstractTexture *normal);
    void specularChanged(const QColor &specular);
    void shininessChanged(float shininess);
    void textureScaleChanged(float textureScale);

protected:
    QNormalDiffuseMapMaterial(QNormalDiffuseMapMaterialPrivate &dd, Qt3DCore::QNode *parent = nullptr);

private:
    Q_DECLARE_PRIVATE(QNormalDiffuseMapMaterial)
};

} // Qt3DExtras

QT_END_NAMESPACE

#endif // QT3DEXTRAS_QNORMALDIFFUSEMAPMATERIAL_H


text:
(Version 0.1, Last Update 14/06/2016)

Tutorial on how to build your own research envirorment for Deep Learning with OpenCV, Python, Tensorfow on Linux Machine and MacintoshOSX.
This Repository try to be a clear summary of the many guides you can find online (I will link in Referencies all the guides, I used to compose this Repository-Tutorial)

The Project follow the below **index**:

1. **[Introduction to the Problem](https://github.com/DrewNF/Build-Deep-Learning-Env-with-Tensorflow-Python-OpenCV/blob/master/README.md#1-introduction-to-the-problem);**
2. **[Possible Solutions](https://github.com/DrewNF/Build-Deep-Learning-Env-with-Tensorflow-Python-OpenCV/blob/master/README.md#2-possible-solutions);**
3. **[Virtual Environment](https://github.com/DrewNF/Build-Deep-Learning-Env-with-Tensorflow-Python-OpenCV/blob/master/README.md#3-virtual-environment)**
      1. **[Virtual Environment & Python](https://github.com/DrewNF/Build-Deep-Learning-Env-with-Tensorflow-Python-OpenCV/blob/master/README.md#ivirtual-environment--python);**
      2. **[OpenCV](https://github.com/DrewNF/Build-Deep-Learning-Env-with-Tensorflow-Python-OpenCV/blob/master/README.md#iiopencv);**
      3. **[Tensorflow](https://github.com/DrewNF/Build-Deep-Learning-Env-with-Tensorflow-Python-OpenCV/blob/master/README.md#iiitensorflow);**
      4. **[CUDA](https://github.com/DrewNF/Build-Deep-Learning-Env-with-Tensorflow-Python-OpenCV/blob/master/README.md#ivcuda);**
      5. **[Other Libraries](https://github.com/DrewNF/Build-Deep-Learning-Env-with-Tensorflow-Python-OpenCV/blob/master/README.md#vother-libraries);**
4. **[Conclusions](https://github.com/DrewNF/Build-Deep-Learning-Env-with-Tensorflow-Python-OpenCV/blob/master/README.md#4-conclusions);**
5. **[References](https://github.com/DrewNF/Build-Deep-Learning-Env-with-Tensorflow-Python-OpenCV/blob/master/README.md#5-references);**
6. **[Copyright](https://github.com/DrewNF/Build-Deep-Learning-Env-with-Tensorflow-Python-OpenCV/blob/master/README.md#6-copyright).**

##1. Introduction to the Problem

Nowadays, the Deep Learning Area use lots of  different libraries, dependicies, script languages, some of the most known are:
- [Caffè](http://caffe.berkeleyvision.org/);
- [Tensorflow](https://www.tensorflow.org/);
- [Keras](http://keras.io/);
- [OpenCV](http://opencv.org/).

So Develop & Research on Deep Learning, now means struggle with lots of error, compilation, installation, and some times most of them comes from updates, new library dependecies, let's see which are the possible solutions.

##2. Possible Solutions

Mainly we have three solutions:
- Install on own machine;
- Install in a server (Use the environment remotly);
- Install on Virtual Environment.
This last one is the one, covered in this Tutorial.

##3. Virtual Environment

**Why Virtual Environment?**

Why is easy: **Virtual Envirorments** lets us to have different dependencies, libraries, updates, of the same or different software, without struggling with error due to mislink or new apis.

The tutorial code consider you are the owner and have all grants to run **sudo** , if you  wanna apply the tutorial to a server you have to ask your administrator to install OpenCV & CUDA on the machine and give you the path to export into the bashrc file, for VirtualEnv, Tensorflow, Python nothing change.

Let's see a four step set up installation for our Research Envirorment with Tensorflow, OpenCV, Python, CUDA and all the libraries that we could need:

### i.Virtual Environment & Python

- **[Preparing Linux Machine](https://github.com/DrewNF/Build-Deep-Learning-Env-with-Tensorflow-Python-OpenCV/blob/master/README.md#preparing-linux-machine);**
- **[Preparing Macintosh OSX Machine](https://github.com/DrewNF/Build-Deep-Learning-Env-with-Tensorflow-Python-OpenCV/blob/master/README.md#preparing-macintosh-osx-machine);**
- **[Set Up the Virtual Env](https://github.com/DrewNF/Build-Deep-Learning-Env-with-Tensorflow-Python-OpenCV/blob/master/README.md#set-up-the-virtual-env);**

#### Preparing Linux Machine

Open up a terminal and update the apt-get package manager followed by upgrading any pre-installed packages:
```
$ sudo apt-get update
$ sudo apt-get upgrade
```
Now we need to install our developer tools:
```
$ sudo apt-get install build-essential cmake git pkg-config
```

The pkg-config is likely already installed, but be sure to include it just in case.
We'll be using git to pull down the OpenCV repositories from GitHub.
The cmake package is used to configure our build.

OpenCV needs to be able to load various image file formats from disk, including JPEG, PNG, TIFF, etc. In order to load these image formats from disk, we'll need our image I/O packages:
```
$ sudo apt-get install libjpeg8-dev libtiff4-dev libjasper-dev libpng12-dev
```
At this point, we have the ability to load a given image off of disk. But how do we display the actual image to our screen? The answer is the GTK development library, which the highgui  module of OpenCV depends on to guild Graphical User Interfaces (GUIs):
```
$ sudo apt-get install libgtk2.0-dev
```
We can load images using OpenCV, but what about processing video streams and accessing individual frames? We've got that covered here:
```
$ sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev
```
Install libraries that are used to optimize various routines inside of OpenCV:
```
$ sudo apt-get install libatlas-base-dev gfortran
```
Install pip, a Python package manager:
```
$ wget https://bootstrap.pypa.io/get-pip.py
$ sudo python get-pip.py
```
#### Preparing Macintosh OSX Machine

Install [Homebrew](http://brew.sh/):
```
$ cd ~
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```
Update Homebrew:

```
$ brew update
```
Before we proceed, we need to update our PATH  in our ~/.bash_profile file to indicate that we want to use Homebrew packages before any system libraries or packages. **This is an absolutely critical step, so be sure not to skip it!**

Open up your ~/.bash_profile  (if it does not exist, create it), and append the following lines:

```
# Homebrew
export PATH=/usr/local/bin:$PATH
```
Then reload the our ~/.bash_profile:

```
$ source ~/.bash_profile
```

And test:

```
$ which python

### OUTPUT MUST BE ###
/usr/local/bin/python
```
First, we'll use brew to install the required developers tools:

```
$ brew install cmake pkg-config
$ brew install jpeg libpng libtiff openexr
$ brew install eigen tbb
```

We are now ready to set up the Virtual Env

#### Set Up the Virtual Env

Install virtualenv and virtualenvwrapper.These two packages allow us to create separate Python environments for each project we are working on. While installing virtualenv  and virtualenvwrapper is not a requirement to get OpenCV 3.0 and Python 2.7+ up and running on your Ubuntu system, I highly recommend it and the rest of this tutorial will assume you have them installed!

```
### Linux

$ sudo pip install virtualenv virtualenvwrapper
$ sudo rm -rf ~/.cache/pip

### Macintosh OSX

$ pip install virtualenv virtualenvwrapper
```
Now that we have virtualenv  and virtualenvwrapper  installed, we need to update our ~/.bashrc/ file:
```
### Linux

$ export WORKON_HOME=$HOME/.virtualenvs

### Linux & Macintosh OSX

$ source /usr/local/bin/virtualenvwrapper.sh
```
This quick update will ensure that both virtualenv  and virtualenvwrapper  are loaded each time you login.
To make the changes to our ~/.bashrc or ~/.bash_profile file take effect, you can either (1) logout and log back in, (2) close your current terminal window and open a new one, or preferably, (3) reload the contents of your ~/.bashrc or ~/.bash_profile file:

```
### Linux

$ source ~/.bashrc

### Macintosh OSX

$ source ~/.bash_profile
```
Lastly, we can create our cv  virtual environment where we'll be doing our computer vision development and OpenCV 3.0 + Python 2.7+ installation:
```
### Linux & Macintosh OSX

$ mkvirtualenv cv
```
As I mentioned above, this tutorial covers how to install OpenCV 3.0 and Python 2.7+, so we'll need to install our Python 2.7 development tools:
```
### Linux

$ sudo apt-get install python2.7-dev
```
Since OpenCV represents images as multi-dimensional NumPy arrays, we better install NumPy into our cv  virtual environment:
```
### Linux & Macintosh OSX

$ pip install numpy
```
### ii.OpenCV
Our environment is now all setup, we can proceed to change to our home directory, pull down OpenCV from GitHub, and checkout the 3.0.0  version:
```
### Linux & Macintosh OSX

$ cd ~ $ git clone https://github.com/Itseez/opencv.git
$ cd opencv
$ git checkout 3.0.0
```
>You can replace the 3.0.0  version with whatever the current release is.
>Be sure to check OpenCV.org for information on the latest release.

We also need the opencv_contrib repo as well. Without this repository, we won't have access to standard keypoint detectors and local invariant descriptors (such as SIFT, SURF, etc.) that were available in the OpenCV 2.4.X version. We'll also be missing out on some of the newer OpenCV 3.0 features like text detection in natural images:
```
### Linux & Macintosh OSX

$ cd ~
$ git clone https://github.com/Itseez/opencv_contrib.git
$ cd opencv_contrib
$ git checkout 3.0.0
```
Again, make sure that you checkout the same version for opencv_contrib that you did for opencv above, otherwise you could run into compilation errors.
Time to setup the build:

```
### Linux & Macintosh OSX

$ cd ~/opencv
$ mkdir build
$ cd build

### Linux

$ cmake -D CMAKE_BUILD_TYPE=RELEASE \ -D CMAKE_INSTALL_PREFIX=/usr/local \ -D INSTALL_C_EXAMPLES=ON \ -D INSTALL_PYTHON_EXAMPLES=ON \ -D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib/modules \ -D BUILD_EXAMPLES=ON ..

### Macintosh OSX

$ cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local \
	-D PYTHON2_PACKAGES_PATH=~/.virtualenvs/cv/lib/python2.7/site-packages \
	-D PYTHON2_LIBRARY=/usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/bin \
	-D PYTHON2_INCLUDE_DIR=/usr/local/Frameworks/Python.framework/Headers \
	-D INSTALL_C_EXAMPLES=ON -D INSTALL_PYTHON_EXAMPLES=ON \
	-D BUILD_EXAMPLES=ON \
	-D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib/modules ..
```

Here some **very important options**, read carefully :

    CMAKE_BUILD_TYPE : This option indicates that we are building a release binary of OpenCV.
    CMAKE_INSTALL_PREFIX : The base directory where OpenCV will be installed.
    PYTHON2_PACKAGES_PATH : The explicit path to where our site-packages  directory lives in our cv  virtual environment.
    PYTHON2_LIBRARY : Path to our Hombrew installation of Python.
    PYTHON2_INCLUDE_DIR : The path to our Python header files for compilation.
    INSTALL_C_EXAMPLES : Indicate that we want to install the C/C++ examples after compilation.
    INSTALL_PYTHON_EXAMPLES : Indicate that we want to install the Python examples after complication.
    BUILD_EXAMPLES : A flag that determines whether or not the included OpenCV examples will be compiled or not.
    OPENCV_EXTRA_MODULES_PATH : This option is extremely important — here we supply the path to the opencv_contrib repo
    				that we pulled down earlier, indicating that OpenCV should compile the extra modules as well.

>The compiling options changes depending on the version of python and most depending on how we are installing all the libraries and the dependencies.

> In order to build OpenCV 3.1.0, you need to set -D INSTALL_C_EXAMPLES=OFF (rather than ON) in the cmake command. There is a bug in the OpenCV v3.1.0 CMake build script that can cause errors if you leave this switch on. Once you set this switch to off, CMake should run without a problem.

Now we can finally compile OpenCV:
```
### Linux & Macintosh OSX

$ make -j4
```
Where you can replace the 4 with the number of available cores on your processor to speedup the compilation.

**OpenCV Linking**: If we have installed OpenCV globally on your PC and you want to link it to the virtualenv, we need to export the two following paths:
- ** export PYTHONPATH="${PYTHONPATH}:/my/other/path"**
(Example of path: /opt/amd64/opencv-3.1.0/lib/python2.7/dist-packages)
- ** export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/my/other/path"**
(Example of path: /opt/amd64/opencv-3.1.0/lib)

Assuming that OpenCV compiled without error, you can now install it on your Ubuntu system:
```
### Linux & Macintosh OSX

$ sudo make install
$ sudo ldconfig
```
If you've reached this step without an error, OpenCV should now be installed in ** /usr/local/lib/python2.7/site-packages**.
However, our cv virtual environment is located in our home directory — thus to use OpenCV within our cv environment, we first need to sym-link OpenCV into the site-packages directory of the cv virtual environment:
```
### Linux

$ cd ~/.virtualenvs/cv/lib/python2.7/site-packages/
$ ln -s /usr/local/lib/python2.7/site-packages/cv2.so cv2.so

### Macintosh OSX

$ cd ~/.virtualenvs/cv/lib/python2.7/site-packages/
$ ls -l cv2.so
-rwxr-xr-x  1 adrian  staff  2013052 Jun  5 15:20 cv2.so

```
**Congratulations! You have successfully installed OpenCV 3.0 with Python 2.7+ bindings on your Linux/MacintoshOSX system!**
To confirm your installation, simply ensure that you are in the cv virtual environment, followed by importing cv2:
```
### Linux

$ workon cv
$ python

### Macintosh OSX

(cv)$ python
```
Your output should be:
```
>>> import cv2
>>> cv2.__version__ '3.0.0'
```

### iii.Tensorflow

For the installation of TensorFlow we can follow the instruction in the Official Turorial, linked at the end, for the Ubuntu case, after activate the envirorment:
```
### Linux 64-bit, CPU only, Python 2.7

(cv)$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.9.0rc0-cp27-none-linux_x86_64.whl

### Linux 64-bit, GPU enabled, Python 2.7
## Requires CUDA toolkit 7.5 and CuDNN v4. For other versions, see "Install from sources" below.

(cv)$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow-0.9.0rc0-cp27-none-linux_x86_64.whl

### Mac OS X, CPU only, Python 2.7:

(cv)$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/mac/tensorflow-0.9.0rc0-py2-none-any.whl

### Linux 64-bit, CPU only, Python 3.4

(cv)$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.9.0rc0-cp34-cp34m-linux_x86_64.whl

###  Linux 64-bit, GPU enabled, Python 3.4
## Requires CUDA toolkit 7.5 and CuDNN v4. For other versions, see "Install from sources" below.

(cv)$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow-0.9.0rc0-cp34-cp34m-linux_x86_64.whl

### Linux 64-bit, CPU only, Python 3.5

(cv)$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.9.0rc0-cp35-cp35m-linux_x86_64.whl

### Linux 64-bit, GPU enabled, Python 3.5
## Requires CUDA toolkit 7.5 and CuDNN v4. For other versions, see "Install from sources" below.

(cv)$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow-0.9.0rc0-cp35-cp35m-linux_x86_64.whl

### Mac OS X, CPU only, Python 3.4 or 3.5:

(cv)$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/mac/tensorflow-0.9.0rc0-py3-none-any.whl

### Linux & Macintosh OSX

# Python 2
(tensorflow)$ sudo pip install --upgrade $TF_BINARY_URL

# Python 3
(tensorflow)$ sudo pip3 install --upgrade $TF_BINARY_URL

```
Test the installation, open a terminal and type the following:
```
### Linux

$ workon cv
$ python

### Linux & Macintosh OSX

(cv)$ python

...
>>> import tensorflow as tf
>>> hello = tf.constant('Hello, TensorFlow!')
>>> sess = tf.Session()
>>> print(sess.run(hello))
Hello, TensorFlow!
>>> a = tf.constant(10)
>>> b = tf.constant(32)
>>> print(sess.run(a + b))
42
>>>
```
Let's run a Model:
```
### Linux & Macintosh OSX

$ python -m tensorflow.models.image.mnist.convolutional
```
### iv.CUDA

Here is covered only the setup of a the preinstalled CUDA, for an indeep tutorial follow the Official One for TensorfFlow or for MAC OSX (Both linked at the end) :

####Setup GPUs

#####1) Download cuDNN 6.5
```
### Linux & Macintosh OSX

$ cd ~
$ wget https://s3-eu-west-1.amazonaws.com/christopherbourez/public/cudnn-6.5-linux-x64-v2.tgz
```
#####2) Add to your .bashrc
```
### Linux & Macintosh OSX

$ export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/cuda-7.0/lib64:/home/users/N!OMUSUARI/cudnn-6.5-linux-x64-v2"
$ export CUDA_HOME=/usr/local/cuda-7.0
```

### v.Other Libraries

 To install other libraries, with the Virtual Environment activated you have just to type:
 ```
 ### Linux & Macintosh OSX

$ pip install packege-name

### Macintosh OSX

$ pip install packege-name

```
Some usefull, could be:
- [Pillow](https://pypi.python.org/pypi/Pillow);
- [ProgressBar](https://pypi.python.org/pypi/progressbar);
- [Pandas](http://pandas.pydata.org/).

 (I will update the list when i found someone useful)

##4. Conclusions

At the end of the guide we have OpenCV, VirtualEnv and CUDA globally installed on our machine.
Then we have Python and Tensorflow installed and working on the VirtualEnv, in this way we have the global and fixed libraries installed correctly and inside the environment all the python Libraries and Tensorflow to not get in conflict with the global ones.

##5. References
Here below all the usefull link to tutorial, guides that I used:
- [Guide VirtualEnv+OpenCV for Linux](http://www.pyimagesearch.com/2015/06/22/install-opencv-3-0-and-python-2-7-on-ubuntu/);
- [Guide VirtualEnv+OpenCV for MacOSX](http://www.pyimagesearch.com/2015/06/15/install-opencv-3-0-and-python-2-7-on-osx/);
- [Official Guide to install OpenCV](http://docs.opencv.org/3.0-last-rst/doc/tutorials/introduction/linux_install/linux_install.html);
- [Official Guide to install Tensorflow](https://www.tensorflow.org/versions/r0.8/get_started/os_setup.html#virtualenv-installation);
- [Official Guide to install CUDA MacOSX](http://docs.nvidia.com/cuda/cuda-installation-guide-mac-os-x/index.html#installation);
- [Official Guide to install CUDA Linux](http://docs.nvidia.com/cuda/cuda-getting-started-guide-for-linux/#axzz49aYMjbtZ).

##6. Copyright

According to the LICENSE file of the original code,
- Me and original author hold no liability for any damages;
- Do not use this on commercial!.


text:
Log out of a Docker Registry located on the specified `SERVER`. You can
specify a URL or a `hostname` for the `SERVER` value. If you do not specify a
`SERVER`, the command attempts to log you out of Docker's public registry
located at `https://registry-1.docker.io/` by default.

# EXAMPLES

## Log out from a registry on your localhost

    # docker logout localhost:8080

# See also
**docker-login(1)** to log in to a registry.


text:
[Tracktics][tracktics] plugin for providing Google Analytics support.

[![npm Version][npm-badge]][npm]
[![Build Status][build-badge]][build-status]
[![Test Coverage][coverage-badge]][coverage-result]
[![Dependency Status][dep-badge]][dep-status]

## Installation

Install using npm:

    $ npm install tracktics-google-analytics

## Usage

Basic usage that integrates with Google Analytics in a simple jQuery app:

```html
<button id="purchase-button"
        type="button"
        data-tracktics-on="click"
        data-tracktics-category="button">Purchase</button>
```

```js
'use strict';

var $ = require('jquery'),
    tracktics = require('tracktics'),
    tracker = tracktics();

// Register the Google Analytics plugin.
tracker.use(require('tracktics-google-analytics')());

$(document).ready(function() {
    // Add event listeners for mouse events on elements that have had
    // data-tracktics-* attributes defined.
    tracker.bind();
});
```

## Declarative Analytics Tracking

In addition to the attributes `data-tracktics-on` and `data-tracktics-event`
provided by Tracktics, tracktics-google-analytics supports the following:

### `data-tracktics-category` (*required*)

The only additionally required attribute for Google Analytics functionality,
`data-tracktics-category` is used to specify category data for the event.
Typically category is the object that was interacted with (e.g., "button").

### `data-tracktics-label`

Used to specify label data for the event. This is useful for further
categorizing events (e.g., "nav buttons").

### `data-tracktics-value`

Used to specify value data for the event. Value must be a non-negative number.
Useful for passing counts (e.g., 4 times).

## API

### `tracktics-google-analytics([windowObject])`

```js
var tracktics = require('tracktics'),
    trackticsGa = require('tracktics-google-analytics'),
    tracker = tracktics();

tracker.use(trackticsGa());
```

The main tracktics-google-analytics export, `tracktics-google-analytics` is a
factory function for generating tracktics-google-analytics plugin instances.
Calling this method returns an object that implements page and event tracking
for Google Analytics. The plugin will intelligently look for a ga function in
the global window namespace, but if `ga` cannot be found, or the wrong `ga` is
found, `ga` can be manually specified by providing a window object placeholder
to the function.

### `#trackPage(url)`

Method for manual page tracking.

### `#trackEvent(action, options)`

Method for manual event tracking. Available options:

 - `category` *(required)*
 - `label`
 - `value`

## License

MIT

[build-badge]: https://img.shields.io/travis/jimf/tracktics-google-analytics/master.svg
[build-status]: https://travis-ci.org/jimf/tracktics-google-analytics
[npm-badge]: https://img.shields.io/npm/v/tracktics-google-analytics.svg
[npm]: https://www.npmjs.org/package/tracktics-google-analytics
[coverage-badge]: https://img.shields.io/coveralls/jimf/tracktics-google-analytics.svg
[coverage-result]: https://coveralls.io/r/jimf/tracktics-google-analytics
[dep-badge]: https://img.shields.io/david/jimf/tracktics-google-analytics.svg
[dep-status]: https://david-dm.org/jimf/tracktics-google-analytics
[tracktics]: https://github.com/jimf/tracktics


text:
<?xml version="1.0" encoding="utf-8" ?>
<widget id="Hopscotch.widgets.HopscotchTour" needsEntityContext="false" xmlns="http://www.mendix.com/widget/1.0/">
	<name>Hopscotch Tour</name>
	<description>The description of this widget.</description>

	<icon></icon>

	<properties>
		<property key="showCloseButton" type="boolean" defaultValue="true" required="true">

Show close button?

			<category>Actions</category>
			<description></description>
		</property>
		<property key="showPrevButton" type="boolean" defaultValue="false" required="true">

Show previous button?

			<category>Actions</category>
			<description></description>
		</property>
		<property key="showNextButton" type="boolean" defaultValue="true" required="true">

Show next button?

			<category>Actions</category>
			<description></description>
		</property>
		<property key="skipIfNoElement" type="boolean" defaultValue="true" required="true">

Skip if no target?

			<category>Actions</category>
			<description>If a specified target element is not found, should we skip to the next step?</description>
		</property>
		<property key="nextOnTargetClick" type="boolean" defaultValue="false" required="true">

Next on target click?

			<category>Actions</category>
			<description>Should we advance to the next step when the user clicks on the target?</description>
		</property>
		<property key="onStartMF" type="microflow" required="false" defaultValue="">

On start

			<category>Actions</category>
			<description>At start of tour</description>
			<returnType type="Boolean"></returnType>
		</property>
		<property key="onEndMF" type="microflow" required="false" defaultValue="">

On end

			<category>Actions</category>
			<description>At end of tour</description>
			<returnType type="Boolean"></returnType>
		</property>
		<property key="onPrevMF" type="microflow" required="false" defaultValue="">

On previous

			<category>Actions</category>
			<description>When previous is clicked</description>
			<returnType type="Boolean"></returnType>
		</property>
		<property key="onNextMF" type="microflow" required="false" defaultValue="">

On next

			<category>Actions</category>
			<description>When next is clicked</description>
			<returnType type="Boolean"></returnType>
		</property>
		<property key="onCloseMF" type="microflow" required="false" defaultValue="">

On close

			<category>Actions</category>
			<description>When tour is closed</description>
			<returnType type="Boolean"></returnType>
		</property>
		<property key="onErrorMF" type="microflow" required="false" defaultValue="">

On error

			<category>Actions</category>
			<description>When element not available</description>
			<returnType type="Boolean"></returnType>
		</property>

		<property key="bubbleWidth" type="integer" required="true" defaultValue="280">

Bubble width

			<category>Appearance</category>
			<description></description>
		</property>
		<property key="bubblePadding" type="integer" required="true" defaultValue="15">

Bubble padding

			<category>Appearance</category>
			<description></description>
		</property>
		<property key="smoothScroll" type="boolean" defaultValue="true" required="true">

Smooth scroll?

			<category>Appearance</category>
			<description></description>
		</property>
		<property key="scrollDuration" type="integer" required="true" defaultValue="1000">

Scroll duration

			<category>Appearance</category>
			<description></description>
		</property>
		<property key="scrollTopMargin" type="integer" required="true" defaultValue="200">

Scroll top margin

			<category>Appearance</category>
			<description>When the page scrolls, how much space should there be between the bubble/targetElement and the top of the viewport?</description>
		</property>
		<property key="arrowWidth" type="integer" required="true" defaultValue="20">

Arrow width

			<category>Appearance</category>
			<description></description>
		</property>

		<property key="multipageid" type="string" defaultValue="" required="false">

ID for multipage

			<category>Extra</category>
			<description></description>
		</property>

		<property key="steps" type="object" isList="true" required="true">

Steps

			<category>Steps</category>
			<description></description>
			<properties>
				<property key="title" type="string" defaultValue="" required="false">

Title

					<category>Content</category>
					<description></description>
				</property>
				<property key="content" type="string" defaultValue="" required="false">

Content

					<category>Content</category>
					<description></description>
				</property>
				<property key="target" type="string" defaultValue="" required="true">

Target selector

					<category>Content</category>
					<description></description>
				</property>

				<property key="placement" type="enumeration" defaultValue="top" required="true">

Placement

					<category>Appearance</category>
					<description></description>
					<enumerationValues>
						<enumerationValue key="top">Top</enumerationValue>
						<enumerationValue key="left">Left</enumerationValue>
						<enumerationValue key="right">Right</enumerationValue>
						<enumerationValue key="bottom">Bottom</enumerationValue>
					</enumerationValues>
				</property>
				<property key="xOffset" type="string" defaultValue="0" required="false">

Horizontal offset

					<category>Appearance</category>
					<description>Value can be number of pixels or "center"</description>
				</property>
				<property key="yOffset" type="string" defaultValue="0" required="false">

Vertical offset

					<category>Appearance</category>
					<description>Value can be number of pixels or "center"</description>
				</property>
				<property key="arrowOffset" type="string" defaultValue="0" required="false">

Arrow offset

					<category>Appearance</category>
					<description>Value can be number of pixels or "center"</description>
				</property>
				<property key="delay" type="integer" required="true" defaultValue="0">

Delay

					<category>Appearance</category>
					<description>Milliseconds to wait before showing step.</description>
				</property>
				<property key="zindex" type="integer" required="true" defaultValue="0">

Z-Index

					<category>Appearance</category>
					<description></description>
				</property>
				<property key="fixedElement" type="boolean" defaultValue="false" required="true">

Fixed element?

					<category>Appearance</category>
					<description>Target has fixed positioning?</description>
				</property>

				<property key="showNextButton" type="boolean" defaultValue="true" required="true">

Show next button?

					<category>Actions</category>
					<description></description>
				</property>
				<property key="showPrevButton" type="boolean" defaultValue="true" required="true">

Show previous button?

					<category>Actions</category>
					<description></description>
				</property>
				<property key="showCloseButton" type="boolean" defaultValue="true" required="true">

Show close button?

					<category>Actions</category>
					<description></description>
				</property>
				<property key="showCTAButton" type="boolean" defaultValue="false" required="true">

Show call-to-action button?

					<category>Actions</category>
					<description></description>
				</property>
				<property key="onShowMF" type="microflow" required="false" defaultValue="">

On show

					<category>Actions</category>
					<description>When bubble is first shown</description>
					<returnType type="Boolean"></returnType>
				</property>
				<property key="onCloseMF" type="microflow" required="false" defaultValue="">

On close

					<category>Actions</category>
					<description>When bubble is closed</description>
					<returnType type="Boolean"></returnType>
				</property>
				<property key="onNextMF" type="microflow" required="false" defaultValue="">

On next button

					<category>Actions</category>
					<description>When next is clicked</description>
					<returnType type="Boolean"></returnType>
				</property>
				<property key="onPrevMF" type="microflow" required="false" defaultValue="">

On previous button

					<category>Actions</category>
					<description>When previous is clicked</description>
					<returnType type="Boolean"></returnType>
				</property>
				<property key="onErrorMF" type="microflow" required="false" defaultValue="">

On error

					<category>Actions</category>
					<description>When element not available</description>
					<returnType type="Boolean"></returnType>
				</property>
				<property key="ctaLabel" type="string" defaultValue="" required="false">

CTA label

					<category>Actions</category>
					<description></description>
				</property>
				<property key="onCtaMF" type="microflow" required="false" defaultValue="">

On CTA

					<category>Actions</category>
					<description>When CTA is clicked</description>
					<returnType type="Boolean"></returnType>
				</property>
				<property key="showSkip" type="boolean" defaultValue="false" required="true">

Replace next with skip?

					<category>Actions</category>
					<description></description>
				</property>

				<property key="multipage" type="boolean" defaultValue="false" required="true">

Next step on different page?

					<category>Extra</category>
					<description></description>
				</property>
			</properties>
		</property>
	</properties>
</widget>


text:
<!doctype html>

		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

		<title>i18n & l10n @ UX Romandie</title>

		<link rel="stylesheet" href="css/reveal.css">
		<link rel="stylesheet" href="css/theme/antistatique.css">

		<link rel="stylesheet" href="lib/css/zenburn.css">

					i18n et l10n

					Internationalisation & Localisation

						Slide de titre, Ça va commencer

						Bonjour · Hallo · Hello

						Ciao · صباح الخير · 你好

						Hej · おはようございます

						Hola · Grützi · Hei

						Добрий ранок · Chào

						Marc Je suis Marc, Software Designer co-fondateur d'Antistatique

						Guillaume Je suis Guillaume, DA d'Antistatique

Disclaimer

						Guillaume

						On a déjà donné ce talk

						Pas que design

						Un peu technique

						Pas que pour les débutants

						Ce talk contient des métaphores culinaires

Introduction

							Marc Une introduction pour vous expliquer pourquoi vous ne devez pas partir tout de suite ;-).

							Marc

							Pourquoi nous avions envie de vous parler de ce sujet ?

							La suisse : 4 langues officielles (FR / DE / IT / RM)

							Tous nos projets même les plus petits sont multi-langue

l10n

							Guillaume

							Commençons par le terme l10n : localisation

							➡ Le fait d'avoir une version spécifique à une culture

							Guillaume

							localisation ... 10 lettres entre le L et le N

i18n

							Guillaume

							Ensuite le i18n : internationalisation

							➡ Le fait de prévoir la prise en charge de multiples cultures

							Guillaume

							internationalisation

							Oups, ça dépasse ;-)

							La on comprend mieux pourquoi nous disons i18n

l10n

i18n

g11n

L12y

NLS

							Guillaume

							Bienvenue dans le monde des numéronymes & accronymes !

							g11n IBM & Sun (globalization / glocalization)

							L12y Microsoft (localizability)

							NLS HP  (National/Native Language Support)

a11y

							Guillaume

							D'ailleurs vous devez connaitre celui-ci

Cultures ?

							Guillaume

							Est-ce que la culture d'une personne peut être définie par un ensemble qui se compose d'un territoires et d'une langue ?

Normes

							Marc

							En tout cas, c'est de cette manière que les normes ISO défnissent la culture

fr_latin_CH

							Marc

						Culture en français -> Locale

						Langue + Script + Territoire
							--> Latin pour les lettres latines A-Z ... pas très utiles pour nous francophone ... mais pensez aux langues comme le japonais que s'écrit en kanji, Hiragana et Katakana
						fr_latin_FR

						fr_GF = "French (French Guiana)"
						fr_TG = "French (Togo)"
						fr_SC = "French (Seychelles)"
						fr_VU = "French (Vanuatu)"
						fr_RE = "French (Réunion)"
						fr_TN = "French (Tunisia)"
						fr_GN = "French (Guinea)"
						fr_HT = "French (Haiti)"
						fr_GP = "French (Guadeloupe)"
						fr_GQ = "French (Equatorial Guinea)"
						fr_CA = "French (Canada)"
						fr_SN = "French (Senegal)"
						fr_CD = "French (Congo - Kinshasa)"
						fr_PF = "French (French Polynesia)"
						fr_CH  = "French (Switzerland)"
						fr_DJ = "French (Djibouti)"
						fr_CF = "French (Central African Republic)"
						fr_CG = "French (Congo - Brazzaville)"
						fr_FR = "French (France)"
						fr_CI = "French (Côte d'Ivoire)"
						fr_BE = "French (Belgium)"
						fr_BF = "French (Burkina Faso)"
						fr_NC = "French (New Caledonia)"
						fr_SY = "French (Syria)"
						fr_PM = "French (St. Pierre & Miquelon)"
						fr_NE = "French (Niger)"
						fr_MA = "French (Morocco)"
						fr_CM = "French (Cameroon)"
						fr_BI = "French (Burundi)"
						fr_BJ = "French (Benin)"
						fr_RW = "French (Rwanda)"
						fr_MC = "French (Monaco)"
						fr_BL = "French (St. Barthélemy)"
						fr_MF = "French (St. Martin)"
						fr_MG = "French (Madagascar)"
						fr_DZ = "French (Algeria)"
						fr_ML = "French (Mali)"
						fr_MQ = "French (Martinique)"
						fr_WF = "French (Wallis & Futuna)"
						fr_MR = "French (Mauritania)"
						fr_MU = "French (Mauritius)"
						fr_KM = "French (Comoros)"
						fr_YT = "French (Mayotte)"
						fr_LU = "French (Luxembourg)"
						fr_GA = "French (Gabon)"
						fr_TD = "French (Chad)"

							Marc

							Les locales francophones supportées dans les librairies iOS

							Guillaume

							Ce thème est important : L'i18n comme l'a11y est une forme d'inclusion de tous les publics (Reconnaissance)

							Marc

							Qu'est-ce que je fais sur ce site de nouille japonaise.

							Bon, maintenant, où est-ce qu'on change la langue ?

							English language

Connaître la "locale" de l'utilisateur c'est important…

							Marc

							On est tous d'accord que connaitre la culture de notre utilisateur est important.
							Comment fait-on pour l'obtenir !

Plutôt de_CH oder fr_CH

							Marc

							Je suis suisse d'accord ... mais

							Marc

							De quoi disposons-nous sur nos visiteurs ?

							- IP, localisation mouais

							- Langue du navigateur

							- Referer (d'où la personne vient)

							- Toutes les infos techniques qui nous servent pas ici ;-) Browser, OS, résolution etc ...

							Marc

							Détection automatique de la culture ?
							Utiliser l'extension de domaine pour arriver sur un pays

							Détecter la langue du navigateur

							Sachez surtout qu'aucun script de géolocalisation n'est fiable

							Marc Bon, un exemple concret.

							Je veux aller visiter la finlande

							Marc

							finnair.com -> global splash screen avec uniquement les pays

							A parfait, la Suisse à droite

							Marc

							J'arrive sur le site en suisse-allemand, super ! (bon j'ai l'habitude, kein problem)

							Je vois le drapeau en haut, je clique

							Marc

							J'arrive à nouveau sur un global splash screen, cette fois avec la langue ?!
							À noter que pour les suisse-italophone, ils devront choisir italien avec les prix en Euro ou Français avec les prix en CHF

							Marc

							Finalement, me voilà sur ma page

							Nous avons effectué des tests utilisateurs sur finnair.com. (URL + je ne vais jamais sur la suisse, les prix sont plus hauts)

							Marc

							Finnair ne proposait que les pays, Facebook ne propose que les langues

							Écrire la langue dans la langue (Français et pas French, 日本語 et pas Japonais)

							Marc

							Vu au Musée olympique

							Marc

							Steam

							Marc

							Si vous ne supportez que quelques langues sur un site national

							Marc

							L'icone de la planète... pour signifier le changement de culture

							Marc

							Un concours de design a été lancé pour résoudre ce problème, voici le vainqueur
							Ne pas utiliser les drapeaux !

Les langues

L'espace et le temps

Les chiffres

Autres

							Marc

							Et maintenant, que l'on sait à qui l'on s'adresse. quelques particularités intéressantes

Les langues

							Guillaume

							Nous avons l'habitude des particularités de langues (direction d'écriture) mais ....

Type d'écritures (latin, arabe, cyrillique, chinois, klingon, etc.)

Spécificités (dialects, registre de langue, styles, etc.)

Conventions d'écriture (des chiffres, des dates, contextuelles, etc.)

Traduction

							Guillaume

							Traduction

							Vidéos (audio, titres, sous-titres, ..)

							Textes (contenu, éléments d'interface, messages d'erreurs, ..)

							Icônes & logos (dans une certaine langue, pour une certaine culture, dans un certain contexte)

Pluralisation

Est-ce que ce mot existe d'ailleurs ?

							Marc

							En russe c'est compliqué .. est-ce que quelqu'un peut nous aider

en : "%count% comment
     |%count% comments"
ru : "%count% комментарий
     |%count% комментария
     |%count% комментариев"
fr : "%count% commentaire
     |%count% commentaires"

Féminisation

Et celui-là ?

							Guillaume

							Parité - ;-)

							vous êtes bien connectée

Temps & espace

							Marc

							Pour chaque culture, d'autres représentation du temps et de l'espace

							Marc

							Les fuseaux horaires

							Meilleur exemple de temps et d'espace

							Respecte ou pas les frontières

							Marc

							Début de semaine

							le classic ... la semaine commence le lundi ou le dimanche ?

							Guillaume

							L'âge des coréens🇰🇷 qui commence à 1 et (qui dépend des calendriers 🌞/🌔)

							Au niveau de la corée du nord, nous avons eu du mal à vérifier

							G -> M
							Le week-end prochain pour vous c'est ce week-end là qui vient ou celui d'après

							On l'a implémenté dans momentJS, une librairie qui s'occupe des manipulations de dates

							M -> G

On se voit à 5 heures

c'est un peu tot ...

							AM/PM tout ça ...

							Marc

							Heure d'été ...

							Au Chili par exemple, il passe à l'heure d'été début avril ...

							Sinon une petite pensée à tous ceux qui prévoient leur backup à 1h30 du matin le week-end de changement d'heure Et qui ont eu 0 backup ce printemps et 2 cet automne.

12/24/2016

ou

24-12-2016

							Marc

							La représentation des dates

							Marc

							Vision du monde

							la frontière entre la chine et le Bhoutan qui est disputées depuis des décénie. GoogleMap affiche une frontière différente selon le pays dans lequel on se connecte

							Marc

							La politique

							ROT, c'est le code ISO de quel pays ? (refugee-olympic-team)

							-> JO pays des réfugiers, certain pays non reconnu par le ONU, mais reconnu par le CIO

							Marc

							Certaine fédérations sportives, comme la lutte, choisi de permettre à certain "pays" de participer

Les chiffres

							Guillaume

							beaucoup de particularité aussi ici ...

Le formatage des milliers

								Locale
								Valeur

								fr_CH
								12'340.40

								fr_FR
								12 340,40

								en_US
								12,340.40

								de_DE
								12.340,40

							Guillaume

La position de la devise

								Locale
								Valeur

								fr_CH
								CHF 12'340.40

								fr_FR
								12 340,40 €

								en_US
								$ 12,340.40

								de_DE
								12.340,40 €

							Guillaume

"Jean-Luc"

votre prénom est invalide

							Guillaume

							nom invalide ...

							Suède numéro postaux avec des espaces

							En Suisse le numéro de rue à la fin de l'adresse ... en France au début : "8, rue de la République"

							Guillaume

							Numéro de téléphone, merci squarespace

							Guillaume

							Systèmes de mesures

							Température, fahrenheit/Celsius, système métrique, tout ça ...

Quelques miscellanées

							Guillaume

							Autres considérations,juste un début de liste ;-)

Typographie(s)

							Guillaume

								Exemple de la Noto :-) 500MO 😱

								Bons caractères (ceux de la langue)

								Bon sens (de lecture) a11y / accessibilité

						<svg id="Calque_1" data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 768 256">
  <defs>

  </defs>
  <title>religion-icons-research</title>
  <g>
    <path class="cls-1" d="M375.91,142.87c0-.15,0-.29-.07-.44s-.06-.26-.09-.39-.06-.25-.1-.37-.09-.25-.13-.37-.08-.25-.13-.37-.1-.23-.16-.34-.11-.25-.18-.37l-.19-.31c-.07-.12-.14-.24-.22-.36s-.16-.22-.24-.33l-.22-.3c-.15-.19-.31-.36-.48-.53l0-.05-40-40a8,8,0,0,0-11.31,11.31L360,147.31V192h-8V160c0-.26,0-.53,0-.79s0-.22,0-.34,0-.29-.07-.44-.06-.26-.09-.39-.06-.25-.1-.37-.09-.25-.13-.37-.08-.25-.13-.37-.1-.23-.16-.34-.11-.25-.18-.37l-.19-.31c-.07-.12-.14-.24-.22-.36s-.16-.22-.24-.33l-.22-.3c-.15-.19-.31-.36-.48-.53l0-.05L312,116.69V56a8,8,0,0,0-16,0v64a8,8,0,0,0,2.34,5.66L336,163.31V208h40V144c0-.26,0-.53,0-.79S375.93,143,375.91,142.87Z"/>
    <path class="cls-1" d="M464,48a8,8,0,0,0-8,8v60.69l-37.66,37.66-.16.18c-.13.13-.25.27-.37.41s-.17.23-.26.34l-.21.29c-.08.13-.16.26-.24.39l-.17.28c-.07.13-.13.26-.19.39s-.1.21-.15.32-.1.26-.14.38-.09.23-.12.36-.07.26-.1.39-.07.24-.09.37,0,.3-.07.46,0,.21,0,.32c0,.27,0,.53,0,.8v32h-8V147.31l37.66-37.66a8,8,0,0,0-11.31-11.31l-40,40-.16.18c-.13.13-.25.27-.37.41s-.17.23-.26.34l-.21.29c-.08.13-.16.26-.24.39l-.17.28c-.07.13-.13.26-.19.39s-.1.21-.15.32-.1.26-.14.38-.09.23-.12.36-.07.26-.1.39-.07.24-.09.37,0,.3-.07.46,0,.21,0,.32c0,.27,0,.53,0,.8v64h40V163.31l37.66-37.66A8,8,0,0,0,472,120V56A8,8,0,0,0,464,48Z"/>
    <path class="cls-1" d="M140.44,97.34a8,8,0,0,0-11.09,2.22l-9.73,14.59-17.22-23a8,8,0,0,0-13.75,1.65l-24,56A8,8,0,0,0,65.75,157l21.6,27H48v16h56a8,8,0,0,0,6.24-13l-29-36.26L97.9,111.87l15.7,20.93a8,8,0,0,0,13.06-.36l16-24A8,8,0,0,0,140.44,97.34Z"/>
    <circle class="cls-1" cx="112" cy="72" r="16"/>
    <path class="cls-1" d="M699.8,92.9a43.18,43.18,0,0,0-10.91-43.32L672,32.69,655.15,49.53a43.19,43.19,0,0,0-11,43.36c-12.38,5-20.2,13.29-20.2,23.1v80c0,16,20.64,28,48,28s48-12,48-28V116C720,106.18,712.18,97.85,699.8,92.9Zm-39.43-23a27,27,0,0,1,6.05-9L672,55.31l5.62,5.62a27.18,27.18,0,0,1,6.15,29.37,9.1,9.1,0,0,1-2.31,2.63A12.43,12.43,0,0,1,679.75,94a8,8,0,0,0-15.5,0,12.45,12.45,0,0,1-1.71-1.12,9.1,9.1,0,0,1-2.31-2.62A27,27,0,0,1,660.37,69.87ZM704,196c0,4.23-12.15,12-32,12s-32-7.77-32-12V137.21c8.37,4.26,19.48,6.79,32,6.79s23.63-2.53,32-6.79Zm-32-68c-19.85,0-32-7.77-32-12,0-2.73,5.05-6.92,14-9.56a29.92,29.92,0,0,0,7.73,3.88c.76.25,1.54.47,2.32.67v1a8,8,0,0,0,16,0v-1c.78-.2,1.55-.42,2.32-.67a29.92,29.92,0,0,0,7.73-3.88c8.9,2.64,14,6.83,14,9.56C704,120.23,691.85,128,672,128Z"/>
  </g>
</svg>

Pictogrammes

							Guillaume

Les représentations de la culture (religion)

Couleurs

							Guillaume

Tout ce qui est valide est vert, chez nous

Particularités culturelles régionales

(voir hyper-régionales ou drôles)

							Guillaume

2.5 pièces à Genève ou Lausanne

Doucette, rampon ou mâche ?

Takeaways

						- Ne partez sur aucun aquis 🙈🙊🙉

						- Nation ≠ culture ≠ langue (et les gens bougent!). Le lieu géographique n'est pas un critère fiable.

						- Basez-vous un maximum sur les librairies d'internationalisation dèjà en place

						- Utilisez les UX-pattern pour le changement de culture (par pitié, pas de drapeaux pour les langues)

						- Responsabilité de ces sujets ... est partagée par tous les membres de l'équipe du projet

Questions & Réponses

Merci !

🐦

@zufrieden  +  @guillaumeberry

						— notes

					antistatique.net

On recrute !

						— notes

					1810.io

Slides

Email pour être tenu au courant !

©

								Présentation
								reveal.js

								Typographie
								Noto Sans Regular

								Noto Sans Bold

								Noto Mono

								Emojis
								emojione.com

						Les crédits