Archived to legacy branch
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index ed2d20d..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,15 +0,0 @@
-lib/
-logs/
-.project
-project/*
-!project/Build.scala
-!project/Common.scala
-!project/plugins.sbt
-target/
-build/
-dist/target/
-vendors
-.DS_Store
-.idea
-.gradle
-*.swp
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index e828ae5..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-language: scala
-env:
-  - PLAY_VERSION=2.2.2
-scala:
-  - "2.10.3"
-jdk:
-  - oraclejdk7
-  - openjdk7
-  - openjdk6
-services: mongodb
-before_script:
-  - wget http://downloads.typesafe.com/play/${PLAY_VERSION}/play-${PLAY_VERSION}.zip
-  - unzip -q play-${PLAY_VERSION}.zip
-script:
-  - sbt test
-  - sbt commons/publish
-  - sbt output/publish
-  - cd servers/admin
-  - ../../play-${PLAY_VERSION}/play test
-  - cd ../api
-  - ../../play-${PLAY_VERSION}/play test
-  - cd ../scheduler
-  - ../../play-${PLAY_VERSION}/play test
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
deleted file mode 100644
index 3220ec0..0000000
--- a/CONTRIBUTING.md
+++ /dev/null
@@ -1,41 +0,0 @@
-Contributing to PredictionIO
-============================
-
-Thank you for your interest in contributing to PredictionIO!
-
-We are building this software together and strongly encourage contributions
-from the community that are within the guidelines set forth below.
-
-
-Bug Fixes and New Features
---------------------------
-
-As your first step, please visit and read the [Contributor License Agreement]
-(http://prediction.io/cla). All contributors are required to sign this
-agreement.
-
-
-Before starting to write code, look for existing [tickets]
-(https://predictionio.atlassian.net/browse/PDIO) or [create one]
-(https://predictionio.atlassian.net/secure/CreateIssue!default.jspa)
-for your bug, issue, or feature request. This helps the community
-avoid working on something that might not be of interest or which
-has already been addressed.
-
-
-Pull Requests
--------------
-
-PredictionIO follows the [git-flow]
-(http://nvie.com/posts/a-successful-git-branching-model/) model where all
-active development goes to the develop branch, and releases go to the master
-branch. Pull requests should be made against the develop branch and include
-relevant tests, if applicable.
-
-
-Talk To Us
-----------
-
-We love to hear from you. If you want to work on something or have
-questions / feedback, please reach out to us at
-https://groups.google.com/forum/#!forum/predictionio-dev
diff --git a/CREDITS b/CREDITS
deleted file mode 100644
index 8e2c84e..0000000
--- a/CREDITS
+++ /dev/null
@@ -1,62 +0,0 @@
-PredictionIO is made possible by the PredictionIO open source project and other open source software.
-
-
-Cascading Tap for Mongodb
-https://github.com/ifesdjeen/cascading-mongodb
-----------------------------------------
-Copyright (C) 2011-2012 Alex Petrov
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-
-GraphChi
-https://github.com/GraphChi/graphchi-cpp
-----------------------------------------
-Copyright [2012] [Aapo Kyrola, Guy Blelloch, Carlos Guestrin / Carnegie Mellon University]
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-
-GraphChi Collaborative Filtering Toolkit
-https://github.com/GraphChi/graphchi-cpp/tree/master/toolkits/collaborative_filtering
-----------------------------------------
-Copyright [2012] [Danny Bickson / Carnegie Mellon University]
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-
-Movie Recommendations and More via MapReduce and Scalding
-https://github.com/echen/scaldingale
-----------------------------------------
-The MIT License (MIT)
-Copyright (c) Edwin Chen
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 0c8aba7..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,16 +0,0 @@
-PredictionIO
-A prediction server for software developers
-Copyright (C) 2012-2014  TappingStone, Inc.
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program.  If not, see <http://www.gnu.org/licenses/>.
diff --git a/README.md b/README.md
deleted file mode 100644
index 3febc71..0000000
--- a/README.md
+++ /dev/null
@@ -1,70 +0,0 @@
-PredictionIO
-============
-
-[![Build Status](https://travis-ci.org/PredictionIO/PredictionIO.svg?branch=develop)](https://travis-ci.org/PredictionIO/PredictionIO)
-
-PredictionIO is a prediction server for building smart applications. You can make
-predictions through PredictionIO just as you would filter data using a database server.
-
-With PredictionIO, you can write apps
-* that predict user behaviors based on solid data science
-* using your choice of state-of-the-art machine learning algorithms
-* without worrying about scalability
-
-Detailed documentation is available on our
-[documentation site](http://docs.prediction.io).
-
-PredictionIO Project Website: [http://prediction.io/](http://prediction.io/).
-
-
-INSTALLATION
-============
-
-Install PredictionIO from Source Code:
-http://docs.prediction.io/current/installation/index.html
-
-
-SUPPORT
-=======
-
-
-Forum
------
-
-https://groups.google.com/group/predictionio-user
-
-
-Issue Tracker
--------------
-
-https://predictionio.atlassian.net
-
-If you are unsure whether a behavior is an issue, bringing it up in the forum is highly encouraged.
-
-
-LICENSE
-=======
-
-The goal of the server license is to require that enhancements to the
-PredictionIO core be released to the community. We promise that your client
-application, which connects to PredictionIO through SDKs or APIs, is a separate
-work. Official PredictionIO SDKs are released under Apache license, which is
-copyleft free.
-
-PredictionIO SDKs
------------------
-
-PredictionIO supported SDKs:
-[Apache License v2.0](http://www.apache.org/licenses/LICENSE-2.0).
-
-PredictionIO Server
--------------------
-
-Free Software Foundation’s
-[GNU AGPL v3.0](http://www.gnu.org/licenses/agpl-3.0.html).
-
-Documentation
--------------
-
-Creative Commons
-[Attribution 3.0 Unported](http://creativecommons.org/licenses/by/3.0/).
diff --git a/bin/build.sh b/bin/build.sh
deleted file mode 100755
index 70280a9..0000000
--- a/bin/build.sh
+++ /dev/null
@@ -1,127 +0,0 @@
-#!/usr/bin/env sh
-
-# PredictionIO Build Script
-
-set -e
-
-# Get the absolute path of the build script
-SCRIPT="$0"
-while [ -h "$SCRIPT" ] ; do
-    SCRIPT=`readlink "$SCRIPT"`
-done
-
-# Get the base directory of the repo
-DIR=`dirname $SCRIPT`/..
-cd $DIR
-BASE=`pwd`
-
-. "$BASE/bin/common.sh"
-. "$BASE/bin/vendors.sh"
-
-# Full rebuild?
-if test "$REBUILD" = "1" ; then
-    echo "Rebuild set."
-    CLEAN=clean
-else
-    echo "Incremental build set. Use \"REBUILD=1 $0\" for clean rebuild."
-    CLEAN=
-fi
-
-echo "Going to build PredictionIO..."
-BASE_TARGETS="update compile commons/publish output/publish"
-
-if test "$SKIP_PROCESS" = "1" ; then
-    echo "Skip building process assemblies."
-else
-    echo "+ Assemble Process Hadoop Scalding"
-    BASE_TARGETS="$BASE_TARGETS processHadoopScalding/assembly"
-fi
-
-# Build Non-distributed Random Algorithm
-echo "+ Pack Non-distributed Random Algorithm"
-BASE_TARGETS="$BASE_TARGETS processEnginesCommonsAlgoScalaRandom/pack"
-
-# Build Generic Single Machine ItemRec Data Preparator
-echo "+ Pack Single Machine Generic ItemRec Data Preparator"
-BASE_TARGETS="$BASE_TARGETS processEnginesItemRecAlgoScalaGeneric/pack"
-
-# Build Mahout ItemRec Job and Model Construcotor
-echo "+ Pack Mahout ItemRec Job and Model Constructor"
-BASE_TARGETS="$BASE_TARGETS processEnginesItemRecAlgoScalaMahout/pack"
-
-# Build GraphChi Model Constructor
-echo "+ Pack GraphChi ItemRec Model Constructor"
-BASE_TARGETS="$BASE_TARGETS processEnginesItemRecAlgoScalaGraphChi/pack"
-
-# Build Generic Single Machine ItemSim Data Preparator
-echo "+ Pack Single Machine Generic ItemSim Data Preparator"
-BASE_TARGETS="$BASE_TARGETS processEnginesItemSimAlgoScalaGeneric/pack"
-
-# Build Mahout ItemSim Job and Model Construcotor
-echo "+ Pack Mahout ItemSim Job and Model Constructor"
-BASE_TARGETS="$BASE_TARGETS processEnginesItemSimAlgoScalaMahout/pack"
-
-# Build GraphChi Model Constructor
-echo "+ Pack GraphChi ItemSim Model Constructor"
-BASE_TARGETS="$BASE_TARGETS processEnginesItemSimAlgoScalaGraphChi/pack"
-
-# Build Single Machine U2I Action Splitter
-echo "+ Pack Single Machine U2I Action Splitter"
-BASE_TARGETS="$BASE_TARGETS processEnginesCommonsEvalScalaU2ISplit/pack"
-
-# Build Single Machine MAP@k
-echo "+ Pack Single Machine MAP@k"
-BASE_TARGETS="$BASE_TARGETS processEnginesCommonsEvalScalaMetricsMAP/pack"
-
-# Build parameter generator
-echo "+ Pack Process Commons Evaluations Scala Parameter Generator"
-BASE_TARGETS="$BASE_TARGETS processEnginesCommonsEvalScalaParamGen/pack"
-
-# Build Single Machine Top-K Collector
-echo "+ Pack Single Machine Top-K Collector"
-BASE_TARGETS="$BASE_TARGETS processEnginesCommonsEvalScalaTopKItems/pack"
-
-echo "+ Pack Process Commons Evaluations Scala U2I Training-Test Splitter Wrapper"
-BASE_TARGETS="$BASE_TARGETS processEnginesCommonsEvalScalaU2ITrainingTestSplit/pack"
-
-# Build connection check tool
-echo "+ Pack Connection Check Tool"
-BASE_TARGETS="$BASE_TARGETS toolsConncheck/pack"
-
-# Build settings initialization tool
-echo "+ Pack Settings Initialization Tool"
-BASE_TARGETS="$BASE_TARGETS toolsSettingsInit/pack"
-
-# Build software manager
-echo "+ Pack Software Manager"
-BASE_TARGETS="$BASE_TARGETS toolsSoftwareManager/pack"
-
-# Build user tool
-echo "+ Pack User Tool"
-BASE_TARGETS="$BASE_TARGETS toolsUsers/pack"
-
-# Build migration tool for 0.7
-echo "+ Pack 0.7 Migration Tool"
-BASE_TARGETS="$BASE_TARGETS toolsMigrationStandardizedInfoIDs/pack"
-
-# Build Feature-based Item Rec
-echo "+ Feature-based Item Rec"
-BASE_TARGETS="$BASE_TARGETS processEnginesItemRecAlgoScalaFeatureBased/pack"
-
-
-$SBT $CLEAN $BASE_TARGETS
-
-# Build admin server
-echo "Going to build PredictionIO Admin Server..."
-cd $BASE/servers/admin
-$PLAY $CLEAN update compile
-
-# Build API server
-echo "Going to build PredictionIO API Server..."
-cd $BASE/servers/api
-$PLAY $CLEAN update compile
-
-# Build scheduler server
-echo "Going to build PredictionIO Scheduler Server..."
-cd $BASE/servers/scheduler
-$PLAY $CLEAN update compile
diff --git a/bin/change-version.py b/bin/change-version.py
deleted file mode 100755
index 170d54e..0000000
--- a/bin/change-version.py
+++ /dev/null
@@ -1,60 +0,0 @@
-#!/usr/bin/env python
-
-import glob
-import os
-import shutil
-import sys
-
-def change(filename, oldversion, newversion):
-    tempfile = filename + '.tmp'
-    fi = open(filename, 'r')
-    fo = open(tempfile, 'w')
-    for line in fi:
-        nl = line.replace(oldversion, newversion)
-        fo.write(nl)
-    fo.close()
-    fi.close()
-    shutil.copymode(filename, tempfile)
-    shutil.move(tempfile, filename)
-    print "Processed " + filename
-
-if len(sys.argv) < 3:
-    print """
-Usage: bin/change-version.py <old-version> <new-version>
-    """
-    sys.exit(-1)
-
-oldversion = sys.argv[1]
-newversion = sys.argv[2]
-files = [
-    'build.sbt',
-    'bin/common.sh',
-    'commons/build.sbt',
-    'dist/bin/*',
-    'dist/bin/*/*',
-    'dist/conf/init.json',
-    'dist/conf/predictionio.conf',
-    'output/build.sbt',
-    'process/commons/hadoop/scalding/build.sbt',
-    'process/engines/itemrec/algorithms/hadoop/scalding/build.sbt',
-    'process/engines/itemrec/algorithms/hadoop/scalding/*/build.sbt',
-    'process/engines/itemrec/algorithms/scala/mahout/build.sbt',
-    'process/engines/itemrec/algorithms/scala/mahout/commons/build.sbt',
-    'process/engines/itemrec/evaluations/hadoop/scalding/build.sbt',
-    'process/engines/itemrec/evaluations/hadoop/scalding/metrics/map/build.sbt',
-    'process/engines/itemrec/evaluations/hadoop/scalding/trainingtestsplit/build.sbt',
-    'process/engines/itemrec/evaluations/scala/*/build.sbt',
-    'process/engines/itemsim/algorithms/hadoop/scalding/build.sbt',
-    'process/engines/itemsim/evaluations/hadoop/scalding/build.sbt',
-    'process/engines/itemsim/evaluations/scala/*/build.sbt',
-    'servers/*/build.sbt',
-    'servers/scheduler/conf/application.conf',
-    'tools/*/build.sbt',
-    'tools/migration/*/*/build.sbt',
-    'tools/softwaremanager/src/main/scala/io/prediction/tools/softwaremanager/*.scala'
-]
-
-for f in files:
-    for rf in glob.glob(f):
-        if os.path.isfile(rf):
-            change(rf, oldversion, newversion)
diff --git a/bin/common.sh b/bin/common.sh
deleted file mode 100644
index 544e393..0000000
--- a/bin/common.sh
+++ /dev/null
@@ -1,37 +0,0 @@
-# PredictionIO Shared Shell Code
-
-# This script should be sourced with $BASE set to the base of the repository
-
-VERSION=0.7.3
-
-# Play framework related
-PLAY_OPTS=
-PLAY_START_OPTS=-Dsbt.log.noformat=true
-
-# Log related
-LOGDIR="$BASE/logs"
-
-# Play apps related
-ADMIN_DIR="$BASE/servers/admin"
-API_DIR="$BASE/servers/api"
-SCHEDULER_DIR="$BASE/servers/scheduler"
-
-ADMIN_LOG="$LOGDIR/admin.log"
-API_LOG="$LOGDIR/api.log"
-SCHEDULER_LOG="$LOGDIR/scheduler.log"
-
-ADMIN_ERR="$LOGDIR/admin.err"
-API_ERR="$LOGDIR/api.err"
-SCHEDULER_ERR="$LOGDIR/scheduler.err"
-
-# Packaging related
-PACKAGE_NAME="PredictionIO-$VERSION"
-PACKAGE_NAME_LINUX32="PredictionIO-linux-i686-$VERSION"
-PACKAGE_NAME_LINUX64="PredictionIO-linux-x86_64-$VERSION"
-DIST_DIR="$BASE/dist"
-PACKAGE_DIR="$DIST_DIR/target/$PACKAGE_NAME"
-PACKAGE_DIR_LINUX32="$DIST_DIR/target/$PACKAGE_NAME_LINUX32"
-PACKAGE_DIR_LINUX64="$DIST_DIR/target/$PACKAGE_NAME_LINUX64"
-
-# Kill the whole shell when Ctrl+C is pressed
-trap "exit 1" INT
diff --git a/bin/package-updater.sh b/bin/package-updater.sh
deleted file mode 100755
index 1b2dbe4..0000000
--- a/bin/package-updater.sh
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/env sh
-
-# PredictionIO Updater Package Script
-
-# NOTE: Run this script after bin/build.sh to package things up as an updater
-
-# Get the absolute path of the build script
-SCRIPT="$0"
-while [ -h "$SCRIPT" ] ; do
-	SCRIPT=`readlink "$SCRIPT"`
-done
-
-# Get the base directory of the repo
-DIR=`dirname $SCRIPT`/..
-cd $DIR
-BASE=`pwd`
-
-. "$BASE/bin/common.sh"
-
-UPDATER_NAME="PredictionIO-$VERSION-updater"
-
-cd "$BASE/tools/softwaremanager/target"
-rm -rf $UPDATER_NAME
-rm -f "$UPDATER_NAME.zip"
-cp -R pack $UPDATER_NAME
-zip -q -r "$UPDATER_NAME.zip" "$UPDATER_NAME"
-
-echo "Packaging finished at $BASE/tools/softwaremanager/target/$UPDATER_NAME.zip"
diff --git a/bin/package.sh b/bin/package.sh
deleted file mode 100755
index 4b1b83b..0000000
--- a/bin/package.sh
+++ /dev/null
@@ -1,147 +0,0 @@
-#!/usr/bin/env sh
-
-# PredictionIO Package Script
-
-# NOTE: Run this script after bin/build.sh to package things up
-
-# This scripts package everything up into a deployable package that runs off a single configuration file
-
-# Get the absolute path of the build script
-SCRIPT="$0"
-while [ -h "$SCRIPT" ] ; do
-    SCRIPT=`readlink "$SCRIPT"`
-done
-
-# Get the base directory of the repo
-DIR=`dirname $SCRIPT`/..
-cd $DIR
-BASE=`pwd`
-
-. "$BASE/bin/common.sh"
-. "$BASE/bin/vendors.sh"
-
-# Package admin server
-echo "Going to package PredictionIO Admin Server..."
-cd $ADMIN_DIR
-$PLAY stage
-
-# Package API server
-echo "Going to package PredictionIO API Server..."
-cd $API_DIR
-$PLAY stage
-
-# Package scheduler server
-echo "Going to package PredictionIO Scheduler Server..."
-cd $SCHEDULER_DIR
-$PLAY stage
-
-# Packaging
-rm -rf $PACKAGE_DIR $PACKAGE_DIR_LINUX32 $PACKAGE_DIR_LINUX64
-mkdir -p "$PACKAGE_DIR/bin"
-mkdir -p "$PACKAGE_DIR/lib"
-
-cp -n $ADMIN_DIR/target/universal/stage/bin/predictionio-admin $PACKAGE_DIR/bin
-cp -n $ADMIN_DIR/target/universal/stage/lib/* $PACKAGE_DIR/lib
-cp -n $API_DIR/target/universal/stage/bin/predictionio-api $PACKAGE_DIR/bin
-cp -n $API_DIR/target/universal/stage/lib/* $PACKAGE_DIR/lib
-cp -n $SCHEDULER_DIR/target/universal/stage/bin/predictionio-scheduler $PACKAGE_DIR/bin
-cp -n $SCHEDULER_DIR/target/universal/stage/lib/* $PACKAGE_DIR/lib
-
-cp -R $DIST_DIR/bin/* $PACKAGE_DIR/bin
-cp $BASE/bin/quiet.sh $PACKAGE_DIR/bin
-cp -R $DIST_DIR/conf $PACKAGE_DIR
-
-cp "$BASE/process/target/scala-2.10/predictionio-process-hadoop-scalding-assembly-$VERSION.jar" "$PACKAGE_DIR/lib"
-
-cp $BASE/process/engines/commons/algorithms/scala/random/target/pack/bin/* $PACKAGE_DIR/bin
-cp -n $BASE/process/engines/commons/algorithms/scala/random/target/pack/lib/* $PACKAGE_DIR/lib
-
-cp $BASE/process/engines/commons/evaluations/scala/map/target/pack/bin/* $PACKAGE_DIR/bin
-cp -n $BASE/process/engines/commons/evaluations/scala/map/target/pack/lib/* $PACKAGE_DIR/lib
-
-cp $BASE/process/engines/commons/evaluations/scala/paramgen/target/pack/bin/* $PACKAGE_DIR/bin
-cp -n $BASE/process/engines/commons/evaluations/scala/paramgen/target/pack/lib/* $PACKAGE_DIR/lib
-
-cp $BASE/process/engines/commons/evaluations/scala/topkitems/target/pack/bin/* $PACKAGE_DIR/bin
-cp -n $BASE/process/engines/commons/evaluations/scala/topkitems/target/pack/lib/* $PACKAGE_DIR/lib
-
-cp $BASE/process/engines/commons/evaluations/scala/u2isplit/target/pack/bin/* $PACKAGE_DIR/bin
-cp -n $BASE/process/engines/commons/evaluations/scala/u2isplit/target/pack/lib/* $PACKAGE_DIR/lib
-
-cp $BASE/process/engines/commons/evaluations/scala/u2itrainingtestsplit/target/pack/bin/* $PACKAGE_DIR/bin
-cp -n $BASE/process/engines/commons/evaluations/scala/u2itrainingtestsplit/target/pack/lib/* $PACKAGE_DIR/lib
-
-cp $BASE/process/engines/itemrec/algorithms/scala/generic/target/pack/bin/* $PACKAGE_DIR/bin
-cp -n $BASE/process/engines/itemrec/algorithms/scala/generic/target/pack/lib/* $PACKAGE_DIR/lib
-
-cp $BASE/process/engines/itemrec/algorithms/scala/mahout/target/pack/bin/* $PACKAGE_DIR/bin
-cp -n $BASE/process/engines/itemrec/algorithms/scala/mahout/target/pack/lib/* $PACKAGE_DIR/lib
-
-cp $BASE/process/engines/itemrec/algorithms/scala/graphchi/target/pack/bin/* $PACKAGE_DIR/bin
-cp -n $BASE/process/engines/itemrec/algorithms/scala/graphchi/target/pack/lib/* $PACKAGE_DIR/lib
-
-cp $BASE/process/engines/itemrec/algorithms/scala/featurebased/target/pack/bin/* $PACKAGE_DIR/bin
-cp -n $BASE/process/engines/itemrec/algorithms/scala/featurebased/target/pack/lib/* $PACKAGE_DIR/lib
-
-cp $BASE/process/engines/itemsim/algorithms/scala/generic/target/pack/bin/* $PACKAGE_DIR/bin
-cp -n $BASE/process/engines/itemsim/algorithms/scala/generic/target/pack/lib/* $PACKAGE_DIR/lib
-
-cp $BASE/process/engines/itemsim/algorithms/scala/mahout/target/pack/bin/* $PACKAGE_DIR/bin
-cp -n $BASE/process/engines/itemsim/algorithms/scala/mahout/target/pack/lib/* $PACKAGE_DIR/lib
-
-cp $BASE/process/engines/itemsim/algorithms/scala/graphchi/target/pack/bin/* $PACKAGE_DIR/bin
-cp -n $BASE/process/engines/itemsim/algorithms/scala/graphchi/target/pack/lib/* $PACKAGE_DIR/lib
-
-cp $BASE/tools/conncheck/target/pack/bin/* $PACKAGE_DIR/bin
-cp -n $BASE/tools/conncheck/target/pack/lib/* $PACKAGE_DIR/lib
-
-cp $BASE/tools/settingsinit/target/pack/bin/* $PACKAGE_DIR/bin
-cp -n $BASE/tools/settingsinit/target/pack/lib/* $PACKAGE_DIR/lib
-
-cp $BASE/tools/softwaremanager/target/pack/bin/* $PACKAGE_DIR/bin
-cp -n $BASE/tools/softwaremanager/target/pack/lib/* $PACKAGE_DIR/lib
-
-cp $BASE/tools/users/target/pack/bin/* $PACKAGE_DIR/bin
-cp -n $BASE/tools/users/target/pack/lib/* $PACKAGE_DIR/lib
-
-cp $BASE/tools/migration/0.7/infos/target/pack/bin/* $PACKAGE_DIR/bin
-cp -n $BASE/tools/migration/0.7/infos/target/pack/lib/* $PACKAGE_DIR/lib
-
-mkdir -p $PACKAGE_DIR/vendors/mahout-distribution-0.9
-cp $VENDOR_MAHOUT/pio-mahout-core-0.9-a91092c0e1-job.jar $PACKAGE_DIR/vendors/mahout-distribution-0.9
-
-cd $DIST_DIR/target
-
-# Multi-arch targets
-
-if test "$MULTI_ARCH" = "1" ; then
-    cp -R $PACKAGE_DIR $PACKAGE_DIR_LINUX64
-    mv $PACKAGE_DIR $PACKAGE_DIR_LINUX32
-
-    cd $PACKAGE_DIR_LINUX32
-    cp $VENDOR_GRAPHCHI_CPP_CF_LINUX32/* $PACKAGE_DIR_LINUX32/bin
-
-    cd $PACKAGE_DIR_LINUX64
-    cp $VENDOR_GRAPHCHI_CPP_CF_LINUX64/* $PACKAGE_DIR_LINUX64/bin
-
-    cd $DIST_DIR/target
-
-    if [ -e "$PACKAGE_NAME_LINUX32.zip" ] ; then
-        rm "$PACKAGE_NAME_LINUX32.zip"
-    fi
-    if [ -e "$PACKAGE_NAME_LINUX64.zip" ] ; then
-        rm "$PACKAGE_NAME_LINUX64.zip"
-    fi
-
-    zip -q -r "$PACKAGE_NAME_LINUX32.zip" "$PACKAGE_NAME_LINUX32"
-    zip -q -r "$PACKAGE_NAME_LINUX64.zip" "$PACKAGE_NAME_LINUX64"
-
-    echo "Packaging finished:"
-    echo "- $DIST_DIR/target/$PACKAGE_NAME_LINUX32.zip"
-    echo "- $DIST_DIR/target/$PACKAGE_NAME_LINUX64.zip"
-else
-    rm "$PACKAGE_NAME.zip"
-    zip -q -r "$PACKAGE_NAME.zip" "$PACKAGE_NAME"
-
-    echo "Packaging finished at $DIST_DIR/target/$PACKAGE_NAME.zip"
-fi
diff --git a/bin/quiet.sh b/bin/quiet.sh
deleted file mode 100755
index 92f0afe..0000000
--- a/bin/quiet.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/sh
-
-$*
-
-exit 0
diff --git a/bin/vendors.sh b/bin/vendors.sh
deleted file mode 100644
index 9bafa53..0000000
--- a/bin/vendors.sh
+++ /dev/null
@@ -1,121 +0,0 @@
-#!/usr/bin/env sh
-
-# PredictionIO Third Party Software Utilities
-
-# Utilities
-command_exists () {
-    command -v "$1" >/dev/null 2>&1
-}
-
-# Third party software
-VENDORS_PATH="$BASE/vendors"
-VENDOR_SBT="$VENDORS_PATH/sbt-0.13.1/sbt"
-VENDOR_PLAY_VERSION="2.2.2"
-VENDOR_PLAY="$VENDORS_PATH/play-$VENDOR_PLAY_VERSION/play"
-VENDOR_MAHOUT="$VENDORS_PATH/mahout-distribution-0.9"
-VENDOR_GRAPHCHI_CPP_CF_LINUX32="$VENDORS_PATH/graphchi-cpp-cf-linux-i686-0a6545ccb7"
-VENDOR_GRAPHCHI_CPP_CF_LINUX64="$VENDORS_PATH/graphchi-cpp-cf-linux-x86_64-0a6545ccb7"
-
-install_sbt () {
-    echo "Going to download and install sbt 0.13.1..."
-    local VENDORS_PATH=$1/sbt-0.13.1
-    mkdir -p $VENDORS_PATH
-    cd $VENDORS_PATH
-    curl -O http://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/sbt-launch/0.13.1/sbt-launch.jar
-    echo 'java -Xms512M -Xmx1536M -Xss1M -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=512M -jar `dirname $0`/sbt-launch.jar "$@"' > sbt
-    chmod a+x sbt
-    cd $BASE
-}
-
-install_play () {
-    echo "Going to download and install Play Framework $VENDOR_PLAY_VERSION..."
-    local VENDORS_PATH=$1
-    mkdir -p $VENDORS_PATH
-    cd $VENDORS_PATH
-    curl -O http://downloads.typesafe.com/play/$VENDOR_PLAY_VERSION/play-$VENDOR_PLAY_VERSION.zip
-    unzip play-$VENDOR_PLAY_VERSION.zip
-    cd $BASE
-}
-
-install_mahout () {
-    echo "Going to download and install Apache Mahout 0.9 (PIO version)..."
-    mkdir -p $VENDORS_PATH
-    cd $VENDORS_PATH
-    mkdir -p mahout-distribution-0.9
-    cd mahout-distribution-0.9
-    curl -O http://download.prediction.io/mahout/pio-mahout-core-0.9-a91092c0e1-job.jar
-    cd $BASE
-}
-
-install_graphchi_cpp_cf_linux32 () {
-    echo "Going to download and install GraphChi C++ CF Toolbox for Linux 32-bit..."
-    mkdir -p $VENDORS_PATH
-    cd $VENDORS_PATH
-    curl -O http://download.prediction.io/graphchi-cpp-cf/graphchi-cpp-cf-linux-i686-0a6545ccb7.tar.gz
-    tar zxvf graphchi-cpp-cf-linux-i686-0a6545ccb7.tar.gz
-    cd $BASE
-}
-
-install_graphchi_cpp_cf_linux64 () {
-    echo "Going to download and install GraphChi C++ CF Toolbox for Linux 64-bit..."
-    mkdir -p $VENDORS_PATH
-    cd $VENDORS_PATH
-    curl -O http://download.prediction.io/graphchi-cpp-cf/graphchi-cpp-cf-linux-x86_64-0a6545ccb7.tar.gz
-    tar zxvf graphchi-cpp-cf-linux-x86_64-0a6545ccb7.tar.gz
-    cd $BASE
-}
-
-# Detect existing installations in search path
-# Do not use existing sbt to enforce JVM settings
-#if command_exists "sbt" ; then
-#   echo "Using sbt in search path. No additional JVM optimization will be set."
-#   SBT=sbt
-if [ -x "$VENDOR_SBT" ] ; then
-    echo "Using sbt 0.13.1 in vendors."
-    SBT="$VENDOR_SBT"
-elif install_sbt "$VENDORS_PATH" ; then
-    SBT="$VENDOR_SBT"
-else
-    echo "Unable to locate sbt 0.13.1 and automatic installation failed. Aborting." >&2
-    exit 1
-fi
-
-# Do not use existing Play due to potential compatibility issue
-#if command_exists "play" ; then
-#   PLAY=play
-if [ -x "$VENDOR_PLAY" ] ; then
-    echo "Using Play Framework $VENDOR_PLAY_VERSION in vendors."
-    PLAY="$VENDOR_PLAY"
-elif install_play "$VENDORS_PATH" ; then
-    PLAY="$VENDOR_PLAY"
-else
-    echo "Unable to locate Play Framework $VENDOR_PLAY_VERSION and automatic installation failed. Aborting." >&2
-    exit 1
-fi
-
-if [ -r "$VENDOR_MAHOUT/pio-mahout-core-0.9-a91092c0e1-job.jar" ] ; then
-    echo "Using Apache Mahout 0.9 (PIO version) in vendors."
-elif install_mahout ; then
-    echo ""
-else
-    echo "Unable to locate Apache Mahout 0.9 and automatic installation failed. Aborting." >&2
-    exit 1
-fi
-
-if [ -r "$VENDOR_GRAPHCHI_CPP_CF_LINUX32/als" ] ; then
-    echo "Using GraphChi C++ CF Toolbox for Linux 32-bit."
-elif install_graphchi_cpp_cf_linux32 ; then
-    echo ""
-else
-    echo "Unable to locate GraphChi C++ CF Toolbox for Linux 32-bit and automatic installation failed. Aborting." >&2
-    exit 1
-fi
-
-if [ -r "$VENDOR_GRAPHCHI_CPP_CF_LINUX64/als" ] ; then
-    echo "Using GraphChi C++ CF Toolbox for Linux 64-bit."
-elif install_graphchi_cpp_cf_linux64 ; then
-    echo ""
-else
-    echo "Unable to locate GraphChi C++ CF Toolbox for Linux 64-bit and automatic installation failed. Aborting." >&2
-    exit 1
-fi
diff --git a/build.sbt b/build.sbt
deleted file mode 100644
index 1873d17..0000000
--- a/build.sbt
+++ /dev/null
@@ -1,272 +0,0 @@
-name := "predictionio"
-
-version in ThisBuild := "0.7.3"
-
-organization in ThisBuild := "io.prediction"
-
-scalaVersion in ThisBuild := "2.10.3"
-
-scalacOptions in ThisBuild ++= Seq("-deprecation", "-unchecked", "-feature")
-
-scalacOptions in (ThisBuild, Test) ++= Seq("-Yrangepos")
-
-javacOptions in ThisBuild ++= Seq("-source", "1.6", "-target", "1.6", "-Xlint:deprecation", "-Xlint:unchecked")
-
-libraryDependencies in ThisBuild ++= Seq(
-  "com.github.nscala-time" %% "nscala-time" % "0.6.0",
-  "org.slf4j" % "slf4j-log4j12" % "1.7.5" % "test",
-  "org.specs2" %% "specs2" % "2.3.10" % "test")
-
-publishTo in ThisBuild := Some(Resolver.file("file",  new File(Path.userHome.absolutePath+"/.m2/repository")))
-
-publishMavenStyle in ThisBuild := true
-
-parallelExecution in (ThisBuild, Test) := false
-
-lazy val root = project.in(file(".")).aggregate(
-  commons,
-  output,
-  processHadoopScalding,
-  processEnginesCommonsAlgoScalaRandom,
-  processEnginesCommonsEvalScalaMetricsMAP,
-  processEnginesCommonsEvalScalaParamGen,
-  processEnginesCommonsEvalScalaTopKItems,
-  processEnginesCommonsEvalScalaU2ITrainingTestSplit,
-  processEnginesItemRecAlgoScalaGeneric,
-  processEnginesItemRecAlgoScalaGraphChi,
-  processEnginesItemRecAlgoScalaMahout,
-  processEnginesItemSimAlgoScalaGeneric,
-  processEnginesItemSimAlgoScalaMahout,
-  processEnginesItemSimEvalScalaTopKItems,
-  toolsConncheck,
-  toolsSettingsInit,
-  toolsSoftwareManager,
-  toolsUsers)
-
-// Commons and Output
-
-lazy val commons = project in file("commons") settings(scalariformSettings: _*)
-
-lazy val output = project.in(file("output")).dependsOn(commons).settings(scalariformSettings: _*)
-
-// Process Assemblies
-
-lazy val processHadoopScalding = project
-  .in(file("process"))
-  .aggregate(
-    processCommonsHadoopScalding,
-    processEnginesCommonsEvalHadoopScalding,
-    processEnginesItemRecAlgoHadoopScalding,
-    processEnginesItemRecEvalHadoopScalding,
-    processEnginesItemSimAlgoHadoopScalding,
-    processEnginesItemSimEvalHadoopScalding)
-  .dependsOn(
-    processCommonsHadoopScalding,
-    processEnginesCommonsEvalHadoopScalding,
-    processEnginesItemRecAlgoHadoopScalding,
-    processEnginesItemRecEvalHadoopScalding,
-    processEnginesItemSimAlgoHadoopScalding,
-    processEnginesItemSimEvalHadoopScalding)
-
-lazy val processCommonsHadoopScalding = project
-  .in(file("process/commons/hadoop/scalding")).dependsOn(commons)
-  .settings(scalariformSettings: _*)
-
-lazy val processEnginesCommonsAlgoScalaRandom = project
-  .in(file("process/engines/commons/algorithms/scala/random"))
-  .dependsOn(commons)
-  .settings(scalariformSettings: _*)
-
-lazy val processEnginesCommonsEvalHadoopScalding = project
-  .in(file("process/engines/commons/evaluations/hadoop/scalding"))
-  .aggregate(processEnginesCommonsEvalHadoopScaldingU2ITrainingTestSplit)
-  .dependsOn(processEnginesCommonsEvalHadoopScaldingU2ITrainingTestSplit)
-
-lazy val processEnginesCommonsEvalHadoopScaldingU2ITrainingTestSplit = project
-  .in(file("process/engines/commons/evaluations/hadoop/scalding/u2itrainingtestsplit"))
-  .dependsOn(processCommonsHadoopScalding)
-  .settings(scalariformSettings: _*)
-
-lazy val processEnginesCommonsEvalScalaMetricsMAP = project
-  .in(file("process/engines/commons/evaluations/scala/map"))
-  .dependsOn(commons)
-  .settings(scalariformSettings: _*)
-
-lazy val processEnginesCommonsEvalScalaParamGen = project
-  .in(file("process/engines/commons/evaluations/scala/paramgen"))
-  .dependsOn(commons)
-  .settings(scalariformSettings: _*)
-
-lazy val processEnginesCommonsEvalScalaTopKItems = project
-  .in(file("process/engines/commons/evaluations/scala/topkitems"))
-  .dependsOn(commons, output)
-  .settings(scalariformSettings: _*)
-
-lazy val processEnginesCommonsEvalScalaU2ISplit = project
-  .in(file("process/engines/commons/evaluations/scala/u2isplit"))
-  .dependsOn(commons)
-  .settings(scalariformSettings: _*)
-
-lazy val processEnginesCommonsEvalScalaU2ITrainingTestSplit = project
-  .in(file("process/engines/commons/evaluations/scala/u2itrainingtestsplit"))
-  .dependsOn(commons)
-  .settings(scalariformSettings: _*)
-
-lazy val processEnginesItemRecAlgoHadoopScalding = project
-  .in(file("process/engines/itemrec/algorithms/hadoop/scalding"))
-  .aggregate(
-    processEnginesItemRecAlgoHadoopScaldingGeneric,
-    processEnginesItemRecAlgoHadoopScaldingKnnitembased,
-    processEnginesItemRecAlgoHadoopScaldingRandomrank,
-    processEnginesItemRecAlgoHadoopScaldingLatestrank,
-    processEnginesItemRecAlgoHadoopScaldingMahout)
-  .dependsOn(
-    processEnginesItemRecAlgoHadoopScaldingGeneric,
-    processEnginesItemRecAlgoHadoopScaldingKnnitembased,
-    processEnginesItemRecAlgoHadoopScaldingRandomrank,
-    processEnginesItemRecAlgoHadoopScaldingLatestrank,
-    processEnginesItemRecAlgoHadoopScaldingMahout)
-
-lazy val processEnginesItemRecAlgoHadoopScaldingGeneric = project
-  .in(file("process/engines/itemrec/algorithms/hadoop/scalding/generic"))
-  .dependsOn(processCommonsHadoopScalding)
-  .settings(scalariformSettings: _*)
-
-lazy val processEnginesItemRecAlgoHadoopScaldingKnnitembased = project
-  .in(file("process/engines/itemrec/algorithms/hadoop/scalding/knnitembased"))
-  .dependsOn(processCommonsHadoopScalding)
-  .settings(scalariformSettings: _*)
-
-lazy val processEnginesItemRecAlgoHadoopScaldingRandomrank = project
-  .in(file("process/engines/itemrec/algorithms/hadoop/scalding/randomrank"))
-  .dependsOn(processCommonsHadoopScalding)
-  .settings(scalariformSettings: _*)
-
-lazy val processEnginesItemRecAlgoHadoopScaldingLatestrank = project
-  .in(file("process/engines/itemrec/algorithms/hadoop/scalding/latestrank"))
-  .dependsOn(processCommonsHadoopScalding)
-  .settings(scalariformSettings: _*)
-
-lazy val processEnginesItemRecAlgoHadoopScaldingMahout = project
-  .in(file("process/engines/itemrec/algorithms/hadoop/scalding/mahout"))
-  .dependsOn(processCommonsHadoopScalding)
-  .settings(scalariformSettings: _*)
-
-lazy val processEnginesItemRecAlgoScalaMahout = project
-  .in(file("process/engines/itemrec/algorithms/scala/mahout"))
-  .dependsOn(commons)
-  .settings(scalariformSettings: _*)
-
-lazy val processEnginesItemRecAlgoScalaGeneric = project
-  .in(file("process/engines/itemrec/algorithms/scala/generic"))
-  .dependsOn(commons)
-  .settings(scalariformSettings: _*)
-
-lazy val processEnginesItemRecAlgoScalaGraphChi = project
-  .in(file("process/engines/itemrec/algorithms/scala/graphchi"))
-  .dependsOn(commons)
-  .settings(scalariformSettings: _*)
-
-lazy val processEnginesItemRecEvalHadoopScalding = project
-  .in(file("process/engines/itemrec/evaluations/hadoop/scalding"))
-  .aggregate(
-    processEnginesItemRecEvalHadoopScaldingMetricsMAP)
-  .dependsOn(
-    processEnginesItemRecEvalHadoopScaldingMetricsMAP)
-
-lazy val processEnginesItemRecEvalHadoopScaldingMetricsMAP = project
-  .in(file("process/engines/itemrec/evaluations/hadoop/scalding/metrics/map"))
-  .dependsOn(processCommonsHadoopScalding)
-  .settings(scalariformSettings: _*)
-
-lazy val processEnginesItemRecAlgoScalaFeatureBased = project
-  .in(file("process/engines/itemrec/algorithms/scala/featurebased"))
-  .dependsOn(commons)
-  //.settings(scalariformSettings: _*)
-
-lazy val processEnginesItemSimAlgoHadoopScalding = project
-  .in(file("process/engines/itemsim/algorithms/hadoop/scalding"))
-  .aggregate(
-    processEnginesItemSimAlgoHadoopScaldingItemSimCF,
-    processEnginesItemSimAlgoHadoopScaldingLatestRank,
-    processEnginesItemSimAlgoHadoopScaldingMahout,
-    processEnginesItemSimAlgoHadoopScaldingRandomRank)
-  .dependsOn(
-    processEnginesItemSimAlgoHadoopScaldingItemSimCF,
-    processEnginesItemSimAlgoHadoopScaldingLatestRank,
-    processEnginesItemSimAlgoHadoopScaldingMahout,
-    processEnginesItemSimAlgoHadoopScaldingRandomRank)
-
-lazy val processEnginesItemSimAlgoHadoopScaldingItemSimCF = project
-  .in(file("process/engines/itemsim/algorithms/hadoop/scalding/itemsimcf"))
-  .dependsOn(processCommonsHadoopScalding)
-  .settings(scalariformSettings: _*)
-
-lazy val processEnginesItemSimAlgoHadoopScaldingLatestRank = project
-  .in(file("process/engines/itemsim/algorithms/hadoop/scalding/latestrank"))
-  .dependsOn(processCommonsHadoopScalding)
-  .settings(scalariformSettings: _*)
-
-lazy val processEnginesItemSimAlgoHadoopScaldingMahout = project
-  .in(file("process/engines/itemsim/algorithms/hadoop/scalding/mahout"))
-  .dependsOn(processCommonsHadoopScalding)
-  .settings(scalariformSettings: _*)
-
-lazy val processEnginesItemSimAlgoHadoopScaldingRandomRank = project
-  .in(file("process/engines/itemsim/algorithms/hadoop/scalding/randomrank"))
-  .dependsOn(processCommonsHadoopScalding)
-  .settings(scalariformSettings: _*)
-
-lazy val processEnginesItemSimAlgoScalaGeneric = project
-  .in(file("process/engines/itemsim/algorithms/scala/generic"))
-  .dependsOn(commons)
-  .settings(scalariformSettings: _*)
-
-lazy val processEnginesItemSimAlgoScalaMahout = project
-  .in(file("process/engines/itemsim/algorithms/scala/mahout"))
-  .dependsOn(commons)
-  .settings(scalariformSettings: _*)
-
-lazy val processEnginesItemSimAlgoScalaGraphChi = project
-  .in(file("process/engines/itemsim/algorithms/scala/graphchi"))
-  .dependsOn(commons)
-  .settings(scalariformSettings: _*)
-
-lazy val processEnginesItemSimEvalHadoopScalding = project
-  .in(file("process/engines/itemsim/evaluations/hadoop/scalding"))
-  .aggregate(
-    processEnginesItemSimEvalHadoopScaldingMetricsISMAP)
-  .dependsOn(
-    processEnginesItemSimEvalHadoopScaldingMetricsISMAP)
-
-lazy val processEnginesItemSimEvalHadoopScaldingMetricsISMAP = project
-  .in(file("process/engines/itemsim/evaluations/hadoop/scalding/metrics/ismap"))
-  .dependsOn(processCommonsHadoopScalding)
-  .settings(scalariformSettings: _*)
-
-lazy val processEnginesItemSimEvalScalaTopKItems = project
-  .in(file("process/engines/itemsim/evaluations/scala/topkitems"))
-  .dependsOn(commons, output)
-  .settings(scalariformSettings: _*)
-
-// Tools Section
-
-lazy val toolsConncheck = project.in(file("tools/conncheck"))
-  .dependsOn(commons)
-  .settings(scalariformSettings: _*)
-
-lazy val toolsSettingsInit = project.in(file("tools/settingsinit"))
-  .dependsOn(commons)
-  .settings(scalariformSettings: _*)
-
-lazy val toolsSoftwareManager = project.in(file("tools/softwaremanager"))
-  .dependsOn(commons)
-  .settings(scalariformSettings: _*)
-
-lazy val toolsUsers = project.in(file("tools/users"))
-  .dependsOn(commons)
-  .settings(scalariformSettings: _*)
-
-lazy val toolsMigrationStandardizedInfoIDs = project.in(file("tools/migration/0.7/infos"))
-  .dependsOn(commons)
-  .settings(scalariformSettings: _*)
diff --git a/commons/.gitignore b/commons/.gitignore
deleted file mode 100644
index 14e65f8..0000000
--- a/commons/.gitignore
+++ /dev/null
@@ -1,13 +0,0 @@
-.ensime
-.ensime_lucene
-project
-target
-
-# Eclipse
-.settings
-.cache
-.project
-.classpath
-.scala_dependencies
-bin
-.metadata
diff --git a/commons/build.sbt b/commons/build.sbt
deleted file mode 100644
index 6ebed54..0000000
--- a/commons/build.sbt
+++ /dev/null
@@ -1,9 +0,0 @@
-name := "predictionio-commons"
-
-scalacOptions in (Compile, doc) ++= Opts.doc.title("PredictionIO Commons API Documentation")
-
-libraryDependencies ++= Seq(
-  "com.typesafe" % "config" % "1.0.2",
-  "org.json4s" %% "json4s-native" % "3.2.7",
-  "org.json4s" %% "json4s-ext" % "3.2.7",
-  "org.mongodb" %% "casbah" % "2.7.2")
diff --git a/commons/src/main/scala/io/prediction/commons/Common.scala b/commons/src/main/scala/io/prediction/commons/Common.scala
deleted file mode 100644
index c59def9..0000000
--- a/commons/src/main/scala/io/prediction/commons/Common.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-package io.prediction.commons
-
-/** Base trait for classes in this module. */
-trait Common {
-  /** Backup all data as a byte array. */
-  def backup(): Array[Byte]
-
-  /** Restore data from a byte array backup created by the current or the immediate previous version of commons. */
-  def restore(bytes: Array[Byte], inplace: Boolean = false, upgrade: Boolean = false): Option[Seq[Any]]
-}
-
-/** Collection of common utilities used by this module. */
-object Common {
-  /**
-   * Sanitize parameters retrieved from deserializing JSON.
-   *
-   * @param params Only values of this mapping will be sanitized.
-   */
-  def sanitize(params: Map[String, Any]) = {
-    params.mapValues { v =>
-      v match {
-        case x: scala.math.BigInt => x.toInt
-        case _ => v
-      }
-    }
-  }
-}
diff --git a/commons/src/main/scala/io/prediction/commons/Config.scala b/commons/src/main/scala/io/prediction/commons/Config.scala
deleted file mode 100644
index 1ba6cc1..0000000
--- a/commons/src/main/scala/io/prediction/commons/Config.scala
+++ /dev/null
@@ -1,892 +0,0 @@
-package io.prediction.commons
-
-import scala.collection.JavaConversions._
-
-import com.mongodb.casbah.Imports._
-import com.typesafe.config._
-
-/**
- * Configuration accessors.
- *
- * This class ensures its users that the config is free of error, and provides default values as necessary.
- */
-class Config {
-  private val config = ConfigFactory.load()
-
-  /** The base directory of PredictionIO deployment/repository. */
-  val base: String = config.getString("io.prediction.base")
-
-  /** The database type that stores PredictionIO settings. */
-  val settingsDbType: String = config.getString("io.prediction.commons.settings.db.type")
-
-  /** The database host(s) that stores PredictionIO settings. */
-  val settingsDbHost: Seq[String] = settingsDbType match {
-    case dbTypeMongoDb =>
-      try {
-        config.getStringList("io.prediction.commons.settings.db.host").toSeq
-      } catch {
-        case _: Throwable => try {
-          Seq(config.getString("io.prediction.commons.settings.db.host"))
-        } catch {
-          case _: Throwable => Seq("localhost")
-        }
-      }
-  }
-
-  /** The database port(s) that stores PredictionIO settings. */
-  val settingsDbPort: Seq[Int] = settingsDbType match {
-    case dbTypeMongoDb =>
-      try {
-        config.getIntList("io.prediction.commons.settings.db.port").toSeq.
-          map(_.toInt)
-      } catch {
-        case _: Throwable => try {
-          Seq(config.getInt("io.prediction.commons.settings.db.port"))
-        } catch {
-          case _: Throwable => Seq(27017)
-        }
-      }
-  }
-
-  /** The database name that stores PredictionIO settings. */
-  val settingsDbName: String = settingsDbType match {
-    case dbTypeMongoDb => try { config.getString("io.prediction.commons.settings.db.name") } catch { case _: Throwable => "predictionio" }
-  }
-
-  /** The installation location of Hadoop (equivalent to HADOOP_HOME). */
-  val settingsHadoopHome: Option[String] = try { Some(config.getString("io.prediction.commons.settings.hadoop.home")) } catch { case _: Throwable => None }
-
-  /** The HDFS root location for PredictionIO data. */
-  val settingsHdfsRoot: String = try { config.getString("io.prediction.commons.settings.hdfs.root") } catch { case _: Throwable => "predictionio/" }
-
-  /** The local temporary root location for PredictionIO data. */
-  val settingsLocalTempRoot: String = try { config.getString("io.prediction.commons.settings.local.temp.root") } catch { case _: Throwable => "/tmp/" }
-
-  /** PredictionIO Scheduler base URL. */
-  val settingsSchedulerUrl: String = try { config.getString("io.prediction.commons.settings.scheduler.url") } catch { case _: Throwable => "http://localhost:7000" }
-
-  /** Whether the scheduler should check for new releases regularly. */
-  val settingsSchedulerUpdatecheck: Boolean = try { config.getBoolean("io.prediction.commons.settings.scheduler.updatecheck") } catch { case _: Throwable => true }
-
-  /** Whether the scheduler should check for new releases regularly. */
-  val schedulerChildJavaOpts: String = try { config.getString("io.prediction.scheduler.child.java.opts") } catch { case _: Throwable => "" }
-
-  val schedulerMapredMinSplitSize: Option[Long] = try { Some(config.getLong("io.prediction.scheduler.mapred.min.split.size")) } catch { case _: Throwable => None }
-
-  val schedulerMapredMapTasks: Option[Int] = try { Some(config.getInt("io.prediction.scheduler.mapred.map.tasks")) } catch { case _: Throwable => None }
-
-  val schedulerMapredReduceTasks: Option[Int] = try { Some(config.getInt("io.prediction.scheduler.mapred.reduce.tasks")) } catch { case _: Throwable => None }
-
-  /** The database user that stores PredictionIO settings. */
-  val settingsDbUser: Option[String] = try { Some(config.getString("io.prediction.commons.settings.db.user")) } catch { case _: Throwable => None }
-
-  /** The database password that stores PredictionIO settings. */
-  val settingsDbPassword: Option[String] = try { Some(config.getString("io.prediction.commons.settings.db.password")) } catch { case _: Throwable => None }
-
-  /** The database type that stores PredictionIO appdata. */
-  val appdataDbType: String = config.getString("io.prediction.commons.appdata.db.type")
-
-  /** The database host(s) that stores PredictionIO appdata. */
-  val appdataDbHost: Seq[String] = appdataDbType match {
-    case dbTypeMongoDb =>
-      try {
-        config.getStringList("io.prediction.commons.appdata.db.host").toSeq
-      } catch {
-        case _: Throwable => try {
-          Seq(config.getString("io.prediction.commons.appdata.db.host"))
-        } catch {
-          case _: Throwable => Seq("localhost")
-        }
-      }
-  }
-
-  /** The database port(s) that stores PredictionIO appdata. */
-  val appdataDbPort: Seq[Int] = appdataDbType match {
-    case dbTypeMongoDb =>
-      try {
-        config.getIntList("io.prediction.commons.appdata.db.port").toSeq.
-          map(_.toInt)
-      } catch {
-        case _: Throwable => try {
-          Seq(config.getInt("io.prediction.commons.appdata.db.port"))
-        } catch {
-          case _: Throwable => Seq(27017)
-        }
-      }
-  }
-
-  /** The database name that stores PredictionIO appdata. */
-  val appdataDbName: String = appdataDbType match {
-    case dbTypeMongoDb => try { config.getString("io.prediction.commons.appdata.db.name") } catch { case _: Throwable => "predictionio_appdata" }
-  }
-
-  /** The database user that stores PredictionIO appdata. */
-  val appdataDbUser: Option[String] = try { Some(config.getString("io.prediction.commons.appdata.db.user")) } catch { case _: Throwable => None }
-
-  /** The database password that stores PredictionIO appdata. */
-  val appdataDbPassword: Option[String] = try { Some(config.getString("io.prediction.commons.appdata.db.password")) } catch { case _: Throwable => None }
-
-  /** The database type that stores PredictionIO training appdata. */
-  val appdataTrainingDbType: String = config.getString("io.prediction.commons.appdata.training.db.type")
-
-  /** The database host that stores PredictionIO training appdata. */
-  val appdataTrainingDbHost: Seq[String] = appdataTrainingDbType match {
-    case dbTypeMongoDb =>
-      try {
-        config.getStringList("io.prediction.commons.appdata.training.db.host").toSeq
-      } catch {
-        case _: Throwable => try {
-          Seq(config.getString("io.prediction.commons.appdata.training.db.host"))
-        } catch {
-          case _: Throwable => Seq("localhost")
-        }
-      }
-  }
-
-  /** The database port that stores PredictionIO training appdata. */
-  val appdataTrainingDbPort: Seq[Int] = appdataTrainingDbType match {
-    case dbTypeMongoDb =>
-      try {
-        config.getIntList("io.prediction.commons.appdata.training.db.port").toSeq.
-          map(_.toInt)
-      } catch {
-        case _: Throwable => try {
-          Seq(config.getInt("io.prediction.commons.appdata.training.db.port"))
-        } catch {
-          case _: Throwable => Seq(27017)
-        }
-      }
-  }
-
-  /** The database name that stores PredictionIO training appdata. */
-  val appdataTrainingDbName: String = appdataTrainingDbType match {
-    case dbTypeMongoDb => try { config.getString("io.prediction.commons.appdata.training.db.name") } catch { case _: Throwable => "predictionio_training_appdata" }
-  }
-
-  /** The database user that stores PredictionIO training appdata. */
-  val appdataTrainingDbUser: Option[String] = try { Some(config.getString("io.prediction.commons.appdata.training.db.user")) } catch { case _: Throwable => None }
-
-  /** The database password that stores PredictionIO training appdata. */
-  val appdataTrainingDbPassword: Option[String] = try { Some(config.getString("io.prediction.commons.appdata.training.db.password")) } catch { case _: Throwable => None }
-
-  /** The database type that stores PredictionIO validation appdata. */
-  val appdataValidationDbType: String = config.getString("io.prediction.commons.appdata.validation.db.type")
-
-  /** The database host that stores PredictionIO validation appdata. */
-  val appdataValidationDbHost: Seq[String] = appdataValidationDbType match {
-    case dbTypeMongoDb =>
-      try {
-        config.getStringList("io.prediction.commons.appdata.validation.db.host").toSeq
-      } catch {
-        case _: Throwable => try {
-          Seq(config.getString("io.prediction.commons.appdata.validation.db.host"))
-        } catch {
-          case _: Throwable => Seq("localhost")
-        }
-      }
-  }
-
-  /** The database port that stores PredictionIO validation appdata. */
-  val appdataValidationDbPort: Seq[Int] = appdataValidationDbType match {
-    case dbTypeMongoDb =>
-      try {
-        config.getIntList("io.prediction.commons.appdata.validation.db.port").
-          toSeq.map(_.toInt)
-      } catch {
-        case _: Throwable => try {
-          Seq(config.getInt("io.prediction.commons.appdata.validation.db.port"))
-        } catch {
-          case _: Throwable => Seq(27017)
-        }
-      }
-  }
-
-  /** The database name that stores PredictionIO validation appdata. */
-  val appdataValidationDbName: String = appdataValidationDbType match {
-    case dbTypeMongoDb => try { config.getString("io.prediction.commons.appdata.validation.db.name") } catch { case _: Throwable => "predictionio_validation_appdata" }
-  }
-
-  /** The database user that stores PredictionIO validation appdata. */
-  val appdataValidationDbUser: Option[String] = try { Some(config.getString("io.prediction.commons.appdata.validation.db.user")) } catch { case _: Throwable => None }
-
-  /** The database password that stores PredictionIO validation appdata. */
-  val appdataValidationDbPassword: Option[String] = try { Some(config.getString("io.prediction.commons.appdata.validation.db.password")) } catch { case _: Throwable => None }
-
-  /** The database type that stores PredictionIO test appdata. */
-  val appdataTestDbType: String = config.getString("io.prediction.commons.appdata.test.db.type")
-
-  /** The database host that stores PredictionIO test appdata. */
-  val appdataTestDbHost: Seq[String] = appdataTestDbType match {
-    case dbTypeMongoDb =>
-      try {
-        config.getStringList("io.prediction.commons.appdata.test.db.host").toSeq
-      } catch {
-        case _: Throwable => try {
-          Seq(config.getString("io.prediction.commons.appdata.test.db.host"))
-        } catch {
-          case _: Throwable => Seq("localhost")
-        }
-      }
-  }
-
-  /** The database port that stores PredictionIO test appdata. */
-  val appdataTestDbPort: Seq[Int] = appdataTestDbType match {
-    case dbTypeMongoDb =>
-      try {
-        config.getIntList("io.prediction.commons.appdata.test.db.port").toSeq.
-          map(_.toInt)
-      } catch {
-        case _: Throwable => try {
-          Seq(config.getInt("io.prediction.commons.appdata.test.db.port"))
-        } catch {
-          case _: Throwable => Seq(27017)
-        }
-      }
-  }
-
-  /** The database name that stores PredictionIO test appdata. */
-  val appdataTestDbName: String = appdataTestDbType match {
-    case dbTypeMongoDb => try { config.getString("io.prediction.commons.appdata.test.db.name") } catch { case _: Throwable => "predictionio_test_appdata" }
-  }
-
-  /** The database user that stores PredictionIO test appdata. */
-  val appdataTestDbUser: Option[String] = try { Some(config.getString("io.prediction.commons.appdata.test.db.user")) } catch { case _: Throwable => None }
-
-  /** The database password that stores PredictionIO test appdata. */
-  val appdataTestDbPassword: Option[String] = try { Some(config.getString("io.prediction.commons.appdata.test.db.password")) } catch { case _: Throwable => None }
-
-  /** The database type that stores PredictionIO modeldata. */
-  val modeldataDbType: String = config.getString("io.prediction.commons.modeldata.db.type")
-
-  /** The database host that stores PredictionIO modeldata. */
-  val modeldataDbHost: Seq[String] = modeldataDbType match {
-    case dbTypeMongoDb =>
-      try {
-        config.getStringList("io.prediction.commons.modeldata.db.host").toSeq
-      } catch {
-        case _: Throwable => try {
-          Seq(config.getString("io.prediction.commons.modeldata.db.host"))
-        } catch {
-          case _: Throwable => Seq("localhost")
-        }
-      }
-  }
-
-  /** The database port that stores PredictionIO modeldata. */
-  val modeldataDbPort: Seq[Int] = modeldataDbType match {
-    case dbTypeMongoDb => try
-      try {
-        config.getIntList("io.prediction.commons.modeldata.db.port").toSeq.
-          map(_.toInt)
-      } catch {
-        case _: Throwable => try {
-          Seq(config.getInt("io.prediction.commons.modeldata.db.port"))
-        } catch {
-          case _: Throwable => Seq(27017)
-        }
-      }
-  }
-
-  /** The database name that stores PredictionIO modeldata. */
-  val modeldataDbName: String = modeldataDbType match {
-    case dbTypeMongoDb => try { config.getString("io.prediction.commons.modeldata.db.name") } catch { case _: Throwable => "predictionio_modeldata" }
-  }
-
-  /** The database user that stores PredictionIO modeldata. */
-  val modeldataDbUser: Option[String] = try { Some(config.getString("io.prediction.commons.modeldata.db.user")) } catch { case _: Throwable => None }
-
-  /** The database password that stores PredictionIO modeldata. */
-  val modeldataDbPassword: Option[String] = try { Some(config.getString("io.prediction.commons.modeldata.db.password")) } catch { case _: Throwable => None }
-
-  /** MongoDB-specific. Enable sharding on modeldata collections. */
-  val modeldataDbSharding: Boolean = try { config.getBoolean("io.prediction.commons.modeldata.db.sharding") } catch { case _: Throwable => false }
-
-  /** MongoDB-specific. Shard keys for sharding modeldata collections. */
-  val modeldataDbShardKeys: Option[Seq[String]] = try { Some(config.getStringList("io.prediction.commons.modeldata.db.shardkeys").toSeq) } catch { case _: Throwable => None }
-
-  /** The database type that stores PredictionIO modeldata. */
-  val modeldataTrainingDbType: String = config.getString("io.prediction.commons.modeldata.training.db.type")
-
-  /** The database host that stores PredictionIO modeldata. */
-  val modeldataTrainingDbHost: Seq[String] = modeldataTrainingDbType match {
-    case dbTypeMongoDb =>
-      try {
-        config.getStringList("io.prediction.commons.modeldata.training.db.host").toSeq
-      } catch {
-        case _: Throwable => try {
-          Seq(config.getString("io.prediction.commons.modeldata.training.db.host"))
-        } catch {
-          case _: Throwable => Seq("localhost")
-        }
-      }
-  }
-
-  /** The database port that stores PredictionIO modeldata. */
-  val modeldataTrainingDbPort: Seq[Int] = modeldataTrainingDbType match {
-    case dbTypeMongoDb =>
-      try {
-        config.getIntList("io.prediction.commons.modeldata.training.db.port").
-          toSeq.map(_.toInt)
-      } catch {
-        case _: Throwable => try {
-          Seq(config.getInt("io.prediction.commons.modeldata.training.db.port"))
-        } catch {
-          case _: Throwable => Seq(27017)
-        }
-      }
-  }
-
-  /** The database name that stores PredictionIO modeldata. */
-  val modeldataTrainingDbName: String = modeldataTrainingDbType match {
-    case dbTypeMongoDb => try { config.getString("io.prediction.commons.modeldata.training.db.name") } catch { case _: Throwable => "predictionio_training_modeldata" }
-  }
-
-  /** The database user that stores PredictionIO modeldata. */
-  val modeldataTrainingDbUser: Option[String] = try { Some(config.getString("io.prediction.commons.modeldata.training.db.user")) } catch { case _: Throwable => None }
-
-  /** The database password that stores PredictionIO modeldata. */
-  val modeldataTrainingDbPassword: Option[String] = try { Some(config.getString("io.prediction.commons.modeldata.training.db.password")) } catch { case _: Throwable => None }
-
-  /** If settingsDbType is "mongodb", this will contain a Some[MongoDB] object. */
-  val settingsMongoDb: Option[MongoDB] = if (settingsDbType == "mongodb") {
-    val db = (if (settingsDbHost.size > 1) {
-      MongoClient(settingsDbHost.zip(settingsDbPort).map(t =>
-        new ServerAddress(t._1, t._2)
-      ).toList)
-    } else MongoClient(settingsDbHost(0), settingsDbPort(0)))(settingsDbName)
-    settingsDbUser map { db.authenticate(_, settingsDbPassword.getOrElse("")) }
-    Some(db)
-  } else None
-
-  /** If appdataDbType is "mongodb", this will contain a Some[MongoDB] object. */
-  val appdataMongoDb: Option[MongoDB] = if (appdataDbType == "mongodb") {
-    val db = (if (appdataDbHost.size > 1) {
-      MongoClient(appdataDbHost.zip(appdataDbPort).map(t =>
-        new ServerAddress(t._1, t._2)
-      ).toList)
-    } else MongoClient(appdataDbHost(0), appdataDbPort(0)))(appdataDbName)
-    appdataDbUser map { db.authenticate(_, appdataDbPassword.getOrElse("")) }
-    Some(db)
-  } else None
-
-  /** If appdataTrainingDbType is "mongodb", this will contain a Some[MongoDB] object. */
-  val appdataTrainingMongoDb: Option[MongoDB] = if (appdataTrainingDbType == "mongodb") {
-    val db = (if (appdataTrainingDbHost.size > 1) {
-      MongoClient(appdataTrainingDbHost.zip(appdataTrainingDbPort).map(t =>
-        new ServerAddress(t._1, t._2)
-      ).toList)
-    } else MongoClient(appdataTrainingDbHost(0), appdataTrainingDbPort(0)))(appdataTrainingDbName)
-    appdataTrainingDbUser map { db.authenticate(_, appdataTrainingDbPassword.getOrElse("")) }
-    Some(db)
-  } else None
-
-  /** If appdataTestDbType is "mongodb", this will contain a Some[MongoDB] object. */
-  val appdataTestMongoDb: Option[MongoDB] = if (appdataTestDbType == "mongodb") {
-    val db = (if (appdataTestDbHost.size > 1) {
-      MongoClient(appdataTestDbHost.zip(appdataTestDbPort).map(t =>
-        new ServerAddress(t._1, t._2)
-      ).toList)
-    } else MongoClient(appdataTestDbHost(0), appdataTestDbPort(0)))(appdataTestDbName)
-    appdataTestDbUser map { db.authenticate(_, appdataTestDbPassword.getOrElse("")) }
-    Some(db)
-  } else None
-
-  /** If appdataValidationDbType is "mongodb", this will contain a Some[MongoDB] object. */
-  val appdataValidationMongoDb: Option[MongoDB] = if (appdataValidationDbType == "mongodb") {
-    val db = (if (appdataValidationDbHost.size > 1) {
-      MongoClient(appdataValidationDbHost.zip(appdataValidationDbPort).map(t =>
-        new ServerAddress(t._1, t._2)
-      ).toList)
-    } else MongoClient(appdataValidationDbHost(0), appdataValidationDbPort(0)))(appdataValidationDbName)
-    appdataValidationDbUser map { db.authenticate(_, appdataValidationDbPassword.getOrElse("")) }
-    Some(db)
-  } else None
-
-  /** If modeldataDbType is "mongodb", this will contain a Some[MongoDB] object. */
-  val modeldataMongoDb: Option[MongoDB] = if (modeldataDbType == "mongodb") {
-    val db = (if (modeldataDbHost.size > 1) {
-      MongoClient(modeldataDbHost.zip(modeldataDbPort).map(t =>
-        new ServerAddress(t._1, t._2)
-      ).toList)
-    } else MongoClient(modeldataDbHost(0), modeldataDbPort(0)))(modeldataDbName)
-    modeldataDbUser map { db.authenticate(_, modeldataDbPassword.getOrElse("")) }
-    Some(db)
-  } else None
-
-  /** If modeldataTrainingDbType is "mongodb", this will contain a Some[MongoDB] object. */
-  val modeldataTrainingMongoDb: Option[MongoDB] = if (modeldataTrainingDbType == "mongodb") {
-    val db = (if (modeldataTrainingDbHost.size > 1) {
-      MongoClient(modeldataTrainingDbHost.zip(modeldataTrainingDbPort).map(t =>
-        new ServerAddress(t._1, t._2)
-      ).toList)
-    } else MongoClient(modeldataTrainingDbHost(0), modeldataTrainingDbPort(0)))(modeldataTrainingDbName)
-    modeldataTrainingDbUser map { db.authenticate(_, modeldataTrainingDbPassword.getOrElse("")) }
-    Some(db)
-  } else None
-
-  private val jarsR = """^io\.prediction\.jars\.(.*)""".r
-
-  /** Returns all PredictionIO job JARs found in the configuration object. */
-  val jars: Map[String, String] = (Map[String, String]() /: (config.entrySet filter { e =>
-    jarsR findPrefixOf e.getKey map { _ => true } getOrElse { false }
-  })) { (x, y) =>
-    val jarsR(key) = y.getKey
-    x + (key -> config.getString(y.getKey))
-  }
-
-  /** Check whether settings database can be connected. */
-  def settingsDbConnectable() = {
-    settingsDbType match {
-      case "mongodb" => {
-        try {
-          settingsMongoDb.get.getCollectionNames()
-          true
-        } catch {
-          case _: Throwable => false
-        }
-      }
-      case _ => false
-    }
-  }
-
-  /** Check whether app data database can be connected. */
-  def appdataDbConnectable() = {
-    appdataDbType match {
-      case "mongodb" => {
-        try {
-          appdataMongoDb.get.getCollectionNames()
-          true
-        } catch {
-          case _: Throwable => false
-        }
-      }
-      case _ => false
-    }
-  }
-
-  /** Check whether app data training database can be connected. */
-  def appdataTrainingDbConnectable() = {
-    appdataTrainingDbType match {
-      case "mongodb" => {
-        try {
-          appdataTrainingMongoDb.get.getCollectionNames()
-          true
-        } catch {
-          case _: Throwable => false
-        }
-      }
-      case _ => false
-    }
-  }
-
-  /** Check whether app data test database can be connected. */
-  def appdataTestDbConnectable() = {
-    appdataTestDbType match {
-      case "mongodb" => {
-        try {
-          appdataTestMongoDb.get.getCollectionNames()
-          true
-        } catch {
-          case _: Throwable => false
-        }
-      }
-      case _ => false
-    }
-  }
-
-  /** Check whether model data database can be connected. */
-  def modeldataDbConnectable() = {
-    modeldataDbType match {
-      case "mongodb" => {
-        try {
-          modeldataMongoDb.get.getCollectionNames()
-          true
-        } catch {
-          case _: Throwable => false
-        }
-      }
-      case _ => false
-    }
-  }
-
-  /** Check whether model data training database can be connected. */
-  def modeldataTrainingDbConnectable() = {
-    modeldataTrainingDbType match {
-      case "mongodb" => {
-        try {
-          modeldataTrainingMongoDb.get.getCollectionNames()
-          true
-        } catch {
-          case _: Throwable => false
-        }
-      }
-      case _ => false
-    }
-  }
-
-  /** Obtains a SystemInfos object with configured backend type. */
-  def getSettingsSystemInfos(): settings.SystemInfos = {
-    settingsDbType match {
-      case "mongodb" => {
-        new settings.mongodb.MongoSystemInfos(settingsMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid settings database type: " + settingsDbType)
-    }
-  }
-
-  /** Obtains a Users object with configured backend type. */
-  def getSettingsUsers(): settings.Users = {
-    settingsDbType match {
-      case "mongodb" => {
-        new settings.mongodb.MongoUsers(settingsMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid settings database type: " + settingsDbType)
-    }
-  }
-
-  /** Obtains an Apps object with configured backend type. */
-  def getSettingsApps(): settings.Apps = {
-    settingsDbType match {
-      case "mongodb" => {
-        new settings.mongodb.MongoApps(settingsMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid settings database type: " + settingsDbType)
-    }
-  }
-
-  /** Obtains an Engines object with configured backend type. */
-  def getSettingsEngines(): settings.Engines = {
-    settingsDbType match {
-      case "mongodb" => {
-        new settings.mongodb.MongoEngines(settingsMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid settings database type: " + settingsDbType)
-    }
-  }
-
-  /** Obtains an EngineInfos object with configured backend type. */
-  def getSettingsEngineInfos(): settings.EngineInfos = {
-    settingsDbType match {
-      case "mongodb" => {
-        new settings.mongodb.MongoEngineInfos(settingsMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid settings database type: " + settingsDbType)
-    }
-  }
-
-  /** Obtains an Algos object with configured backend type. */
-  def getSettingsAlgos(): settings.Algos = {
-    settingsDbType match {
-      case "mongodb" => {
-        new settings.mongodb.MongoAlgos(settingsMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid settings database type: " + settingsDbType)
-    }
-  }
-
-  /** Obtains an AlgoInfos object with configured backend type. */
-  def getSettingsAlgoInfos(): settings.AlgoInfos = {
-    settingsDbType match {
-      case "mongodb" => {
-        new settings.mongodb.MongoAlgoInfos(settingsMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid settings database type: " + settingsDbType)
-    }
-  }
-
-  /** Obtains a OfflineEvalSplitterInfos object with configured backend type. */
-  def getSettingsOfflineEvalSplitterInfos(): settings.OfflineEvalSplitterInfos = {
-    settingsDbType match {
-      case "mongodb" => {
-        new settings.mongodb.MongoOfflineEvalSplitterInfos(settingsMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid settings database type: " + settingsDbType)
-    }
-  }
-
-  /** Obtains a OfflineEvalMetricInfos object with configured backend type. */
-  def getSettingsOfflineEvalMetricInfos(): settings.OfflineEvalMetricInfos = {
-    settingsDbType match {
-      case "mongodb" => {
-        new settings.mongodb.MongoOfflineEvalMetricInfos(settingsMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid settings database type: " + settingsDbType)
-    }
-  }
-
-  /** Obtains an OfflineEvals object with configured backend type. */
-  def getSettingsOfflineEvals(): settings.OfflineEvals = {
-    settingsDbType match {
-      case "mongodb" => {
-        new settings.mongodb.MongoOfflineEvals(settingsMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid settings database type: " + settingsDbType)
-    }
-  }
-
-  /** Obtains an OfflineEvalMetrics object with configured backend type. */
-  def getSettingsOfflineEvalMetrics(): settings.OfflineEvalMetrics = {
-    settingsDbType match {
-      case "mongodb" => {
-        new settings.mongodb.MongoOfflineEvalMetrics(settingsMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid settings database type: " + settingsDbType)
-    }
-  }
-
-  /** Obtains an OfflineEvalResults object with configured backend type. */
-  def getSettingsOfflineEvalResults(): settings.OfflineEvalResults = {
-    settingsDbType match {
-      case "mongodb" => {
-        new settings.mongodb.MongoOfflineEvalResults(settingsMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid settings database type: " + settingsDbType)
-    }
-  }
-
-  /** Obtains an OfflineEvalSplitters object with configured backend type. */
-  def getSettingsOfflineEvalSplitters(): settings.OfflineEvalSplitters = {
-    settingsDbType match {
-      case "mongodb" => {
-        new settings.mongodb.MongoOfflineEvalSplitters(settingsMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid settings database type: " + settingsDbType)
-    }
-  }
-
-  /** Obtains an OfflineTunes object with configured backend type. */
-  def getSettingsOfflineTunes(): settings.OfflineTunes = {
-    settingsDbType match {
-      case "mongodb" => {
-        new settings.mongodb.MongoOfflineTunes(settingsMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid settings database type: " + settingsDbType)
-    }
-  }
-
-  /** Obtains an ParamGens object with configured backend type. */
-  def getSettingsParamGens(): settings.ParamGens = {
-    settingsDbType match {
-      case "mongodb" => {
-        new settings.mongodb.MongoParamGens(settingsMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid settings database type: " + settingsDbType)
-    }
-  }
-
-  /** Obtains a ParamGenInfos object with configured backend type. */
-  def getSettingsParamGenInfos(): settings.ParamGenInfos = {
-    settingsDbType match {
-      case "mongodb" => {
-        new settings.mongodb.MongoParamGenInfos(settingsMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid settings database type: " + settingsDbType)
-    }
-  }
-
-  /** Obtains a Users object with configured backend type. */
-  def getAppdataUsers(): appdata.Users = {
-    appdataDbType match {
-      case "mongodb" => {
-        new appdata.mongodb.MongoUsers(appdataMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid appdata database type: " + appdataDbType)
-    }
-  }
-
-  /** Obtains an Items object with configured backend type. */
-  def getAppdataItems(): appdata.Items = {
-    appdataDbType match {
-      case "mongodb" => {
-        new appdata.mongodb.MongoItems(appdataMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid appdata database type: " + appdataDbType)
-    }
-  }
-
-  /** Obtains a U2IActions object with configured backend type. */
-  def getAppdataU2IActions(): appdata.U2IActions = {
-    appdataDbType match {
-      case "mongodb" => {
-        new appdata.mongodb.MongoU2IActions(appdataMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid appdata database type: " + appdataDbType)
-    }
-  }
-
-  /** Obtains a Users object with configured backend type. */
-  def getAppdataTrainingUsers(): appdata.Users = {
-    appdataTrainingDbType match {
-      case "mongodb" => {
-        new appdata.mongodb.MongoUsers(appdataTrainingMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid appdata database type: " + appdataTrainingDbType)
-    }
-  }
-
-  /** Obtains an Items object with configured backend type. */
-  def getAppdataTrainingItems(): appdata.Items = {
-    appdataTrainingDbType match {
-      case "mongodb" => {
-        new appdata.mongodb.MongoItems(appdataTrainingMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid appdata database type: " + appdataTrainingDbType)
-    }
-  }
-
-  /** Obtains a U2IActions object with configured backend type. */
-  def getAppdataTrainingU2IActions(): appdata.U2IActions = {
-    appdataTrainingDbType match {
-      case "mongodb" => {
-        new appdata.mongodb.MongoU2IActions(appdataTrainingMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid appdata database type: " + appdataTrainingDbType)
-    }
-  }
-
-  /** Obtains a Users object with configured backend type. */
-  def getAppdataTestUsers(): appdata.Users = {
-    appdataTestDbType match {
-      case "mongodb" => {
-        new appdata.mongodb.MongoUsers(appdataTestMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid appdata database type: " + appdataTestDbType)
-    }
-  }
-
-  /** Obtains an Items object with configured backend type. */
-  def getAppdataTestItems(): appdata.Items = {
-    appdataTestDbType match {
-      case "mongodb" => {
-        new appdata.mongodb.MongoItems(appdataTestMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid appdata database type: " + appdataTestDbType)
-    }
-  }
-
-  /** Obtains a U2IActions object with configured backend type. */
-  def getAppdataTestU2IActions(): appdata.U2IActions = {
-    appdataTestDbType match {
-      case "mongodb" => {
-        new appdata.mongodb.MongoU2IActions(appdataTestMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid appdata database type: " + appdataTestDbType)
-    }
-  }
-
-  /** Obtains a Users object of the validation set with configured backend type. */
-  def getAppdataValidationUsers(): appdata.Users = {
-    appdataValidationDbType match {
-      case "mongodb" => {
-        new appdata.mongodb.MongoUsers(appdataValidationMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid appdata database type: " + appdataValidationDbType)
-    }
-  }
-
-  /** Obtains an Items object of the validation set with configured backend type. */
-  def getAppdataValidationItems(): appdata.Items = {
-    appdataValidationDbType match {
-      case "mongodb" => {
-        new appdata.mongodb.MongoItems(appdataValidationMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid appdata database type: " + appdataValidationDbType)
-    }
-  }
-
-  /** Obtains a U2IActions object of the validation set with configured backend type. */
-  def getAppdataValidationU2IActions(): appdata.U2IActions = {
-    appdataValidationDbType match {
-      case "mongodb" => {
-        new appdata.mongodb.MongoU2IActions(appdataValidationMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid appdata database type: " + appdataValidationDbType)
-    }
-  }
-
-  /** Obtains a generic ModelData object with configured backend type. */
-  def getModeldata(engineinfoid: String): modeldata.ModelData = {
-    modeldataDbType match {
-      case "mongodb" => {
-        val thisObj = this
-        engineinfoid match {
-          case "itemrec" => getModeldataItemRecScores
-          case "itemsim" => getModeldataItemSimScores
-          case _ => new modeldata.mongodb.MongoModelData {
-            val config = thisObj
-            val mongodb = modeldataMongoDb.get
-          }
-        }
-      }
-      case _ => throw new RuntimeException("Invalid modeldata database type: " + modeldataDbType)
-    }
-  }
-
-  /** Obtains an ItemRecScores object with configured backend type. */
-  def getModeldataItemRecScores(): modeldata.ItemRecScores = {
-    modeldataDbType match {
-      case "mongodb" => {
-        new modeldata.mongodb.MongoItemRecScores(this, modeldataMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid modeldata database type: " + modeldataDbType)
-    }
-  }
-
-  /** Obtains an ItemSimScores object with configured backend type. */
-  def getModeldataItemSimScores(): modeldata.ItemSimScores = {
-    modeldataDbType match {
-      case "mongodb" => {
-        new modeldata.mongodb.MongoItemSimScores(this, modeldataMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid modeldata database type: " + modeldataDbType)
-    }
-  }
-
-  /** Obtain an MetadataKeyvals object. */
-  def getModeldataMetadataKeyvals(): modeldata.MetadataKeyvals = {
-    modeldataDbType match {
-      case "mongodb" => {
-        new modeldata.mongodb.MongoMetadataKeyvals(this, modeldataMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid modeldata database type: " + modeldataDbType)
-    }
-  }
-
-  /** Obtains a generic ModelData object for training with configured backend type. */
-  def getModeldataTraining(engineinfoid: String): modeldata.ModelData = {
-    modeldataTrainingDbType match {
-      case "mongodb" => {
-        val thisObj = this
-        engineinfoid match {
-          case "itemrec" => getModeldataTrainingItemRecScores
-          case "itemsim" => getModeldataTrainingItemSimScores
-          case _ => new modeldata.mongodb.MongoModelData {
-            val config = thisObj
-            val mongodb = modeldataTrainingMongoDb.get
-          }
-        }
-      }
-      case _ => throw new RuntimeException("Invalid modeldata database type: " + modeldataTrainingDbType)
-    }
-  }
-
-  /** Obtains an ItemRecScores object for training with configured backend type. */
-  def getModeldataTrainingItemRecScores(): modeldata.ItemRecScores = {
-    modeldataTrainingDbType match {
-      case "mongodb" => {
-        new modeldata.mongodb.MongoItemRecScores(this, modeldataTrainingMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid modeldata database type: " + modeldataTrainingDbType)
-    }
-  }
-
-  /** Obtains an ItemSimScores object for training with configured backend type. */
-  def getModeldataTrainingItemSimScores(): modeldata.ItemSimScores = {
-    modeldataTrainingDbType match {
-      case "mongodb" => {
-        new modeldata.mongodb.MongoItemSimScores(this, modeldataTrainingMongoDb.get)
-      }
-      case _ => throw new RuntimeException("Invalid modeldata database type: " + modeldataTrainingDbType)
-    }
-  }
-}
diff --git a/commons/src/main/scala/io/prediction/commons/MongoUtils.scala b/commons/src/main/scala/io/prediction/commons/MongoUtils.scala
deleted file mode 100644
index c6f403f..0000000
--- a/commons/src/main/scala/io/prediction/commons/MongoUtils.scala
+++ /dev/null
@@ -1,62 +0,0 @@
-package io.prediction.commons
-
-import com.mongodb.casbah.Imports._
-
-object MongoUtils {
-  /** Empty MongoDBObject. */
-  val emptyObj = MongoDBObject()
-
-  /** Modified from Salat. */
-  def dbObjToMap(dbObj: DBObject): Map[String, Any] = {
-    val builder = Map.newBuilder[String, Any]
-
-    dbObj foreach {
-      case (field, value) =>
-        builder += field -> value
-    }
-
-    builder.result()
-  }
-
-  def dbObjToMapOfString(dbObj: DBObject): Map[String, String] = dbObjToMap(dbObj) mapValues { _.asInstanceOf[String] }
-
-  /** Converts MongoDBList to List of String. */
-  def mongoDbListToListOfString(dbList: MongoDBList): List[String] = {
-    dbList.toList.map(_.asInstanceOf[String])
-  }
-
-  /** Converts BasicDBList to List of String. */
-  def basicDBListToListOfString(dbList: BasicDBList): List[String] = {
-    dbList.toList.map(_.asInstanceOf[String])
-  }
-
-  /** Converts MongoDBList to List of Double. */
-  def mongoDbListToListOfDouble(dbList: MongoDBList): List[Double] = {
-    dbList.toList.map(_.asInstanceOf[Double])
-  }
-
-  def mongoDbListToListofListOfString(dbList: MongoDBList): List[List[String]] = {
-    dbList.toList.map(x => basicDBListToListOfString(x.asInstanceOf[BasicDBList]))
-  }
-
-  /**
-   * Convert custom attributes Map into MongoDBObject and add prefix "ca_"
-   *  eg.
-   *  from attributes = Map("gender" -> "female", "member" -> "gold")
-   *  to MongoDBObject("ca_gender" : "female", "ca_member" : "gold" )
-   */
-  def attributesToMongoDBObject(attributes: Map[String, Any]) = {
-    MongoDBObject((attributes map { case (k, v) => ("ca_" + k, v) }).toList)
-  }
-
-  /** Extract custom attributes (with prefix "ca_") from DBObject, strip prefix and create Map[String, Any] */
-  def getAttributesFromDBObject(dbObj: DBObject): Map[String, Any] = {
-    dbObj.filter { case (k, v) => (k.startsWith("ca_")) }.toList.map { case (k, v) => (k.stripPrefix("ca_"), v) }.toMap
-  }
-
-  /**
-   * Appends App ID to any ID.
-   * Used for distinguishing different app's data within a single collection.
-   */
-  def idWithAppid(appid: Int, id: String) = appid + "_" + id
-}
diff --git a/commons/src/main/scala/io/prediction/commons/appdata/Items.scala b/commons/src/main/scala/io/prediction/commons/appdata/Items.scala
deleted file mode 100644
index 7f39453..0000000
--- a/commons/src/main/scala/io/prediction/commons/appdata/Items.scala
+++ /dev/null
@@ -1,82 +0,0 @@
-package io.prediction.commons.appdata
-
-import com.github.nscala_time.time.Imports._
-
-/**
- * Item object.
- *
- * @param id ID.
- * @param appid App ID that this item belongs to.
- * @param ct Creation time.
- * @param itypes Item types.
- * @param starttime The start time when this item becomes valid.
- * @param endtime The end time when this item becomes invalid.
- * @param price Price of this item.
- * @param profit Net profit made by this item.
- * @param latlng Geolocation of this item.
- * @param inactive Whether to disregard this item during any computation.
- * @param attributes Attributes associated with this item.
- */
-case class Item(
-  id: String,
-  appid: Int,
-  ct: DateTime,
-  itypes: Seq[String],
-  starttime: Option[DateTime],
-  endtime: Option[DateTime],
-  price: Option[Double] = None,
-  profit: Option[Double] = None,
-  latlng: Option[Tuple2[Double, Double]] = None,
-  inactive: Option[Boolean] = None,
-  attributes: Option[Map[String, Any]] = None)
-
-/**
- * Base trait for implementations that interact with items in the backend app
- * data store.
- */
-trait Items {
-  /** Insert a new item. */
-  def insert(item: Item): Unit
-
-  /** Get an item by ID. */
-  def get(appid: Int, id: String): Option[Item]
-
-  /** Find all items by App ID. */
-  def getByAppid(appid: Int): Iterator[Item]
-
-  /** Find items by App ID sorted by geolocation distance. */
-  def getByAppidAndLatlng(appid: Int, latlng: Tuple2[Double, Double],
-    within: Option[Double], unit: Option[String]): Iterator[Item]
-
-  /** Find items by App ID which belong to one of the itypes. */
-  def getByAppidAndItypes(appid: Int, itypes: Seq[String]): Iterator[Item]
-
-  /** Find current items by App ID which belong to one of the itypes. */
-  def getByAppidAndItypesAndTime(appid: Int,
-    optItypes: Option[Seq[String]] = None,
-    optTime: Option[DateTime] = None): Iterator[Item]
-
-  /**
-   * Get items by IDs. Items returned are not guaranteed to be in the same order
-   * as the input, as some IDs may not be valid.
-   */
-  def getByIds(appid: Int, ids: Seq[String]): Seq[Item]
-
-  /** Get items by IDs sorted by their start time in descending order. */
-  def getRecentByIds(appid: Int, ids: Seq[String]): Seq[Item]
-
-  /** Update an item. */
-  def update(item: Item): Unit
-
-  /** Delete an item. */
-  def delete(appid: Int, id: String): Unit
-
-  /** Delete an item. */
-  def delete(item: Item): Unit
-
-  /** Delete all items by App ID */
-  def deleteByAppid(appid: Int): Unit
-
-  /** count number of records by App ID*/
-  def countByAppid(appid: Int): Long
-}
diff --git a/commons/src/main/scala/io/prediction/commons/appdata/U2IActions.scala b/commons/src/main/scala/io/prediction/commons/appdata/U2IActions.scala
deleted file mode 100644
index 03c989c..0000000
--- a/commons/src/main/scala/io/prediction/commons/appdata/U2IActions.scala
+++ /dev/null
@@ -1,63 +0,0 @@
-package io.prediction.commons.appdata
-
-import com.github.nscala_time.time.Imports._
-
-/**
- * User-to-item action object.
- *
- * @param appid App ID that this item belongs to.
- * @param action Type of this action.
- * @param uid User ID of this action.
- * @param iid Item ID of this action.
- * @param t Time of this action.
- * @param latlng Geolocation of this action.
- * @param v The value of this action (if applicable).
- * @param price Price associated with this action (if applicable).
- */
-case class U2IAction(
-  appid: Int,
-  action: String,
-  uid: String,
-  iid: String,
-  t: DateTime,
-  latlng: Option[Tuple2[Double, Double]] = None,
-  v: Option[Int] = None,
-  price: Option[Double] = None)
-
-/** Base trait for implementations that interact with user-to-item actions in the backend app data store. */
-trait U2IActions {
-  /** Represents a user-rate-item action. */
-  val rate = "rate"
-
-  /** Represents a user-like/dislike-item action. */
-  val like = "like"
-
-  val dislike = "dislike"
-
-  /** Represents a user-view-item action. */
-  val view = "view"
-
-  /** Represents a user-view-item's details action. */
-  val viewDetails = "viewDetails"
-
-  /** Represents a user-item conversion (e.g. buy) action. */
-  val conversion = "conversion"
-
-  /** Inserts a user-to-item action. */
-  def insert(u2iAction: U2IAction): Unit
-
-  /** Gets all user-to-item actions by App ID. */
-  def getAllByAppid(appid: Int): Iterator[U2IAction]
-
-  /** Gets all user-to-item actions by App ID, User ID, and Item IDs. */
-  def getAllByAppidAndUidAndIids(appid: Int, uid: String, iids: Seq[String]): Iterator[U2IAction]
-
-  /** Get all users-to-item actions by AppID, Item ID and optionally sort by User ID */
-  def getAllByAppidAndIid(appid: Int, iid: String, sortedByUid: Boolean = true): Iterator[U2IAction]
-
-  /** Delete all user-to-item actions by App ID */
-  def deleteByAppid(appid: Int): Unit
-
-  /** count number of records by App ID*/
-  def countByAppid(appid: Int): Long
-}
diff --git a/commons/src/main/scala/io/prediction/commons/appdata/Users.scala b/commons/src/main/scala/io/prediction/commons/appdata/Users.scala
deleted file mode 100644
index 42c1d3c..0000000
--- a/commons/src/main/scala/io/prediction/commons/appdata/Users.scala
+++ /dev/null
@@ -1,49 +0,0 @@
-package io.prediction.commons.appdata
-
-import com.github.nscala_time.time.Imports._
-
-/**
- * User object.
- *
- * @param id ID.
- * @param appid App ID that this user belongs to.
- * @param ct Creation time.
- * @param latlng Geolocation of this user.
- * @param inactive Whether to disregard this user during any computation.
- * @param attributes Attributes associated with this user.
- */
-case class User(
-  id: String,
-  appid: Int,
-  ct: DateTime,
-  latlng: Option[Tuple2[Double, Double]] = None,
-  inactive: Option[Boolean] = None,
-  attributes: Option[Map[String, Any]] = None)
-
-/** Base trait for implementations that interact with users in the backend app data store. */
-trait Users {
-  /** Insert a new user. */
-  def insert(user: User): Unit
-
-  /** Find a user by ID. */
-  def get(appid: Int, id: String): Option[User]
-
-  /** Find all users by App ID. */
-  def getByAppid(appid: Int): Iterator[User]
-
-  /** Update a user. */
-  def update(user: User): Unit
-
-  /** Delete a user. */
-  def delete(appid: Int, id: String): Unit
-
-  /** Delete a user. */
-  def delete(user: User): Unit
-
-  /** Delete all users by App ID */
-  def deleteByAppid(appid: Int): Unit
-
-  /** count number of records by App ID*/
-  def countByAppid(appid: Int): Long
-
-}
diff --git a/commons/src/main/scala/io/prediction/commons/appdata/mongodb/MongoItems.scala b/commons/src/main/scala/io/prediction/commons/appdata/mongodb/MongoItems.scala
deleted file mode 100644
index a720a6c..0000000
--- a/commons/src/main/scala/io/prediction/commons/appdata/mongodb/MongoItems.scala
+++ /dev/null
@@ -1,140 +0,0 @@
-package io.prediction.commons.appdata.mongodb
-
-import io.prediction.commons.MongoUtils.{ emptyObj, mongoDbListToListOfString, idWithAppid }
-import io.prediction.commons.MongoUtils.{ attributesToMongoDBObject, getAttributesFromDBObject }
-import io.prediction.commons.appdata.{ Item, Items }
-
-import com.mongodb.casbah.Imports._
-import com.mongodb.casbah.commons.conversions.scala._
-import com.github.nscala_time.time.Imports._
-
-/** MongoDB implementation of Items. */
-class MongoItems(db: MongoDB) extends Items {
-  private val itemColl = db("items")
-
-  /** Indices and hints. */
-  val starttimeIndex = MongoDBObject("starttime" -> -1)
-  val lnglatIndex = MongoDBObject("lnglat" -> "2d")
-  itemColl.ensureIndex(starttimeIndex)
-  itemColl.ensureIndex(lnglatIndex)
-
-  RegisterJodaTimeConversionHelpers()
-
-  def insert(item: Item) = {
-    val id = MongoDBObject("_id" -> idWithAppid(item.appid, item.id))
-    val appid = MongoDBObject("appid" -> item.appid)
-    val ct = MongoDBObject("ct" -> item.ct)
-    val itypes = MongoDBObject("itypes" -> item.itypes)
-    val starttime = item.starttime map { s => MongoDBObject("starttime" -> s) } getOrElse emptyObj
-    val endtime = item.endtime map { e => MongoDBObject("endtime" -> e) } getOrElse emptyObj
-    val price = item.price map { p => MongoDBObject("price" -> p) } getOrElse emptyObj
-    val profit = item.profit map { p => MongoDBObject("profit" -> p) } getOrElse emptyObj
-    val lnglat = item.latlng map { l => MongoDBObject("lnglat" -> MongoDBList(l._2, l._1)) } getOrElse emptyObj
-    val inactive = item.inactive map { i => MongoDBObject("inactive" -> i) } getOrElse emptyObj
-    //val attributes = item.attributes map { a => MongoDBObject("attributes" -> a) } getOrElse emptyObj
-    // add "ca_" prefix for custom attributes
-    val attributes = item.attributes map { a => attributesToMongoDBObject(a) } getOrElse emptyObj
-    itemColl.save(id ++ appid ++ ct ++ itypes ++ starttime ++ endtime ++ price ++ profit ++ lnglat ++ inactive ++ attributes)
-  }
-
-  def get(appid: Int, id: String) = {
-    itemColl.findOne(MongoDBObject("_id" -> idWithAppid(appid, id))) map { dbObjToItem(_) }
-  }
-
-  def getByAppid(appid: Int) = new MongoItemsIterator(itemColl.find(MongoDBObject("appid" -> appid)))
-
-  def getByAppidAndLatlng(appid: Int, latlng: Tuple2[Double, Double], within: Option[Double], unit: Option[String]) = {
-    val earthRadiusInKm = 6371
-    val earthRadiusInMiles = 3959
-
-    val nearSphereObj = MongoDBObject("$nearSphere" -> MongoDBList(latlng._2, latlng._1))
-    val maxDistObj = within map { maxDist =>
-      unit match {
-        case Some("km") => MongoDBObject("$maxDistance" -> maxDist / earthRadiusInKm)
-        case Some("mi") => MongoDBObject("$maxDistance" -> maxDist / earthRadiusInMiles)
-        case _ => MongoDBObject("$maxDistance" -> maxDist / earthRadiusInKm)
-      }
-    } getOrElse emptyObj
-
-    new MongoItemsIterator(itemColl.find(MongoDBObject("appid" -> appid, "lnglat" -> (nearSphereObj ++ maxDistObj))))
-  }
-
-  def getByAppidAndItypes(appid: Int, itypes: Seq[String]): Iterator[Item] = {
-    getByAppidAndItypesAndTime(appid, optItypes = Some(itypes), optTime = None)
-  }
-
-  def getByAppidAndItypesAndTime(appid: Int,
-    optItypes: Option[Seq[String]] = None,
-    optTime: Option[DateTime] = None): Iterator[Item] = {
-    val queryObj = ("appid" $eq appid)
-    if (!optItypes.isEmpty)
-      queryObj ++= ("itypes" $in optItypes.get)
-    if (!optTime.isEmpty) {
-      val time = optTime.get
-      queryObj ++= ("starttime" $lt time)
-      // Need to create an ugly DBObject as casbah don't have scala-ble support
-      // for $or
-      queryObj ++= DBObject("$or" -> MongoDBList(
-        ("endtime" $exists false),
-        ("endtime" $gt time)))
-    }
-    new MongoItemsIterator(itemColl.find(queryObj))
-  }
-
-  def getByIds(appid: Int, ids: Seq[String]) = {
-    itemColl.find(MongoDBObject("_id" -> MongoDBObject("$in" -> ids.map(idWithAppid(appid, _))))).toList map { dbObjToItem(_) }
-  }
-
-  def getRecentByIds(appid: Int, ids: Seq[String]) = {
-    itemColl.find(MongoDBObject("_id" -> MongoDBObject("$in" -> ids.map(idWithAppid(appid, _))))).sort(starttimeIndex).toList map { dbObjToItem(_) }
-  }
-
-  def update(item: Item) = {
-    val id = MongoDBObject("_id" -> idWithAppid(item.appid, item.id))
-    val appid = MongoDBObject("appid" -> item.appid)
-    val ct = MongoDBObject("ct" -> item.ct)
-    val itypes = MongoDBObject("itypes" -> item.itypes)
-    val starttime = item.starttime map { s => MongoDBObject("starttime" -> s) } getOrElse emptyObj
-    val endtime = item.endtime map { e => MongoDBObject("endtime" -> e) } getOrElse emptyObj
-    val price = item.price map { p => MongoDBObject("price" -> p) } getOrElse emptyObj
-    val profit = item.profit map { p => MongoDBObject("profit" -> p) } getOrElse emptyObj
-    val lnglat = item.latlng map { l => MongoDBObject("lnglat" -> MongoDBList(l._2, l._1)) } getOrElse emptyObj
-    val inactive = item.inactive map { i => MongoDBObject("inactive" -> i) } getOrElse emptyObj
-    //val attributes = item.attributes map { a => MongoDBObject("attributes" -> a) } getOrElse emptyObj
-    // add "ca_" prefix for custom attributes
-    val attributes = item.attributes map { a => attributesToMongoDBObject(a) } getOrElse emptyObj
-    itemColl.update(id, id ++ appid ++ ct ++ itypes ++ starttime ++ endtime ++ price ++ profit ++ lnglat ++ inactive ++ attributes)
-  }
-
-  def delete(appid: Int, id: String) = itemColl.remove(MongoDBObject("_id" -> idWithAppid(appid, id)))
-  def delete(item: Item) = delete(item.appid, item.id)
-
-  def deleteByAppid(appid: Int): Unit = {
-    itemColl.remove(MongoDBObject("appid" -> appid))
-  }
-
-  def countByAppid(appid: Int): Long = itemColl.count(MongoDBObject("appid" -> appid))
-
-  private def dbObjToItem(dbObj: DBObject) = {
-    val appid = dbObj.as[Int]("appid")
-    Item(
-      id = dbObj.as[String]("_id").drop(appid.toString.length + 1),
-      appid = appid,
-      ct = dbObj.as[DateTime]("ct"),
-      itypes = mongoDbListToListOfString(dbObj.as[MongoDBList]("itypes")),
-      starttime = dbObj.getAs[DateTime]("starttime"),
-      endtime = dbObj.getAs[DateTime]("endtime"),
-      price = dbObj.getAs[Double]("price"),
-      profit = dbObj.getAs[Double]("profit"),
-      latlng = dbObj.getAs[MongoDBList]("lnglat") map { lnglat => (lnglat(1).asInstanceOf[Double], lnglat(0).asInstanceOf[Double]) },
-      inactive = dbObj.getAs[Boolean]("inactive"),
-      //attributes = dbObj.getAs[DBObject]("attributes") map { dbObjToMap(_) }
-      attributes = Option(getAttributesFromDBObject(dbObj)).filter(!_.isEmpty)
-    )
-  }
-
-  class MongoItemsIterator(it: MongoCursor) extends Iterator[Item] {
-    def next = dbObjToItem(it.next)
-    def hasNext = it.hasNext
-  }
-}
diff --git a/commons/src/main/scala/io/prediction/commons/appdata/mongodb/MongoU2IActions.scala b/commons/src/main/scala/io/prediction/commons/appdata/mongodb/MongoU2IActions.scala
deleted file mode 100644
index fb7bee4..0000000
--- a/commons/src/main/scala/io/prediction/commons/appdata/mongodb/MongoU2IActions.scala
+++ /dev/null
@@ -1,66 +0,0 @@
-package io.prediction.commons.appdata.mongodb
-
-import io.prediction.commons.MongoUtils._
-import io.prediction.commons.appdata.{ U2IAction, U2IActions }
-
-import com.mongodb.casbah.Imports._
-import com.mongodb.casbah.commons.conversions.scala._
-import com.github.nscala_time.time.Imports._
-
-/** MongoDB implementation of Items. */
-class MongoU2IActions(db: MongoDB) extends U2IActions {
-  private val emptyObj = MongoDBObject()
-  private val u2iActionColl = db("u2iActions")
-
-  RegisterJodaTimeConversionHelpers()
-
-  def insert(u2iAction: U2IAction) = {
-    val appid = MongoDBObject("appid" -> u2iAction.appid)
-    val action = MongoDBObject("action" -> u2iAction.action)
-    val uid = MongoDBObject("uid" -> idWithAppid(u2iAction.appid, u2iAction.uid))
-    val iid = MongoDBObject("iid" -> idWithAppid(u2iAction.appid, u2iAction.iid))
-    val t = MongoDBObject("t" -> u2iAction.t)
-    val lnglat = u2iAction.latlng map { l => MongoDBObject("lnglat" -> MongoDBList(l._2, l._1)) } getOrElse emptyObj
-    val v = u2iAction.v map { v => MongoDBObject("v" -> v) } getOrElse emptyObj
-    val price = u2iAction.price map { p => MongoDBObject("price" -> p) } getOrElse emptyObj
-    u2iActionColl.insert(appid ++ action ++ uid ++ iid ++ t ++ lnglat ++ v ++ price)
-  }
-
-  def getAllByAppid(appid: Int) = new MongoU2IActionIterator(u2iActionColl.find(MongoDBObject("appid" -> appid)))
-
-  def getAllByAppidAndUidAndIids(appid: Int, uid: String, iids: Seq[String]) = new MongoU2IActionIterator(
-    u2iActionColl.find(MongoDBObject("appid" -> appid, "uid" -> idWithAppid(appid, uid), "iid" -> MongoDBObject("$in" -> iids.map(idWithAppid(appid, _)))))
-  )
-
-  def getAllByAppidAndIid(appid: Int, iid: String, sortedByUid: Boolean = true): Iterator[U2IAction] = {
-    if (sortedByUid)
-      new MongoU2IActionIterator(u2iActionColl.find(MongoDBObject("appid" -> appid, "iid" -> idWithAppid(appid, iid))).sort(MongoDBObject("uid" -> 1)))
-    else
-      new MongoU2IActionIterator(u2iActionColl.find(MongoDBObject("appid" -> appid, "iid" -> idWithAppid(appid, iid))))
-  }
-
-  def deleteByAppid(appid: Int): Unit = {
-    u2iActionColl.remove(MongoDBObject("appid" -> appid))
-  }
-
-  def countByAppid(appid: Int): Long = u2iActionColl.count(MongoDBObject("appid" -> appid))
-
-  private def dbObjToU2IAction(dbObj: DBObject) = {
-    val appid = dbObj.as[Int]("appid")
-    U2IAction(
-      appid = appid,
-      action = dbObj.as[String]("action"),
-      uid = dbObj.as[String]("uid").drop(appid.toString.length + 1),
-      iid = dbObj.as[String]("iid").drop(appid.toString.length + 1),
-      t = dbObj.as[DateTime]("t"),
-      latlng = dbObj.getAs[MongoDBList]("lnglat") map { lnglat => (lnglat(1).asInstanceOf[Double], lnglat(0).asInstanceOf[Double]) },
-      v = dbObj.getAs[Int]("v"),
-      price = dbObj.getAs[Double]("price")
-    )
-  }
-
-  class MongoU2IActionIterator(it: MongoCursor) extends Iterator[U2IAction] {
-    def next = dbObjToU2IAction(it.next)
-    def hasNext = it.hasNext
-  }
-}
diff --git a/commons/src/main/scala/io/prediction/commons/appdata/mongodb/MongoUsers.scala b/commons/src/main/scala/io/prediction/commons/appdata/mongodb/MongoUsers.scala
deleted file mode 100644
index e005d00..0000000
--- a/commons/src/main/scala/io/prediction/commons/appdata/mongodb/MongoUsers.scala
+++ /dev/null
@@ -1,71 +0,0 @@
-package io.prediction.commons.appdata.mongodb
-
-import io.prediction.commons.MongoUtils.{ emptyObj, mongoDbListToListOfString, idWithAppid }
-import io.prediction.commons.MongoUtils.{ attributesToMongoDBObject, getAttributesFromDBObject }
-import io.prediction.commons.appdata.{ User, Users }
-
-import com.mongodb.casbah.Imports._
-import com.mongodb.casbah.commons.conversions.scala._
-import com.github.nscala_time.time.Imports._
-
-/** MongoDB implementation of Users. */
-class MongoUsers(db: MongoDB) extends Users {
-  private val emptyObj = MongoDBObject()
-  private val userColl = db("users")
-
-  RegisterJodaTimeConversionHelpers()
-
-  def insert(user: User) = {
-    val id = MongoDBObject("_id" -> idWithAppid(user.appid, user.id))
-    val appid = MongoDBObject("appid" -> user.appid)
-    val ct = MongoDBObject("ct" -> user.ct)
-    val lnglat = user.latlng map { l => MongoDBObject("lnglat" -> MongoDBList(l._2, l._1)) } getOrElse emptyObj
-    val inactive = user.inactive map { i => MongoDBObject("inactive" -> i) } getOrElse emptyObj
-    //val attributes = user.attributes map { a => MongoDBObject("attributes" -> a) } getOrElse emptyObj
-    // add "ca_" prefix for custom attributes
-    val attributes = user.attributes map { a => attributesToMongoDBObject(a) } getOrElse emptyObj
-    userColl.save(id ++ appid ++ ct ++ lnglat ++ inactive ++ attributes)
-  }
-
-  def get(appid: Int, id: String) = userColl.findOne(MongoDBObject("_id" -> idWithAppid(appid, id))) map { dbObjToUser(_) }
-
-  def getByAppid(appid: Int) = new MongoUsersIterator(userColl.find(MongoDBObject("appid" -> appid)))
-
-  def update(user: User) = {
-    val id = MongoDBObject("_id" -> idWithAppid(user.appid, user.id))
-    val appid = MongoDBObject("appid" -> user.appid)
-    val ct = MongoDBObject("ct" -> user.ct)
-    val lnglat = user.latlng map { l => MongoDBObject("lnglat" -> MongoDBList(l._2, l._1)) } getOrElse emptyObj
-    val inactive = user.inactive map { i => MongoDBObject("inactive" -> i) } getOrElse emptyObj
-    //val attributes = user.attributes map { a => MongoDBObject("attributes" -> a) } getOrElse emptyObj
-    val attributes = user.attributes map { a => attributesToMongoDBObject(a) } getOrElse emptyObj
-    userColl.update(id, id ++ appid ++ ct ++ lnglat ++ inactive ++ attributes)
-  }
-
-  def delete(appid: Int, id: String) = userColl.remove(MongoDBObject("_id" -> idWithAppid(appid, id)))
-  def delete(user: User) = delete(user.appid, user.id)
-
-  def deleteByAppid(appid: Int): Unit = {
-    userColl.remove(MongoDBObject("appid" -> appid))
-  }
-
-  def countByAppid(appid: Int): Long = userColl.count(MongoDBObject("appid" -> appid))
-
-  private def dbObjToUser(dbObj: DBObject) = {
-    val appid = dbObj.as[Int]("appid")
-    User(
-      id = dbObj.as[String]("_id").drop(appid.toString.length + 1),
-      appid = appid,
-      ct = dbObj.as[DateTime]("ct"),
-      latlng = dbObj.getAs[MongoDBList]("lnglat") map { lnglat => (lnglat(1).asInstanceOf[Double], lnglat(0).asInstanceOf[Double]) },
-      inactive = dbObj.getAs[Boolean]("inactive"),
-      //attributes = dbObj.getAs[DBObject]("attributes") map { dbObjToMap(_) }
-      attributes = Option(getAttributesFromDBObject(dbObj)).filter(!_.isEmpty)
-    )
-  }
-
-  class MongoUsersIterator(it: MongoCursor) extends Iterator[User] {
-    def next = dbObjToUser(it.next)
-    def hasNext = it.hasNext
-  }
-}
diff --git a/commons/src/main/scala/io/prediction/commons/filepath/EngineFile.scala b/commons/src/main/scala/io/prediction/commons/filepath/EngineFile.scala
deleted file mode 100644
index 39da626..0000000
--- a/commons/src/main/scala/io/prediction/commons/filepath/EngineFile.scala
+++ /dev/null
@@ -1,104 +0,0 @@
-package io.prediction.commons.filepath
-
-/**
- * These objects are used for returning HDFS file path
- */
-
-object BaseDir {
-
-  def appDir(rootDir: String, appId: Int): String = rootDir + "apps/" + appId + "/"
-
-  def engineDir(rootDir: String, appId: Int, engineId: Int): String = appDir(rootDir, appId) + "engines/" + engineId + "/"
-
-  def offlineEvalDir(rootDir: String, appId: Int, engineId: Int, evalId: Int): String = engineDir(rootDir, appId, engineId) + "offlineeval/" + evalId + "/"
-
-  def algoDir(rootDir: String, appId: Int, engineId: Int, algoId: Int, evalId: Option[Int]): String = {
-    evalId match {
-      case Some(eva) => offlineEvalDir(rootDir, appId, engineId, eva) + "algos/" + algoId + "/"
-      case _ => engineDir(rootDir, appId, engineId) + "batch/" + "algos/" + algoId + "/"
-    }
-  }
-
-  def offlineMetricDir(rootDir: String, appId: Int, engineId: Int, algoId: Int, evalId: Int, metricId: Int): String = {
-    offlineEvalDir(rootDir, appId, engineId, evalId) + "metrics/" + metricId + "/algos/" + algoId + "/"
-  }
-
-}
-
-/*
- * process internal file 
- */
-
-/**
- * For Data Preparator output
- */
-object DataFile {
-
-  def apply(rootDir: String, appId: Int, engineId: Int, algoId: Int, evalId: Option[Int], name: String): String =
-    BaseDir.algoDir(rootDir, appId, engineId, algoId, evalId) + "data/" + name
-
-}
-
-/**
- * For Data Preparator output
- */
-object AlgoFile {
-
-  def apply(rootDir: String, appId: Int, engineId: Int, algoId: Int, evalId: Option[Int], name: String): String =
-    BaseDir.algoDir(rootDir, appId, engineId, algoId, evalId) + "algo/" + name
-
-}
-
-/**
- * Metrics Data Preparator output file
- */
-object OfflineMetricFile {
-
-  def apply(rootDir: String, appId: Int, engineId: Int, evalId: Int, metricId: Int, algoId: Int, name: String): String =
-    BaseDir.offlineMetricDir(rootDir, appId, engineId, algoId, evalId, metricId) + "metric/" + name
-}
-
-/**
- * Training Test Set Generator Internal File
- */
-object U2ITrainingTestSplitFile {
-
-  def apply(rootDir: String, appId: Int, engineId: Int, evalId: Int, name: String): String =
-    BaseDir.offlineEvalDir(rootDir, appId, engineId, evalId) + "u2itrainingtestsplit/" + name
-}
-
-/*
- * standard
- */
-
-/**
- * For Model Constructor output
- */
-object ModelDataDir {
-
-  def apply(rootDir: String, appId: Int, engineId: Int, algoId: Int, evalId: Option[Int]): String =
-    BaseDir.algoDir(rootDir, appId, engineId, algoId, evalId) + "modeldata/"
-}
-
-/**
- * Offline Evaluation output file
- */
-object OfflineEvalResultsDir {
-
-  def apply(rootDir: String, appId: Int, engineId: Int, evalId: Int, metricId: Int, algoId: Int): String =
-    BaseDir.offlineMetricDir(rootDir, appId, engineId, algoId, evalId, metricId) + "evalresults/"
-}
-
-/**
- * AppData
- */
-object AppDataDir {
-
-  def apply(rootDir: String, appId: Int, engineId: Option[Int], evalId: Option[Int], testSet: Option[Boolean]): String = {
-    (engineId, evalId, testSet) match {
-      case (Some(eng), Some(eva), Some(test)) => BaseDir.offlineEvalDir(rootDir, appId, eng, eva) + "appdata/" + (if (test) "test/" else "training/")
-      case _ => BaseDir.appDir(rootDir, appId) + "appdata/"
-    }
-  }
-}
-
diff --git a/commons/src/main/scala/io/prediction/commons/modeldata/ItemRecScores.scala b/commons/src/main/scala/io/prediction/commons/modeldata/ItemRecScores.scala
deleted file mode 100644
index 7fe8531..0000000
--- a/commons/src/main/scala/io/prediction/commons/modeldata/ItemRecScores.scala
+++ /dev/null
@@ -1,71 +0,0 @@
-package io.prediction.commons.modeldata
-
-import io.prediction.commons.settings.{ Algo, App, OfflineEval }
-
-/**
- * ItemRecScore object.
- * This object represents an item to be recommended to a user.
- *
- * @param uid User ID.
- * @param iids Seq of item IDs.
- * @param scores Seq of recommendation score.
- * @param itypes Seq of item types of the item recommended. Copied from the item
- *               when a batch mode algorithm is run.
- * @param appid App ID of this record.
- * @param algoid Algo ID of this record.
- * @param modelset Model data set.
- * @param id ItemRecScore ID (optional field used internally for sorting)
- */
-case class ItemRecScore(
-  uid: String,
-  iids: Seq[String],
-  scores: Seq[Double],
-  itypes: Seq[Seq[String]],
-  appid: Int,
-  algoid: Int,
-  modelset: Boolean,
-  id: Option[Any] = None)
-
-/**
- * Base trait for implementations that interact with itemrec scores in the
- * backend data store.
- */
-trait ItemRecScores extends ModelData {
-  /**
-   * Insert an ItemRecScore and return it with a real ID, if any (database
-   * vendor dependent).
-   */
-  def insert(itemRecScore: ItemRecScore): ItemRecScore
-
-  /** Insert ItemRecScore(s) and return them with real IDs, if any (database vendor dependent). */
-  def insert(itemRecScores: Seq[ItemRecScore]): Seq[ItemRecScore]
-
-  /** get an ItemRecScore by uid */
-  def getByUid(uid: String)(implicit app: App, algo: Algo,
-    offlineEval: Option[OfflineEval] = None): Option[ItemRecScore]
-
-  /**
-   * Get the top N ranked iids.
-   * @param n If n == 0, return as many iids as available
-   */
-  def getTopNIids(uid: String, n: Int,
-    itypes: Option[Seq[String]])(implicit app: App,
-      algo: Algo, offlineEval: Option[OfflineEval] = None): Iterator[String]
-
-  /**
-   * Get the top N ranked iids.
-   * @param n If n == 0, return as many iids as available
-   */
-  def getTopNIidsAndScores(uid: String, n: Int,
-    itypes: Option[Seq[String]])(implicit app: App, algo: Algo,
-      offlineEval: Option[OfflineEval] = None): Seq[(String, Double)]
-
-  /** Delete by Algo ID. */
-  def deleteByAlgoid(algoid: Int)
-
-  /** Delete by Algo ID and model set. */
-  def deleteByAlgoidAndModelset(algoid: Int, modelset: Boolean)
-
-  /** Check whether data exist for a given Algo. */
-  def existByAlgo(algo: Algo): Boolean
-}
diff --git a/commons/src/main/scala/io/prediction/commons/modeldata/ItemSimScores.scala b/commons/src/main/scala/io/prediction/commons/modeldata/ItemSimScores.scala
deleted file mode 100644
index b50282a..0000000
--- a/commons/src/main/scala/io/prediction/commons/modeldata/ItemSimScores.scala
+++ /dev/null
@@ -1,68 +0,0 @@
-package io.prediction.commons.modeldata
-
-import io.prediction.commons.settings.{ Algo, App, OfflineEval }
-
-/**
- * ItemSimScore object.
- * This object represents an item that is similar to an item.
- *
- * @param iid Item ID.
- * @param simiids Seq of similar item ID.
- * @param scores Seq of similarity score.
- * @param itypes Seq of item types of the similar item. Copied from the item
- *               when a batch mode algorithm is run.
- * @param appid App ID of this record.
- * @param algoid Algo ID of this record.
- * @param modelset Model data set.
- * @param id ItemSimScore ID (optional field used internally for sorting)
- */
-case class ItemSimScore(
-  iid: String,
-  simiids: Seq[String],
-  scores: Seq[Double],
-  itypes: Seq[Seq[String]],
-  appid: Int,
-  algoid: Int,
-  modelset: Boolean,
-  id: Option[Any] = None)
-
-/**
- * Base trait for implementations that interact with itemsim scores in the
- * backend data store.
- */
-trait ItemSimScores extends ModelData {
-  /**
-   * Insert an ItemSimScore and return it with a real ID, if any (database
-   * vendor dependent).
-   */
-  def insert(itemSimScore: ItemSimScore): ItemSimScore
-
-  /** get an ItemSimScore by iid */
-  def getByIid(iid: String)(implicit app: App, algo: Algo,
-    offlineEval: Option[OfflineEval] = None): Option[ItemSimScore]
-
-  /**
-   * Get the top N ranked iids
-   * @param n if n == 0, return iids as many as avaiable
-   */
-  def getTopNIids(iid: String, n: Int,
-    itypes: Option[Seq[String]])(implicit app: App, algo: Algo,
-      offlineEval: Option[OfflineEval] = None): Iterator[String]
-
-  /**
-   * Get the top N ranked iids.
-   * @param n If n == 0, return as many iids as available
-   */
-  def getTopNIidsAndScores(iid: String, n: Int,
-    itypes: Option[Seq[String]])(implicit app: App, algo: Algo,
-      offlineEval: Option[OfflineEval] = None): Seq[(String, Double)]
-
-  /** Delete by Algo ID. */
-  def deleteByAlgoid(algoid: Int)
-
-  /** Delete by Algo ID and model set. */
-  def deleteByAlgoidAndModelset(algoid: Int, modelset: Boolean)
-
-  /** Check whether data exist for a given Algo. */
-  def existByAlgo(algo: Algo): Boolean
-}
diff --git a/commons/src/main/scala/io/prediction/commons/modeldata/MetaData.scala b/commons/src/main/scala/io/prediction/commons/modeldata/MetaData.scala
deleted file mode 100644
index 02db1ac..0000000
--- a/commons/src/main/scala/io/prediction/commons/modeldata/MetaData.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package io.prediction.commons.modeldata
-
-import io.prediction.commons.{ Config }
-
-case class MetadataKeyval(
-  algoid: Int,
-  modelset: Boolean,
-  key: String,
-  value: String)
-
-trait MetadataKeyvals extends ModelData {
-  def upsert(algoid: Int, modelset: Boolean, key: String, value: String): Unit
-  def upsert(keyval: MetadataKeyval): Unit
-  def get(algoid: Int, modelset: Boolean, key: String): Option[String]
-}
diff --git a/commons/src/main/scala/io/prediction/commons/modeldata/ModelData.scala b/commons/src/main/scala/io/prediction/commons/modeldata/ModelData.scala
deleted file mode 100644
index a80f05c..0000000
--- a/commons/src/main/scala/io/prediction/commons/modeldata/ModelData.scala
+++ /dev/null
@@ -1,36 +0,0 @@
-package io.prediction.commons.modeldata
-
-/** Base trait for all model data classes. */
-trait ModelData {
-  /**
-   * Delete model data of the specified Algo ID and set.
-   *
-   * @param algoid Algo ID.
-   * @param modelset Set of model data.
-   */
-  def delete(algoid: Int, modelset: Boolean)
-
-  /**
-   * Whether model data of the specified Algo ID and set is empty.
-   *
-   * @param algoid Algo ID.
-   * @param modelset Set of model data.
-   */
-  def empty(algoid: Int, modelset: Boolean): Boolean
-
-  /**
-   * Logic to be performed before batch writing model data.
-   *
-   * @param algoid Algo ID.
-   * @param modelset Set of model data.
-   */
-  def before(algoid: Int, modelset: Boolean)
-
-  /**
-   * Logic to be performed after batch writing model data.
-   *
-   * @param algoid Algo ID.
-   * @param modelset Set of model data.
-   */
-  def after(algoid: Int, modelset: Boolean)
-}
diff --git a/commons/src/main/scala/io/prediction/commons/modeldata/mongodb/MongoItemRecScores.scala b/commons/src/main/scala/io/prediction/commons/modeldata/mongodb/MongoItemRecScores.scala
deleted file mode 100644
index 2f9c066..0000000
--- a/commons/src/main/scala/io/prediction/commons/modeldata/mongodb/MongoItemRecScores.scala
+++ /dev/null
@@ -1,166 +0,0 @@
-package io.prediction.commons.modeldata.mongodb
-
-import io.prediction.commons.Config
-import io.prediction.commons.MongoUtils._
-import io.prediction.commons.modeldata.{ ItemRecScore, ItemRecScores }
-import io.prediction.commons.settings.{ Algo, App, OfflineEval }
-
-import com.mongodb.casbah.Imports._
-
-/** MongoDB implementation of ItemRecScores. */
-class MongoItemRecScores(cfg: Config, db: MongoDB) extends ItemRecScores with MongoModelData {
-  val config = cfg
-  val mongodb = db
-
-  /** Indices and hints. */
-  val queryIndex = MongoDBObject("uid" -> 1)
-
-  def getByUid(uid: String)(implicit app: App, algo: Algo, offlineEval: Option[OfflineEval] = None): Option[ItemRecScore] = {
-    val modelset = offlineEval map { _ => false } getOrElse algo.modelset
-    val itemRecScoreColl = db(collectionName(algo.id, modelset))
-
-    itemRecScoreColl.ensureIndex(queryIndex) // not needed here. it's called in after(), just safety measure in case after() is not called
-
-    itemRecScoreColl.findOne(MongoDBObject("uid" -> idWithAppid(app.id, uid))).map(dbObjToItemRecScore(_, app.id))
-  }
-
-  def getTopNIids(uid: String, n: Int, itypes: Option[Seq[String]])(implicit app: App, algo: Algo, offlineEval: Option[OfflineEval] = None): Iterator[String] = {
-    val modelset = offlineEval map { _ => false } getOrElse algo.modelset
-    val itemRecScoreColl = db(collectionName(algo.id, modelset))
-
-    itemRecScoreColl.ensureIndex(queryIndex) // not needed here. it's called in after(), just safety measure in case after() is not called
-
-    itemRecScoreColl.findOne(MongoDBObject("uid" -> idWithAppid(app.id, uid))).map(dbObjToItemRecScore(_, app.id)).map {
-      x: ItemRecScore =>
-
-        val iids = itypes.map { s =>
-          val iidsAndItypes = x.iids.zip(x.itypes.map(_.toSet)) // List( (iid, Set(itypes of this iid)), ... )
-          val itypesSet: Set[String] = s.toSet // query itypes Set
-          val itypesSetSize = itypesSet.size
-
-          iidsAndItypes.filter {
-            case (iid, iiditypes) =>
-              // if there are some elements in s existing in iiditypes, then s.diff(iiditypes) size will be < original size of s
-              // it means itypes match the item
-              (itypesSet.diff(iiditypes).size < itypesSetSize)
-          }.map(_._1) // only return the iid
-        }.getOrElse {
-          x.iids
-        }
-
-        val topNIids = if (n == 0) iids else iids.take(n)
-
-        topNIids
-    }.getOrElse(Seq()).toIterator
-  }
-
-  def getTopNIidsAndScores(uid: String, n: Int,
-    itypes: Option[Seq[String]])(implicit app: App, algo: Algo,
-      offlineEval: Option[OfflineEval] = None): Seq[(String, Double)] = {
-    val modelset = offlineEval map { _ => false } getOrElse algo.modelset
-    val itemRecScoreColl = db(collectionName(algo.id, modelset))
-
-    itemRecScoreColl.findOne(MongoDBObject(
-      "uid" -> idWithAppid(app.id, uid))).map(
-      dbObjToItemRecScore(_, app.id)).map {
-        x: ItemRecScore =>
-          val iids = itypes.map { s =>
-            val zippedIids = (x.iids, x.scores, x.itypes).zipped.toSeq
-            val itypesSet: Set[String] = s.toSet // query itypes Set
-            val itypesSetSize = itypesSet.size
-
-            zippedIids.filter { z =>
-              // if there are some elements in s existing in iiditypes, then
-              // s.diff(iiditypes) size will be < original size of s
-              // it means itypes match the item
-              (itypesSet.diff(z._3.toSet).size < itypesSetSize)
-            }.map(z => (z._1, z._2)) // only return the iid
-          }.getOrElse {
-            x.iids.zip(x.scores)
-          }
-          if (n == 0) iids else iids.take(n)
-      } getOrElse {
-        Seq[(String, Double)]()
-      }
-  }
-
-  def insert(itemRecScore: ItemRecScore) = {
-    val id = new ObjectId
-    val itemRecObj = MongoDBObject(
-      "_id" -> id,
-      "uid" -> idWithAppid(itemRecScore.appid, itemRecScore.uid),
-      "iids" -> itemRecScore.iids.map(i => idWithAppid(itemRecScore.appid, i)),
-      "scores" -> itemRecScore.scores,
-      "itypes" -> itemRecScore.itypes,
-      "algoid" -> itemRecScore.algoid,
-      "modelset" -> itemRecScore.modelset
-    )
-    db(collectionName(itemRecScore.algoid, itemRecScore.modelset))
-      .insert(itemRecObj)
-    itemRecScore.copy(id = Some(id))
-  }
-
-  /**
-   * Insert ItemRecScore(s) and return them with real IDs.
-   * This method uses the Algo ID and model set of the first
-   * ItemRecScore in the sequence as the collection name.
-   */
-  def insert(itemRecScores: Seq[ItemRecScore]) = {
-    val size = itemRecScores.size
-    if (size == 0) Seq[ItemRecScore]()
-    else {
-      val algoid = itemRecScores(0).algoid
-      val modelset = itemRecScores(0).modelset
-      val ids = Seq.fill(itemRecScores.size)(new ObjectId)
-      val itemRecObjsAndIds = itemRecScores.zip(ids)
-      val itemRecObjs = itemRecObjsAndIds.map(t => MongoDBObject(
-        "_id" -> t._2,
-        "uid" -> idWithAppid(t._1.appid, t._1.uid),
-        "iids" -> t._1.iids.map(i => idWithAppid(t._1.appid, i)),
-        "scores" -> t._1.scores,
-        "itypes" -> t._1.itypes,
-        "algoid" -> t._1.algoid,
-        "modelset" -> t._1.modelset))
-      db(collectionName(algoid, modelset)).insert(itemRecObjs: _*)
-      itemRecObjsAndIds.map(t => t._1.copy(id = Some(t._2)))
-    }
-  }
-
-  def deleteByAlgoid(algoid: Int) = {
-    db(collectionName(algoid, true)).drop()
-    db(collectionName(algoid, false)).drop()
-  }
-
-  def deleteByAlgoidAndModelset(algoid: Int, modelset: Boolean) = {
-    db(collectionName(algoid, modelset)).drop()
-  }
-
-  def existByAlgo(algo: Algo) = {
-    db.collectionExists(collectionName(algo.id, algo.modelset)) && db(collectionName(algo.id, algo.modelset)).find().hasNext
-  }
-
-  override def after(algoid: Int, modelset: Boolean) = {
-    val coll = db(collectionName(algoid, modelset))
-
-    coll.ensureIndex(queryIndex)
-  }
-
-  /** Private mapping function to map DB Object to ItemRecScore object */
-  private def dbObjToItemRecScore(dbObj: DBObject, appid: Int) = {
-    ItemRecScore(
-      uid = dbObj.as[String]("uid").drop(appid.toString.length + 1),
-      iids = mongoDbListToListOfString(dbObj.as[MongoDBList]("iids")).map(_.drop(appid.toString.length + 1)),
-      scores = mongoDbListToListOfDouble(dbObj.as[MongoDBList]("scores")),
-      itypes = mongoDbListToListofListOfString(dbObj.as[MongoDBList]("itypes")),
-      appid = appid,
-      algoid = dbObj.as[Int]("algoid"),
-      modelset = dbObj.as[Boolean]("modelset"),
-      id = Some(dbObj.as[ObjectId]("_id"))
-    )
-  }
-
-  class MongoItemRecScoreIterator(it: MongoCursor, appid: Int) extends Iterator[ItemRecScore] {
-    def hasNext = it.hasNext
-    def next = dbObjToItemRecScore(it.next, appid)
-  }
-}
diff --git a/commons/src/main/scala/io/prediction/commons/modeldata/mongodb/MongoItemSimScores.scala b/commons/src/main/scala/io/prediction/commons/modeldata/mongodb/MongoItemSimScores.scala
deleted file mode 100644
index 2410a0d..0000000
--- a/commons/src/main/scala/io/prediction/commons/modeldata/mongodb/MongoItemSimScores.scala
+++ /dev/null
@@ -1,140 +0,0 @@
-package io.prediction.commons.modeldata.mongodb
-
-import io.prediction.commons.Config
-import io.prediction.commons.MongoUtils._
-import io.prediction.commons.modeldata.{ ItemSimScore, ItemSimScores }
-import io.prediction.commons.settings.{ Algo, App, OfflineEval }
-
-import com.mongodb.casbah.Imports._
-
-/** MongoDB implementation of ItemSimScores. */
-class MongoItemSimScores(cfg: Config, db: MongoDB) extends ItemSimScores with MongoModelData {
-  val config = cfg
-  val mongodb = db
-
-  /** Indices and hints. */
-  val queryIndex = MongoDBObject("iid" -> 1)
-
-  def getByIid(iid: String)(implicit app: App, algo: Algo, offlineEval: Option[OfflineEval] = None): Option[ItemSimScore] = {
-    val modelset = offlineEval map { _ => false } getOrElse algo.modelset
-    val itemSimScoreColl = db(collectionName(algo.id, modelset))
-
-    itemSimScoreColl.ensureIndex(queryIndex) // not needed here. it's called in after(), just safety measure in case after() is not called
-
-    itemSimScoreColl.findOne(MongoDBObject("iid" -> idWithAppid(app.id, iid))).map(dbObjToItemSimScore(_, app.id))
-  }
-
-  def getTopNIids(iid: String, n: Int, itypes: Option[Seq[String]])(implicit app: App, algo: Algo, offlineEval: Option[OfflineEval] = None): Iterator[String] = {
-    val modelset = offlineEval map { _ => false } getOrElse algo.modelset
-    val itemSimScoreColl = db(collectionName(algo.id, modelset))
-
-    itemSimScoreColl.ensureIndex(queryIndex) // not needed here. it's called in after(), just safety measure in case after() is not called
-
-    itemSimScoreColl.findOne(MongoDBObject("iid" -> idWithAppid(app.id, iid))).map(dbObjToItemSimScore(_, app.id)).map {
-      x: ItemSimScore =>
-
-        val simiids = itypes.map { s =>
-          val simiidsAndItypes = x.simiids.zip(x.itypes.map(_.toSet)) // List( (iid, Set(itypes of this iid)), ... )
-          val itypesSet: Set[String] = s.toSet // query itypes Set
-          val itypesSetSize = itypesSet.size
-
-          simiidsAndItypes.filter {
-            case (simiid, iiditypes) =>
-              // if there are some elements in s existing in iiditypes, then s.diff(iiditypes) size will be < original size of s
-              // it means itypes match the item
-              (itypesSet.diff(iiditypes).size < itypesSetSize)
-          }.map(_._1) // only return the iid
-        }.getOrElse {
-          x.simiids
-        }
-
-        val topNIids = if (n == 0) simiids else simiids.take(n)
-
-        topNIids
-    }.getOrElse(Seq()).toIterator
-
-  }
-
-  def getTopNIidsAndScores(iid: String, n: Int,
-    itypes: Option[Seq[String]])(implicit app: App, algo: Algo,
-      offlineEval: Option[OfflineEval] = None): Seq[(String, Double)] = {
-    val modelset = offlineEval map { _ => false } getOrElse algo.modelset
-    val itemRecScoreColl = db(collectionName(algo.id, modelset))
-
-    itemRecScoreColl.findOne(MongoDBObject(
-      "iid" -> idWithAppid(app.id, iid))).map(
-      dbObjToItemSimScore(_, app.id)).map {
-        x: ItemSimScore =>
-          val iids = itypes.map { s =>
-            val zippedIids = (x.simiids, x.scores, x.itypes).zipped.toSeq
-            val itypesSet: Set[String] = s.toSet // query itypes Set
-            val itypesSetSize = itypesSet.size
-
-            zippedIids.filter { z =>
-              // if there are some elements in s existing in iiditypes, then
-              // s.diff(iiditypes) size will be < original size of s
-              // it means itypes match the item
-              (itypesSet.diff(z._3.toSet).size < itypesSetSize)
-            }.map(z => (z._1, z._2)) // only return the iid
-          }.getOrElse {
-            x.simiids.zip(x.scores)
-          }
-          if (n == 0) iids else iids.take(n)
-      } getOrElse {
-        Seq[(String, Double)]()
-      }
-  }
-
-  def insert(itemSimScore: ItemSimScore) = {
-    val id = new ObjectId
-    val itemSimObj = MongoDBObject(
-      "_id" -> id,
-      "iid" -> idWithAppid(itemSimScore.appid, itemSimScore.iid),
-      "simiids" -> itemSimScore.simiids.map(i => idWithAppid(itemSimScore.appid, i)),
-      "scores" -> itemSimScore.scores,
-      "simitypes" -> itemSimScore.itypes,
-      "algoid" -> itemSimScore.algoid,
-      "modelset" -> itemSimScore.modelset
-    )
-    db(collectionName(itemSimScore.algoid, itemSimScore.modelset)).insert(itemSimObj)
-    itemSimScore.copy(id = Some(id))
-  }
-
-  def deleteByAlgoid(algoid: Int) = {
-    db(collectionName(algoid, true)).drop()
-    db(collectionName(algoid, false)).drop()
-  }
-
-  def deleteByAlgoidAndModelset(algoid: Int, modelset: Boolean) = {
-    db(collectionName(algoid, modelset)).drop()
-  }
-
-  def existByAlgo(algo: Algo) = {
-    db.collectionExists(collectionName(algo.id, algo.modelset)) && db(collectionName(algo.id, algo.modelset)).find().hasNext
-  }
-
-  override def after(algoid: Int, modelset: Boolean) = {
-    val coll = db(collectionName(algoid, modelset))
-
-    coll.ensureIndex(queryIndex)
-  }
-
-  /** Private mapping function to map DB Object to ItemSimScore object */
-  private def dbObjToItemSimScore(dbObj: DBObject, appid: Int) = {
-    ItemSimScore(
-      iid = dbObj.as[String]("iid").drop(appid.toString.length + 1),
-      simiids = mongoDbListToListOfString(dbObj.as[MongoDBList]("simiids")).map(_.drop(appid.toString.length + 1)),
-      scores = mongoDbListToListOfDouble(dbObj.as[MongoDBList]("scores")),
-      itypes = mongoDbListToListofListOfString(dbObj.as[MongoDBList]("simitypes")),
-      appid = appid,
-      algoid = dbObj.as[Int]("algoid"),
-      modelset = dbObj.as[Boolean]("modelset"),
-      id = Some(dbObj.as[ObjectId]("_id"))
-    )
-  }
-
-  class MongoItemSimScoreIterator(it: MongoCursor, appid: Int) extends Iterator[ItemSimScore] {
-    def hasNext = it.hasNext
-    def next = dbObjToItemSimScore(it.next, appid)
-  }
-}
diff --git a/commons/src/main/scala/io/prediction/commons/modeldata/mongodb/MongoMetaData.scala b/commons/src/main/scala/io/prediction/commons/modeldata/mongodb/MongoMetaData.scala
deleted file mode 100644
index a9305ed..0000000
--- a/commons/src/main/scala/io/prediction/commons/modeldata/mongodb/MongoMetaData.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-package io.prediction.commons.modeldata.mongodb
-
-import io.prediction.commons.Config
-import io.prediction.commons.MongoUtils
-import io.prediction.commons.modeldata.{ MetadataKeyval, MetadataKeyvals }
-
-import com.mongodb.casbah.Imports._
-
-class MongoMetadataKeyvals(cfg: Config, db: MongoDB)
-    extends MetadataKeyvals with MongoModelData {
-  val config = cfg
-  val mongodb = db
-
-  override protected def collectionName(algoid: Int, modelset: Boolean) =
-    s"algo_${algoid}_${modelset}_meta"
-
-  def upsert(algoid: Int, modelset: Boolean, key: String, value: String) = {
-    val q = MongoDBObject("_id" -> key)
-    val obj = MongoDBObject("_id" -> key, "value" -> value)
-    db(collectionName(algoid, modelset)).update(q, obj, true)
-  }
-
-  def upsert(keyval: MetadataKeyval) = {
-    upsert(keyval.algoid, keyval.modelset, keyval.key, keyval.value)
-  }
-
-  def get(algoid: Int, modelset: Boolean, key: String): Option[String] = {
-    val coll = db(collectionName(algoid, modelset))
-    coll.findOne(MongoDBObject("_id" -> key)).map(_.as[String]("value"))
-  }
-}
diff --git a/commons/src/main/scala/io/prediction/commons/modeldata/mongodb/MongoModelData.scala b/commons/src/main/scala/io/prediction/commons/modeldata/mongodb/MongoModelData.scala
deleted file mode 100644
index e34abfb..0000000
--- a/commons/src/main/scala/io/prediction/commons/modeldata/mongodb/MongoModelData.scala
+++ /dev/null
@@ -1,37 +0,0 @@
-package io.prediction.commons.modeldata.mongodb
-
-import io.prediction.commons.Config
-import io.prediction.commons.modeldata.ModelData
-
-import com.mongodb.casbah.Imports._
-
-trait MongoModelData extends ModelData {
-  val config: Config
-  val mongodb: MongoDB
-
-  def delete(algoid: Int, modelset: Boolean) = {
-    mongodb(collectionName(algoid, modelset)).drop()
-  }
-
-  def empty(algoid: Int, modelset: Boolean) = {
-    !mongodb.collectionExists(collectionName(algoid, modelset)) ||
-      mongodb(collectionName(algoid, modelset)).count() == 0
-  }
-
-  override def before(algoid: Int, modelset: Boolean) = {
-    if (config.modeldataDbSharding) {
-      config.modeldataDbShardKeys map { seqOfKeys =>
-        if (seqOfKeys.length != 0) {
-          val keysObj = seqOfKeys map { k => MongoDBObject(k -> 1) } reduce { _ ++ _ }
-          mongodb.command(MongoDBObject(
-            "shardCollection" -> collectionName(algoid, modelset),
-            "key" -> keysObj))
-        }
-      }
-    }
-  }
-
-  override def after(algoid: Int, modelset: Boolean) = {}
-
-  protected def collectionName(algoid: Int, modelset: Boolean) = s"algo_${algoid}_${modelset}"
-}
diff --git a/commons/src/main/scala/io/prediction/commons/settings/AlgoInfos.scala b/commons/src/main/scala/io/prediction/commons/settings/AlgoInfos.scala
deleted file mode 100644
index 22d34b4..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/AlgoInfos.scala
+++ /dev/null
@@ -1,72 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Common
-
-import org.json4s._
-import org.json4s.native.Serialization
-
-/**
- * AlgoInfo object.
- *
- * @param id Unique identifier. Usually identical to the algorithm's namespace.
- * @param name Algorithm name.
- * @param description A long description of the algorithm.
- * @param batchcommands Command templates for running the algorithm in batch mode.
- * @param offlineevalcommands Command templates for running the algorithm in offline evaluation mode.
- * @param params Map of Param objects, with keys equal to IDs of Param objects it contains.
- * @param paramorder The display order of parameters.
- * @param engineinfoid The EngineInfo ID of the engine that can run this algorithm.
- * @param techreq Technology requirement for this algorithm to run.
- * @param datareq Data requirement for this algorithm to run.
- * @param capabilities Engine features that this algorithm can handle.
- */
-case class AlgoInfo(
-  id: String,
-  name: String,
-  description: Option[String],
-  batchcommands: Option[Seq[String]],
-  offlineevalcommands: Option[Seq[String]],
-  params: Map[String, Param],
-  paramsections: Seq[ParamSection],
-  paramorder: Seq[String],
-  engineinfoid: String,
-  techreq: Seq[String],
-  datareq: Seq[String],
-  capabilities: Seq[String] = Seq()) extends Info
-
-/** Base trait for implementations that interact with algo info in the backend data store. */
-trait AlgoInfos extends Common {
-  /** Insert an algo info. */
-  def insert(algoInfo: AlgoInfo): Unit
-
-  /** Get algo info by its ID. */
-  def get(id: String): Option[AlgoInfo]
-
-  /** Get all algo info. */
-  def getAll(): Seq[AlgoInfo]
-
-  /** Get algo info by their engine type. */
-  def getByEngineInfoId(engineinfoid: String): Seq[AlgoInfo]
-
-  /** Update an algo info. */
-  def update(algoInfo: AlgoInfo, upsert: Boolean = false): Unit
-
-  /** Delete an algo info by its ID. */
-  def delete(id: String): Unit
-
-  implicit val formats = Serialization.formats(NoTypeHints) + new ParamSerializer
-
-  /** Backup all AlgoInfos as a byte array. */
-  def backup(): Array[Byte] = Serialization.write(getAll()).getBytes("UTF-8")
-
-  /** Restore AlgoInfos from a byte array backup created by the current or the immediate previous version of commons. */
-  def restore(bytes: Array[Byte], inplace: Boolean = false, upgrade: Boolean = false): Option[Seq[AlgoInfo]] = {
-    try {
-      val rdata = Serialization.read[Seq[AlgoInfo]](new String(bytes, "UTF-8"))
-      if (inplace) rdata foreach { update(_, true) }
-      Some(rdata)
-    } catch {
-      case e: MappingException => None
-    }
-  }
-}
diff --git a/commons/src/main/scala/io/prediction/commons/settings/Algos.scala b/commons/src/main/scala/io/prediction/commons/settings/Algos.scala
deleted file mode 100644
index 84600f5..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/Algos.scala
+++ /dev/null
@@ -1,146 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Common
-
-import com.github.nscala_time.time.Imports._
-import org.json4s._
-import org.json4s.native.Serialization
-
-/**
- * Algo object.
- *
- * @param id ID.
- * @param engineid App ID that owns this engine.
- * @param name Algo name.
- * @param infoid AlgoInfo ID
- * @param command Command template for running the algo.
- * @param params Algo parameters as key-value pairs.
- * @param settings Algo settings as key-value pairs.
- * @param modelset Indicates which model output set to be used by the API.
- * @param createtime Creation time of this Algo.
- * @param updatetime Last update time of this Algo's settings.
- * @param status The status of the algo. eg "ready", "tuning".
- * @param offlineevalid The id of OfflineEval which uses this algo for offline evaluation
- * @param offlinetuneid The id of OfflineTune
- * @param loop The iteration number used by auto tune. (NOTE: loop=0 reserved for baseline algo)
- * @param paramset The param generation set number
- * @param lasttraintime Time of last successful training.
- */
-case class Algo(
-  id: Int,
-  engineid: Int,
-  name: String,
-  infoid: String,
-  command: String,
-  params: Map[String, Any] = Map(),
-  settings: Map[String, Any] = Map(),
-  modelset: Boolean,
-  createtime: DateTime,
-  updatetime: DateTime,
-  status: String = "",
-  offlineevalid: Option[Int] = None,
-  offlinetuneid: Option[Int] = None,
-  loop: Option[Int] = None,
-  paramset: Option[Int] = None,
-  lasttraintime: Option[DateTime] = None)
-
-/** Base trait for implementations that interact with algos in the backend data store. */
-trait Algos extends Common {
-  /** Inserts an algo. */
-  def insert(algo: Algo): Int
-
-  /** Get an algo by its ID. */
-  def get(id: Int): Option[Algo]
-
-  /** Get all algos. */
-  def getAll(): Iterator[Algo]
-
-  /** Get algos by engine ID. */
-  def getByEngineid(engineid: Int): Iterator[Algo]
-
-  /** Get deployed algos by engine ID. */
-  def getDeployedByEngineid(engineid: Int): Iterator[Algo]
-
-  /** Get by OfflineEval ID. */
-  def getByOfflineEvalid(evalid: Int, loop: Option[Int] = None, paramset: Option[Int] = None): Iterator[Algo]
-
-  /** Get the auto tune subject by OfflineTune ID. */
-  def getTuneSubjectByOfflineTuneid(tuneid: Int): Option[Algo]
-
-  /** Get the algo by its ID and engine ID. */
-  def getByIdAndEngineid(id: Int, engineid: Int): Option[Algo]
-
-  /** Update an algo. */
-  def update(algo: Algo, upsert: Boolean = false)
-
-  /** Delete an algo by its ID. */
-  def delete(id: Int)
-
-  /**
-   * Check existence of an algo by its engine ID and name.
-   * Algos that are part of an offline evaluation or tuning are not counted.
-   */
-  def existsByEngineidAndName(engineid: Int, name: String): Boolean
-
-  implicit val formats = Serialization.formats(NoTypeHints) + new AlgoSerializer
-
-  /** Backup all Algos as a byte array. */
-  def backup(): Array[Byte] = Serialization.write(getAll().toSeq).getBytes("UTF-8")
-
-  /** Restore Algos from a byte array backup created by the current or the immediate previous version of commons. */
-  def restore(bytes: Array[Byte], inplace: Boolean = false, upgrade: Boolean = false): Option[Seq[Algo]] = {
-    try {
-      val rdata = Serialization.read[Seq[Algo]](new String(bytes, "UTF-8"))
-      if (inplace) rdata foreach { update(_, true) }
-      Some(rdata)
-    } catch {
-      case e: MappingException => None
-    }
-  }
-}
-
-/** json4s serializer for the Algo class. */
-class AlgoSerializer extends CustomSerializer[Algo](format => (
-  {
-    case x: JObject =>
-      implicit val formats = Serialization.formats(NoTypeHints) ++ org.json4s.ext.JodaTimeSerializers.all
-      Algo(
-        id = (x \ "id").extract[Int],
-        engineid = (x \ "engineid").extract[Int],
-        name = (x \ "name").extract[String],
-        infoid = (x \ "infoid").extract[String],
-        command = (x \ "command").extract[String],
-        params = Common.sanitize((x \ "params").asInstanceOf[JObject].values),
-        settings = Common.sanitize((x \ "settings").asInstanceOf[JObject].values),
-        modelset = (x \ "modelset").extract[Boolean],
-        createtime = (x \ "createtime").extract[DateTime],
-        updatetime = (x \ "updatetime").extract[DateTime],
-        status = (x \ "status").extract[String],
-        offlineevalid = (x \ "offlineevalid").extract[Option[Int]],
-        offlinetuneid = (x \ "offlinetuneid").extract[Option[Int]],
-        loop = (x \ "loop").extract[Option[Int]],
-        paramset = (x \ "paramset").extract[Option[Int]],
-        lasttraintime = (x \ "lasttraintime").extract[Option[DateTime]])
-  },
-  {
-    case x: Algo =>
-      implicit val formats = Serialization.formats(NoTypeHints) ++ org.json4s.ext.JodaTimeSerializers.all
-      JObject(
-        JField("id", Extraction.decompose(x.id)) ::
-          JField("engineid", Extraction.decompose(x.engineid)) ::
-          JField("name", Extraction.decompose(x.name)) ::
-          JField("infoid", Extraction.decompose(x.infoid)) ::
-          JField("command", Extraction.decompose(x.command)) ::
-          JField("params", Extraction.decompose(x.params)) ::
-          JField("settings", Extraction.decompose(x.settings)) ::
-          JField("modelset", Extraction.decompose(x.modelset)) ::
-          JField("createtime", Extraction.decompose(x.createtime)) ::
-          JField("updatetime", Extraction.decompose(x.updatetime)) ::
-          JField("status", Extraction.decompose(x.status)) ::
-          JField("offlineevalid", Extraction.decompose(x.offlineevalid)) ::
-          JField("offlinetuneid", Extraction.decompose(x.offlinetuneid)) ::
-          JField("loop", Extraction.decompose(x.loop)) ::
-          JField("paramset", Extraction.decompose(x.paramset)) ::
-          JField("lasttraintime", Extraction.decompose(x.lasttraintime)) :: Nil)
-  })
-)
diff --git a/commons/src/main/scala/io/prediction/commons/settings/Apps.scala b/commons/src/main/scala/io/prediction/commons/settings/Apps.scala
deleted file mode 100644
index 82b0cb1..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/Apps.scala
+++ /dev/null
@@ -1,92 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Common
-
-import org.json4s._
-import org.json4s.native.Serialization
-
-/**
- * App object.
- *
- * @param id ID.
- * @param userid User ID that owns this app.
- * @param appkey The appkey used to access this app via REST API.
- * @param display The app's display name.
- * @param url The URL where the app is used.
- * @param cat The app's category.
- * @param desc The app's description.
- * @param timezone The app's timezone.
- */
-case class App(
-  id: Int,
-  userid: Int,
-  appkey: String,
-  display: String,
-  url: Option[String] = None,
-  cat: Option[String] = None,
-  desc: Option[String] = None,
-  timezone: String = "UTC")
-
-/** Base trait for implementations that interact with apps in the backend data store. */
-trait Apps extends Common {
-  /**
-   * Insert a new App with basic fields defined.
-   *
-   * @param app An App object to be inserted. The ID will be ignored and replaced by an implementation of this trait.
-   */
-  def insert(app: App): Int
-
-  /** Get an App by its ID. */
-  def get(id: Int): Option[App]
-
-  /** Get all Apps. */
-  def getAll(): Iterator[App]
-
-  /** Get Apps by user ID. */
-  def getByUserid(userid: Int): Iterator[App]
-
-  /** Get an App by its appkey. */
-  def getByAppkey(appkey: String): Option[App]
-
-  /** Get an App by its appkey and user ID. */
-  def getByAppkeyAndUserid(appkey: String, userid: Int): Option[App]
-
-  /** Get an App by its ID and user ID. */
-  def getByIdAndUserid(id: Int, userid: Int): Option[App]
-
-  /** Update app information. */
-  def update(app: App, upsert: Boolean = false)
-
-  /** Update app's appkey by its appkey and user ID. */
-  def updateAppkeyByAppkeyAndUserid(appkey: String, userid: Int, newAppkey: String): Option[App]
-
-  /** Update app's timezone by its appkey and user ID. */
-  def updateTimezoneByAppkeyAndUserid(appkey: String, userid: Int, timezone: String): Option[App]
-
-  /** Delete an App by ID and user ID. */
-  def deleteByIdAndUserid(id: Int, userid: Int)
-
-  /**
-   * Check if this app exists by its ID, appkey and user ID.
-   *
-   * For purpose of making sure this app exists and belongs to the specified
-   * user ID.
-   */
-  def existsByIdAndAppkeyAndUserid(id: Int, appkey: String, userid: Int): Boolean
-
-  implicit val formats = Serialization.formats(NoTypeHints)
-
-  /** Backup all data as a byte array. */
-  def backup(): Array[Byte] = Serialization.write(getAll().toSeq).getBytes("UTF-8")
-
-  /** Restore data from a byte array backup created by the current or the immediate previous version of commons. */
-  def restore(bytes: Array[Byte], inplace: Boolean = false, upgrade: Boolean = false): Option[Seq[App]] = {
-    try {
-      val rdata = Serialization.read[Seq[App]](new String(bytes, "UTF-8"))
-      if (inplace) rdata foreach { update(_, true) }
-      Some(rdata)
-    } catch {
-      case e: MappingException => None
-    }
-  }
-}
diff --git a/commons/src/main/scala/io/prediction/commons/settings/EngineInfos.scala b/commons/src/main/scala/io/prediction/commons/settings/EngineInfos.scala
deleted file mode 100644
index e597f44..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/EngineInfos.scala
+++ /dev/null
@@ -1,61 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Common
-
-import org.json4s._
-import org.json4s.native.Serialization
-
-/**
- * EngineInfo object.
- *
- * @param id Unique identifier of an engine type.
- * @param name Engine name.
- * @param description A long description of the engine.
- * @param defaultsettings Default engine settings.
- * @param defaultalgoinfoid Default AlgoInfo ID for this engine.
- * @param defaultofflineevalmetricinfoid Default OfflineEvalMetricInfo ID for this engine.
- * @param defaultofflineevalsplitterinfoid Default OfflineEvalSplitter ID for this engine.
- */
-case class EngineInfo(
-  id: String,
-  name: String,
-  description: Option[String],
-  params: Map[String, Param],
-  paramsections: Seq[ParamSection],
-  defaultalgoinfoid: String,
-  defaultofflineevalmetricinfoid: String,
-  defaultofflineevalsplitterinfoid: String) extends Info
-
-/** Base trait for implementations that interact with engine info in the backend data store. */
-trait EngineInfos extends Common {
-  /** Inserts an engine info. */
-  def insert(engineInfo: EngineInfo): Unit
-
-  /** Get an engine info by its ID. */
-  def get(id: String): Option[EngineInfo]
-
-  /** Get all engine info. */
-  def getAll(): Seq[EngineInfo]
-
-  /** Updates an engine info. */
-  def update(engineInfo: EngineInfo, upsert: Boolean = false): Unit
-
-  /** Delete an engine info by its ID. */
-  def delete(id: String): Unit
-
-  implicit val formats = Serialization.formats(NoTypeHints) + new ParamSerializer
-
-  /** Backup all EngineInfos as a byte array. */
-  def backup(): Array[Byte] = Serialization.write(getAll()).getBytes("UTF-8")
-
-  /** Restore EngineInfos from a byte array backup created by the current or the immediate previous version of commons. */
-  def restore(bytes: Array[Byte], inplace: Boolean = false, upgrade: Boolean = false): Option[Seq[EngineInfo]] = {
-    try {
-      val rdata = Serialization.read[Seq[EngineInfo]](new String(bytes, "UTF-8"))
-      if (inplace) rdata foreach { update(_, true) }
-      Some(rdata)
-    } catch {
-      case e: MappingException => None
-    }
-  }
-}
diff --git a/commons/src/main/scala/io/prediction/commons/settings/Engines.scala b/commons/src/main/scala/io/prediction/commons/settings/Engines.scala
deleted file mode 100644
index 72a4c7c..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/Engines.scala
+++ /dev/null
@@ -1,104 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Common
-
-import org.json4s._
-import org.json4s.native.Serialization
-
-/**
- * Engine object.
- *
- * @param id ID.
- * @param appid App ID that owns this engine.
- * @param name Engine name.
- * @param infoid EngineInfo ID.
- * @param itypes List of item types.
- * @param params Engine parameters as key-value pairs.
- * @param trainingdisabled Whether training is disabled or not. If value is undefined, assume training is not disabled.
- * @param trainingschedule Training schedule of this engine in cron expression. Default to an hourly schedule at 0 minute.
- */
-case class Engine(
-  id: Int,
-  appid: Int,
-  name: String,
-  infoid: String,
-  itypes: Option[Seq[String]],
-  params: Map[String, Any],
-  trainingdisabled: Option[Boolean] = None,
-  trainingschedule: Option[String] = None)
-
-/** Base trait for implementations that interact with engines in the backend data store. */
-trait Engines extends Common {
-  /** Inserts an engine. */
-  def insert(engine: Engine): Int
-
-  /** Get an engine by its ID. */
-  def get(id: Int): Option[Engine]
-
-  /** Get all engines. */
-  def getAll(): Iterator[Engine]
-
-  /** Get engines by app ID. */
-  def getByAppid(appid: Int): Iterator[Engine]
-
-  /** Get an engine by app ID and name. */
-  def getByAppidAndName(appid: Int, name: String): Option[Engine]
-
-  /** Get an engine by its ID and app ID. */
-  def getByIdAndAppid(id: Int, appid: Int): Option[Engine]
-
-  /** Update an engine. */
-  def update(engine: Engine, upsert: Boolean = false)
-
-  /** Delete an engine by its ID and app ID. */
-  def deleteByIdAndAppid(id: Int, appid: Int)
-
-  /** Check existence of an engine by its app ID and name. */
-  def existsByAppidAndName(appid: Int, name: String): Boolean
-
-  implicit val formats = Serialization.formats(NoTypeHints) + new EngineSerializer
-
-  /** Backup all Engines as a byte array. */
-  def backup(): Array[Byte] = Serialization.write(getAll().toSeq).getBytes("UTF-8")
-
-  /** Restore Engines from a byte array backup created by the current or the immediate previous version of commons. */
-  def restore(bytes: Array[Byte], inplace: Boolean = false, upgrade: Boolean = false): Option[Seq[Engine]] = {
-    try {
-      val rdata = Serialization.read[Seq[Engine]](new String(bytes, "UTF-8"))
-      if (inplace) rdata foreach { update(_, true) }
-      Some(rdata)
-    } catch {
-      case e: MappingException => { println(e.getMessage()); None }
-    }
-  }
-}
-
-/** json4s serializer for the Engine class. */
-class EngineSerializer extends CustomSerializer[Engine](format => (
-  {
-    case x: JObject =>
-      implicit val formats = Serialization.formats(NoTypeHints)
-      Engine(
-        id = (x \ "id").extract[Int],
-        appid = (x \ "appid").extract[Int],
-        name = (x \ "name").extract[String],
-        infoid = (x \ "infoid").extract[String],
-        itypes = (x \ "itypes").extract[Option[Seq[String]]],
-        params = Common.sanitize((x \ "params").asInstanceOf[JObject].values),
-        trainingdisabled = (x \ "trainingdisabled").extract[Option[Boolean]],
-        trainingschedule = (x \ "trainingschedule").extract[Option[String]])
-  },
-  {
-    case x: Engine =>
-      implicit val formats = Serialization.formats(NoTypeHints)
-      JObject(
-        JField("id", Extraction.decompose(x.id)) ::
-          JField("appid", Extraction.decompose(x.appid)) ::
-          JField("name", Extraction.decompose(x.name)) ::
-          JField("infoid", Extraction.decompose(x.infoid)) ::
-          JField("itypes", Extraction.decompose(x.itypes)) ::
-          JField("params", Extraction.decompose(x.params)) ::
-          JField("trainingdisabled", Extraction.decompose(x.trainingdisabled)) ::
-          JField("trainingschedule", Extraction.decompose(x.trainingschedule)) :: Nil)
-  })
-)
diff --git a/commons/src/main/scala/io/prediction/commons/settings/Info.scala b/commons/src/main/scala/io/prediction/commons/settings/Info.scala
deleted file mode 100644
index 4f7e269..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/Info.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-package io.prediction.commons.settings
-
-trait Info {
-  def params: Map[String, Param]
-  def paramsections: Seq[ParamSection]
-}
diff --git a/commons/src/main/scala/io/prediction/commons/settings/Metadata.scala b/commons/src/main/scala/io/prediction/commons/settings/Metadata.scala
deleted file mode 100644
index 4a4098d..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/Metadata.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Common
-
-/** Base trait for implementations that interact with metadata in the backend data store. */
-trait Metadata extends Common
diff --git a/commons/src/main/scala/io/prediction/commons/settings/OfflineEvalMetricInfos.scala b/commons/src/main/scala/io/prediction/commons/settings/OfflineEvalMetricInfos.scala
deleted file mode 100644
index dfc73da..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/OfflineEvalMetricInfos.scala
+++ /dev/null
@@ -1,66 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Common
-
-import org.json4s._
-import org.json4s.native.Serialization
-
-/**
- * OfflineEvalMetricInfo object.
- *
- * @param id Unique identifier of a metric.
- * @param name Metric name.
- * @param description A long description of the metric.
- * @param engineinfoids A list of EngineInfo IDs that this metric can apply to.
- * @param commands A sequence of commands to run this metric.
- * @param paramdefaults Default parameters as key-value pairs. Usually used by substituting template variables in command templates.
- * @param paramnames Key value pairs of (parameter -> display name).
- * @param paramdescription Key value pairs of (parameter -> description).
- * @param paramorder The display order of parameters.
- */
-case class OfflineEvalMetricInfo(
-  id: String,
-  name: String,
-  description: Option[String],
-  engineinfoids: Seq[String],
-  commands: Option[Seq[String]],
-  params: Map[String, Param],
-  paramsections: Seq[ParamSection],
-  paramorder: Seq[String]) extends Info
-
-/** Base trait for implementations that interact with metric info in the backend data store. */
-trait OfflineEvalMetricInfos extends Common {
-  /** Inserts a metric info. */
-  def insert(metricInfo: OfflineEvalMetricInfo): Unit
-
-  /** Get a metric info by its ID. */
-  def get(id: String): Option[OfflineEvalMetricInfo]
-
-  /** Get all metric info. */
-  def getAll(): Seq[OfflineEvalMetricInfo]
-
-  /** Get all metric info by engineinfo ID */
-  def getByEngineinfoid(engineinfoid: String): Seq[OfflineEvalMetricInfo]
-
-  /** Updates a metric info. */
-  def update(metricInfo: OfflineEvalMetricInfo, upsert: Boolean = false): Unit
-
-  /** Delete a metric info by its ID. */
-  def delete(id: String): Unit
-
-  implicit val formats = Serialization.formats(NoTypeHints) + new ParamSerializer
-
-  /** Backup all OfflineEvalMetricInfos as a byte array. */
-  def backup(): Array[Byte] = Serialization.write(getAll()).getBytes("UTF-8")
-
-  /** Restore OfflineEvalMetricInfos from a byte array backup created by the current or the immediate previous version of commons. */
-  def restore(bytes: Array[Byte], inplace: Boolean = false, upgrade: Boolean = false): Option[Seq[OfflineEvalMetricInfo]] = {
-    try {
-      val rdata = Serialization.read[Seq[OfflineEvalMetricInfo]](new String(bytes, "UTF-8"))
-      if (inplace) rdata foreach { update(_, true) }
-      Some(rdata)
-    } catch {
-      case e: MappingException => None
-    }
-  }
-}
diff --git a/commons/src/main/scala/io/prediction/commons/settings/OfflineEvalMetrics.scala b/commons/src/main/scala/io/prediction/commons/settings/OfflineEvalMetrics.scala
deleted file mode 100644
index 673af76..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/OfflineEvalMetrics.scala
+++ /dev/null
@@ -1,79 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Common
-
-import org.json4s._
-import org.json4s.native.Serialization
-
-/**
- * OfflineEvalMetric Object
- *
- * @param id ID
- * @param infoid MetricInfo ID
- * @param evalid ID of the OfflineEval which uses this metric
- * @param params Metric parameters as key-value pairs
- */
-case class OfflineEvalMetric(
-  id: Int,
-  infoid: String,
-  evalid: Int,
-  params: Map[String, Any])
-
-trait OfflineEvalMetrics extends Common {
-
-  /** Insert a metric and return ID. */
-  def insert(metric: OfflineEvalMetric): Int
-
-  /** Get a metric by its ID. */
-  def get(id: Int): Option[OfflineEvalMetric]
-
-  /** Get all metrics. */
-  def getAll(): Iterator[OfflineEvalMetric]
-
-  /** Get metrics by OfflineEval ID. */
-  def getByEvalid(evalid: Int): Iterator[OfflineEvalMetric]
-
-  /** Update metric. */
-  def update(metric: OfflineEvalMetric, upsert: Boolean = false)
-
-  /** Delete metric by its ID. */
-  def delete(id: Int)
-
-  implicit val formats = Serialization.formats(NoTypeHints) + new OfflineEvalMetricSerializer
-
-  /** Backup all OfflineEvalMetrics as a byte array. */
-  def backup(): Array[Byte] = Serialization.write(getAll().toSeq).getBytes("UTF-8")
-
-  /** Restore OfflineEvalMetrics from a byte array backup created by the current or the immediate previous version of commons. */
-  def restore(bytes: Array[Byte], inplace: Boolean = false, upgrade: Boolean = false): Option[Seq[OfflineEvalMetric]] = {
-    try {
-      val rdata = Serialization.read[Seq[OfflineEvalMetric]](new String(bytes, "UTF-8"))
-      if (inplace) rdata foreach { update(_, true) }
-      Some(rdata)
-    } catch {
-      case e: MappingException => None
-    }
-  }
-}
-
-/** json4s serializer for the OfflineEvalMetric class. */
-class OfflineEvalMetricSerializer extends CustomSerializer[OfflineEvalMetric](format => (
-  {
-    case x: JObject =>
-      implicit val formats = Serialization.formats(NoTypeHints)
-      OfflineEvalMetric(
-        id = (x \ "id").extract[Int],
-        infoid = (x \ "infoid").extract[String],
-        evalid = (x \ "evalid").extract[Int],
-        params = Common.sanitize((x \ "params").asInstanceOf[JObject].values))
-  },
-  {
-    case x: OfflineEvalMetric =>
-      implicit val formats = Serialization.formats(NoTypeHints)
-      JObject(
-        JField("id", Extraction.decompose(x.id)) ::
-          JField("infoid", Extraction.decompose(x.infoid)) ::
-          JField("evalid", Extraction.decompose(x.evalid)) ::
-          JField("params", Extraction.decompose(x.params)) :: Nil)
-  })
-)
diff --git a/commons/src/main/scala/io/prediction/commons/settings/OfflineEvalResults.scala b/commons/src/main/scala/io/prediction/commons/settings/OfflineEvalResults.scala
deleted file mode 100644
index 69d8ae3..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/OfflineEvalResults.scala
+++ /dev/null
@@ -1,58 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Common
-
-import org.json4s._
-import org.json4s.native.Serialization
-
-/**
- * OfflineEvalResult Object
- *
- * @param evalid ID of the OfflineEval
- * @param metricid ID of the metric
- * @param algoid ID of the algo
- * @param score The offline evaluation score
- * @param iteration The iteration number
- * @param splitset The name of the set used as test data (eg. "test", "validation")
- */
-case class OfflineEvalResult(
-  evalid: Int,
-  metricid: Int,
-  algoid: Int,
-  score: Double,
-  iteration: Int,
-  splitset: String = "")
-
-trait OfflineEvalResults extends Common {
-
-  /** save(update existing or create a new one) a OfflineEvalResult and return id */
-  def save(result: OfflineEvalResult): String
-
-  /** Get all results. */
-  def getAll(): Iterator[OfflineEvalResult]
-
-  /** Get a result by its OfflineEval ID, OfflineEvalMetric ID, and Algo ID. */
-  def getByEvalidAndMetricidAndAlgoid(evalid: Int, metricid: Int, algoid: Int): Iterator[OfflineEvalResult]
-
-  /** get results by OfflineEval ID */
-  def getByEvalid(evalid: Int): Iterator[OfflineEvalResult]
-
-  /** delete all results with this OfflineEval ID */
-  def deleteByEvalid(evalid: Int)
-
-  implicit val formats = Serialization.formats(NoTypeHints)
-
-  /** Backup all OfflineEvalResults as a byte array. */
-  def backup(): Array[Byte] = Serialization.write(getAll().toSeq).getBytes("UTF-8")
-
-  /** Restore OfflineEvalResults from a byte array backup created by the current or the immediate previous version of commons. */
-  def restore(bytes: Array[Byte], inplace: Boolean = false, upgrade: Boolean = false): Option[Seq[OfflineEvalResult]] = {
-    try {
-      val rdata = Serialization.read[Seq[OfflineEvalResult]](new String(bytes, "UTF-8"))
-      if (inplace) rdata foreach { save(_) }
-      Some(rdata)
-    } catch {
-      case e: MappingException => None
-    }
-  }
-}
diff --git a/commons/src/main/scala/io/prediction/commons/settings/OfflineEvalSplitterInfos.scala b/commons/src/main/scala/io/prediction/commons/settings/OfflineEvalSplitterInfos.scala
deleted file mode 100644
index e665a06..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/OfflineEvalSplitterInfos.scala
+++ /dev/null
@@ -1,65 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Common
-
-import org.json4s._
-import org.json4s.native.Serialization
-
-/**
- * OfflineEvalSplitterInfo object.
- *
- * @param id Unique identifier of a splitter.
- * @param name Splitter name.
- * @param description A long description of the splitter.
- * @param engineinfoids A list of EngineInfo IDs that this splitter can apply to.
- * @param commands A sequence of commands to run this metric.
- * @param params Map of Param objects, with keys equal to IDs of Param objects it contains.
- * @param paramsections Seq of ParamSection objects
- * @param paramorder The display order of parameters.
- */
-case class OfflineEvalSplitterInfo(
-  id: String,
-  name: String,
-  description: Option[String],
-  engineinfoids: Seq[String],
-  commands: Option[Seq[String]],
-  params: Map[String, Param],
-  paramsections: Seq[ParamSection],
-  paramorder: Seq[String]) extends Info
-
-/** Base trait for implementations that interact with metric info in the backend data store. */
-trait OfflineEvalSplitterInfos extends Common {
-  /** Inserts a splitter info. */
-  def insert(offlineEvalSplitterInfo: OfflineEvalSplitterInfo): Unit
-
-  /** Get a splitter info by its ID. */
-  def get(id: String): Option[OfflineEvalSplitterInfo]
-
-  /** Get all splitter info. */
-  def getAll(): Seq[OfflineEvalSplitterInfo]
-
-  /** Get all splitter info by engineinfo ID */
-  def getByEngineinfoid(engineinfoid: String): Seq[OfflineEvalSplitterInfo]
-
-  /** Updates a splitter info. */
-  def update(offlineEvalSplitterInfo: OfflineEvalSplitterInfo, upsert: Boolean = false): Unit
-
-  /** Delete a splitter info by its ID. */
-  def delete(id: String): Unit
-
-  implicit val formats = Serialization.formats(NoTypeHints) + new ParamSerializer
-
-  /** Backup all data as a byte array. */
-  def backup(): Array[Byte] = Serialization.write(getAll()).getBytes("UTF-8")
-
-  /** Restore data from a byte array backup created by the current or the immediate previous version of commons. */
-  def restore(bytes: Array[Byte], inplace: Boolean = false, upgrade: Boolean = false): Option[Seq[OfflineEvalSplitterInfo]] = {
-    try {
-      val rdata = Serialization.read[Seq[OfflineEvalSplitterInfo]](new String(bytes, "UTF-8"))
-      if (inplace) rdata foreach { update(_, true) }
-      Some(rdata)
-    } catch {
-      case e: MappingException => None
-    }
-  }
-}
diff --git a/commons/src/main/scala/io/prediction/commons/settings/OfflineEvalSplitters.scala b/commons/src/main/scala/io/prediction/commons/settings/OfflineEvalSplitters.scala
deleted file mode 100644
index cb09e35..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/OfflineEvalSplitters.scala
+++ /dev/null
@@ -1,83 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Common
-
-import org.json4s._
-import org.json4s.native.Serialization
-
-/**
- * OfflineEvalSplitter object.
- *
- * @param id ID.
- * @param evalid Eval ID that owns this split.
- * @param name Split name.
- * @param infoid OfflineEvalSplitInfo ID.
- * @param settings Split settings as key-value pairs.
- */
-case class OfflineEvalSplitter(
-  id: Int,
-  evalid: Int,
-  name: String,
-  infoid: String,
-  settings: Map[String, Any])
-
-/** Base trait for implementations that interact with engines in the backend data store. */
-trait OfflineEvalSplitters extends Common {
-  /** Inserts an offline evaluation splitter. */
-  def insert(splitter: OfflineEvalSplitter): Int
-
-  /** Get an offline evaluation splitter by its ID. */
-  def get(id: Int): Option[OfflineEvalSplitter]
-
-  /** Get all offline evaluation splitters. */
-  def getAll(): Iterator[OfflineEvalSplitter]
-
-  /** Get offline evluation splitters by Offline Eval ID */
-  def getByEvalid(evalid: Int): Iterator[OfflineEvalSplitter]
-
-  /** Update an offline evaluation splitter. */
-  def update(splitter: OfflineEvalSplitter, upsert: Boolean = false)
-
-  /** Delete an offline evaluation splitter by its ID. */
-  def delete(id: Int)
-
-  implicit val formats = Serialization.formats(NoTypeHints) + new OfflineEvalSplitterSerializer
-
-  /** Backup all data as a byte array. */
-  def backup(): Array[Byte] = Serialization.write(getAll().toSeq).getBytes("UTF-8")
-
-  /** Restore data from a byte array backup created by the current or the immediate previous version of commons. */
-  def restore(bytes: Array[Byte], inplace: Boolean = false, upgrade: Boolean = false): Option[Seq[OfflineEvalSplitter]] = {
-    try {
-      val rdata = Serialization.read[Seq[OfflineEvalSplitter]](new String(bytes, "UTF-8"))
-      if (inplace) rdata foreach { update(_, true) }
-      Some(rdata)
-    } catch {
-      case e: MappingException => None
-    }
-  }
-}
-
-/** json4s serializer for the OfflineEvalSplitter class. */
-class OfflineEvalSplitterSerializer extends CustomSerializer[OfflineEvalSplitter](format => (
-  {
-    case x: JObject =>
-      implicit val formats = Serialization.formats(NoTypeHints)
-      OfflineEvalSplitter(
-        id = (x \ "id").extract[Int],
-        evalid = (x \ "evalid").extract[Int],
-        name = (x \ "name").extract[String],
-        infoid = (x \ "infoid").extract[String],
-        settings = Common.sanitize((x \ "settings").asInstanceOf[JObject].values))
-  },
-  {
-    case x: OfflineEvalSplitter =>
-      implicit val formats = Serialization.formats(NoTypeHints)
-      JObject(
-        JField("id", Extraction.decompose(x.id)) ::
-          JField("evalid", Extraction.decompose(x.evalid)) ::
-          JField("name", Extraction.decompose(x.name)) ::
-          JField("infoid", Extraction.decompose(x.infoid)) ::
-          JField("settings", Extraction.decompose(x.settings)) :: Nil)
-  })
-)
diff --git a/commons/src/main/scala/io/prediction/commons/settings/OfflineEvals.scala b/commons/src/main/scala/io/prediction/commons/settings/OfflineEvals.scala
deleted file mode 100644
index aefe12a..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/OfflineEvals.scala
+++ /dev/null
@@ -1,76 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Common
-
-import com.github.nscala_time.time.Imports._
-import org.json4s._
-import org.json4s.native.Serialization
-
-/**
- * OfflineEval object
- *
- * @param id ID.
- * @param engineid The id of Engine object which owns this OfflineEval.
- * @param name The name of the this Offline Evaluation.
- * @param tuneid The OfflineTune ID
- * @param createtime The Creation time of the evaluation
- * @param starttime The Starting time of the evaluation
- * @param endtime The End time of the the evaluation. It's still running if it's None.
- * @param iterations Number of iterations. Default to 1.
- */
-case class OfflineEval(
-  id: Int,
-  engineid: Int,
-  name: String,
-  iterations: Int = 1,
-  tuneid: Option[Int],
-  createtime: Option[DateTime],
-  starttime: Option[DateTime],
-  endtime: Option[DateTime])
-
-trait OfflineEvals extends Common {
-
-  /**
-   * Insert an OfflineEval and return id
-   *
-   * NOTE: can't use id of the offlineEval parameter
-   */
-  def insert(offlineEval: OfflineEval): Int
-
-  /** Get OfflineEval by its id */
-  def get(id: Int): Option[OfflineEval]
-
-  /** Get all OfflineEvals. */
-  def getAll(): Iterator[OfflineEval]
-
-  /** Get OfflineEval by engine id */
-  def getByEngineid(engineid: Int): Iterator[OfflineEval]
-
-  /** Get OfflineEval by offline tune id */
-  def getByTuneid(tuneid: Int): Iterator[OfflineEval]
-
-  /** Get OfflineEval by its ID and engine ID */
-  def getByIdAndEngineid(id: Int, engineid: Int): Option[OfflineEval]
-
-  /** Update OfflineEval (create new one if the it doesn't exist) */
-  def update(offlineEval: OfflineEval, upsert: Boolean = false)
-
-  /** delete OfflineEval by it's id) */
-  def delete(id: Int)
-
-  implicit val formats = Serialization.formats(NoTypeHints) ++ org.json4s.ext.JodaTimeSerializers.all
-
-  /** Backup all data as a byte array. */
-  def backup(): Array[Byte] = Serialization.write(getAll().toSeq).getBytes("UTF-8")
-
-  /** Restore data from a byte array backup created by the current or the immediate previous version of commons. */
-  def restore(bytes: Array[Byte], inplace: Boolean = false, upgrade: Boolean = false): Option[Seq[OfflineEval]] = {
-    try {
-      val rdata = Serialization.read[Seq[OfflineEval]](new String(bytes, "UTF-8"))
-      if (inplace) rdata foreach { update(_, true) }
-      Some(rdata)
-    } catch {
-      case e: MappingException => None
-    }
-  }
-}
diff --git a/commons/src/main/scala/io/prediction/commons/settings/OfflineTunes.scala b/commons/src/main/scala/io/prediction/commons/settings/OfflineTunes.scala
deleted file mode 100644
index 7132966..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/OfflineTunes.scala
+++ /dev/null
@@ -1,62 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Common
-
-import com.github.nscala_time.time.Imports._
-import org.json4s._
-import org.json4s.native.Serialization
-
-/**
- * OfflineTune Object
- *
- * @param id Id
- * @param engineid The Engine ID
- * @param loops Number of offline tune loops
- * @param createtime The Creation time of the offline tune
- * @param starttime The Starting time of the offline tune
- * @param endtime The End time of the the offline tune
- */
-case class OfflineTune(
-  id: Int,
-  engineid: Int,
-  loops: Int,
-  createtime: Option[DateTime],
-  starttime: Option[DateTime],
-  endtime: Option[DateTime])
-
-trait OfflineTunes extends Common {
-
-  /** Insert an OfflineTune and return its ID. */
-  def insert(offlineTune: OfflineTune): Int
-
-  /** Get OfflineTune by its ID. */
-  def get(id: Int): Option[OfflineTune]
-
-  /** Get all OfflineTunes. */
-  def getAll(): Iterator[OfflineTune]
-
-  /** Get OfflineTune's by Engine ID. */
-  def getByEngineid(engineid: Int): Iterator[OfflineTune]
-
-  /** Update OfflineTune (create new one if the it doesn't exist). */
-  def update(offlineTune: OfflineTune, upsert: Boolean = false)
-
-  /** Delete OfflineTune by its ID. */
-  def delete(id: Int)
-
-  implicit val formats = Serialization.formats(NoTypeHints) ++ org.json4s.ext.JodaTimeSerializers.all
-
-  /** Backup all data as a byte array. */
-  def backup(): Array[Byte] = Serialization.write(getAll().toSeq).getBytes("UTF-8")
-
-  /** Restore data from a byte array backup created by the current or the immediate previous version of commons. */
-  def restore(bytes: Array[Byte], inplace: Boolean = false, upgrade: Boolean = false): Option[Seq[OfflineTune]] = {
-    try {
-      val rdata = Serialization.read[Seq[OfflineTune]](new String(bytes, "UTF-8"))
-      if (inplace) rdata foreach { update(_, true) }
-      Some(rdata)
-    } catch {
-      case e: MappingException => None
-    }
-  }
-}
diff --git a/commons/src/main/scala/io/prediction/commons/settings/Param.scala b/commons/src/main/scala/io/prediction/commons/settings/Param.scala
deleted file mode 100644
index 4a7b134..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/Param.scala
+++ /dev/null
@@ -1,174 +0,0 @@
-package io.prediction.commons.settings
-
-import org.json4s._
-import org.json4s.native.JsonMethods._
-import org.json4s.native.Serialization
-
-/**
- * Contains metadata for a parameter that is used in an Info object.
- *
- * @param id ID.
- * @param name Parameter name.
- * @param description Parameter description.
- * @param defaultvalue Default value of the parameter.
- * @param constraint Constraint of the parameter.
- * @param ui UI information of the parameter.
- * @param scopes Scopes where this parameter is required.
- */
-case class Param(
-  id: String,
-  name: String,
-  description: Option[String],
-  defaultvalue: Any,
-  constraint: ParamConstraint,
-  ui: ParamUI,
-  scopes: Option[Set[String]] = None)
-
-/**
- * Base trait for a parameter constraint.
- */
-trait ParamConstraint {
-  /**
-   * Parameter type.
-   * Can be "boolean", "double", "integer", "long", or "string".
-   */
-  def paramtype: String
-}
-
-/**
- * Indicates a parameter of type Boolean.
- */
-case class ParamBooleanConstraint(paramtype: String = "boolean")
-  extends ParamConstraint
-
-/**
- * Indicates a parameter of type Double.
- *
- * @param min Minimum allowed value.
- * @param max Maximum allowed value.
- */
-case class ParamDoubleConstraint(
-  paramtype: String = "double",
-  min: Option[Double] = None,
-  max: Option[Double] = None)
-    extends ParamConstraint
-
-/**
- * Indicates a parameter of type Int.
- *
- * @param min Minimum allowed value.
- * @param max Maximum allowed value.
- */
-case class ParamIntegerConstraint(
-  paramtype: String = "integer",
-  min: Option[Int] = None,
-  max: Option[Int] = None)
-    extends ParamConstraint
-
-/**
- * Indicates a parameter of type Long.
- *
- * @param min Minimum allowed value.
- * @param max Maximum allowed value.
- */
-case class ParamLongConstraint(
-  paramtype: String = "long",
-  min: Option[Long] = None,
-  max: Option[Long] = None)
-    extends ParamConstraint
-
-/**
- * Indicates a parameter of type String.
- */
-case class ParamStringConstraint(paramtype: String = "string")
-  extends ParamConstraint
-
-/**
- * Defines the parameter's user interface that will be used in the
- * administration user interface.
- *
- * @param uitype User interface type. Can be "text", "slider", and "selection".
- * @param selections List of selectable items to be displayed when UI type is
- *                   "selection".
- * @param slidermin Minimum value of the slider when UI type is "slider".
- * @param slidermax Maximum value of the slider when UI type is "slider".
- * @param sliderstep Step size of the slider when UI type is "slider".
- */
-case class ParamUI(
-  uitype: String = "text",
-  selections: Option[Seq[ParamSelectionUI]] = None,
-  slidermin: Option[Int] = None,
-  slidermax: Option[Int] = None,
-  sliderstep: Option[Int] = None)
-
-/**
- * A selectable item for the selection user interface.
- *
- * @param value Selection's value.
- * @param name Selection's name.
- */
-case class ParamSelectionUI(value: String, name: String)
-
-/**
- * Defines a section that contains parameters to be displayed in the user
- * interface.
- *
- * @param name Section's name.
- * @param sectiontype Section's type. Can be "normal" and "tuning".
- * @param description Section's description.
- * @param subsections A list of subsections.
- * @param params A list of parameters of this section.
- */
-case class ParamSection(
-  name: String,
-  sectiontype: String = "normal",
-  description: Option[String] = None,
-  subsections: Option[Seq[ParamSection]] = None,
-  params: Option[Seq[String]] = None)
-
-/** json4s serializer for the Param class. */
-class ParamSerializer extends CustomSerializer[Param](format => (
-  {
-    case x: JObject =>
-      implicit val formats = Serialization.formats(ShortTypeHints(List(
-        classOf[ParamBooleanConstraint],
-        classOf[ParamDoubleConstraint],
-        classOf[ParamIntegerConstraint],
-        classOf[ParamLongConstraint],
-        classOf[ParamStringConstraint])))
-      val constraint = (x \ "constraint").extract[ParamConstraint]
-      val dv = x \ "defaultvalue"
-      val defaultvalue = constraint match {
-        case c: ParamBooleanConstraint => dv.extract[Boolean]
-        case c: ParamDoubleConstraint => dv.extract[Double]
-        case c: ParamIntegerConstraint => dv.extract[Int]
-        case c: ParamLongConstraint => dv.extract[Long]
-        case c: ParamStringConstraint => dv.extract[String]
-      }
-      Param(
-        id = (x \ "id").extract[String],
-        name = (x \ "name").extract[String],
-        description = (x \ "description").extract[Option[String]],
-        defaultvalue = defaultvalue,
-        constraint = constraint,
-        ui = (x \ "ui").extract[ParamUI],
-        scopes = (x \ "scopes").extract[Option[Set[String]]])
-  },
-  {
-    case p: Param =>
-      implicit val formats = Serialization.formats(ShortTypeHints(List(
-        classOf[ParamBooleanConstraint],
-        classOf[ParamDoubleConstraint],
-        classOf[ParamIntegerConstraint],
-        classOf[ParamLongConstraint],
-        classOf[ParamStringConstraint])))
-      JObject(
-        JField("id", Extraction.decompose(p.id)) ::
-          JField("name", Extraction.decompose(p.name)) ::
-          JField("description", Extraction.decompose(p.description)) ::
-          JField("defaultvalue", Extraction.decompose(p.defaultvalue)) ::
-          JField("constraint", Extraction.decompose(p.constraint)) ::
-          JField("ui", Extraction.decompose(p.ui)) ::
-          JField("scopes", Extraction.decompose(p.scopes)) :: Nil)
-  })
-)
diff --git a/commons/src/main/scala/io/prediction/commons/settings/ParamGenInfos.scala b/commons/src/main/scala/io/prediction/commons/settings/ParamGenInfos.scala
deleted file mode 100644
index 3513e8f..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/ParamGenInfos.scala
+++ /dev/null
@@ -1,92 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Common
-
-import org.json4s._
-import org.json4s.native.Serialization
-
-/**
- * ParamGenInfo object.
- *
- * @param id Unique identifier of a parameter generator.
- * @param name Generator name.
- * @param description A long description of the generator.
- * @param commands A sequence of commands to run this generator.
- * @param paramdefaults Default parameters as key-value pairs. Usually used by substituting template variables in command templates.
- * @param paramnames Key value paris of (parameter -> display name).
- * @param paramdescription Key value paris of (parameter -> description).
- * @param paramorder The display order of parameters.
- */
-case class ParamGenInfo(
-  id: String,
-  name: String,
-  description: Option[String],
-  commands: Option[Seq[String]],
-  paramdefaults: Map[String, Any],
-  paramnames: Map[String, String],
-  paramdescription: Map[String, String],
-  paramorder: Seq[String])
-
-/** Base trait for implementations that interact with parameter generator info in the backend data store. */
-trait ParamGenInfos extends Common {
-  /** Inserts a parameter generator info. */
-  def insert(paramGenInfo: ParamGenInfo): Unit
-
-  /** Get a parameter generator info by its ID. */
-  def get(id: String): Option[ParamGenInfo]
-
-  /** Get all parameter generator info. */
-  def getAll(): Seq[ParamGenInfo]
-
-  /** Updates a parameter generator info. */
-  def update(paramGenInfo: ParamGenInfo, upsert: Boolean = false): Unit
-
-  /** Delete a parameter generator info by its ID. */
-  def delete(id: String): Unit
-
-  implicit val formats = Serialization.formats(NoTypeHints) + new ParamGenInfoSerializer
-
-  /** Backup all data as a byte array. */
-  def backup(): Array[Byte] = Serialization.write(getAll()).getBytes("UTF-8")
-
-  /** Restore data from a byte array backup created by the current or the immediate previous version of commons. */
-  def restore(bytes: Array[Byte], inplace: Boolean = false, upgrade: Boolean = false): Option[Seq[ParamGenInfo]] = {
-    try {
-      val rdata = Serialization.read[Seq[ParamGenInfo]](new String(bytes, "UTF-8"))
-      if (inplace) rdata foreach { update(_, true) }
-      Some(rdata)
-    } catch {
-      case e: MappingException => None
-    }
-  }
-}
-
-/** json4s serializer for the OfflineEvalSplitterInfo class. */
-class ParamGenInfoSerializer extends CustomSerializer[ParamGenInfo](format => (
-  {
-    case x: JObject =>
-      implicit val formats = Serialization.formats(NoTypeHints)
-      ParamGenInfo(
-        id = (x \ "id").extract[String],
-        name = (x \ "name").extract[String],
-        description = (x \ "description").extract[Option[String]],
-        commands = (x \ "commands").extract[Option[Seq[String]]],
-        paramdefaults = Common.sanitize((x \ "paramdefaults").asInstanceOf[JObject].values),
-        paramnames = (x \ "paramnames").extract[Map[String, String]],
-        paramdescription = (x \ "paramdescription").extract[Map[String, String]],
-        paramorder = (x \ "paramorder").extract[Seq[String]])
-  },
-  {
-    case x: ParamGenInfo =>
-      implicit val formats = Serialization.formats(NoTypeHints)
-      JObject(
-        JField("id", Extraction.decompose(x.id)) ::
-          JField("name", Extraction.decompose(x.name)) ::
-          JField("description", Extraction.decompose(x.description)) ::
-          JField("commands", Extraction.decompose(x.commands)) ::
-          JField("paramdefaults", Extraction.decompose(x.paramdefaults)) ::
-          JField("paramnames", Extraction.decompose(x.paramnames)) ::
-          JField("paramdescription", Extraction.decompose(x.paramdescription)) ::
-          JField("paramorder", Extraction.decompose(x.paramorder)) :: Nil)
-  })
-)
diff --git a/commons/src/main/scala/io/prediction/commons/settings/ParamGens.scala b/commons/src/main/scala/io/prediction/commons/settings/ParamGens.scala
deleted file mode 100644
index a8a0e92..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/ParamGens.scala
+++ /dev/null
@@ -1,79 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Common
-
-import org.json4s._
-import org.json4s.native.Serialization
-
-/**
- * ParamGen Object
- *
- * @param id ID
- * @param infoid param gen info id
- * @param tuneid ID of the OfflineTune
- * @param params param gen parameters as key-value pairs
- */
-case class ParamGen(
-  id: Int,
-  infoid: String,
-  tuneid: Int,
-  params: Map[String, Any])
-
-trait ParamGens extends Common {
-
-  /** Insert a paramGen and return ID */
-  def insert(paramGen: ParamGen): Int
-
-  /** Get a paramGen by its ID */
-  def get(id: Int): Option[ParamGen]
-
-  /** Get all parameter generators. */
-  def getAll(): Iterator[ParamGen]
-
-  /** Get paramGen by offline tune ID */
-  def getByTuneid(tuneid: Int): Iterator[ParamGen]
-
-  /** Update paramGen */
-  def update(paramGen: ParamGen, upsert: Boolean = false)
-
-  /** Delete paramGen by its ID */
-  def delete(id: Int)
-
-  implicit val formats = Serialization.formats(NoTypeHints) + new ParamGenSerializer
-
-  /** Backup all data as a byte array. */
-  def backup(): Array[Byte] = Serialization.write(getAll().toSeq).getBytes("UTF-8")
-
-  /** Restore data from a byte array backup created by the current or the immediate previous version of commons. */
-  def restore(bytes: Array[Byte], inplace: Boolean = false, upgrade: Boolean = false): Option[Seq[ParamGen]] = {
-    try {
-      val rdata = Serialization.read[Seq[ParamGen]](new String(bytes, "UTF-8"))
-      if (inplace) rdata foreach { update(_, true) }
-      Some(rdata)
-    } catch {
-      case e: MappingException => None
-    }
-  }
-}
-
-/** json4s serializer for the ParamGen class. */
-class ParamGenSerializer extends CustomSerializer[ParamGen](format => (
-  {
-    case x: JObject =>
-      implicit val formats = Serialization.formats(NoTypeHints)
-      ParamGen(
-        id = (x \ "id").extract[Int],
-        infoid = (x \ "infoid").extract[String],
-        tuneid = (x \ "tuneid").extract[Int],
-        params = Common.sanitize((x \ "params").asInstanceOf[JObject].values))
-  },
-  {
-    case x: ParamGen =>
-      implicit val formats = Serialization.formats(NoTypeHints)
-      JObject(
-        JField("id", Extraction.decompose(x.id)) ::
-          JField("infoid", Extraction.decompose(x.infoid)) ::
-          JField("tuneid", Extraction.decompose(x.tuneid)) ::
-          JField("params", Extraction.decompose(x.params)) :: Nil)
-  })
-)
diff --git a/commons/src/main/scala/io/prediction/commons/settings/SystemInfos.scala b/commons/src/main/scala/io/prediction/commons/settings/SystemInfos.scala
deleted file mode 100644
index b46f0e5..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/SystemInfos.scala
+++ /dev/null
@@ -1,52 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Common
-
-import org.json4s._
-import org.json4s.native.Serialization
-
-/**
- * SystemInfo object.
- *
- * @param id Unique identifier of the info entry.
- * @param value Value of the info entry.
- * @param description A long description of the info entry.
- */
-case class SystemInfo(
-  id: String,
-  value: String,
-  description: Option[String])
-
-/** Base trait for implementations that interact with system info in the backend data store. */
-trait SystemInfos extends Common {
-  /** Inserts a system info entry. */
-  def insert(systemInfo: SystemInfo): Unit
-
-  /** Get system info entry by its ID. */
-  def get(id: String): Option[SystemInfo]
-
-  /** Get all system info entries. */
-  def getAll(): Seq[SystemInfo]
-
-  /** Updates a system info entry. */
-  def update(systemInfo: SystemInfo, upsert: Boolean = false): Unit
-
-  /** Delete a system info entry by its ID. */
-  def delete(id: String): Unit
-
-  implicit val formats = Serialization.formats(NoTypeHints)
-
-  /** Backup all data as a byte array. */
-  def backup(): Array[Byte] = Serialization.write(getAll()).getBytes("UTF-8")
-
-  /** Restore data from a byte array backup created by the current or the immediate previous version of commons. */
-  def restore(bytes: Array[Byte], inplace: Boolean = false, upgrade: Boolean = false): Option[Seq[SystemInfo]] = {
-    try {
-      val rdata = Serialization.read[Seq[SystemInfo]](new String(bytes, "UTF-8"))
-      if (inplace) rdata foreach { update(_, true) }
-      Some(rdata)
-    } catch {
-      case e: MappingException => None
-    }
-  }
-}
diff --git a/commons/src/main/scala/io/prediction/commons/settings/Users.scala b/commons/src/main/scala/io/prediction/commons/settings/Users.scala
deleted file mode 100644
index f5bd2c4..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/Users.scala
+++ /dev/null
@@ -1,84 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Common
-
-import org.json4s._
-import org.json4s.native.Serialization
-
-/**
- * User object.
- *
- * @param id ID.
- * @param firstName First name.
- * @param lastName Last name.
- * @param email E-mail.
- */
-case class User(
-  id: Int,
-  firstName: String,
-  lastName: Option[String],
-  email: String,
-  password: String = "",
-  confirm: Option[String] = None)
-
-/** Base trait for implementations that interact with users in the backend data store. */
-trait Users extends Common {
-  /** Authenticate a user by ID and password. */
-  def authenticate(id: Int, password: String): Boolean
-
-  /** Authenticate a user by e-mail and password. */
-  def authenticateByEmail(email: String, password: String): Option[Int]
-
-  /** Inserts a new user. */
-  def insert(email: String, password: String, firstname: String, lastname: Option[String], confirm: String): Int
-
-  /** Finds a user by ID. */
-  def get(id: Int): Option[User]
-
-  /** Finds all users. */
-  def getAll(): Iterator[User]
-
-  /** Finds a user by e-mail. */
-  def getByEmail(email: String): Option[User]
-
-  /** Update a user. */
-  def update(user: User, upsert: Boolean = false)
-
-  /** Update email address by ID. */
-  def updateEmail(id: Int, email: String)
-
-  /** Update password by ID. */
-  def updatePassword(id: Int, password: String)
-
-  /**
-   * Update password by e-mail.
-   *
-   * Note: For reset password requests.
-   */
-  def updatePasswordByEmail(email: String, password: String)
-
-  /** Confirms a new user. */
-  def confirm(confirm: String): Option[User]
-
-  /** Check if an e-mail address exists. */
-  def emailExists(email: String): Boolean
-
-  /** Check if an ID and e-mail combination exists. */
-  def idAndEmailExists(userid: Int, email: String): Boolean
-
-  implicit val formats = Serialization.formats(NoTypeHints)
-
-  /** Backup all data as a byte array. */
-  def backup(): Array[Byte] = Serialization.write(getAll().toSeq).getBytes("UTF-8")
-
-  /** Restore data from a byte array backup created by the current or the immediate previous version of commons. */
-  def restore(bytes: Array[Byte], inplace: Boolean = false, upgrade: Boolean = false): Option[Seq[User]] = {
-    try {
-      val rdata = Serialization.read[Seq[User]](new String(bytes, "UTF-8"))
-      if (inplace) rdata foreach { update(_, true) }
-      Some(rdata)
-    } catch {
-      case e: MappingException => None
-    }
-  }
-}
diff --git a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoAlgoInfos.scala b/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoAlgoInfos.scala
deleted file mode 100644
index 7516a38..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoAlgoInfos.scala
+++ /dev/null
@@ -1,74 +0,0 @@
-package io.prediction.commons.settings.mongodb
-
-import io.prediction.commons.MongoUtils
-import io.prediction.commons.settings.{ AlgoInfo, AlgoInfos, Param }
-
-import com.mongodb.casbah.Imports._
-
-/** MongoDB implementation of AlgoInfos. */
-class MongoAlgoInfos(db: MongoDB) extends AlgoInfos {
-  private val coll = db("algoInfos")
-
-  private def dbObjToAlgoInfo(dbObj: DBObject) = {
-    AlgoInfo(
-      id = dbObj.as[String]("_id"),
-      name = dbObj.as[String]("name"),
-      description = dbObj.getAs[String]("description"),
-      batchcommands = dbObj.getAs[MongoDBList]("batchcommands") map { MongoUtils.mongoDbListToListOfString(_) },
-      offlineevalcommands = dbObj.getAs[MongoDBList]("offlineevalcommands") map { MongoUtils.mongoDbListToListOfString(_) },
-      params = (dbObj.as[DBObject]("params") map { p => (p._1, MongoParam.dbObjToParam(p._1, p._2.asInstanceOf[DBObject])) }).toMap,
-      paramsections = dbObj.as[Seq[DBObject]]("paramsections") map { MongoParam.dbObjToParamSection(_) },
-      paramorder = MongoUtils.mongoDbListToListOfString(dbObj.as[MongoDBList]("paramorder")),
-      engineinfoid = dbObj.as[String]("engineinfoid"),
-      techreq = MongoUtils.mongoDbListToListOfString(dbObj.as[MongoDBList]("techreq")),
-      datareq = MongoUtils.mongoDbListToListOfString(dbObj.as[MongoDBList]("datareq")),
-      capabilities = dbObj.getAs[MongoDBList]("capabilities") map { MongoUtils.mongoDbListToListOfString(_) } getOrElse Seq[String]())
-  }
-
-  def insert(algoInfo: AlgoInfo) = {
-    // required fields
-    val obj = MongoDBObject(
-      "_id" -> algoInfo.id,
-      "name" -> algoInfo.name,
-      "params" -> (algoInfo.params mapValues { MongoParam.paramToDBObj(_) }),
-      "paramsections" -> (algoInfo.paramsections map { MongoParam.paramSectionToDBObj(_) }),
-      "paramorder" -> algoInfo.paramorder,
-      "engineinfoid" -> algoInfo.engineinfoid,
-      "techreq" -> algoInfo.techreq,
-      "datareq" -> algoInfo.datareq,
-      "capabilities" -> algoInfo.capabilities)
-
-    // optional fields
-    val descriptionObj = algoInfo.description.map { d => MongoDBObject("description" -> d) } getOrElse MongoUtils.emptyObj
-    val batchcommandsObj = algoInfo.batchcommands.map { c => MongoDBObject("batchcommands" -> c) } getOrElse MongoUtils.emptyObj
-    val offlineevalcommandsObj = algoInfo.offlineevalcommands.map { c => MongoDBObject("offlineevalcommands" -> c) } getOrElse MongoUtils.emptyObj
-
-    coll.insert(obj ++ descriptionObj ++ batchcommandsObj ++ offlineevalcommandsObj)
-  }
-
-  def get(id: String) = coll.findOne(MongoDBObject("_id" -> id)) map { dbObjToAlgoInfo(_) }
-
-  def getAll() = coll.find().toSeq map { dbObjToAlgoInfo(_) }
-
-  def getByEngineInfoId(engineinfoid: String) = coll.find(MongoDBObject("engineinfoid" -> engineinfoid)).sort(MongoDBObject("_id" -> 1)).toSeq map { dbObjToAlgoInfo(_) }
-
-  def update(algoInfo: AlgoInfo, upsert: Boolean = false) = {
-    val idObj = MongoDBObject("_id" -> algoInfo.id)
-    val requiredObj = MongoDBObject(
-      "name" -> algoInfo.name,
-      "params" -> (algoInfo.params mapValues { MongoParam.paramToDBObj(_) }),
-      "paramsections" -> (algoInfo.paramsections map { MongoParam.paramSectionToDBObj(_) }),
-      "paramorder" -> algoInfo.paramorder,
-      "engineinfoid" -> algoInfo.engineinfoid,
-      "techreq" -> algoInfo.techreq,
-      "datareq" -> algoInfo.datareq,
-      "capabilities" -> algoInfo.capabilities)
-    val descriptionObj = algoInfo.description.map { d => MongoDBObject("description" -> d) } getOrElse MongoUtils.emptyObj
-    val batchcommandsObj = algoInfo.batchcommands.map { c => MongoDBObject("batchcommands" -> c) } getOrElse MongoUtils.emptyObj
-    val offlineevalcommandsObj = algoInfo.offlineevalcommands.map { c => MongoDBObject("offlineevalcommands" -> c) } getOrElse MongoUtils.emptyObj
-
-    coll.update(idObj, idObj ++ requiredObj ++ descriptionObj ++ batchcommandsObj ++ offlineevalcommandsObj, upsert)
-  }
-
-  def delete(id: String) = coll.remove(MongoDBObject("_id" -> id))
-}
diff --git a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoAlgos.scala b/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoAlgos.scala
deleted file mode 100644
index a95b213..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoAlgos.scala
+++ /dev/null
@@ -1,121 +0,0 @@
-package io.prediction.commons.settings.mongodb
-
-import io.prediction.commons.MongoUtils
-import io.prediction.commons.settings.{ Algo, Algos }
-
-import com.mongodb.casbah.Imports._
-import com.mongodb.casbah.commons.conversions.scala.RegisterJodaTimeConversionHelpers
-import com.github.nscala_time.time.Imports._
-
-/** MongoDB implementation of Algos. */
-class MongoAlgos(db: MongoDB) extends Algos {
-  private val algoColl = db("algos")
-  private val seq = new MongoSequences(db)
-
-  RegisterJodaTimeConversionHelpers()
-
-  private def dbObjToAlgo(dbObj: DBObject) = {
-    Algo(
-      id = dbObj.as[Int]("_id"),
-      engineid = dbObj.as[Int]("engineid"),
-      name = dbObj.as[String]("name"),
-      infoid = dbObj.getAs[String]("infoid").getOrElse("pdio-knnitembased"), // TODO: tempararily default for backward compatiblity
-      command = dbObj.as[String]("command"),
-      params = MongoUtils.dbObjToMap(dbObj.as[DBObject]("params")),
-      settings = MongoUtils.dbObjToMap(dbObj.as[DBObject]("settings")),
-      modelset = dbObj.as[Boolean]("modelset"),
-      createtime = dbObj.as[DateTime]("createtime"),
-      updatetime = dbObj.as[DateTime]("updatetime"),
-      status = dbObj.as[String]("status"),
-      offlineevalid = dbObj.getAs[Int]("offlineevalid"),
-      offlinetuneid = dbObj.getAs[Int]("offlinetuneid"),
-      loop = dbObj.getAs[Int]("loop"),
-      paramset = dbObj.getAs[Int]("paramset"),
-      lasttraintime = dbObj.getAs[DateTime]("lasttraintime"))
-  }
-
-  def insert(algo: Algo) = {
-    val id = seq.genNext("algoid")
-
-    // required fields
-    val obj = MongoDBObject(
-      "_id" -> id,
-      "engineid" -> algo.engineid,
-      "name" -> algo.name,
-      "infoid" -> algo.infoid,
-      "command" -> algo.command,
-      "params" -> algo.params,
-      "settings" -> algo.settings,
-      "modelset" -> algo.modelset,
-      "createtime" -> algo.createtime,
-      "updatetime" -> algo.updatetime,
-      "status" -> algo.status)
-
-    // optional fields
-    val optObj = algo.offlineevalid.map(x => MongoDBObject("offlineevalid" -> x)).getOrElse(MongoUtils.emptyObj) ++
-      algo.offlinetuneid.map(x => MongoDBObject("offlinetuneid" -> x)).getOrElse(MongoUtils.emptyObj) ++
-      algo.loop.map(x => MongoDBObject("loop" -> x)).getOrElse(MongoUtils.emptyObj) ++
-      algo.paramset.map(x => MongoDBObject("paramset" -> x)).getOrElse(MongoUtils.emptyObj) ++
-      algo.lasttraintime.map(x => MongoDBObject("lasttraintime" -> x)).getOrElse(MongoUtils.emptyObj)
-
-    algoColl.insert(obj ++ optObj)
-
-    id
-  }
-
-  def get(id: Int) = algoColl.findOne(MongoDBObject("_id" -> id)) map { dbObjToAlgo(_) }
-
-  def getAll() = new MongoAlgoIterator(algoColl.find())
-
-  def getByEngineid(engineid: Int) = new MongoAlgoIterator(
-    algoColl.find(MongoDBObject("engineid" -> engineid)).sort(MongoDBObject("name" -> 1))
-  )
-
-  def getDeployedByEngineid(engineid: Int) = new MongoAlgoIterator(
-    algoColl.find(MongoDBObject("engineid" -> engineid, "status" -> "deployed")).sort(MongoDBObject("name" -> 1))
-  )
-
-  def getByOfflineEvalid(evalid: Int, loop: Option[Int] = None, paramset: Option[Int] = None) = {
-    val q = MongoDBObject("offlineevalid" -> evalid) ++ loop.map(l => MongoDBObject("loop" -> l)).getOrElse(MongoUtils.emptyObj) ++ paramset.map(p => MongoDBObject("paramset" -> p)).getOrElse(MongoUtils.emptyObj)
-    new MongoAlgoIterator(algoColl.find(q).sort(MongoDBObject("name" -> 1)))
-  }
-
-  def getTuneSubjectByOfflineTuneid(tuneid: Int) = algoColl.findOne(MongoDBObject("offlinetuneid" -> tuneid, "loop" -> null, "paramset" -> null)) map { dbObjToAlgo(_) }
-
-  def getByIdAndEngineid(id: Int, engineid: Int): Option[Algo] = algoColl.findOne(MongoDBObject("_id" -> id, "engineid" -> engineid)) map { dbObjToAlgo(_) }
-
-  def update(algo: Algo, upsert: Boolean = false) = {
-
-    // required fields
-    val obj = MongoDBObject(
-      "_id" -> algo.id,
-      "engineid" -> algo.engineid,
-      "name" -> algo.name,
-      "infoid" -> algo.infoid,
-      "command" -> algo.command,
-      "params" -> algo.params,
-      "settings" -> algo.settings,
-      "modelset" -> algo.modelset,
-      "createtime" -> algo.createtime,
-      "updatetime" -> algo.updatetime,
-      "status" -> algo.status)
-
-    // optional fields
-    val optObj = algo.offlineevalid.map(x => MongoDBObject("offlineevalid" -> x)).getOrElse(MongoUtils.emptyObj) ++
-      algo.offlinetuneid.map(x => MongoDBObject("offlinetuneid" -> x)).getOrElse(MongoUtils.emptyObj) ++
-      algo.loop.map(x => MongoDBObject("loop" -> x)).getOrElse(MongoUtils.emptyObj) ++
-      algo.paramset.map(x => MongoDBObject("paramset" -> x)).getOrElse(MongoUtils.emptyObj) ++
-      algo.lasttraintime.map(x => MongoDBObject("lasttraintime" -> x)).getOrElse(MongoUtils.emptyObj)
-
-    algoColl.update(MongoDBObject("_id" -> algo.id), obj ++ optObj, upsert)
-  }
-
-  def delete(id: Int) = algoColl.remove(MongoDBObject("_id" -> id))
-
-  def existsByEngineidAndName(engineid: Int, name: String) = algoColl.findOne(MongoDBObject("name" -> name, "engineid" -> engineid, "offlineevalid" -> null)) map { _ => true } getOrElse false
-
-  class MongoAlgoIterator(it: MongoCursor) extends Iterator[Algo] {
-    def next = dbObjToAlgo(it.next)
-    def hasNext = it.hasNext
-  }
-}
diff --git a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoApps.scala b/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoApps.scala
deleted file mode 100644
index 264476e..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoApps.scala
+++ /dev/null
@@ -1,89 +0,0 @@
-package io.prediction.commons.settings.mongodb
-
-import io.prediction.commons.settings.{ App, Apps }
-
-import com.mongodb.casbah.Imports._
-import com.mongodb.casbah.WriteConcern
-
-/** MongoDB implementation of Apps. */
-class MongoApps(db: MongoDB) extends Apps {
-  private val emptyObj = MongoDBObject()
-  private val appColl = db("apps")
-  private val seq = new MongoSequences(db)
-  private val getFields = MongoDBObject("userid" -> 1, "appkey" -> 1, "display" -> 1, "url" -> 1, "cat" -> 1, "desc" -> 1, "timezone" -> 1)
-
-  appColl.setWriteConcern(WriteConcern.JournalSafe)
-
-  private def dbObjToApp(dbObj: DBObject) = {
-    App(
-      id = dbObj.as[Int]("_id"),
-      userid = dbObj.as[Int]("userid"),
-      appkey = dbObj.as[String]("appkey"),
-      display = dbObj.as[String]("display"),
-      url = dbObj.getAs[String]("url"),
-      cat = dbObj.getAs[String]("cat"),
-      desc = dbObj.getAs[String]("desc"),
-      timezone = dbObj.as[String]("timezone")
-    )
-  }
-
-  class MongoAppIterator(it: MongoCursor) extends Iterator[App] {
-    def next = dbObjToApp(it.next)
-    def hasNext = it.hasNext
-  }
-
-  def insert(app: App) = {
-    val id = seq.genNext("appid")
-    val must = MongoDBObject(
-      "_id" -> id,
-      "userid" -> app.userid,
-      "appkey" -> app.appkey,
-      "display" -> app.display,
-      "timezone" -> app.timezone
-    )
-    val url = app.url map { url => MongoDBObject("url" -> url) } getOrElse emptyObj
-    val cat = app.cat map { cat => MongoDBObject("cat" -> cat) } getOrElse emptyObj
-    val desc = app.desc map { desc => MongoDBObject("desc" -> desc) } getOrElse emptyObj
-
-    appColl.insert(must ++ url ++ cat ++ desc)
-    id
-  }
-
-  def get(id: Int) = appColl.findOne(MongoDBObject("_id" -> id), getFields) map { dbObjToApp(_) }
-
-  def getAll() = new MongoAppIterator(appColl.find())
-
-  def getByUserid(userid: Int) = new MongoAppIterator(appColl.find(MongoDBObject("userid" -> userid), getFields))
-
-  def getByAppkey(appkey: String) = appColl.findOne(MongoDBObject("appkey" -> appkey), getFields) map { dbObjToApp(_) }
-
-  def getByAppkeyAndUserid(appkey: String, userid: Int) = appColl.findOne(MongoDBObject("appkey" -> appkey, "userid" -> userid), getFields) map { dbObjToApp(_) }
-
-  def getByIdAndUserid(id: Int, userid: Int) = appColl.findOne(MongoDBObject("_id" -> id, "userid" -> userid), getFields) map { dbObjToApp(_) }
-
-  def update(app: App, upsert: Boolean = false) = {
-    val must = MongoDBObject(
-      "_id" -> app.id,
-      "userid" -> app.userid,
-      "appkey" -> app.appkey,
-      "display" -> app.display,
-      "timezone" -> app.timezone)
-    val url = app.url map { url => MongoDBObject("url" -> url) } getOrElse emptyObj
-    val cat = app.cat map { cat => MongoDBObject("cat" -> cat) } getOrElse emptyObj
-    val desc = app.desc map { desc => MongoDBObject("desc" -> desc) } getOrElse emptyObj
-
-    appColl.update(MongoDBObject("_id" -> app.id), must ++ url ++ cat ++ desc, upsert)
-  }
-
-  def updateAppkeyByAppkeyAndUserid(appkey: String, userid: Int, newAppkey: String) = {
-    appColl.findAndModify(MongoDBObject("appkey" -> appkey, "userid" -> userid), MongoDBObject("$set" -> MongoDBObject("appkey" -> newAppkey))) map { dbObjToApp(_) }
-  }
-
-  def updateTimezoneByAppkeyAndUserid(appkey: String, userid: Int, timezone: String) = {
-    appColl.findAndModify(MongoDBObject("appkey" -> appkey, "userid" -> userid), MongoDBObject("$set" -> MongoDBObject("timezone" -> timezone))) map { dbObjToApp(_) }
-  }
-
-  def deleteByIdAndUserid(id: Int, userid: Int) = appColl.remove(MongoDBObject("_id" -> id, "userid" -> userid))
-
-  def existsByIdAndAppkeyAndUserid(id: Int, appkey: String, userid: Int) = appColl.findOne(MongoDBObject("_id" -> id, "appkey" -> appkey, "userid" -> userid)) map { _ => true } getOrElse false
-}
diff --git a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoEngineInfos.scala b/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoEngineInfos.scala
deleted file mode 100644
index 8655c20..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoEngineInfos.scala
+++ /dev/null
@@ -1,58 +0,0 @@
-package io.prediction.commons.settings.mongodb
-
-import io.prediction.commons.MongoUtils
-import io.prediction.commons.settings.{ EngineInfo, EngineInfos }
-
-import com.mongodb.casbah.Imports._
-
-/** MongoDB implementation of EngineInfos. */
-class MongoEngineInfos(db: MongoDB) extends EngineInfos {
-  private val coll = db("engineInfos")
-
-  private def dbObjToEngineInfo(dbObj: DBObject) = EngineInfo(
-    id = dbObj.as[String]("_id"),
-    name = dbObj.as[String]("name"),
-    description = dbObj.getAs[String]("description"),
-    params = (dbObj.as[DBObject]("params") map { p => (p._1, MongoParam.dbObjToParam(p._1, p._2.asInstanceOf[DBObject])) }).toMap,
-    paramsections = dbObj.as[Seq[DBObject]]("paramsections") map { MongoParam.dbObjToParamSection(_) },
-    defaultalgoinfoid = dbObj.as[String]("defaultalgoinfoid"),
-    defaultofflineevalmetricinfoid = dbObj.as[String]("defaultofflineevalmetricinfoid"),
-    defaultofflineevalsplitterinfoid = dbObj.as[String]("defaultofflineevalsplitterinfoid"))
-
-  def insert(engineInfo: EngineInfo) = {
-    // required fields
-    val obj = MongoDBObject(
-      "_id" -> engineInfo.id,
-      "name" -> engineInfo.name,
-      "params" -> (engineInfo.params mapValues { MongoParam.paramToDBObj(_) }),
-      "paramsections" -> (engineInfo.paramsections map { MongoParam.paramSectionToDBObj(_) }),
-      "defaultalgoinfoid" -> engineInfo.defaultalgoinfoid,
-      "defaultofflineevalmetricinfoid" -> engineInfo.defaultofflineevalmetricinfoid,
-      "defaultofflineevalsplitterinfoid" -> engineInfo.defaultofflineevalsplitterinfoid)
-
-    // optional fields
-    val optObj = engineInfo.description.map { d => MongoDBObject("description" -> d) } getOrElse MongoUtils.emptyObj
-
-    coll.insert(obj ++ optObj)
-  }
-
-  def get(id: String) = coll.findOne(MongoDBObject("_id" -> id)) map { dbObjToEngineInfo(_) }
-
-  def getAll() = coll.find().toSeq map { dbObjToEngineInfo(_) }
-
-  def update(engineInfo: EngineInfo, upsert: Boolean = false) = {
-    val idObj = MongoDBObject("_id" -> engineInfo.id)
-    val requiredObj = MongoDBObject(
-      "name" -> engineInfo.name,
-      "params" -> (engineInfo.params mapValues { MongoParam.paramToDBObj(_) }),
-      "paramsections" -> (engineInfo.paramsections map { MongoParam.paramSectionToDBObj(_) }),
-      "defaultalgoinfoid" -> engineInfo.defaultalgoinfoid,
-      "defaultofflineevalmetricinfoid" -> engineInfo.defaultofflineevalmetricinfoid,
-      "defaultofflineevalsplitterinfoid" -> engineInfo.defaultofflineevalsplitterinfoid)
-    val descriptionObj = engineInfo.description.map { d => MongoDBObject("description" -> d) } getOrElse MongoUtils.emptyObj
-
-    coll.update(idObj, idObj ++ requiredObj ++ descriptionObj, upsert)
-  }
-
-  def delete(id: String) = coll.remove(MongoDBObject("_id" -> id))
-}
diff --git a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoEngines.scala b/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoEngines.scala
deleted file mode 100644
index 436b0e4..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoEngines.scala
+++ /dev/null
@@ -1,97 +0,0 @@
-package io.prediction.commons.settings.mongodb
-
-import io.prediction.commons.MongoUtils
-import io.prediction.commons.settings.{ Engine, Engines }
-
-import com.mongodb.casbah.Imports._
-
-/** MongoDB implementation of Engines. */
-class MongoEngines(db: MongoDB) extends Engines {
-  private val engineColl = db("engines")
-  private val seq = new MongoSequences(db)
-
-  private def dbObjToEngine(dbObj: DBObject) = {
-    /** Transparent upgrade. Remove in next minor version. */
-    dbObj.getAs[DBObject]("settings") map { settings =>
-      val e = Engine(
-        id = dbObj.as[Int]("_id"),
-        appid = dbObj.as[Int]("appid"),
-        name = dbObj.as[String]("name"),
-        infoid = dbObj.as[String]("infoid"),
-        itypes = dbObj.getAs[MongoDBList]("itypes") map { MongoUtils.mongoDbListToListOfString(_) },
-        params = MongoUtils.dbObjToMap(settings),
-        trainingdisabled = dbObj.getAs[Boolean]("trainingdisabled"),
-        trainingschedule = dbObj.getAs[String]("trainingschedule"))
-      update(e)
-      e
-    } getOrElse {
-      Engine(
-        id = dbObj.as[Int]("_id"),
-        appid = dbObj.as[Int]("appid"),
-        name = dbObj.as[String]("name"),
-        infoid = dbObj.as[String]("infoid"),
-        itypes = dbObj.getAs[MongoDBList]("itypes") map { MongoUtils.mongoDbListToListOfString(_) },
-        params = MongoUtils.dbObjToMap(dbObj.as[DBObject]("params")),
-        trainingdisabled = dbObj.getAs[Boolean]("trainingdisabled"),
-        trainingschedule = dbObj.getAs[String]("trainingschedule"))
-    }
-  }
-
-  class MongoEngineIterator(it: MongoCursor) extends Iterator[Engine] {
-    def next = dbObjToEngine(it.next)
-    def hasNext = it.hasNext
-  }
-
-  def insert(engine: Engine) = {
-    val id = seq.genNext("engineid")
-
-    // required fields
-    val obj = MongoDBObject(
-      "_id" -> id,
-      "appid" -> engine.appid,
-      "name" -> engine.name,
-      "infoid" -> engine.infoid,
-      "params" -> engine.params
-    )
-
-    // optional fields
-    val optObj = engine.itypes.map(x => MongoDBObject("itypes" -> x)).getOrElse(MongoUtils.emptyObj) ++
-      engine.trainingdisabled.map(x => MongoDBObject("trainingdisabled" -> x)).getOrElse(MongoUtils.emptyObj) ++
-      engine.trainingschedule.map(x => MongoDBObject("trainingschedule" -> x)).getOrElse(MongoUtils.emptyObj)
-
-    engineColl.insert(obj ++ optObj)
-
-    id
-  }
-
-  def get(id: Int) = engineColl.findOne(MongoDBObject("_id" -> id)) map { dbObjToEngine(_) }
-
-  def getAll() = new MongoEngineIterator(engineColl.find())
-
-  def getByAppid(appid: Int) = new MongoEngineIterator(engineColl.find(MongoDBObject("appid" -> appid)).sort(MongoDBObject("name" -> 1)))
-
-  def getByAppidAndName(appid: Int, name: String) = engineColl.findOne(MongoDBObject("appid" -> appid, "name" -> name)) map { dbObjToEngine(_) }
-
-  def getByIdAndAppid(id: Int, appid: Int): Option[Engine] = engineColl.findOne(MongoDBObject("_id" -> id, "appid" -> appid)) map { dbObjToEngine(_) }
-
-  def update(engine: Engine, upsert: Boolean = false) = {
-    val idObj = MongoDBObject("_id" -> engine.id)
-    val nameObj = MongoDBObject("name" -> engine.name)
-    val appidObj = MongoDBObject("appid" -> engine.appid)
-    val infoidObj = MongoDBObject("infoid" -> engine.infoid)
-    val itypesObj = engine.itypes.map(x => MongoDBObject("itypes" -> x)).getOrElse(MongoUtils.emptyObj)
-    val paramsObj = MongoDBObject("params" -> engine.params)
-    val trainingdisabledObj = engine.trainingdisabled.map(x => MongoDBObject("trainingdisabled" -> x)).getOrElse(MongoUtils.emptyObj)
-    val trainingscheduleObj = engine.trainingschedule.map(x => MongoDBObject("trainingschedule" -> x)).getOrElse(MongoUtils.emptyObj)
-
-    engineColl.update(
-      idObj,
-      idObj ++ appidObj ++ nameObj ++ infoidObj ++ itypesObj ++ paramsObj ++ trainingdisabledObj ++ trainingscheduleObj,
-      upsert
-    )
-  }
-
-  def deleteByIdAndAppid(id: Int, appid: Int) = engineColl.remove(MongoDBObject("_id" -> id, "appid" -> appid))
-
-  def existsByAppidAndName(appid: Int, name: String) = engineColl.findOne(MongoDBObject("name" -> name, "appid" -> appid)) map { _ => true } getOrElse false
-}
diff --git a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoMetadata.scala b/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoMetadata.scala
deleted file mode 100644
index 8d38d17..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoMetadata.scala
+++ /dev/null
@@ -1,44 +0,0 @@
-package io.prediction.commons.settings.mongodb
-
-import io.prediction.commons.settings.Metadata
-
-import com.mongodb.casbah.Imports._
-import org.json4s._
-import org.json4s.native.Serialization
-
-/** MongoDB implementation of AlgoInfos. */
-class MongoMetadata(db: MongoDB) extends Metadata {
-  private val seqColl = db("seq")
-
-  implicit val formats = Serialization.formats(NoTypeHints)
-
-  def backup(): Array[Byte] = {
-    val backup = seqColl.find().toSeq.map { b =>
-      try {
-        MongoMetadataEntry(id = b.as[String]("_id"), next = b.as[Double]("next"))
-      } catch {
-        case e: ClassCastException =>
-          MongoMetadataEntry(id = b.as[String]("_id"), next = b.as[Int]("next").toDouble)
-      }
-    }
-    Serialization.write(backup).getBytes("UTF-8")
-  }
-
-  def restore(bytes: Array[Byte], inplace: Boolean = false, upgrade: Boolean = false): Option[Seq[MongoMetadataEntry]] = {
-    try {
-      val rdata = Serialization.read[Seq[MongoMetadataEntry]](new String(bytes, "UTF-8"))
-      if (inplace) rdata foreach { data =>
-        val idObj = MongoDBObject("_id" -> data.id)
-        seqColl.update(
-          idObj,
-          idObj ++ MongoDBObject("next" -> data.next),
-          true)
-      }
-      Some(rdata)
-    } catch {
-      case e: MappingException => None
-    }
-  }
-}
-
-case class MongoMetadataEntry(id: String, next: Double)
diff --git a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoOfflineEvalMetricInfos.scala b/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoOfflineEvalMetricInfos.scala
deleted file mode 100644
index 2246ff0..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoOfflineEvalMetricInfos.scala
+++ /dev/null
@@ -1,65 +0,0 @@
-package io.prediction.commons.settings.mongodb
-
-import io.prediction.commons.MongoUtils
-import io.prediction.commons.settings.{ OfflineEvalMetricInfo, OfflineEvalMetricInfos }
-
-import com.mongodb.casbah.Imports._
-
-/** MongoDB implementation of OfflineEvalMetricInfos. */
-class MongoOfflineEvalMetricInfos(db: MongoDB) extends OfflineEvalMetricInfos {
-  private val coll = db("offlineEvalMetricInfos")
-
-  private def dbObjToOfflineEvalMetricInfo(dbObj: DBObject) = {
-
-    OfflineEvalMetricInfo(
-      id = dbObj.as[String]("_id"),
-      name = dbObj.as[String]("name"),
-      description = dbObj.getAs[String]("description"),
-      engineinfoids = MongoUtils.mongoDbListToListOfString(dbObj.as[MongoDBList]("engineinfoids")),
-      commands = dbObj.getAs[MongoDBList]("commands") map { MongoUtils.mongoDbListToListOfString(_) },
-      params = (dbObj.as[DBObject]("params") map { p => (p._1, MongoParam.dbObjToParam(p._1, p._2.asInstanceOf[DBObject])) }).toMap,
-      paramsections = dbObj.as[Seq[DBObject]]("paramsections") map { MongoParam.dbObjToParamSection(_) },
-      paramorder = MongoUtils.mongoDbListToListOfString(dbObj.as[MongoDBList]("paramorder")))
-  }
-
-  def insert(offlineEvalMetricInfo: OfflineEvalMetricInfo) = {
-    // required fields
-    val obj = MongoDBObject(
-      "_id" -> offlineEvalMetricInfo.id,
-      "name" -> offlineEvalMetricInfo.name,
-      "engineinfoids" -> offlineEvalMetricInfo.engineinfoids,
-      "params" -> offlineEvalMetricInfo.params.mapValues { MongoParam.paramToDBObj(_) },
-      "paramsections" -> offlineEvalMetricInfo.paramsections.map { MongoParam.paramSectionToDBObj(_) },
-      "paramorder" -> offlineEvalMetricInfo.paramorder)
-    // optional fields
-    val descriptionObj = offlineEvalMetricInfo.description.map { d => MongoDBObject("description" -> d) } getOrElse MongoUtils.emptyObj
-    val commandsObj = offlineEvalMetricInfo.commands.map { c => MongoDBObject("commands" -> c) } getOrElse MongoUtils.emptyObj
-
-    coll.insert(obj ++ descriptionObj ++ commandsObj)
-  }
-
-  def get(id: String) = coll.findOne(MongoDBObject("_id" -> id)) map { dbObjToOfflineEvalMetricInfo(_) }
-
-  def getAll() = coll.find().toSeq map { dbObjToOfflineEvalMetricInfo(_) }
-
-  def getByEngineinfoid(engineinfoid: String): Seq[OfflineEvalMetricInfo] = {
-    coll.find(MongoDBObject("engineinfoids" -> MongoDBObject("$in" -> Seq(engineinfoid)))).toSeq map { dbObjToOfflineEvalMetricInfo(_) }
-  }
-
-  def update(offlineEvalMetricInfo: OfflineEvalMetricInfo, upsert: Boolean = false) = {
-    val idObj = MongoDBObject("_id" -> offlineEvalMetricInfo.id)
-    val requiredObj = MongoDBObject(
-      "name" -> offlineEvalMetricInfo.name,
-      "engineinfoids" -> offlineEvalMetricInfo.engineinfoids,
-      "params" -> offlineEvalMetricInfo.params.mapValues { MongoParam.paramToDBObj(_) },
-      "paramsections" -> offlineEvalMetricInfo.paramsections.map { MongoParam.paramSectionToDBObj(_) },
-      "paramorder" -> offlineEvalMetricInfo.paramorder)
-
-    val descriptionObj = offlineEvalMetricInfo.description.map { d => MongoDBObject("description" -> d) } getOrElse MongoUtils.emptyObj
-    val commandsObj = offlineEvalMetricInfo.commands.map { c => MongoDBObject("commands" -> c) } getOrElse MongoUtils.emptyObj
-
-    coll.update(idObj, idObj ++ requiredObj ++ descriptionObj ++ commandsObj, upsert)
-  }
-
-  def delete(id: String) = coll.remove(MongoDBObject("_id" -> id))
-}
diff --git a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoOfflineEvalMetrics.scala b/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoOfflineEvalMetrics.scala
deleted file mode 100644
index 66d981f..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoOfflineEvalMetrics.scala
+++ /dev/null
@@ -1,76 +0,0 @@
-package io.prediction.commons.settings.mongodb
-
-import io.prediction.commons.MongoUtils
-import io.prediction.commons.settings.{ OfflineEvalMetric, OfflineEvalMetrics }
-
-import com.mongodb.casbah.Imports._
-
-class MongoOfflineEvalMetrics(db: MongoDB) extends OfflineEvalMetrics {
-
-  private val emptyObj = MongoDBObject()
-  private val offlineEvalMetricsColl = db("offlineEvalMetrics")
-  private val seq = new MongoSequences(db)
-  private def genNextId = seq.genNext("offlineEvalMetricid")
-
-  private val getFields = MongoDBObject( // fields to be read
-    "infoid" -> 1,
-    "evalid" -> 1,
-    "params" -> 1
-  )
-
-  class MongoOfflineEvalMetricIterator(it: MongoCursor) extends Iterator[OfflineEvalMetric] {
-    def next = dbObjToOfflineEvalMetric(it.next)
-    def hasNext = it.hasNext
-  }
-
-  /** create OfflineEvalMetric object from DBObject */
-  private def dbObjToOfflineEvalMetric(dbObj: DBObject) = {
-    OfflineEvalMetric(
-      id = dbObj.as[Int]("_id"),
-      infoid = dbObj.as[String]("infoid"),
-      evalid = dbObj.as[Int]("evalid"),
-      params = MongoUtils.dbObjToMap(dbObj.as[DBObject]("params"))
-    )
-  }
-
-  /** Insert a metric and return id */
-  def insert(metric: OfflineEvalMetric): Int = {
-    val id = genNextId
-
-    offlineEvalMetricsColl.insert(MongoDBObject(
-      "_id" -> id,
-      "infoid" -> metric.infoid,
-      "evalid" -> metric.evalid,
-      "params" -> metric.params
-    ))
-
-    id
-  }
-
-  /** Get a metric by its ID */
-  def get(id: Int): Option[OfflineEvalMetric] = {
-    offlineEvalMetricsColl.findOne(MongoDBObject("_id" -> id), getFields) map { dbObjToOfflineEvalMetric(_) }
-  }
-
-  def getAll() = new MongoOfflineEvalMetricIterator(offlineEvalMetricsColl.find())
-
-  /** Get metrics by OfflineEval id */
-  def getByEvalid(evalid: Int): Iterator[OfflineEvalMetric] = new MongoOfflineEvalMetricIterator(
-    offlineEvalMetricsColl.find(MongoDBObject("evalid" -> evalid), getFields).sort(MongoDBObject("infoid" -> 1))
-  )
-
-  /** Update metric */
-  def update(metric: OfflineEvalMetric, upsert: Boolean = false) = {
-    offlineEvalMetricsColl.update(MongoDBObject("_id" -> metric.id), MongoDBObject(
-      "_id" -> metric.id,
-      "infoid" -> metric.infoid,
-      "evalid" -> metric.evalid,
-      "params" -> metric.params
-    ), upsert)
-  }
-
-  /** Delete metric by its ID */
-  def delete(id: Int) = {
-    offlineEvalMetricsColl.remove(MongoDBObject("_id" -> id))
-  }
-}
diff --git a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoOfflineEvalResults.scala b/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoOfflineEvalResults.scala
deleted file mode 100644
index c3299e1..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoOfflineEvalResults.scala
+++ /dev/null
@@ -1,66 +0,0 @@
-package io.prediction.commons.settings.mongodb
-
-import io.prediction.commons.settings.{ OfflineEvalResult, OfflineEvalResults }
-import com.mongodb.casbah.Imports._
-
-class MongoOfflineEvalResults(db: MongoDB) extends OfflineEvalResults {
-
-  private val emptyObj = MongoDBObject()
-  private val offlineEvalResultsColl = db("offlineEvalResults")
-  private val getFields = MongoDBObject( // fields to be read
-    "evalid" -> 1,
-    "metricid" -> 1,
-    "algoid" -> 1,
-    "score" -> 1,
-    "iteration" -> 1,
-    "splitset" -> 1
-  )
-
-  private def dbObjToOfflineEvalResult(dbObj: DBObject) = {
-    OfflineEvalResult(
-      evalid = dbObj.as[Int]("evalid"),
-      metricid = dbObj.as[Int]("metricid"),
-      algoid = dbObj.as[Int]("algoid"),
-      score = dbObj.as[Double]("score"),
-      iteration = dbObj.as[Int]("iteration"),
-      splitset = dbObj.as[String]("splitset")
-    )
-  }
-
-  class MongoOfflineEvalResultIterator(it: MongoCursor) extends Iterator[OfflineEvalResult] {
-    def next = dbObjToOfflineEvalResult(it.next)
-    def hasNext = it.hasNext
-  }
-
-  /** save(update existing or create a new one) a OfflineEvalResult and return id*/
-  def save(result: OfflineEvalResult): String = {
-    val id = (result.evalid + "_" + result.metricid + "_" + result.algoid + "_" + result.iteration + "_" + result.splitset)
-    offlineEvalResultsColl.save(MongoDBObject(
-      "_id" -> id,
-      "evalid" -> result.evalid,
-      "metricid" -> result.metricid,
-      "algoid" -> result.algoid,
-      "score" -> result.score,
-      "iteration" -> result.iteration,
-      "splitset" -> result.splitset
-    ))
-
-    id
-  }
-
-  def getAll() = new MongoOfflineEvalResultIterator(offlineEvalResultsColl.find())
-
-  def getByEvalidAndMetricidAndAlgoid(evalid: Int, metricid: Int, algoid: Int): Iterator[OfflineEvalResult] = new MongoOfflineEvalResultIterator(
-    offlineEvalResultsColl.find(MongoDBObject("evalid" -> evalid, "metricid" -> metricid, "algoid" -> algoid), getFields)
-  )
-
-  /** get results by OfflineEval ID */
-  def getByEvalid(evalid: Int): Iterator[OfflineEvalResult] = new MongoOfflineEvalResultIterator(
-    offlineEvalResultsColl.find(MongoDBObject("evalid" -> evalid), getFields)
-  )
-
-  /** delete all results with this OfflineEval ID */
-  def deleteByEvalid(evalid: Int) = {
-    offlineEvalResultsColl.remove(MongoDBObject("evalid" -> evalid))
-  }
-}
diff --git a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoOfflineEvalSplitterInfos.scala b/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoOfflineEvalSplitterInfos.scala
deleted file mode 100644
index 274962a..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoOfflineEvalSplitterInfos.scala
+++ /dev/null
@@ -1,65 +0,0 @@
-package io.prediction.commons.settings.mongodb
-
-import io.prediction.commons.MongoUtils
-import io.prediction.commons.settings.{ OfflineEvalSplitterInfo, OfflineEvalSplitterInfos }
-
-import com.mongodb.casbah.Imports._
-
-/** MongoDB implementation of OfflineEvalSplitterInfos. */
-class MongoOfflineEvalSplitterInfos(db: MongoDB) extends OfflineEvalSplitterInfos {
-  private val coll = db("offlineEvalSplitterInfos")
-
-  private def dbObjToOfflineEvalSplitterInfo(dbObj: DBObject) = {
-    OfflineEvalSplitterInfo(
-      id = dbObj.as[String]("_id"),
-      name = dbObj.as[String]("name"),
-      description = dbObj.getAs[String]("description"),
-      engineinfoids = MongoUtils.mongoDbListToListOfString(dbObj.as[MongoDBList]("engineinfoids")),
-      commands = dbObj.getAs[MongoDBList]("commands") map { MongoUtils.mongoDbListToListOfString(_) },
-      params = (dbObj.as[DBObject]("params") map { p => (p._1, MongoParam.dbObjToParam(p._1, p._2.asInstanceOf[DBObject])) }).toMap,
-      paramsections = dbObj.as[Seq[DBObject]]("paramsections") map { MongoParam.dbObjToParamSection(_) },
-      paramorder = MongoUtils.mongoDbListToListOfString(dbObj.as[MongoDBList]("paramorder")))
-  }
-
-  def insert(offlineEvalSplitterInfo: OfflineEvalSplitterInfo) = {
-    // required fields
-    val obj = MongoDBObject(
-      "_id" -> offlineEvalSplitterInfo.id,
-      "name" -> offlineEvalSplitterInfo.name,
-      "engineinfoids" -> offlineEvalSplitterInfo.engineinfoids,
-      "params" -> offlineEvalSplitterInfo.params.mapValues { MongoParam.paramToDBObj(_) },
-      "paramsections" -> offlineEvalSplitterInfo.paramsections.map { MongoParam.paramSectionToDBObj(_) },
-      "paramorder" -> offlineEvalSplitterInfo.paramorder)
-
-    // optional fields
-    val descriptionObj = offlineEvalSplitterInfo.description.map { d => MongoDBObject("description" -> d) } getOrElse MongoUtils.emptyObj
-    val commandsObj = offlineEvalSplitterInfo.commands.map { c => MongoDBObject("commands" -> c) } getOrElse MongoUtils.emptyObj
-
-    coll.insert(obj ++ descriptionObj ++ commandsObj)
-  }
-
-  def get(id: String) = coll.findOne(MongoDBObject("_id" -> id)) map { dbObjToOfflineEvalSplitterInfo(_) }
-
-  def getAll() = coll.find().toSeq map { dbObjToOfflineEvalSplitterInfo(_) }
-
-  def getByEngineinfoid(engineinfoid: String): Seq[OfflineEvalSplitterInfo] = {
-    coll.find(MongoDBObject("engineinfoids" -> MongoDBObject("$in" -> Seq(engineinfoid)))).toSeq map { dbObjToOfflineEvalSplitterInfo(_) }
-  }
-
-  def update(offlineEvalSplitterInfo: OfflineEvalSplitterInfo, upsert: Boolean = false) = {
-    val idObj = MongoDBObject("_id" -> offlineEvalSplitterInfo.id)
-    val requiredObj = MongoDBObject(
-      "name" -> offlineEvalSplitterInfo.name,
-      "engineinfoids" -> offlineEvalSplitterInfo.engineinfoids,
-      "params" -> offlineEvalSplitterInfo.params.mapValues { MongoParam.paramToDBObj(_) },
-      "paramsections" -> offlineEvalSplitterInfo.paramsections.map { MongoParam.paramSectionToDBObj(_) },
-      "paramorder" -> offlineEvalSplitterInfo.paramorder)
-
-    val descriptionObj = offlineEvalSplitterInfo.description.map { d => MongoDBObject("description" -> d) } getOrElse MongoUtils.emptyObj
-    val commandsObj = offlineEvalSplitterInfo.commands.map { c => MongoDBObject("commands" -> c) } getOrElse MongoUtils.emptyObj
-
-    coll.update(idObj, idObj ++ requiredObj ++ descriptionObj ++ commandsObj, upsert)
-  }
-
-  def delete(id: String) = coll.remove(MongoDBObject("_id" -> id))
-}
diff --git a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoOfflineEvalSplitters.scala b/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoOfflineEvalSplitters.scala
deleted file mode 100644
index f245147..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoOfflineEvalSplitters.scala
+++ /dev/null
@@ -1,67 +0,0 @@
-package io.prediction.commons.settings.mongodb
-
-import io.prediction.commons.MongoUtils
-import io.prediction.commons.settings.{ OfflineEvalSplitter, OfflineEvalSplitters }
-
-import com.mongodb.casbah.Imports._
-
-/** MongoDB implementation of OfflineEvalSplitters. */
-class MongoOfflineEvalSplitters(db: MongoDB) extends OfflineEvalSplitters {
-  private val coll = db("offlineEvalSplitters")
-  private val seq = new MongoSequences(db)
-
-  private def dbObjToOfflineEvalSplitter(dbObj: DBObject) = {
-    OfflineEvalSplitter(
-      id = dbObj.as[Int]("_id"),
-      evalid = dbObj.as[Int]("evalid"),
-      name = dbObj.as[String]("name"),
-      infoid = dbObj.as[String]("infoid"),
-      settings = MongoUtils.dbObjToMap(dbObj.as[DBObject]("settings"))
-    )
-  }
-
-  class MongoOfflineEvalSplitterIterator(it: MongoCursor) extends Iterator[OfflineEvalSplitter] {
-    def next = dbObjToOfflineEvalSplitter(it.next)
-    def hasNext = it.hasNext
-  }
-
-  def insert(splitter: OfflineEvalSplitter) = {
-    val id = seq.genNext("offlineEvalSplitterId")
-
-    // required fields
-    val obj = MongoDBObject(
-      "_id" -> id,
-      "evalid" -> splitter.evalid,
-      "name" -> splitter.name,
-      "infoid" -> splitter.infoid,
-      "settings" -> splitter.settings
-    )
-
-    coll.insert(obj)
-
-    id
-  }
-
-  def get(id: Int) = coll.findOne(MongoDBObject("_id" -> id)) map { dbObjToOfflineEvalSplitter(_) }
-
-  def getAll() = new MongoOfflineEvalSplitterIterator(coll.find())
-
-  def getByEvalid(evalid: Int): Iterator[OfflineEvalSplitter] = new MongoOfflineEvalSplitterIterator(
-    coll.find(MongoDBObject("evalid" -> evalid)).sort(MongoDBObject("infoid" -> 1))
-  )
-
-  def update(splitter: OfflineEvalSplitter, upsert: Boolean = false) = {
-    val idObj = MongoDBObject("_id" -> splitter.id)
-    val evalidObj = MongoDBObject("evalid" -> splitter.evalid)
-    val nameObj = MongoDBObject("name" -> splitter.name)
-    val infoidObj = MongoDBObject("infoid" -> splitter.infoid)
-    val settingsObj = MongoDBObject("settings" -> splitter.settings)
-
-    coll.update(
-      idObj,
-      idObj ++ evalidObj ++ nameObj ++ infoidObj ++ settingsObj,
-      upsert)
-  }
-
-  def delete(id: Int) = coll.remove(MongoDBObject("_id" -> id))
-}
diff --git a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoOfflineEvals.scala b/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoOfflineEvals.scala
deleted file mode 100644
index af6fdfe..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoOfflineEvals.scala
+++ /dev/null
@@ -1,107 +0,0 @@
-package io.prediction.commons.settings.mongodb
-
-import io.prediction.commons.settings.{ OfflineEval, OfflineEvals }
-
-import com.mongodb.casbah.Imports._
-import com.mongodb.casbah.commons.conversions.scala.RegisterJodaTimeConversionHelpers
-import com.github.nscala_time.time.Imports._
-
-class MongoOfflineEvals(db: MongoDB) extends OfflineEvals {
-
-  private val emptyObj = MongoDBObject()
-  private val offlineEvalColl = db("offlineEvals")
-  private val seq = new MongoSequences(db)
-  private def genNextId = seq.genNext("offlineEvalid")
-  private val getFields = MongoDBObject( // fields to be read
-    "engineid" -> 1,
-    "name" -> 1,
-    "iterations" -> 1,
-    "tuneid" -> 1,
-    "createtime" -> 1,
-    "starttime" -> 1,
-    "endtime" -> 1
-  )
-
-  RegisterJodaTimeConversionHelpers()
-
-  private def dbObjToOfflineEval(dbObj: DBObject) = {
-    OfflineEval(
-      id = dbObj.as[Int]("_id"),
-      engineid = dbObj.as[Int]("engineid"),
-      name = dbObj.as[String]("name"),
-      iterations = dbObj.as[Int]("iterations"),
-      tuneid = dbObj.getAs[Int]("tuneid"),
-      createtime = dbObj.getAs[DateTime]("createtime"),
-      starttime = dbObj.getAs[DateTime]("starttime"),
-      endtime = dbObj.getAs[DateTime]("endtime")
-    )
-  }
-
-  class MongoOfflineEvalIterator(it: MongoCursor) extends Iterator[OfflineEval] {
-    def next = dbObjToOfflineEval(it.next)
-    def hasNext = it.hasNext
-  }
-
-  /** Insert an OfflineEval and return id (id of the offlineEval parameter is not used) */
-  def insert(offlineEval: OfflineEval): Int = {
-    val id = genNextId
-
-    // required fields
-    val obj = MongoDBObject(
-      "_id" -> id,
-      "engineid" -> offlineEval.engineid,
-      "name" -> offlineEval.name,
-      "iterations" -> offlineEval.iterations,
-      "tuneid" -> offlineEval.tuneid)
-
-    // option fields
-    val createtimeObj = offlineEval.createtime.map(x => MongoDBObject("createtime" -> x)).getOrElse(emptyObj)
-    val starttimeObj = offlineEval.starttime.map(x => MongoDBObject("starttime" -> x)).getOrElse(emptyObj)
-    val endtimeObj = offlineEval.endtime.map(x => MongoDBObject("endtime" -> x)).getOrElse(emptyObj)
-
-    val optObj = createtimeObj ++ starttimeObj ++ endtimeObj
-
-    offlineEvalColl.insert(obj ++ optObj)
-
-    id
-  }
-
-  def get(id: Int): Option[OfflineEval] = {
-    // NOTE: _id field is always returned although it is not specified in getFields.
-    offlineEvalColl.findOne(MongoDBObject("_id" -> id), getFields) map { dbObjToOfflineEval(_) }
-  }
-
-  def getAll() = new MongoOfflineEvalIterator(offlineEvalColl.find())
-
-  def getByEngineid(engineid: Int): Iterator[OfflineEval] = new MongoOfflineEvalIterator(
-    offlineEvalColl.find(MongoDBObject("engineid" -> engineid), getFields).sort(MongoDBObject("name" -> 1))
-  )
-
-  def getByTuneid(tuneid: Int): Iterator[OfflineEval] = new MongoOfflineEvalIterator(
-    offlineEvalColl.find(MongoDBObject("tuneid" -> tuneid), getFields).sort(MongoDBObject("name" -> 1))
-  )
-
-  def getByIdAndEngineid(id: Int, engineid: Int): Option[OfflineEval] = offlineEvalColl.findOne(MongoDBObject("_id" -> id, "engineid" -> engineid)) map { dbObjToOfflineEval(_) }
-
-  def update(offlineEval: OfflineEval, upsert: Boolean = false) = {
-    val obj = MongoDBObject(
-      "_id" -> offlineEval.id,
-      "engineid" -> offlineEval.engineid,
-      "name" -> offlineEval.name,
-      "iterations" -> offlineEval.iterations,
-      "tuneid" -> offlineEval.tuneid)
-
-    // option fields
-    val createtimeObj = offlineEval.createtime.map(x => MongoDBObject("createtime" -> x)).getOrElse(emptyObj)
-    val starttimeObj = offlineEval.starttime.map(x => MongoDBObject("starttime" -> x)).getOrElse(emptyObj)
-    val endtimeObj = offlineEval.endtime.map(x => MongoDBObject("endtime" -> x)).getOrElse(emptyObj)
-
-    val optObj = createtimeObj ++ starttimeObj ++ endtimeObj
-
-    offlineEvalColl.update(MongoDBObject("_id" -> offlineEval.id), obj ++ optObj, upsert)
-  }
-
-  def delete(id: Int) = {
-    offlineEvalColl.remove(MongoDBObject("_id" -> id))
-  }
-}
diff --git a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoOfflineTunes.scala b/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoOfflineTunes.scala
deleted file mode 100644
index a2f26fa..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoOfflineTunes.scala
+++ /dev/null
@@ -1,91 +0,0 @@
-package io.prediction.commons.settings.mongodb
-
-import io.prediction.commons.settings.{ OfflineTune, OfflineTunes }
-
-import com.mongodb.casbah.Imports._
-import com.mongodb.casbah.commons.conversions.scala.RegisterJodaTimeConversionHelpers
-import com.github.nscala_time.time.Imports._
-
-class MongoOfflineTunes(db: MongoDB) extends OfflineTunes {
-
-  private val emptyObj = MongoDBObject()
-  private val offlineTuneColl = db("offlineTunes")
-  private val seq = new MongoSequences(db)
-  private def genNextId = seq.genNext("offlineTuneid")
-  private val getFields = MongoDBObject( // fields to be read
-    "engineid" -> 1,
-    "loops" -> 1,
-    "createtime" -> 1,
-    "starttime" -> 1,
-    "endtime" -> 1
-  )
-
-  RegisterJodaTimeConversionHelpers()
-
-  private def dbObjToOfflineTune(dbObj: DBObject) = {
-    OfflineTune(
-      id = dbObj.as[Int]("_id"),
-      engineid = dbObj.as[Int]("engineid"),
-      loops = dbObj.as[Int]("loops"),
-      createtime = dbObj.getAs[DateTime]("createtime"),
-      starttime = dbObj.getAs[DateTime]("starttime"),
-      endtime = dbObj.getAs[DateTime]("endtime")
-    )
-  }
-
-  class MongoOfflineTuneIterator(it: MongoCursor) extends Iterator[OfflineTune] {
-    def next = dbObjToOfflineTune(it.next)
-    def hasNext = it.hasNext
-  }
-
-  def insert(offlineTune: OfflineTune): Int = {
-    val id = genNextId
-
-    val obj = MongoDBObject(
-      "_id" -> id,
-      "engineid" -> offlineTune.engineid,
-      "loops" -> offlineTune.loops
-    )
-
-    // optional fields
-    val createtimeObj = offlineTune.createtime.map(x => MongoDBObject("createtime" -> x)).getOrElse(emptyObj)
-    val starttimeObj = offlineTune.starttime.map(x => MongoDBObject("starttime" -> x)).getOrElse(emptyObj)
-    val endtimeObj = offlineTune.endtime.map(x => MongoDBObject("endtime" -> x)).getOrElse(emptyObj)
-
-    val optObj = createtimeObj ++ starttimeObj ++ endtimeObj
-
-    offlineTuneColl.insert(obj ++ optObj)
-
-    id
-  }
-
-  def get(id: Int): Option[OfflineTune] = {
-    offlineTuneColl.findOne(MongoDBObject("_id" -> id), getFields) map { dbObjToOfflineTune(_) }
-  }
-
-  def getAll() = new MongoOfflineTuneIterator(offlineTuneColl.find())
-
-  def getByEngineid(engineid: Int): Iterator[OfflineTune] = new MongoOfflineTuneIterator(offlineTuneColl.find(MongoDBObject("engineid" -> engineid), getFields))
-
-  def update(offlineTune: OfflineTune, upsert: Boolean = false) = {
-
-    val obj = MongoDBObject(
-      "_id" -> offlineTune.id,
-      "engineid" -> offlineTune.engineid,
-      "loops" -> offlineTune.loops
-    )
-
-    // optional fields
-    val createtimeObj = offlineTune.createtime.map(x => MongoDBObject("createtime" -> x)).getOrElse(emptyObj)
-    val starttimeObj = offlineTune.starttime.map(x => MongoDBObject("starttime" -> x)).getOrElse(emptyObj)
-    val endtimeObj = offlineTune.endtime.map(x => MongoDBObject("endtime" -> x)).getOrElse(emptyObj)
-
-    val optObj = createtimeObj ++ starttimeObj ++ endtimeObj
-
-    offlineTuneColl.update(MongoDBObject("_id" -> offlineTune.id), obj ++ optObj, upsert)
-  }
-
-  def delete(id: Int) = {
-    offlineTuneColl.remove(MongoDBObject("_id" -> id))
-  }
-}
diff --git a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoParam.scala b/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoParam.scala
deleted file mode 100644
index 5c905f9..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoParam.scala
+++ /dev/null
@@ -1,124 +0,0 @@
-package io.prediction.commons.settings.mongodb
-
-import io.prediction.commons.MongoUtils
-import io.prediction.commons.settings._
-
-import com.mongodb.casbah.Imports._
-
-/** MongoDB implementation of Param. */
-object MongoParam {
-  def dbObjToParam(id: String, dbObj: DBObject) = {
-    val constraintObj = dbObj.as[DBObject]("constraint")
-    Param(
-      id = id,
-      name = dbObj.as[String]("name"),
-      description = dbObj.getAs[String]("description"),
-      defaultvalue = dbObj("defaultvalue"),
-      constraint = constraintObj.as[String]("paramtype") match {
-        case "boolean" => ParamBooleanConstraint()
-        case "double" => ParamDoubleConstraint(
-          min = constraintObj.getAs[Double]("min"),
-          max = constraintObj.getAs[Double]("max"))
-        case "integer" => ParamIntegerConstraint(
-          min = constraintObj.getAs[Int]("min"),
-          max = constraintObj.getAs[Int]("max"))
-        case "long" => ParamLongConstraint(
-          min = constraintObj.getAs[Long]("min"),
-          max = constraintObj.getAs[Long]("max"))
-        case "string" => ParamStringConstraint()
-        case _ => ParamStringConstraint()
-      },
-      ui = asParamUI(dbObj.as[DBObject]("ui")),
-      scopes = dbObj.getAs[MongoDBList]("scopes") map {
-        _.toSet.map((x: Any) => x.toString)
-      })
-  }
-
-  def paramToDBObj(param: Param) = {
-    MongoDBObject(
-      "name" -> param.name,
-      "defaultvalue" -> param.defaultvalue,
-      "constraint" -> (MongoDBObject("paramtype" ->
-        param.constraint.paramtype) ++ (param.constraint.paramtype match {
-        case "boolean" => MongoUtils.emptyObj
-        case "double" =>
-          (param.constraint.asInstanceOf[ParamDoubleConstraint].min map {
-            x => MongoDBObject("min" -> x)
-          } getOrElse MongoUtils.emptyObj) ++
-            (param.constraint.asInstanceOf[ParamDoubleConstraint].max map {
-              x => MongoDBObject("max" -> x)
-            } getOrElse MongoUtils.emptyObj)
-        case "integer" =>
-          (param.constraint.asInstanceOf[ParamIntegerConstraint].min map {
-            x => MongoDBObject("min" -> x)
-          } getOrElse MongoUtils.emptyObj) ++
-            (param.constraint.asInstanceOf[ParamIntegerConstraint].max map {
-              x => MongoDBObject("max" -> x)
-            } getOrElse MongoUtils.emptyObj)
-        case "long" =>
-          (param.constraint.asInstanceOf[ParamLongConstraint].min map {
-            x => MongoDBObject("min" -> x)
-          } getOrElse MongoUtils.emptyObj) ++
-            (param.constraint.asInstanceOf[ParamLongConstraint].max map {
-              x => MongoDBObject("max" -> x)
-            } getOrElse MongoUtils.emptyObj)
-        case "string" => MongoUtils.emptyObj
-        case _ => MongoUtils.emptyObj
-      })),
-      "ui" -> (MongoDBObject("uitype" -> param.ui.uitype) ++
-        param.ui.slidermin.map(m => MongoDBObject("slidermin" -> m))
-        .getOrElse(MongoUtils.emptyObj) ++
-        param.ui.slidermax.map(m => MongoDBObject("slidermax" -> m))
-        .getOrElse(MongoUtils.emptyObj) ++
-        param.ui.sliderstep.map(m => MongoDBObject("sliderstep" -> m))
-        .getOrElse(MongoUtils.emptyObj) ++
-        (param.ui.selections map { selections =>
-          MongoDBObject("selections" -> (selections map { selection =>
-            MongoDBObject("value" -> selection.value, "name" -> selection.name)
-          }))
-        } getOrElse MongoUtils.emptyObj))) ++
-      (param.description map { d =>
-        MongoDBObject("description" -> d)
-      } getOrElse MongoUtils.emptyObj) ++
-      (param.scopes map { s =>
-        MongoDBObject("scopes" -> s.toSeq)
-      } getOrElse MongoUtils.emptyObj)
-  }
-
-  def dbObjToParamSection(dbObj: DBObject): ParamSection = ParamSection(
-    name = dbObj.as[String]("name"),
-    sectiontype = dbObj.as[String]("sectiontype"),
-    description = dbObj.getAs[String]("description"),
-    subsections = dbObj.getAs[Seq[DBObject]]("subsections").map(
-      _.map(dbObjToParamSection(_))),
-    params = dbObj.getAs[Seq[String]]("params"))
-
-  def paramSectionToDBObj(paramsection: ParamSection): MongoDBObject = {
-    MongoDBObject("name" -> paramsection.name,
-      "sectiontype" -> paramsection.sectiontype) ++
-      (paramsection.description map { d =>
-        MongoDBObject("description" -> d)
-      } getOrElse MongoUtils.emptyObj) ++
-      (paramsection.subsections map { ss =>
-        MongoDBObject("subsections" -> ss.map(s => paramSectionToDBObj(s)))
-      } getOrElse MongoUtils.emptyObj) ++
-      (paramsection.params map { ps =>
-        MongoDBObject("params" -> ps)
-      } getOrElse MongoUtils.emptyObj)
-  }
-
-  private def asParamUI(uiObj: DBObject): ParamUI = {
-    ParamUI(
-      uitype = uiObj.as[String]("uitype"),
-      selections = uiObj.getAs[MongoDBList]("selections") map { selections =>
-        selections map { s =>
-          val selection = s.asInstanceOf[DBObject]
-          ParamSelectionUI(selection.as[String]("value"),
-            selection.as[String]("name"))
-        }
-      },
-      slidermin = uiObj.getAs[Int]("slidermin"),
-      slidermax = uiObj.getAs[Int]("slidermax"),
-      sliderstep = uiObj.getAs[Int]("sliderstep"))
-  }
-}
diff --git a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoParamGenInfos.scala b/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoParamGenInfos.scala
deleted file mode 100644
index e823d76..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoParamGenInfos.scala
+++ /dev/null
@@ -1,69 +0,0 @@
-package io.prediction.commons.settings.mongodb
-
-import io.prediction.commons.MongoUtils
-import io.prediction.commons.settings.{ ParamGenInfo, ParamGenInfos }
-
-import com.mongodb.casbah.Imports._
-
-/** MongoDB implementation of ParamGenInfos. */
-class MongoParamGenInfos(db: MongoDB) extends ParamGenInfos {
-  private val coll = db("paramGenInfos")
-
-  private def dbObjToParamGenInfo(dbObj: DBObject) = {
-    val params = dbObj.as[MongoDBList]("params")
-    val paramorder = params map { p => p.asInstanceOf[DBObject].as[String]("param") }
-    val paramdefaults = params map { p => p.asInstanceOf[DBObject].as[Any]("default") }
-    val paramnames = params map { p => p.asInstanceOf[DBObject].as[String]("name") }
-    val paramdescription = params map { p => p.asInstanceOf[DBObject].as[String]("description") }
-    ParamGenInfo(
-      id = dbObj.as[String]("_id"),
-      name = dbObj.as[String]("name"),
-      description = dbObj.getAs[String]("description"),
-      commands = dbObj.getAs[MongoDBList]("commands") map { MongoUtils.mongoDbListToListOfString(_) },
-      paramdefaults = Map() ++ (paramorder zip paramdefaults),
-      paramnames = Map() ++ (paramorder zip paramnames),
-      paramdescription = Map() ++ (paramorder zip paramdescription),
-      paramorder = paramorder)
-  }
-
-  private def mergeParams(order: Seq[String], names: Map[String, String], defaults: Map[String, Any], description: Map[String, String]): Seq[Map[String, Any]] = {
-    val listBuffer = collection.mutable.ListBuffer[Map[String, Any]]()
-
-    order foreach { k =>
-      listBuffer += Map("param" -> k, "default" -> defaults(k), "name" -> names(k), "description" -> description(k))
-    }
-
-    listBuffer.toSeq
-  }
-
-  def insert(ParamGenInfo: ParamGenInfo) = {
-    // required fields
-    val obj = MongoDBObject(
-      "_id" -> ParamGenInfo.id,
-      "name" -> ParamGenInfo.name,
-      "params" -> mergeParams(ParamGenInfo.paramorder, ParamGenInfo.paramnames, ParamGenInfo.paramdefaults, ParamGenInfo.paramdescription))
-
-    // optional fields
-    val descriptionObj = ParamGenInfo.description.map { d => MongoDBObject("description" -> d) } getOrElse MongoUtils.emptyObj
-    val commandsObj = ParamGenInfo.commands.map { c => MongoDBObject("commands" -> c) } getOrElse MongoUtils.emptyObj
-
-    coll.insert(obj ++ descriptionObj ++ commandsObj)
-  }
-
-  def get(id: String) = coll.findOne(MongoDBObject("_id" -> id)) map { dbObjToParamGenInfo(_) }
-
-  def getAll = coll.find().toSeq map { dbObjToParamGenInfo(_) }
-
-  def update(ParamGenInfo: ParamGenInfo, upsert: Boolean = false) = {
-    val idObj = MongoDBObject("_id" -> ParamGenInfo.id)
-    val requiredObj = MongoDBObject(
-      "name" -> ParamGenInfo.name,
-      "params" -> mergeParams(ParamGenInfo.paramorder, ParamGenInfo.paramnames, ParamGenInfo.paramdefaults, ParamGenInfo.paramdescription))
-    val descriptionObj = ParamGenInfo.description.map { d => MongoDBObject("description" -> d) } getOrElse MongoUtils.emptyObj
-    val commandsObj = ParamGenInfo.commands.map { c => MongoDBObject("commands" -> c) } getOrElse MongoUtils.emptyObj
-
-    coll.update(idObj, idObj ++ requiredObj ++ descriptionObj ++ commandsObj, upsert)
-  }
-
-  def delete(id: String) = coll.remove(MongoDBObject("_id" -> id))
-}
diff --git a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoParamGens.scala b/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoParamGens.scala
deleted file mode 100644
index c1dbd31..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoParamGens.scala
+++ /dev/null
@@ -1,75 +0,0 @@
-package io.prediction.commons.settings.mongodb
-
-import io.prediction.commons.MongoUtils
-import io.prediction.commons.settings.{ ParamGen, ParamGens }
-
-import com.mongodb.casbah.Imports._
-
-class MongoParamGens(db: MongoDB) extends ParamGens {
-
-  private val emptyObj = MongoDBObject()
-  private val paramGensColl = db("paramGens")
-  private val seq = new MongoSequences(db)
-  private def genNextId = seq.genNext("paramGenid")
-
-  private val getFields = MongoDBObject( // fields to be read
-    "infoid" -> 1,
-    "tuneid" -> 1,
-    "params" -> 1
-  )
-
-  class MongoParamGenIterator(it: MongoCursor) extends Iterator[ParamGen] {
-    def next = dbObjToParamGen(it.next)
-    def hasNext = it.hasNext
-  }
-
-  /** create ParamGen object from DBObject */
-  private def dbObjToParamGen(dbObj: DBObject) = {
-    ParamGen(
-      id = dbObj.as[Int]("_id"),
-      infoid = dbObj.as[String]("infoid"),
-      tuneid = dbObj.as[Int]("tuneid"),
-      params = MongoUtils.dbObjToMap(dbObj.as[DBObject]("params"))
-    )
-  }
-
-  /** Insert a paramGen and return id */
-  def insert(paramGen: ParamGen): Int = {
-    val id = genNextId
-
-    paramGensColl.insert(MongoDBObject(
-      "_id" -> id,
-      "infoid" -> paramGen.infoid,
-      "tuneid" -> paramGen.tuneid,
-      "params" -> paramGen.params
-    ))
-
-    id
-  }
-
-  /** Get a paramGen by its ID */
-  def get(id: Int): Option[ParamGen] = {
-    paramGensColl.findOne(MongoDBObject("_id" -> id), getFields) map { dbObjToParamGen(_) }
-  }
-
-  def getAll() = new MongoParamGenIterator(paramGensColl.find())
-
-  def getByTuneid(tuneid: Int): Iterator[ParamGen] = new MongoParamGenIterator(
-    paramGensColl.find(MongoDBObject("tuneid" -> tuneid), getFields).sort(MongoDBObject("_id" -> 1))
-  )
-
-  /** Update paramGen */
-  def update(paramGen: ParamGen, upsert: Boolean = false) = {
-    paramGensColl.update(MongoDBObject("_id" -> paramGen.id), MongoDBObject(
-      "_id" -> paramGen.id,
-      "infoid" -> paramGen.infoid,
-      "tuneid" -> paramGen.tuneid,
-      "params" -> paramGen.params
-    ), upsert)
-  }
-
-  /** Delete paramGen by its ID */
-  def delete(id: Int) = {
-    paramGensColl.remove(MongoDBObject("_id" -> id))
-  }
-}
diff --git a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoSequences.scala b/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoSequences.scala
deleted file mode 100644
index 286f3bc..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoSequences.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package io.prediction.commons.settings.mongodb
-
-import com.mongodb.casbah.Imports.MongoDB
-import com.mongodb.casbah.query.Imports._
-
-/** Provides incremental sequence number generation. */
-class MongoSequences(db: MongoDB) {
-  private val seqColl = db("seq")
-
-  /** Get the next sequence number from the given sequence name. */
-  def genNext(name: String): Int = {
-    val qFind = MongoDBObject("_id" -> name)
-    val qField = MongoDBObject("next" -> 1)
-    val qSort = MongoDBObject()
-    val qRemove = false
-    val qModify = $inc("next" -> 1)
-    val qReturnNew = true
-    val qUpsert = true
-    seqColl.findAndModify(qFind, qField, qSort, qRemove, qModify, qReturnNew, qUpsert).get.getAsOrElse[Number]("next", 0).intValue
-  }
-}
\ No newline at end of file
diff --git a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoSystemInfos.scala b/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoSystemInfos.scala
deleted file mode 100644
index f6fc40c..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoSystemInfos.scala
+++ /dev/null
@@ -1,44 +0,0 @@
-package io.prediction.commons.settings.mongodb
-
-import io.prediction.commons.MongoUtils
-import io.prediction.commons.settings.{ SystemInfo, SystemInfos }
-
-import com.mongodb.casbah.Imports._
-
-/** MongoDB implementation of SystemInfos. */
-class MongoSystemInfos(db: MongoDB) extends SystemInfos {
-  private val coll = db("systemInfos")
-
-  private def dbObjToSystemInfo(dbObj: DBObject) = {
-    SystemInfo(
-      id = dbObj.as[String]("_id"),
-      value = dbObj.as[String]("value"),
-      description = dbObj.getAs[String]("description"))
-  }
-
-  def insert(systemInfo: SystemInfo) = {
-    // required fields
-    val obj = MongoDBObject(
-      "_id" -> systemInfo.id,
-      "value" -> systemInfo.value)
-
-    // optional fields
-    val optObj = systemInfo.description.map { d => MongoDBObject("description" -> d) } getOrElse MongoUtils.emptyObj
-
-    coll.insert(obj ++ optObj)
-  }
-
-  def get(id: String) = coll.findOne(MongoDBObject("_id" -> id)) map { dbObjToSystemInfo(_) }
-
-  def getAll = coll.find().toSeq map { dbObjToSystemInfo(_) }
-
-  def update(systemInfo: SystemInfo, upsert: Boolean = false) = {
-    val idObj = MongoDBObject("_id" -> systemInfo.id)
-    val valueObj = MongoDBObject("value" -> systemInfo.value)
-    val descriptionObj = systemInfo.description.map { d => MongoDBObject("description" -> d) } getOrElse MongoUtils.emptyObj
-
-    coll.update(idObj, idObj ++ valueObj ++ descriptionObj, upsert)
-  }
-
-  def delete(id: String) = coll.remove(MongoDBObject("_id" -> id))
-}
diff --git a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoUsers.scala b/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoUsers.scala
deleted file mode 100644
index 04eab9b..0000000
--- a/commons/src/main/scala/io/prediction/commons/settings/mongodb/MongoUsers.scala
+++ /dev/null
@@ -1,98 +0,0 @@
-package io.prediction.commons.settings.mongodb
-
-import io.prediction.commons.MongoUtils
-import io.prediction.commons.settings.{ User, Users }
-
-import com.mongodb.casbah.Imports._
-import com.mongodb.casbah.WriteConcern
-
-/** MongoDB implementation of Users. */
-class MongoUsers(db: MongoDB) extends Users {
-  private val emptyObj = MongoDBObject()
-  private val userColl = db("users")
-  private val seq = new MongoSequences(db)
-
-  userColl.setWriteConcern(WriteConcern.JournalSafe)
-
-  def authenticate(id: Int, password: String) = {
-    userColl.findOne(MongoDBObject("_id" -> id, "password" -> password) ++ ("confirm" $exists false)) map { _ => true } getOrElse false
-  }
-
-  def authenticateByEmail(email: String, password: String) = {
-    userColl.findOne(MongoDBObject("email" -> email, "password" -> password) ++ ("confirm" $exists false)) map { _.as[Int]("_id") }
-  }
-
-  def insert(email: String, password: String, firstname: String, lastname: Option[String], confirm: String) = {
-    val id = seq.genNext("userid")
-    val userObj = MongoDBObject(
-      "_id" -> id,
-      "email" -> email,
-      "password" -> password,
-      "firstname" -> firstname,
-      "confirm" -> confirm)
-    val lastnameObj = lastname.map(ln => MongoDBObject("lastname" -> ln)).getOrElse(emptyObj)
-    userColl.save(userObj ++ lastnameObj)
-    id
-  }
-
-  def get(id: Int) = {
-    userColl.findOne(MongoDBObject("_id" -> id)) map { dbObjToUser(_) }
-  }
-
-  def getAll() = new MongoUserIterator(userColl.find())
-
-  def getByEmail(email: String) = {
-    userColl.findOne(MongoDBObject("email" -> email)) map { dbObjToUser(_) }
-  }
-
-  def update(user: User, upsert: Boolean = false) = {
-    val requiredObj = MongoDBObject(
-      "_id" -> user.id,
-      "email" -> user.email,
-      "password" -> user.password,
-      "firstname" -> user.firstName)
-    val lastnameObj = user.lastName map { x => MongoDBObject("lastname" -> x) } getOrElse { MongoUtils.emptyObj }
-    val confirmObj = user.confirm map { x => MongoDBObject("confirm" -> x) } getOrElse { MongoUtils.emptyObj }
-    userColl.update(MongoDBObject("_id" -> user.id), requiredObj ++ lastnameObj ++ confirmObj, upsert)
-  }
-
-  def updateEmail(id: Int, email: String) = {
-    userColl.update(MongoDBObject("_id" -> id), MongoDBObject("$set" -> MongoDBObject("email" -> email)))
-  }
-
-  def updatePassword(userid: Int, password: String) = {
-    userColl.update(MongoDBObject("_id" -> userid), MongoDBObject("$set" -> MongoDBObject("password" -> password)))
-  }
-
-  def updatePasswordByEmail(email: String, password: String) = {
-    userColl.update(MongoDBObject("email" -> email), MongoDBObject("$set" -> MongoDBObject("password" -> password)))
-  }
-
-  def confirm(confirm: String) = {
-    userColl.findAndModify(MongoDBObject("confirm" -> confirm), MongoDBObject("$unset" -> MongoDBObject("confirm" -> 1))) map { dbObjToUser(_) }
-  }
-
-  def emailExists(email: String) = {
-    userColl.findOne(MongoDBObject("email" -> email)).map(_ => true).getOrElse(false)
-  }
-
-  def idAndEmailExists(userid: Int, email: String) = {
-    userColl.findOne(MongoDBObject("_id" -> userid, "email" -> email)).map(_ => true).getOrElse(false)
-  }
-
-  private def dbObjToUser(dbObj: DBObject): User = {
-    User(
-      id = dbObj.as[Int]("_id"),
-      firstName = dbObj.as[String]("firstname"),
-      lastName = dbObj.getAs[String]("lastname"),
-      email = dbObj.as[String]("email"),
-      password = dbObj.as[String]("password"),
-      confirm = dbObj.getAs[String]("confirm")
-    )
-  }
-
-  class MongoUserIterator(it: MongoCursor) extends Iterator[User] {
-    def next = dbObjToUser(it.next)
-    def hasNext = it.hasNext
-  }
-}
\ No newline at end of file
diff --git a/commons/src/test/resources/application.conf b/commons/src/test/resources/application.conf
deleted file mode 100644
index b8e6e64..0000000
--- a/commons/src/test/resources/application.conf
+++ /dev/null
@@ -1,42 +0,0 @@
-io.prediction.base=..
-
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.name=predictionio_config_test
-io.prediction.commons.settings.db.user=predictionio
-io.prediction.commons.settings.db.password=foobar
-
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.name=predictionio_config_test
-io.prediction.commons.appdata.db.user=predictionio
-io.prediction.commons.appdata.db.password=foobar
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.name=predictionio_config_test
-io.prediction.commons.appdata.training.db.user=predictionio
-io.prediction.commons.appdata.training.db.password=foobar
-
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.name=predictionio_config_test
-io.prediction.commons.appdata.validation.db.user=predictionio
-io.prediction.commons.appdata.validation.db.password=foobar
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.name=predictionio_config_test
-io.prediction.commons.appdata.test.db.user=predictionio
-io.prediction.commons.appdata.test.db.password=foobar
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.name=predictionio_config_test
-io.prediction.commons.modeldata.db.user=predictionio
-io.prediction.commons.modeldata.db.password=foobar
-io.prediction.commons.modeldata.db.sharding=true
-io.prediction.commons.modeldata.db.shardkeys=[foo,bar]
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.name=predictionio_config_test
-io.prediction.commons.modeldata.training.db.user=predictionio
-io.prediction.commons.modeldata.training.db.password=foobar
-
-io.prediction.jars.algorithms.scalding.itemrec.generic=${io.prediction.base}/lib/predictionio-process-itemrec-algorithms-hadoop-scalding-assembly-0.7.0-SNAPSHOT.jar
-io.prediction.jars.algorithms.mahout.itemrec=${io.prediction.base}/lib/predictionio-process-itemrec-algorithms-scala-mahout-assembly-0.7.0-SNAPSHOT.jar
-io.prediction.jars.algorithms.mahout.corejob=${io.prediction.base}/vendors/mahout-distribution-0.8/mahout-core-0.8-job.jar
diff --git a/commons/src/test/scala/io/prediction/commons/ConfigSpec.scala b/commons/src/test/scala/io/prediction/commons/ConfigSpec.scala
deleted file mode 100644
index de471dd..0000000
--- a/commons/src/test/scala/io/prediction/commons/ConfigSpec.scala
+++ /dev/null
@@ -1,61 +0,0 @@
-package io.prediction.commons
-
-import org.specs2._
-import org.specs2.specification.Step
-import com.mongodb.casbah.Imports._
-
-class ConfigSpec extends Specification {
-  def is = s2"""
-
-  PredictionIO Config Specification
-
-    load an existing config file ${load()}
-    get raw config ${dbtype()}
-    get a MongoUsers implementation ${getMongoUsers()}
-    get a MongoApps implementation ${getMongoApps()}
-    get a MongoEngines implementation ${getMongoEngines()}
-    get a MongoAlgos implementation ${getMongoAlgos()}
-    get a list of job JARs ${jars()}
-    get sharding configuration ${sharding()}
-    (database cleanup) ${Step(Spec.mongoClient(mongoConfig.settingsDbName).dropDatabase())}
-
-  """
-
-  lazy val mongoConfig = new Config
-
-  def load() = {
-    mongoConfig must beAnInstanceOf[Config]
-  }
-
-  def dbtype() = {
-    mongoConfig.settingsDbType must beEqualTo("mongodb")
-  }
-
-  def getMongoUsers() = {
-    mongoConfig.getSettingsUsers() must beAnInstanceOf[settings.mongodb.MongoUsers]
-  }
-
-  def getMongoApps() = {
-    mongoConfig.getSettingsApps() must beAnInstanceOf[settings.mongodb.MongoApps]
-  }
-
-  def getMongoEngines() = {
-    mongoConfig.getSettingsEngines() must beAnInstanceOf[settings.mongodb.MongoEngines]
-  }
-
-  def getMongoAlgos() = {
-    mongoConfig.getSettingsAlgos() must beAnInstanceOf[settings.mongodb.MongoAlgos]
-  }
-
-  def jars() = {
-    mongoConfig.jars must havePairs(
-      "algorithms.mahout.itemrec" -> "../lib/predictionio-process-itemrec-algorithms-scala-mahout-assembly-0.7.0-SNAPSHOT.jar",
-      "algorithms.mahout.corejob" -> "../vendors/mahout-distribution-0.8/mahout-core-0.8-job.jar",
-      "algorithms.scalding.itemrec.generic" -> "../lib/predictionio-process-itemrec-algorithms-hadoop-scalding-assembly-0.7.0-SNAPSHOT.jar")
-  }
-
-  def sharding() = {
-    mongoConfig.modeldataDbSharding must beTrue and
-      (mongoConfig.modeldataDbShardKeys must beSome(===(Seq("foo", "bar"))))
-  }
-}
diff --git a/commons/src/test/scala/io/prediction/commons/Spec.scala b/commons/src/test/scala/io/prediction/commons/Spec.scala
deleted file mode 100644
index 202975f..0000000
--- a/commons/src/test/scala/io/prediction/commons/Spec.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package io.prediction.commons
-
-import com.mongodb.casbah.Imports._
-import org.specs2._
-
-object Spec {
-  val mongoClient = MongoClient()
-}
diff --git a/commons/src/test/scala/io/prediction/commons/appdata/ItemsSpec.scala b/commons/src/test/scala/io/prediction/commons/appdata/ItemsSpec.scala
deleted file mode 100644
index 4bc0099..0000000
--- a/commons/src/test/scala/io/prediction/commons/appdata/ItemsSpec.scala
+++ /dev/null
@@ -1,546 +0,0 @@
-package io.prediction.commons.appdata
-
-import io.prediction.commons.Spec
-
-import org.specs2._
-import org.specs2.specification.Step
-
-import com.mongodb.casbah.Imports._
-import com.github.nscala_time.time.Imports._
-
-class ItemsSpec extends Specification {
-  def is = s2"""
-
-  PredictionIO App Data Items Specification
-
-    Items can be implemented by:
-    - MongoItems ${mongoItems}
-
-  """
-
-  def mongoItems = s2"""
-
-    MongoItems should
-    - behave like any Items implementation ${items(newMongoItems)}
-    - (database cleanup) ${Step(Spec.mongoClient(mongoDbName).dropDatabase())}
-
-  """
-
-  def items(items: Items) = s2"""
-
-    inserting and getting an item ${insert(items)}
-    getting items by App ID and geo data ${getByAppidAndLatlng(items)}
-    getting items by App ID and itypes ${getByAppidAndItypes(items)}
-    getting items by IDs ${getByIds(items)}
-    getting items by IDs sorted by start time ${getRecentByIds(items)}
-    updating an item ${update(items)}
-    deleting an item ${delete(items)}
-    deleting items by appid ${deleteByAppid(items)}
-    count items by appid ${countByAppid(items)}
-    getting items by App ID and itypes and time ${getByAppidAndItypesAndTime(items)}
-
-  """
-
-  val mongoDbName = "predictionio_appdata_mongoitems_test"
-  def newMongoItems = new mongodb.MongoItems(Spec.mongoClient(mongoDbName))
-
-  def insert(items: Items) = {
-    val appid = 0
-    val id1 = "insert1"
-    val item1 = Item(
-      id = id1,
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now.hour(23).minute(13)),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((47.8948, -29.79783)),
-      inactive = None,
-      attributes = Some(Map("foo" -> "bar"))
-    )
-    val id2 = "insert2"
-    val item2 = Item(
-      id = id2,
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now.hour(23).minute(13)),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((47.8948, -29.79783)),
-      inactive = Some(true),
-      attributes = None
-    )
-    items.insert(item1)
-    items.insert(item2)
-    (items.get(appid, id1) must beSome(item1)) and
-      (items.get(appid, id2) must beSome(item2))
-  }
-
-  def getByAppidAndLatlng(items: Items) = {
-    val id = "getByAppidAndLatlng"
-    val appid = 5
-    val dac = Item(
-      id = id + "dac",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now.hour(14).minute(13)),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.3197611, -122.0466141)),
-      inactive = None,
-      attributes = Some(Map("foo" -> "bar", "foo2" -> "bar2")))
-    val hsh = Item(
-      id = id + "hsh",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now.hour(23).minute(13)),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.3370801, -122.0493201)),
-      inactive = None,
-      attributes = None)
-    val mvh = Item(
-      id = id + "mvh",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now.hour(17).minute(13)),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.3154153, -122.0566829)),
-      inactive = None,
-      attributes = Some(Map("foo3" -> "bar3")))
-    val lbh = Item(
-      id = id + "lbh",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now.hour(3).minute(13)),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.2997029, -122.0034684)),
-      inactive = None,
-      attributes = Some(Map("foo4" -> "bar4", "foo5" -> "bar5")))
-    val allItems = Seq(dac, hsh, lbh, mvh)
-    allItems foreach { items.insert(_) }
-    (items.getByAppidAndLatlng(appid, (37.336402, -122.040467), None, None).toSeq must beEqualTo(Seq(hsh, dac, mvh, lbh))) and
-      (items.getByAppidAndLatlng(appid, (37.3229978, -122.0321823), None, None).toSeq must beEqualTo(Seq(dac, hsh, mvh, lbh))) and
-      (items.getByAppidAndLatlng(appid, (37.3229978, -122.0321823), Some(2.2), None).toSeq must beEqualTo(Seq(dac, hsh))) and
-      (items.getByAppidAndLatlng(appid, (37.3229978, -122.0321823), Some(2.2), Some("mi")).toSeq must beEqualTo(Seq(dac, hsh, mvh)))
-  }
-
-  def getByAppidAndItypes(items: Items) = {
-    val id = "getByAppidAndItypes"
-    val appid = 56
-    val dac = Item(
-      id = id + "dac",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("type1", "type2"),
-      starttime = Some(DateTime.now.hour(14).minute(13)),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.3197611, -122.0466141)),
-      inactive = None,
-      attributes = Some(Map("foo" -> "bar", "foo2" -> "bar2")))
-    val hsh = Item(
-      id = id + "hsh",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("type1"),
-      starttime = Some(DateTime.now.hour(23).minute(13)),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.3370801, -122.0493201)),
-      inactive = None,
-      attributes = None)
-    val mvh = Item(
-      id = id + "mvh",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("type2", "type3"),
-      starttime = Some(DateTime.now.hour(17).minute(13)),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.3154153, -122.0566829)),
-      inactive = None,
-      attributes = Some(Map("foo3" -> "bar3")))
-    val lbh = Item(
-      id = id + "lbh",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("type4"),
-      starttime = Some(DateTime.now.hour(3).minute(13)),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.2997029, -122.0034684)),
-      inactive = None,
-      attributes = Some(Map("foo4" -> "bar4", "foo5" -> "bar5")))
-
-    val allItems = Seq(dac, hsh, lbh, mvh)
-    allItems foreach { items.insert(_) }
-
-    (items.getByAppidAndItypes(appid, Seq("type1", "type2", "type3", "type4"))).toSeq must beEqualTo(Seq(dac, hsh, lbh, mvh)) and
-      ((items.getByAppidAndItypes(appid, Seq("type1"))).toSeq must beEqualTo(Seq(dac, hsh))) and
-      ((items.getByAppidAndItypes(appid, Seq("type2"))).toSeq must beEqualTo(Seq(dac, mvh))) and
-      ((items.getByAppidAndItypes(appid, Seq("type3", "type4"))).toSeq must beEqualTo(Seq(lbh, mvh)))
-
-  }
-
-  def getByAppidAndItypesAndTime(items: Items) = {
-    val id = "getByAppidAndItypesAndTime_"
-    val appid = 20130423
-
-    val s1e2 = Item(id = id + "s1e2", appid = appid, ct = DateTime.now,
-      itypes = List[String](),
-      starttime = Some(new DateTime("2013-01-15T12:34:56.789-08:00")),
-      endtime = Some(new DateTime("2013-02-15T12:34:56.789-08:00")))
-
-    val s1e3a = Item(id = id + "s1e3a", appid = appid, ct = DateTime.now,
-      itypes = List[String]("a"),
-      starttime = Some(new DateTime("2013-01-15T12:34:56.789-08:00")),
-      endtime = Some(new DateTime("2013-03-15T12:34:56.789-08:00")))
-
-    val s2e3a = Item(id = id + "s2e3a", appid = appid, ct = DateTime.now,
-      itypes = List[String]("a"),
-      starttime = Some(new DateTime("2013-02-15T12:34:56.789-08:00")),
-      endtime = Some(new DateTime("2013-03-15T12:34:56.789-08:00")))
-
-    val s2e3b = Item(id = id + "s2e3b", appid = appid, ct = DateTime.now,
-      itypes = List[String]("b"),
-      starttime = Some(new DateTime("2013-02-15T12:34:56.789-08:00")),
-      endtime = Some(new DateTime("2013-03-15T12:34:56.789-08:00")))
-
-    val s4e6 = Item(id = id + "s4e6", appid = appid, ct = DateTime.now,
-      itypes = List[String](),
-      starttime = Some(new DateTime("2013-04-15T12:34:56.789-08:00")),
-      endtime = Some(new DateTime("2013-06-15T12:34:56.789-08:00")))
-
-    val s1 = Item(id = id + "s1", appid = appid, ct = DateTime.now,
-      itypes = List[String](),
-      starttime = Some(new DateTime("2013-01-15T12:34:56.789-08:00")),
-      endtime = None)
-
-    val s2 = Item(id = id + "s2", appid = appid, ct = DateTime.now,
-      itypes = List[String](),
-      starttime = Some(new DateTime("2013-02-15T12:34:56.789-08:00")),
-      endtime = None)
-
-    Seq(s1e2, s1e3a, s2e3a, s2e3b, s4e6, s1, s2).foreach { items.insert }
-
-    val t2 = new DateTime("2013-02-01T12:34:56.789-08:00")
-    val t3 = new DateTime("2013-03-01T12:34:56.789-08:00")
-
-    val tests = List(
-      (items.getByAppidAndItypesAndTime(appid, optTime = Some(t3)).toSeq
-        must containTheSameElementsAs(Seq(s1e3a, s2e3a, s2e3b, s1, s2))),
-      (items.getByAppidAndItypesAndTime(
-        appid, optItypes = Some(List("b")), optTime = Some(t3)).toSeq
-        must containTheSameElementsAs(Seq(s2e3b))),
-      (items.getByAppidAndItypesAndTime(
-        appid, optItypes = Some(List("a")), optTime = Some(t3)).toSeq
-        must containTheSameElementsAs(Seq(s1e3a, s2e3a))),
-      (items.getByAppidAndItypesAndTime(appid, optTime = Some(t2)).toSeq
-        must containTheSameElementsAs(Seq(s1e2, s1e3a, s1)))
-    )
-
-    tests.reduce(_ and _)
-  }
-
-  def getByIds(items: Items) = {
-    val id = "getByIds"
-    val appid = 4
-    val someItems = List(Item(
-      id = id + "foo",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now.hour(14).minute(13)),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((47.8948, -29.79783)),
-      inactive = None,
-      attributes = Some(Map("foo" -> "bar", "foo2" -> "bar2"))
-    ), Item(
-      id = id + "bar",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now.hour(23).minute(13)),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((47.8948, -29.79783)),
-      inactive = None,
-      attributes = None
-    ), Item(
-      id = id + "baz",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now.hour(17).minute(13)),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((47.8948, -29.79783)),
-      inactive = None,
-      attributes = Some(Map("foo3" -> "bar3"))
-    ), Item(
-      id = id + "pub",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now.hour(3).minute(13)),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((47.8948, -29.79783)),
-      inactive = None,
-      attributes = Some(Map("foo4" -> "bar4", "foo5" -> "bar5"))
-    ))
-    someItems foreach { items.insert(_) }
-    val setOfItems = items.getByIds(appid, List(id + "pub", id + "bar", id + "baz")).toSet
-    setOfItems.contains(someItems(1)) and setOfItems.contains(someItems(2)) and setOfItems.contains(someItems(3))
-  }
-
-  def getRecentByIds(items: Items) = {
-    val id = "getRecentByIds"
-    val appid = 3
-    val timedItems = List(Item(
-      id = id + "foo",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now.hour(14).minute(13)),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((47.8948, -29.79783)),
-      inactive = None,
-      attributes = Some(Map("foo" -> "bar"))
-    ), Item(
-      id = id + "bar",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now.hour(23).minute(13)),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((47.8948, -29.79783)),
-      inactive = None,
-      attributes = Some(Map("foo" -> "bar"))
-    ), Item(
-      id = id + "baz",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now.hour(17).minute(13)),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((47.8948, -29.79783)),
-      inactive = None,
-      attributes = Some(Map("foo" -> "bar"))
-    ), Item(
-      id = id + "pub",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now.hour(3).minute(13)),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((47.8948, -29.79783)),
-      inactive = None,
-      attributes = Some(Map("foo" -> "bar"))
-    ))
-    timedItems foreach { items.insert(_) }
-    items.getRecentByIds(appid, List(id + "pub", id + "bar", id + "baz")) must beEqualTo(List(timedItems(1), timedItems(2), timedItems(3)))
-  }
-
-  def update(items: Items) = {
-    val appid = 1
-    val id = "update"
-    val item = Item(
-      id = id,
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("slash", "dot"),
-      starttime = None,
-      endtime = None,
-      price = None,
-      profit = None,
-      latlng = None,
-      inactive = None,
-      attributes = Some(Map("foo" -> "baz"))
-    )
-
-    val updatedItem = item.copy(
-      endtime = Some(DateTime.now.minute(47)),
-      price = Some(99.99),
-      latlng = Some((43, 48.378)),
-      attributes = Some(Map("raw" -> "beef"))
-    )
-    items.insert(item)
-    items.update(updatedItem)
-    items.get(appid, id) must beSome(updatedItem)
-  }
-
-  def delete(items: Items) = {
-    val appid = 2
-    val id = "delete"
-    val item = Item(
-      id = id,
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now.hour(23).minute(13)),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((47.8948, -29.79783)),
-      inactive = None,
-      attributes = Some(Map("foo" -> "bar"))
-    )
-    items.delete(item)
-    items.get(appid, id) must beNone
-  }
-
-  def deleteByAppid(items: Items) = {
-    // insert a few items with appid1 and a few items with appid2.
-    // delete all items of appid1.
-    // items of appid1 should be deleted and items of appid2 should still exist.
-    // delete all items of appid2
-    // items of appid2 should be deleted
-
-    val appid1 = 10
-    val appid2 = 11
-
-    val ida = "deleteByAppid-ida"
-    val idb = "deleteByAppid-idb"
-    val idc = "deleteByAppid-idc"
-
-    val item1a = Item(
-      id = ida,
-      appid = appid1,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now.hour(23).minute(13)),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((47.8948, -29.79783)),
-      inactive = None,
-      attributes = Some(Map("foo" -> "bar"))
-    )
-    val item1b = item1a.copy(
-      id = idb,
-      price = Some(1.23)
-    )
-    val item1c = item1a.copy(
-      id = idc,
-      price = Some(2.45)
-    )
-
-    val item2a = item1a.copy(
-      appid = appid2
-    )
-    val item2b = item1b.copy(
-      appid = appid2
-    )
-    val item2c = item1c.copy(
-      appid = appid2
-    )
-
-    items.insert(item1a)
-    items.insert(item1b)
-    items.insert(item1c)
-    items.insert(item2a)
-    items.insert(item2b)
-    items.insert(item2c)
-
-    val g1_1a = items.get(appid1, ida)
-    val g1_1b = items.get(appid1, idb)
-    val g1_1c = items.get(appid1, idc)
-
-    val g1_2a = items.get(appid2, ida)
-    val g1_2b = items.get(appid2, idb)
-    val g1_2c = items.get(appid2, idc)
-
-    items.deleteByAppid(appid1)
-
-    val g2_1a = items.get(appid1, ida)
-    val g2_1b = items.get(appid1, idb)
-    val g2_1c = items.get(appid1, idc)
-
-    val g2_2a = items.get(appid2, ida)
-    val g2_2b = items.get(appid2, idb)
-    val g2_2c = items.get(appid2, idc)
-
-    items.deleteByAppid(appid2)
-
-    val g3_2a = items.get(appid2, ida)
-    val g3_2b = items.get(appid2, idb)
-    val g3_2c = items.get(appid2, idc)
-
-    (g1_1a, g1_1b, g1_1c) must be_==((Some(item1a), Some(item1b), Some(item1c))) and
-      ((g1_2a, g1_2b, g1_2c) must be_==((Some(item2a), Some(item2b), Some(item2c)))) and
-      ((g2_1a, g2_1b, g2_1c) must be_==((None, None, None))) and
-      ((g2_2a, g2_2b, g2_2c) must be_==((Some(item2a), Some(item2b), Some(item2c)))) and
-      ((g3_2a, g3_2b, g3_2c) must be_==((None, None, None)))
-
-  }
-
-  def countByAppid(items: Items) = {
-    val appid1 = 20
-    val appid2 = 21
-    val appid3 = 22
-
-    val ida = "countByAppid-ida"
-    val idb = "countByAppid-idb"
-
-    val item1a = Item(
-      id = ida,
-      appid = appid1,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now.hour(23).minute(13)),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((47.8948, -29.79783)),
-      inactive = None,
-      attributes = Some(Map("foo" -> "bar"))
-    )
-    val item1b = item1a.copy(
-      id = idb
-    )
-    val item2a = item1a.copy(
-      appid = appid2
-    )
-
-    items.insert(item1a)
-    items.insert(item1b)
-    items.insert(item2a)
-
-    items.countByAppid(appid1) must be_==(2) and
-      (items.countByAppid(appid2) must be_==(1)) and
-      (items.countByAppid(appid3) must be_==(0))
-  }
-}
diff --git a/commons/src/test/scala/io/prediction/commons/appdata/U2IActionsSpec.scala b/commons/src/test/scala/io/prediction/commons/appdata/U2IActionsSpec.scala
deleted file mode 100644
index ff7f219..0000000
--- a/commons/src/test/scala/io/prediction/commons/appdata/U2IActionsSpec.scala
+++ /dev/null
@@ -1,285 +0,0 @@
-package io.prediction.commons.appdata
-
-import io.prediction.commons.Spec
-
-import org.specs2._
-import org.specs2.specification.Step
-
-import com.mongodb.casbah.Imports._
-import com.github.nscala_time.time.Imports._
-
-class U2IActionsSpec extends Specification {
-  def is = s2"""
-
-  PredictionIO App Data User-to-item Actions Specification
-
-    U2IActions can be implemented by:
-    - MongoU2IActions ${mongoU2IActions}
-
-  """
-
-  def mongoU2IActions = s2"""
-
-    MongoU2IActions should" ^
-    - behave like any U2IActions implementation ${u2iActions(newMongoU2IActions)}
-    - (database cleanup) ${Step(Spec.mongoClient(mongoDbName).dropDatabase())}
-
-  """
-
-  def u2iActions(u2iActions: U2IActions) = s2"""
-
-    inserting and getting 3 U2IAction's ${insert(u2iActions)}
-    getting U2IActions by App ID, User ID, and Item IDs ${getAllByAppidAndUidAndIids(u2iActions)}
-    getting U2IActions by App ID, Item ${getAllByAppidAndIid(u2iActions)}
-    delete U2IActions by appid ${deleteByAppid(u2iActions)}
-    count U2IActions by appid ${countByAppid(u2iActions)}
-
-  """
-
-  val mongoDbName = "predictionio_appdata_mongou2iactions_test"
-  def newMongoU2IActions = new mongodb.MongoU2IActions(Spec.mongoClient(mongoDbName))
-
-  def insert(u2iActions: U2IActions) = {
-    val appid = 0
-    val actions = List(U2IAction(
-      appid = appid,
-      action = u2iActions.rate,
-      uid = "dead",
-      iid = "meat",
-      t = DateTime.now,
-      latlng = None,
-      v = Some(3),
-      price = None
-    ), U2IAction(
-      appid = appid,
-      action = u2iActions.view,
-      uid = "avatar",
-      iid = "creeper",
-      t = DateTime.now,
-      latlng = Some((94.3904, -29.4839)),
-      v = None,
-      price = None
-    ), U2IAction(
-      appid = appid,
-      action = u2iActions.like,
-      uid = "pub",
-      iid = "sub",
-      t = DateTime.now,
-      latlng = None,
-      v = Some(1),
-      price = Some(49.40)
-    ))
-    actions foreach { u2iActions.insert(_) }
-    val results = u2iActions.getAllByAppid(appid)
-    val r1 = results.next
-    val r2 = results.next
-    val r3 = results.next
-    results.hasNext must beFalse and
-      (r1 must beEqualTo(actions(0))) and
-      (r2 must beEqualTo(actions(1))) and
-      (r3 must beEqualTo(actions(2)))
-  }
-
-  def getAllByAppidAndUidAndIids(u2iActions: U2IActions) = {
-    val appid = 1
-    val actions = List(U2IAction(
-      appid = appid,
-      action = u2iActions.rate,
-      uid = "dead",
-      iid = "meat",
-      t = DateTime.now,
-      latlng = None,
-      v = Some(3),
-      price = None
-    ), U2IAction(
-      appid = appid,
-      action = u2iActions.view,
-      uid = "dead",
-      iid = "creeper",
-      t = DateTime.now,
-      latlng = Some((94.3904, -29.4839)),
-      v = None,
-      price = None
-    ), U2IAction(
-      appid = appid,
-      action = u2iActions.like,
-      uid = "dead",
-      iid = "sub",
-      t = DateTime.now,
-      latlng = None,
-      v = Some(1),
-      price = Some(49.40)
-    ))
-    actions foreach { u2iActions.insert(_) }
-    val results = u2iActions.getAllByAppidAndUidAndIids(appid, "dead", List("sub", "meat")).toList.sortWith((s, t) => s.iid < t.iid)
-    results.size must beEqualTo(2) and
-      (results(0) must beEqualTo(actions(0))) and
-      (results(1) must beEqualTo(actions(2)))
-  }
-
-  def getAllByAppidAndIid(u2iActions: U2IActions) = {
-    val appid = 109
-    val actions = List(U2IAction(
-      appid = appid,
-      action = u2iActions.rate,
-      uid = "dead",
-      iid = "meat",
-      t = DateTime.now,
-      latlng = None,
-      v = Some(3),
-      price = None
-    ), U2IAction(
-      appid = appid,
-      action = u2iActions.view,
-      uid = "dead",
-      iid = "creeper",
-      t = DateTime.now,
-      latlng = Some((94.3904, -29.4839)),
-      v = None,
-      price = None
-    ), U2IAction(
-      appid = appid,
-      action = u2iActions.like,
-      uid = "dead",
-      iid = "sub",
-      t = DateTime.now,
-      latlng = None,
-      v = Some(1),
-      price = Some(49.40)
-    ), U2IAction(
-      appid = appid,
-      action = u2iActions.rate,
-      uid = "dead2",
-      iid = "meat",
-      t = DateTime.now,
-      latlng = None,
-      v = Some(2),
-      price = None
-    ), U2IAction(
-      appid = appid,
-      action = u2iActions.rate,
-      uid = "dead3",
-      iid = "meat",
-      t = DateTime.now,
-      latlng = None,
-      v = Some(5),
-      price = None
-    ), U2IAction(
-      appid = appid,
-      action = u2iActions.rate,
-      uid = "dead4",
-      iid = "meat",
-      t = DateTime.now,
-      latlng = None,
-      v = Some(1),
-      price = None
-    ))
-    actions foreach { u2iActions.insert(_) }
-    val results = u2iActions.getAllByAppidAndIid(appid, "meat", sortedByUid = true).toList
-    val resultsNoSort = u2iActions.getAllByAppidAndIid(appid, "meat", sortedByUid = false).toList.sortWith((s, t) => s.uid < t.uid)
-
-    results.size must beEqualTo(4) and
-      (results(0) must beEqualTo(actions(0))) and
-      (results(1) must beEqualTo(actions(3))) and
-      (results(2) must beEqualTo(actions(4))) and
-      (results(3) must beEqualTo(actions(5))) and
-      (resultsNoSort(0) must beEqualTo(actions(0))) and
-      (resultsNoSort(1) must beEqualTo(actions(3))) and
-      (resultsNoSort(2) must beEqualTo(actions(4))) and
-      (resultsNoSort(3) must beEqualTo(actions(5)))
-  }
-
-  def deleteByAppid(u2iActions: U2IActions) = {
-    // insert a few u2iActions with appid1 and a few u2iActions with appid2.
-    // delete all u2iActions of appid1.
-    // u2iActions of appid1 should be deleted and u2iActions of appid2 should still exist.
-    // delete all u2iActions of appid2
-    // u2iActions of appid2 should be deleted
-
-    val appid1 = 10
-    val appid2 = 11
-
-    val ida = "deleteByAppid-ida"
-    val idb = "deleteByAppid-idb"
-    val idc = "deleteByAppid-idc"
-
-    val u2iAction1a = U2IAction(
-      appid = appid1,
-      action = u2iActions.rate,
-      uid = "dead",
-      iid = "meat",
-      t = DateTime.now,
-      latlng = None,
-      v = Some(3),
-      price = None
-    )
-    val u2iActionsApp1 = List(
-      u2iAction1a,
-      u2iAction1a.copy(
-        v = Some(1)
-      ),
-      u2iAction1a.copy(
-        v = Some(2)
-      ))
-
-    val u2iActionsApp2 = u2iActionsApp1 map (x => x.copy(appid = appid2))
-
-    u2iActionsApp1 foreach { u2iActions.insert(_) }
-    u2iActionsApp2 foreach { u2iActions.insert(_) }
-
-    // NOTE: Call toList to retrieve all results first.
-    // If call toList after delete, the data is gone because getAllByAppid returns
-    // iterator which doesn't actually retrieve the result yet.
-    val g1_App1 = u2iActions.getAllByAppid(appid1).toList
-    val g1_App2 = u2iActions.getAllByAppid(appid2).toList
-
-    u2iActions.deleteByAppid(appid1)
-
-    val g2_App1 = u2iActions.getAllByAppid(appid1).toList
-    val g2_App2 = u2iActions.getAllByAppid(appid2).toList
-
-    u2iActions.deleteByAppid(appid2)
-
-    val g3_App2 = u2iActions.getAllByAppid(appid2).toList
-
-    g1_App1 must containTheSameElementsAs(u2iActionsApp1) and
-      (g1_App2 must containTheSameElementsAs(u2iActionsApp2)) and
-      (g2_App1 must be empty) and
-      (g2_App2 must containTheSameElementsAs(u2iActionsApp2)) and
-      (g3_App2 must be empty)
-
-  }
-
-  def countByAppid(u2iActions: U2IActions) = {
-    val appid1 = 20
-    val appid2 = 21
-    val appid3 = 22
-
-    val u2iAction1a = U2IAction(
-      appid = appid1,
-      action = u2iActions.rate,
-      uid = "dead",
-      iid = "meat",
-      t = DateTime.now,
-      latlng = None,
-      v = Some(3),
-      price = None
-    )
-    val u2iAction1b = u2iAction1a.copy(
-      appid = appid1
-    )
-    val u2iAction2a = u2iAction1a.copy(
-      appid = appid2
-    )
-
-    u2iActions.insert(u2iAction1a)
-    u2iActions.insert(u2iAction1b)
-    u2iActions.insert(u2iAction2a)
-
-    u2iActions.countByAppid(appid1) must be_==(2) and
-      (u2iActions.countByAppid(appid2) must be_==(1)) and
-      (u2iActions.countByAppid(appid3) must be_==(0))
-
-  }
-
-}
diff --git a/commons/src/test/scala/io/prediction/commons/appdata/UsersSpec.scala b/commons/src/test/scala/io/prediction/commons/appdata/UsersSpec.scala
deleted file mode 100644
index e5da249..0000000
--- a/commons/src/test/scala/io/prediction/commons/appdata/UsersSpec.scala
+++ /dev/null
@@ -1,250 +0,0 @@
-package io.prediction.commons.appdata
-
-import io.prediction.commons.Spec
-
-import org.specs2._
-import org.specs2.specification.Step
-
-import com.mongodb.casbah.Imports._
-import com.github.nscala_time.time.Imports._
-
-class UsersSpec extends Specification {
-  def is = s2"""
-
-  PredictionIO App Data Users Specification
-
-    Users can be implemented by:
-    - MongoUsers ${mongoUsers}
-
-  """
-
-  def mongoUsers = s2"""
-
-    MongoUsers should
-    - behave like any Users implementation ${users(newMongoUsers)}
-    - (database cleanup) ${Step(Spec.mongoClient(mongoDbName).dropDatabase())}
-
-  """
-
-  def users(users: Users) = s2"""
-
-    inserting and getting a user ${insert(users)}
-    getting all users by App ID ${getByAppid(users)}
-    updating a user ${update(users)}
-    deleting a user ${delete(users)}
-    deleting users by appid ${deleteByAppid(users)}
-    count users by appid ${countByAppid(users)}
-
-  """
-
-  val mongoDbName = "predictionio_appdata_mongousers_test"
-  def newMongoUsers = new mongodb.MongoUsers(Spec.mongoClient(mongoDbName))
-
-  def insert(users: Users) = {
-    val appid = 0
-    val id1 = "insert1"
-    val user1 = User(
-      id = id1,
-      appid = appid,
-      ct = DateTime.now,
-      latlng = Some((47.8948, -29.79783)),
-      inactive = None,
-      attributes = Some(Map("foo" -> "bar"))
-    )
-    val id2 = "insert2"
-    val user2 = User(
-      id = id2,
-      appid = appid,
-      ct = DateTime.now,
-      latlng = Some((47.8948, -29.79783)),
-      inactive = Some(true),
-      attributes = None
-    )
-    users.insert(user1)
-    users.insert(user2)
-    users.get(appid, id1) must beSome(user1) and
-      (users.get(appid, id2) must beSome(user2))
-
-  }
-
-  def getByAppid(users: Users) = {
-    val appid = 3
-    val ourUsers = List(
-      User(
-        id = "getByAppid-3",
-        appid = appid,
-        ct = DateTime.now,
-        latlng = Some((47.8948, -29.79783)),
-        inactive = None,
-        attributes = Some(Map("foo" -> "bar"))),
-      User(
-        id = "getByAppid-2",
-        appid = appid,
-        ct = DateTime.now,
-        latlng = Some((47.8948, -29.79783)),
-        inactive = None,
-        attributes = Some(Map("foo" -> "bar"))),
-      User(
-        id = "getByAppid-1",
-        appid = appid,
-        ct = DateTime.now,
-        latlng = Some((47.8948, -29.79783)),
-        inactive = None,
-        attributes = Some(Map("foo" -> "bar"))))
-    ourUsers foreach { users.insert(_) }
-    val getUsers = users.getByAppid(appid).toList.sortWith((x, y) => x.id < y.id)
-    getUsers(0) must beEqualTo(ourUsers(2)) and
-      (getUsers(1) must beEqualTo(ourUsers(1))) and
-      (getUsers(2) must beEqualTo(ourUsers(0)))
-  }
-
-  def update(users: Users) = {
-    val appid = 1
-    val id = "update"
-    val user = User(
-      id = id,
-      appid = appid,
-      ct = DateTime.now,
-      latlng = Some((47.8948, -29.79783)),
-      inactive = None,
-      attributes = Some(Map("foo" -> "bar"))
-    )
-    val updatedUser = user.copy(
-      latlng = None,
-      inactive = Some(true),
-      attributes = Some(Map("dead" -> "beef"))
-    )
-    users.insert(user)
-    users.update(updatedUser)
-    users.get(appid, id) must beSome(updatedUser)
-  }
-
-  def delete(users: Users) = {
-    val appid = 2
-    val id = "delete"
-    val user = User(
-      id = id,
-      appid = appid,
-      ct = DateTime.now,
-      latlng = Some((47.8948, -29.79783)),
-      inactive = None,
-      attributes = Some(Map("foo" -> "bar"))
-    )
-    users.delete(user)
-    users.get(appid, id) must beNone
-  }
-
-  def deleteByAppid(users: Users) = {
-    // insert a few users with appid1 and a few users with appid2.
-    // delete all users of appid1.
-    // users of appid1 should be deleted and users of appid2 should still exist.
-    // delete all users of appid2
-    // users of appid2 should be deleted
-
-    val appid1 = 10
-    val appid2 = 11
-
-    val ida = "deleteByAppid-ida"
-    val idb = "deleteByAppid-idb"
-    val idc = "deleteByAppid-idc"
-
-    val user1a = User(
-      id = ida,
-      appid = appid1,
-      ct = DateTime.now,
-      latlng = Some((47.8948, -29.79783)),
-      inactive = None,
-      attributes = Some(Map("c" -> "d"))
-    )
-    val user1b = user1a.copy(
-      id = idb,
-      attributes = Some(Map("e" -> "f"))
-    )
-    val user1c = user1a.copy(
-      id = idc,
-      attributes = Some(Map("g" -> "h"))
-    )
-
-    val user2a = user1a.copy(
-      appid = appid2
-    )
-    val user2b = user1b.copy(
-      appid = appid2
-    )
-    val user2c = user1c.copy(
-      appid = appid2
-    )
-
-    users.insert(user1a)
-    users.insert(user1b)
-    users.insert(user1c)
-    users.insert(user2a)
-    users.insert(user2b)
-    users.insert(user2c)
-
-    val g1_1a = users.get(appid1, ida)
-    val g1_1b = users.get(appid1, idb)
-    val g1_1c = users.get(appid1, idc)
-
-    val g1_2a = users.get(appid2, ida)
-    val g1_2b = users.get(appid2, idb)
-    val g1_2c = users.get(appid2, idc)
-
-    users.deleteByAppid(appid1)
-
-    val g2_1a = users.get(appid1, ida)
-    val g2_1b = users.get(appid1, idb)
-    val g2_1c = users.get(appid1, idc)
-
-    val g2_2a = users.get(appid2, ida)
-    val g2_2b = users.get(appid2, idb)
-    val g2_2c = users.get(appid2, idc)
-
-    users.deleteByAppid(appid2)
-
-    val g3_2a = users.get(appid2, ida)
-    val g3_2b = users.get(appid2, idb)
-    val g3_2c = users.get(appid2, idc)
-
-    (g1_1a, g1_1b, g1_1c) must be_==((Some(user1a), Some(user1b), Some(user1c))) and
-      ((g1_2a, g1_2b, g1_2c) must be_==((Some(user2a), Some(user2b), Some(user2c)))) and
-      ((g2_1a, g2_1b, g2_1c) must be_==((None, None, None))) and
-      ((g2_2a, g2_2b, g2_2c) must be_==((Some(user2a), Some(user2b), Some(user2c)))) and
-      ((g3_2a, g3_2b, g3_2c) must be_==((None, None, None)))
-
-  }
-
-  def countByAppid(users: Users) = {
-    val appid1 = 23
-    val appid2 = 24
-    val appid3 = 25
-
-    val ida = "countByAppid-ida"
-    val idb = "countByAppid-idb"
-
-    val user1a = User(
-      id = ida,
-      appid = appid1,
-      ct = DateTime.now,
-      latlng = Some((47.8948, -29.79783)),
-      inactive = None,
-      attributes = Some(Map("c" -> "d"))
-    )
-    val user1b = user1a.copy(
-      id = idb,
-      appid = appid1,
-      attributes = Some(Map("e" -> "f"))
-    )
-    val user2a = user1a.copy(
-      appid = appid2
-    )
-
-    users.insert(user1a)
-    users.insert(user1b)
-    users.insert(user2a)
-
-    users.countByAppid(appid1) must be_==(2) and
-      (users.countByAppid(appid2) must be_==(1)) and
-      (users.countByAppid(appid3) must be_==(0))
-  }
-}
diff --git a/commons/src/test/scala/io/prediction/commons/filepath/EngineFileTest.scala b/commons/src/test/scala/io/prediction/commons/filepath/EngineFileTest.scala
deleted file mode 100644
index 474f0be..0000000
--- a/commons/src/test/scala/io/prediction/commons/filepath/EngineFileTest.scala
+++ /dev/null
@@ -1,87 +0,0 @@
-package io.prediction.commons.filepath
-
-import org.specs2.mutable._
-
-class EngineFileTest extends Specification {
-
-  "BaseDir" should {
-    "correctly return appDir" in {
-      BaseDir.appDir("testroot/", appId = 4) must be_==("testroot/apps/4/")
-    }
-    "correctly return engineDir" in {
-      BaseDir.engineDir("testroot/", appId = 4, engineId = 5) must be_==("testroot/apps/4/engines/5/")
-    }
-    "correctly return offlineEvalDir" in {
-      BaseDir.offlineEvalDir("testroot/", appId = 4, engineId = 5, evalId = 6) must be_==("testroot/apps/4/engines/5/offlineeval/6/")
-    }
-    "correctly return algoDir" in {
-      BaseDir.algoDir("testroot/", appId = 4, engineId = 5, algoId = 7, evalId = None) must be_==("testroot/apps/4/engines/5/batch/algos/7/")
-    }
-    "correctly return algoDir for offline eval" in {
-      BaseDir.algoDir("testroot/", appId = 4, engineId = 5, algoId = 7, evalId = Some(8)) must be_==("testroot/apps/4/engines/5/offlineeval/8/algos/7/")
-    }
-    "correctly return offlineMetricDir" in {
-      BaseDir.offlineMetricDir("testroot/", appId = 4, engineId = 5, algoId = 17, evalId = 8, metricId = 9) must be_==("testroot/apps/4/engines/5/offlineeval/8/metrics/9/algos/17/")
-    }
-  }
-
-  // simple tests
-  "DataFile" should {
-    "correctly return path in batch mode" in {
-      DataFile("hdfs/predictionio/", 21, 4, 20, None, "test6.tsv") must be_==("hdfs/predictionio/apps/21/engines/4/batch/algos/20/data/test6.tsv")
-    }
-    "correctly return path in offline eval mode" in {
-      DataFile("hdfs/predictionio/", 12, 5, 1, Some(9), "test7.tsv") must be_==("hdfs/predictionio/apps/12/engines/5/offlineeval/9/algos/1/data/test7.tsv")
-    }
-  }
-
-  "AlgoFile" should {
-    "correctly return path in batch mode" in {
-      AlgoFile("hdfs/predictionio/", 22, 4, 20, None, "test10.tsv") must be_==("hdfs/predictionio/apps/22/engines/4/batch/algos/20/algo/test10.tsv")
-    }
-    "correctly return path in offline eval mode" in {
-      AlgoFile("hdfs/predictionio/", 23, 3, 12, Some(101), "test22.tsv") must be_==("hdfs/predictionio/apps/23/engines/3/offlineeval/101/algos/12/algo/test22.tsv")
-    }
-  }
-
-  "OfflineMetricFile" should {
-    "corretly return path" in {
-      OfflineMetricFile("hdfs/predictionio/", 2, 11, 22, 33, 44, "test.tsv") must be_==("hdfs/predictionio/apps/2/engines/11/offlineeval/22/metrics/33/algos/44/metric/test.tsv")
-    }
-  }
-
-  "U2ITrainingTestSplitFile" should {
-    "correctly return path" in {
-      U2ITrainingTestSplitFile("hdfs/predictionio/", 2, 4, 6, "test8.tsv") must be_==("hdfs/predictionio/apps/2/engines/4/offlineeval/6/u2itrainingtestsplit/test8.tsv")
-    }
-  }
-
-  "ModelDataDir" should {
-    "correctly return path in batch mode" in {
-      ModelDataDir("hdfs/predictionio/", 24, 6, 7, None) must be_==("hdfs/predictionio/apps/24/engines/6/batch/algos/7/modeldata/")
-    }
-    "correctly return path in offline eval mode" in {
-      ModelDataDir("hdfs/predictionio/", 21, 5, 6, Some(11)) must be_==("hdfs/predictionio/apps/21/engines/5/offlineeval/11/algos/6/modeldata/")
-    }
-  }
-
-  "OfflineEvalResultsDir" should {
-    "corretly return path" in {
-      OfflineEvalResultsDir("hdfs/predictionio/", 3, 12, 23, 34, 45) must be_==("hdfs/predictionio/apps/3/engines/12/offlineeval/23/metrics/34/algos/45/evalresults/")
-    }
-  }
-
-  "AppDataDir" should {
-    "correctly return path" in {
-      AppDataDir("hdfs/predictionio/", 8, None, None, None) must be_==("hdfs/predictionio/apps/8/appdata/")
-    }
-    "correctly return path in offline eval mode and test set" in {
-      AppDataDir("hdfs/predictionio/", 7, Some(2), Some(3), Some(true)) must be_==("hdfs/predictionio/apps/7/engines/2/offlineeval/3/appdata/test/")
-    }
-    "correctly return path in offline eval mode and training set" in {
-      AppDataDir("hdfs/predictionio/", 6, Some(2), Some(3), Some(false)) must be_==("hdfs/predictionio/apps/6/engines/2/offlineeval/3/appdata/training/")
-    }
-
-  }
-
-}
diff --git a/commons/src/test/scala/io/prediction/commons/modeldata/ItemRecScoresSpec.scala b/commons/src/test/scala/io/prediction/commons/modeldata/ItemRecScoresSpec.scala
deleted file mode 100644
index 377066e..0000000
--- a/commons/src/test/scala/io/prediction/commons/modeldata/ItemRecScoresSpec.scala
+++ /dev/null
@@ -1,356 +0,0 @@
-package io.prediction.commons.modeldata
-
-import io.prediction.commons.Config
-import io.prediction.commons.Spec
-import io.prediction.commons.settings.{ Algo, App }
-
-import org.specs2._
-import org.specs2.specification.Step
-import com.mongodb.casbah.Imports._
-import com.github.nscala_time.time.Imports._
-
-class ItemRecScoresSpec extends Specification {
-  def is = s2"""
-
-    PredictionIO Model Data Item Recommendation Scores Specification
-
-    ItemRecScores can be implemented by:
-    1. MongoItemRecScores ${mongoItemRecScores}
-
-  """
-
-  def mongoItemRecScores = s2"""
-
-    MongoItemRecScores should
-
-    - behave like any ItemRecScores implementation ${itemRecScores(newMongoItemRecScores)}
-
-    (clean up database after test) ${Step(Spec.mongoClient(mongoDbName).dropDatabase())}
-
-  """
-
-  def itemRecScores(itemRecScores: ItemRecScores) = s2"""
-
-    inserting and getting 3 ItemRecScores ${insert(itemRecScores)}
-    getting Top N Iids ${getTopNIids(itemRecScores)}
-    delete ItemRecScores by algoid ${deleteByAlgoid(itemRecScores)}
-    existence by Algo ${existByAlgo(itemRecScores)}
-
-  """
-
-  val mongoDbName = "predictionio_modeldata_mongoitemrecscore_test"
-
-  def newMongoItemRecScores = new mongodb.MongoItemRecScores(
-    new Config, Spec.mongoClient(mongoDbName))
-
-  def insert(itemRecScores: ItemRecScores) = {
-    implicit val app = App(
-      id = 0,
-      userid = 0,
-      appkey = "",
-      display = "",
-      url = None,
-      cat = None,
-      desc = None,
-      timezone = "UTC"
-    )
-    implicit val algo = Algo(
-      id = 110101,
-      engineid = 0,
-      name = "",
-      infoid = "abc",
-      command = "",
-      params = Map(),
-      settings = Map(),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed",
-      offlineevalid = None,
-      offlinetuneid = None,
-      loop = None,
-      paramset = None
-    )
-    val itemScores = List(ItemRecScore(
-      uid = "testUser",
-      iids = Seq("testUserItem4", "testUserItem3", "testUserItem2",
-        "testUserItem1"),
-      scores = Seq(999, 124.678, 10, -5.6),
-      itypes = Seq(List("invalid"), List("7", "8", "9"), List("4", "5", "6"),
-        List("1", "2", "3")),
-      appid = app.id,
-      algoid = algo.id,
-      modelset = algo.modelset
-    ), ItemRecScore(
-      uid = "testUser2",
-      iids = Seq("b", "c", "d", "e"),
-      scores = Seq(8, 5.4, 2, 1),
-      itypes = Seq(List("invalid"), List("7"), List("6"), List("1", "2", "3")),
-      appid = app.id,
-      algoid = algo.id,
-      modelset = algo.modelset
-    ), ItemRecScore(
-      uid = "testUser3",
-      iids = Seq("b", "c", "e", "s"),
-      scores = Seq(999, 124.678, 10, -5.6),
-      itypes = Seq(List("1"), List("7", "8", "9"), List("4", "5", "6"),
-        List("1")),
-      appid = app.id,
-      algoid = algo.id,
-      modelset = algo.modelset
-    ))
-    val dbItemScores = itemRecScores.insert(itemScores)
-    val results = itemRecScores.getByUid("testUser")
-    val results2 = itemRecScores.getByUid("testUser2")
-    val results3 = itemRecScores.getByUid("testUser3")
-
-    results must beSome(dbItemScores(0)) and
-      (results2 must beSome(dbItemScores(1))) and
-      (results3 must beSome(dbItemScores(2)))
-  }
-
-  def getTopNIids(itemRecScores: ItemRecScores) = {
-    implicit val app = App(
-      id = 234,
-      userid = 0,
-      appkey = "",
-      display = "",
-      url = None,
-      cat = None,
-      desc = None,
-      timezone = "UTC")
-    implicit val algo = Algo(
-      id = 234,
-      engineid = 0,
-      name = "",
-      infoid = "abc",
-      command = "",
-      params = Map(),
-      settings = Map(),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed",
-      offlineevalid = None,
-      offlinetuneid = None,
-      loop = None,
-      paramset = None)
-    val itemScores = List(ItemRecScore(
-      uid = "testUser",
-      iids = Seq("testUserItem10", "testUserItem8", "testUserItem4",
-        "testUserItem9", "testUserItem7", "testUserItem3", "testUserItem2",
-        "testUserItem6", "testUserItem1", "testUserItem5"),
-      scores = Seq(10000, 999, 999, 124.678, 124.678, 124.678, 10, 10, -5.6,
-        -5.6),
-      itypes = Seq(List("invalid"), List("invalid"), List("invalid"),
-        List("1", "2", "3"), List("1", "2", "4"), List("3"),
-        List("5", "6", "7"), List("5", "6", "8"), List("1", "2", "3"),
-        List("1", "2", "3")),
-      appid = app.id,
-      algoid = algo.id,
-      modelset = true
-    ))
-
-    val dbItemScores = itemScores map {
-      itemRecScores.insert(_)
-    }
-
-    val resultsAllTop5 = itemRecScores.getTopNIidsAndScores("testUser", 5, None)
-    val resultsAllTop1 = itemRecScores.getTopNIidsAndScores("testUser", 1, None)
-    val resultsAllTop0 = itemRecScores.getTopNIidsAndScores("testUser", 0, None)
-    val results23Top4 = itemRecScores.getTopNIids("testUser", 4,
-      Some(List("2", "3"))).toSeq
-    val results23Top100 = itemRecScores.getTopNIids("testUser", 100,
-      Some(List("2", "3"))).toSeq
-    val results8Top4 = itemRecScores.getTopNIids("testUser", 4,
-      Some(List("8"))).toSeq
-    val results8Top0 = itemRecScores.getTopNIids("testUser", 0,
-      Some(List("8"))).toSeq
-    val resultUnknownAllTop4 = itemRecScores.getTopNIids("unknown", 4,
-      None).toSeq
-    val resultUnknown18Top4 = itemRecScores.getTopNIids("unknown", 4,
-      Some(List("1", "8"))).toSeq
-
-    resultsAllTop5 must beEqualTo(Seq(("testUserItem10", 10000.0),
-      ("testUserItem8", 999.0), ("testUserItem4", 999.0),
-      ("testUserItem9", 124.678), ("testUserItem7", 124.678))) and
-      (resultsAllTop1 must beEqualTo(Seq(("testUserItem10", 10000)))) and
-      (resultsAllTop0 must beEqualTo(Seq(("testUserItem10", 10000),
-        ("testUserItem8", 999), ("testUserItem4", 999),
-        ("testUserItem9", 124.678), ("testUserItem7", 124.678),
-        ("testUserItem3", 124.678), ("testUserItem2", 10),
-        ("testUserItem6", 10), ("testUserItem1", -5.6),
-        ("testUserItem5", -5.6)))) and
-      (results23Top4 must beEqualTo(Seq("testUserItem9", "testUserItem7",
-        "testUserItem3", "testUserItem1"))) and
-      (results23Top100 must beEqualTo(Seq("testUserItem9", "testUserItem7",
-        "testUserItem3", "testUserItem1", "testUserItem5"))) and
-      (results8Top4 must beEqualTo(Seq("testUserItem6"))) and
-      (results8Top0 must beEqualTo(Seq("testUserItem6"))) and
-      (resultUnknownAllTop4 must beEqualTo(Seq())) and
-      (resultUnknown18Top4 must beEqualTo(Seq()))
-  }
-
-  def deleteByAlgoid(itemRecScores: ItemRecScores) = {
-
-    implicit val app = App(
-      id = 0,
-      userid = 0,
-      appkey = "",
-      display = "",
-      url = None,
-      cat = None,
-      desc = None,
-      timezone = "UTC"
-    )
-
-    val algo1 = Algo(
-      id = 1,
-      engineid = 0,
-      name = "algo1",
-      infoid = "abc",
-      command = "",
-      params = Map(),
-      settings = Map(),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed",
-      offlineevalid = None,
-      offlinetuneid = None,
-      loop = None,
-      paramset = None
-    )
-
-    val algo2 = algo1.copy(id = 2) // NOTE: different id
-
-    val itemScores1 = List(ItemRecScore(
-      uid = "deleteByAlgoidUser",
-      iids = Seq("testUserItem10", "testUserItem8", "testUserItem4",
-        "testUserItem9", "testUserItem7", "testUserItem3", "testUserItem2",
-        "testUserItem6", "testUserItem1", "testUserItem5"),
-      scores = Seq(10000, 999, 999, 124.678, 124.678, 124.678, 10, 10, -5.6,
-        -5.6),
-      itypes = Seq(List("invalid"), List("invalid"), List("invalid"),
-        List("1", "2", "3"), List("1", "2", "4"), List("2", "3", "4"),
-        List("5", "6", "7"), List("5", "6", "8"), List("1", "2", "3"),
-        List("1", "2", "3")),
-      appid = app.id,
-      algoid = algo1.id,
-      modelset = algo1.modelset
-    ), ItemRecScore(
-      uid = "deleteByAlgoidUser2",
-      iids = Seq("a", "b", "c", "d"),
-      scores = Seq(10, 9, 8, 7),
-      itypes = Seq(List("invalid"), List("5", "6", "7"), List("5", "6", "8"),
-        List("4")),
-      appid = app.id,
-      algoid = algo1.id,
-      modelset = algo1.modelset
-    ))
-
-    val itemScores2 = List(ItemRecScore(
-      uid = "deleteByAlgoidUser",
-      iids = Seq("testUserItem10", "testUserItem8", "testUserItem4",
-        "testUserItem9", "testUserItem7", "testUserItem3", "testUserItem2",
-        "testUserItem6", "testUserItem1", "testUserItem5"),
-      scores = Seq(10000, 999, 999, 124.678, 124.678, 124.678, 10, 10, -5.6,
-        -5.6),
-      itypes = Seq(List("invalid"), List("invalid"), List("invalid"),
-        List("1", "2", "3"), List("1", "2", "4"), List("2", "3", "4"),
-        List("5", "6", "7"), List("5", "6", "8"), List("1", "2", "3"),
-        List("1", "2", "3")),
-      appid = app.id,
-      algoid = algo2.id,
-      modelset = algo2.modelset
-    ), ItemRecScore(
-      uid = "deleteByAlgoidUser2",
-      iids = Seq("a", "b", "c", "d"),
-      scores = Seq(10, 9, 8, 7),
-      itypes = Seq(List("invalid"), List("5", "6", "7"), List("5", "6", "8"),
-        List("4")),
-      appid = app.id,
-      algoid = algo2.id,
-      modelset = algo2.modelset
-    ))
-
-    val dbItemScores1 = itemScores1 map {
-      itemRecScores.insert(_)
-    }
-
-    val dbItemScores2 = itemScores2 map {
-      itemRecScores.insert(_)
-    }
-
-    val results1 = itemRecScores.getByUid("deleteByAlgoidUser")(app, algo1)
-    val results1u2 = itemRecScores.getByUid("deleteByAlgoidUser2")(app, algo1)
-    val results2 = itemRecScores.getByUid("deleteByAlgoidUser")(app, algo2)
-    val results2u2 = itemRecScores.getByUid("deleteByAlgoidUser2")(app, algo2)
-
-    itemRecScores.deleteByAlgoid(algo1.id)
-
-    val results1b = itemRecScores.getByUid("deleteByAlgoidUser")(app, algo1)
-    val results1bu2 = itemRecScores.getByUid("deleteByAlgoidUser2")(app, algo1)
-    val results2b = itemRecScores.getByUid("deleteByAlgoidUser")(app, algo2)
-    val results2bu2 = itemRecScores.getByUid("deleteByAlgoidUser2")(app, algo2)
-
-    itemRecScores.deleteByAlgoid(algo2.id)
-
-    val results2c = itemRecScores.getByUid("deleteByAlgoidUser")(app, algo2)
-    val results2cu2 = itemRecScores.getByUid("deleteByAlgoidUser2")(app, algo2)
-
-    results1 must beSome(dbItemScores1(0)) and
-      (results1u2 must beSome(dbItemScores1(1))) and
-      (results2 must beSome(dbItemScores2(0))) and
-      (results2u2 must beSome(dbItemScores2(1))) and
-      (results1b must beNone) and
-      (results1bu2 must beNone) and
-      (results2b must beSome(dbItemScores2(0))) and
-      (results2bu2 must beSome(dbItemScores2(1))) and
-      (results2c must beNone) and
-      (results2cu2 must beNone)
-
-  }
-
-  def existByAlgo(itemRecScores: ItemRecScores) = {
-    implicit val app = App(
-      id = 345,
-      userid = 0,
-      appkey = "",
-      display = "",
-      url = None,
-      cat = None,
-      desc = None,
-      timezone = "UTC"
-    )
-    val algo1 = Algo(
-      id = 345,
-      engineid = 0,
-      name = "",
-      infoid = "dummy",
-      command = "",
-      params = Map(),
-      settings = Map(),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed",
-      offlineevalid = None,
-      offlinetuneid = None,
-      loop = None,
-      paramset = None
-    )
-    val algo2 = algo1.copy(id = 3456)
-    itemRecScores.insert(ItemRecScore(
-      uid = "testUser",
-      iids = Seq("testUserItem4"),
-      scores = Seq(999),
-      itypes = Seq(List("invalid")),
-      appid = app.id,
-      algoid = algo1.id,
-      modelset = algo1.modelset
-    ))
-    itemRecScores.existByAlgo(algo1) must beTrue and
-      (itemRecScores.existByAlgo(algo2) must beFalse)
-  }
-}
diff --git a/commons/src/test/scala/io/prediction/commons/modeldata/ItemSimScoresSpec.scala b/commons/src/test/scala/io/prediction/commons/modeldata/ItemSimScoresSpec.scala
deleted file mode 100644
index 56a5f87..0000000
--- a/commons/src/test/scala/io/prediction/commons/modeldata/ItemSimScoresSpec.scala
+++ /dev/null
@@ -1,361 +0,0 @@
-package io.prediction.commons.modeldata
-
-import io.prediction.commons.Config
-import io.prediction.commons.Spec
-import io.prediction.commons.settings.{ Algo, App }
-
-import org.specs2._
-import org.specs2.specification.Step
-import com.mongodb.casbah.Imports._
-import com.github.nscala_time.time.Imports._
-
-class ItemSimScoresSpec extends Specification {
-  def is = s2"""
-
-    PredictionIO Model Data Item Similarity Scores Specification
-
-    ItemSimScores can be implemented by:
-    1. MongoItemSimScores ${mongoItemSimScores}
-
-  """
-
-  def mongoItemSimScores = s2"""
-
-    MongoItemSimScores should
-
-    - behave like any ItemSimScores implementation ${itemSimScores(newMongoItemSimScores)}
-
-    (clean up database after test)
-    ${Step(Spec.mongoClient(mongoDbName).dropDatabase())}
-
-  """
-
-  def itemSimScores(itemSimScores: ItemSimScores) = s2"""
-
-    inserting and getting 3 ItemSimScores ${insert(itemSimScores)}
-    getting Top N Iids ${getTopNIids(itemSimScores)}
-    delete ItemSimScores by algoid ${deleteByAlgoid(itemSimScores)}
-    existence by Algo ${existByAlgo(itemSimScores)}
-
-  """
-
-  val mongoDbName = "predictionio_modeldata_mongoitemsimscore_test"
-
-  def newMongoItemSimScores = new mongodb.MongoItemSimScores(
-    new Config, Spec.mongoClient(mongoDbName))
-
-  def insert(itemSimScores: ItemSimScores) = {
-    implicit val app = App(
-      id = 0,
-      userid = 0,
-      appkey = "",
-      display = "",
-      url = None,
-      cat = None,
-      desc = None,
-      timezone = "UTC"
-    )
-    implicit val algo = Algo(
-      id = 110101,
-      engineid = 0,
-      name = "",
-      infoid = "abc",
-      command = "",
-      params = Map(),
-      settings = Map(),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed",
-      offlineevalid = None,
-      offlinetuneid = None,
-      loop = None,
-      paramset = None
-    )
-    val itemScores = List(ItemSimScore(
-      iid = "testUser",
-      simiids = Seq("testUserItem4", "testUserItem3", "testUserItem2",
-        "testUserItem1"),
-      scores = Seq(999, 124.678, 10, -5.6),
-      itypes = Seq(List("invalid"), List("7", "8", "9"), List("4", "5", "6"),
-        List("1", "2", "3")),
-      appid = app.id,
-      algoid = algo.id,
-      modelset = algo.modelset
-    ), ItemSimScore(
-      iid = "testUser2",
-      simiids = Seq("b", "c", "d", "e"),
-      scores = Seq(8, 5.4, 2, 1),
-      itypes = Seq(List("invalid"), List("7"), List("6"), List("1", "2", "3")),
-      appid = app.id,
-      algoid = algo.id,
-      modelset = algo.modelset
-    ), ItemSimScore(
-      iid = "testUser3",
-      simiids = Seq("b", "c", "e", "s"),
-      scores = Seq(999, 124.678, 10, -5.6),
-      itypes = Seq(List("1"), List("7", "8", "9"), List("4", "5", "6"),
-        List("1")),
-      appid = app.id,
-      algoid = algo.id,
-      modelset = algo.modelset
-    ))
-
-    val dbItemScores = itemScores map {
-      itemSimScores.insert(_)
-    }
-    val results = itemSimScores.getByIid("testUser")
-    val results2 = itemSimScores.getByIid("testUser2")
-    val results3 = itemSimScores.getByIid("testUser3")
-
-    results must beSome(dbItemScores(0)) and
-      (results2 must beSome(dbItemScores(1))) and
-      (results3 must beSome(dbItemScores(2)))
-  }
-
-  def getTopNIids(itemSimScores: ItemSimScores) = {
-    implicit val app = App(
-      id = 234,
-      userid = 0,
-      appkey = "",
-      display = "",
-      url = None,
-      cat = None,
-      desc = None,
-      timezone = "UTC"
-    )
-    implicit val algo = Algo(
-      id = 234,
-      engineid = 0,
-      name = "",
-      infoid = "abc",
-      command = "",
-      params = Map(),
-      settings = Map(),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed",
-      offlineevalid = None,
-      offlinetuneid = None,
-      loop = None,
-      paramset = None
-    )
-    val itemScores = List(ItemSimScore(
-      iid = "testUser",
-      simiids = Seq("testUserItem10", "testUserItem8", "testUserItem4",
-        "testUserItem9", "testUserItem7", "testUserItem3", "testUserItem2",
-        "testUserItem6", "testUserItem1", "testUserItem5"),
-      scores = Seq(10000, 999, 999, 124.678, 124.678, 124.678, 10, 10, -5.6,
-        -5.6),
-      itypes = Seq(List("invalid"), List("invalid"), List("invalid"),
-        List("1", "2", "3"), List("1", "2", "4"), List("3"),
-        List("5", "6", "7"), List("5", "6", "8"), List("1", "2", "3"),
-        List("1", "2", "3")),
-      appid = app.id,
-      algoid = algo.id,
-      modelset = true
-    ))
-
-    val dbItemScores = itemScores map {
-      itemSimScores.insert(_)
-    }
-
-    val resultsAllTop5 = itemSimScores.getTopNIidsAndScores("testUser", 5, None)
-    val resultsAllTop1 = itemSimScores.getTopNIidsAndScores("testUser", 1, None)
-    val resultsAllTop0 = itemSimScores.getTopNIidsAndScores("testUser", 0, None)
-    val results23Top4 = itemSimScores.getTopNIids("testUser", 4,
-      Some(List("2", "3"))).toSeq
-    val results23Top100 = itemSimScores.getTopNIids("testUser", 100,
-      Some(List("2", "3"))).toSeq
-    val results8Top4 = itemSimScores.getTopNIids("testUser", 4,
-      Some(List("8"))).toSeq
-    val results8Top0 = itemSimScores.getTopNIids("testUser", 0,
-      Some(List("8"))).toSeq
-    val resultUnknownAllTop4 = itemSimScores.getTopNIids("unknown", 4, None)
-      .toSeq
-    val resultUnknown18Top4 = itemSimScores.getTopNIids("unknown", 4,
-      Some(List("1", "8"))).toSeq
-
-    resultsAllTop5 must beEqualTo(Seq(("testUserItem10", 10000.0),
-      ("testUserItem8", 999.0), ("testUserItem4", 999.0),
-      ("testUserItem9", 124.678), ("testUserItem7", 124.678))) and
-      (resultsAllTop1 must beEqualTo(Seq(("testUserItem10", 10000)))) and
-      (resultsAllTop0 must beEqualTo(Seq(("testUserItem10", 10000),
-        ("testUserItem8", 999), ("testUserItem4", 999),
-        ("testUserItem9", 124.678), ("testUserItem7", 124.678),
-        ("testUserItem3", 124.678), ("testUserItem2", 10),
-        ("testUserItem6", 10), ("testUserItem1", -5.6),
-        ("testUserItem5", -5.6)))) and
-      (results23Top4 must beEqualTo(Seq("testUserItem9", "testUserItem7",
-        "testUserItem3", "testUserItem1"))) and
-      (results23Top100 must beEqualTo(Seq("testUserItem9", "testUserItem7",
-        "testUserItem3", "testUserItem1", "testUserItem5"))) and
-      (results8Top4 must beEqualTo(Seq("testUserItem6"))) and
-      (results8Top0 must beEqualTo(Seq("testUserItem6"))) and
-      (resultUnknownAllTop4 must beEqualTo(Seq())) and
-      (resultUnknown18Top4 must beEqualTo(Seq()))
-  }
-
-  def deleteByAlgoid(itemSimScores: ItemSimScores) = {
-
-    implicit val app = App(
-      id = 0,
-      userid = 0,
-      appkey = "",
-      display = "",
-      url = None,
-      cat = None,
-      desc = None,
-      timezone = "UTC"
-    )
-
-    val algo1 = Algo(
-      id = 1,
-      engineid = 0,
-      name = "algo1",
-      infoid = "abc",
-      command = "",
-      params = Map(),
-      settings = Map(),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed",
-      offlineevalid = None,
-      offlinetuneid = None,
-      loop = None,
-      paramset = None
-    )
-
-    val algo2 = algo1.copy(id = 2) // NOTE: different id
-
-    val itemScores1 = List(ItemSimScore(
-      iid = "deleteByAlgoidUser",
-      simiids = Seq("testUserItem10", "testUserItem8", "testUserItem4",
-        "testUserItem9", "testUserItem7", "testUserItem3", "testUserItem2",
-        "testUserItem6", "testUserItem1", "testUserItem5"),
-      scores = Seq(10000, 999, 999, 124.678, 124.678, 124.678, 10, 10, -5.6,
-        -5.6),
-      itypes = Seq(List("invalid"), List("invalid"), List("invalid"),
-        List("1", "2", "3"), List("1", "2", "4"), List("2", "3", "4"),
-        List("5", "6", "7"), List("5", "6", "8"), List("1", "2", "3"),
-        List("1", "2", "3")),
-      appid = app.id,
-      algoid = algo1.id,
-      modelset = algo1.modelset
-    ), ItemSimScore(
-      iid = "deleteByAlgoidUser2",
-      simiids = Seq("a", "b", "c", "d"),
-      scores = Seq(10, 9, 8, 7),
-      itypes = Seq(List("invalid"), List("5", "6", "7"), List("5", "6", "8"),
-        List("4")),
-      appid = app.id,
-      algoid = algo1.id,
-      modelset = algo1.modelset
-    ))
-
-    val itemScores2 = List(ItemSimScore(
-      iid = "deleteByAlgoidUser",
-      simiids = Seq("testUserItem10", "testUserItem8", "testUserItem4",
-        "testUserItem9", "testUserItem7", "testUserItem3", "testUserItem2",
-        "testUserItem6", "testUserItem1", "testUserItem5"),
-      scores = Seq(10000, 999, 999, 124.678, 124.678, 124.678, 10, 10, -5.6,
-        -5.6),
-      itypes = Seq(List("invalid"), List("invalid"), List("invalid"),
-        List("1", "2", "3"), List("1", "2", "4"), List("2", "3", "4"),
-        List("5", "6", "7"), List("5", "6", "8"), List("1", "2", "3"),
-        List("1", "2", "3")),
-      appid = app.id,
-      algoid = algo2.id,
-      modelset = algo2.modelset
-    ), ItemSimScore(
-      iid = "deleteByAlgoidUser2",
-      simiids = Seq("a", "b", "c", "d"),
-      scores = Seq(10, 9, 8, 7),
-      itypes = Seq(List("invalid"), List("5", "6", "7"), List("5", "6", "8"),
-        List("4")),
-      appid = app.id,
-      algoid = algo2.id,
-      modelset = algo2.modelset
-    ))
-
-    val dbItemScores1 = itemScores1 map {
-      itemSimScores.insert(_)
-    }
-
-    val dbItemScores2 = itemScores2 map {
-      itemSimScores.insert(_)
-    }
-
-    val results1 = itemSimScores.getByIid("deleteByAlgoidUser")(app, algo1)
-    val results1u2 = itemSimScores.getByIid("deleteByAlgoidUser2")(app, algo1)
-    val results2 = itemSimScores.getByIid("deleteByAlgoidUser")(app, algo2)
-    val results2u2 = itemSimScores.getByIid("deleteByAlgoidUser2")(app, algo2)
-
-    itemSimScores.deleteByAlgoid(algo1.id)
-
-    val results1b = itemSimScores.getByIid("deleteByAlgoidUser")(app, algo1)
-    val results1bu2 = itemSimScores.getByIid("deleteByAlgoidUser2")(app, algo1)
-    val results2b = itemSimScores.getByIid("deleteByAlgoidUser")(app, algo2)
-    val results2bu2 = itemSimScores.getByIid("deleteByAlgoidUser2")(app, algo2)
-
-    itemSimScores.deleteByAlgoid(algo2.id)
-
-    val results2c = itemSimScores.getByIid("deleteByAlgoidUser")(app, algo2)
-    val results2cu2 = itemSimScores.getByIid("deleteByAlgoidUser2")(app, algo2)
-
-    results1 must beSome(dbItemScores1(0)) and
-      (results1u2 must beSome(dbItemScores1(1))) and
-      (results2 must beSome(dbItemScores2(0))) and
-      (results2u2 must beSome(dbItemScores2(1))) and
-      (results1b must beNone) and
-      (results1bu2 must beNone) and
-      (results2b must beSome(dbItemScores2(0))) and
-      (results2bu2 must beSome(dbItemScores2(1))) and
-      (results2c must beNone) and
-      (results2cu2 must beNone)
-  }
-
-  def existByAlgo(itemSimScores: ItemSimScores) = {
-    implicit val app = App(
-      id = 345,
-      userid = 0,
-      appkey = "",
-      display = "",
-      url = None,
-      cat = None,
-      desc = None,
-      timezone = "UTC"
-    )
-    val algo1 = Algo(
-      id = 345,
-      engineid = 0,
-      name = "",
-      infoid = "dummy",
-      command = "",
-      params = Map(),
-      settings = Map(),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed",
-      offlineevalid = None,
-      offlinetuneid = None,
-      loop = None,
-      paramset = None
-    )
-    val algo2 = algo1.copy(id = 3456)
-    itemSimScores.insert(ItemSimScore(
-      iid = "testUser",
-      simiids = Seq("testUserItem4"),
-      scores = Seq(999),
-      itypes = Seq(List("invalid")),
-      appid = app.id,
-      algoid = algo1.id,
-      modelset = algo1.modelset
-    ))
-    itemSimScores.existByAlgo(algo1) must beTrue and
-      (itemSimScores.existByAlgo(algo2) must beFalse)
-  }
-}
diff --git a/commons/src/test/scala/io/prediction/commons/modeldata/MetadataKeyvalsSpec.scala b/commons/src/test/scala/io/prediction/commons/modeldata/MetadataKeyvalsSpec.scala
deleted file mode 100644
index 94e586a..0000000
--- a/commons/src/test/scala/io/prediction/commons/modeldata/MetadataKeyvalsSpec.scala
+++ /dev/null
@@ -1,66 +0,0 @@
-package io.prediction.commons.modeldata
-
-import io.prediction.commons.Config
-import io.prediction.commons.Spec
-import io.prediction.commons.settings.{ Algo, App }
-
-import org.specs2._
-import org.specs2.specification.Step
-import com.mongodb.casbah.Imports._
-import com.github.nscala_time.time.Imports._
-
-class ModelMetadataKeyvals extends Specification {
-  def is = s2"""
-
-    PredictionIO Model Data Metadata Keyval Specification
-
-    MetadataKeyvals can be implemented by:
-    1. MongoMetadataKeyvals ${mongoMetadataKeyvals}
-
-  """
-
-  def mongoMetadataKeyvals = s2"""
-
-    MongoMetadataKeyvals should
-
-    - behave like any MetadataKeyvals implementation
-    ${metadataKeyvals(newMongoMetadataKeyvals)}
-
-    (clean up database after test)
-    ${Step(Spec.mongoClient(mongoDbName).dropDatabase())}
-
-  """
-
-  def metadataKeyvals(metadataKeyvals: MetadataKeyvals) = s2"""
-
-    upserting and getting MetadataKeyval ${upsertAndGet(metadataKeyvals)}
-
-  """
-
-  val mongoDbName = "predictionio_modeldata_mongometadatakeyval_test"
-
-  def newMongoMetadataKeyvals = new mongodb.MongoMetadataKeyvals(
-    new Config, Spec.mongoClient(mongoDbName))
-
-  def upsertAndGet(keyvals: MetadataKeyvals) = {
-    val algoid = 1
-    val modelset = true
-    val otherAlgoid = 2
-    val notExistsAlgoid = 3
-    val keyval0 = MetadataKeyval(algoid, modelset, "foo", "1")
-    val keyval1 = MetadataKeyval(algoid, modelset, "bar", "3")
-    val keyval2 = MetadataKeyval(algoid, modelset, "foo", "2")
-    val keyval3 = MetadataKeyval(otherAlgoid, modelset, "bar", "4")
-
-    keyvals.upsert(keyval0)
-    keyvals.upsert(keyval1)
-    keyvals.upsert(keyval2)
-    keyvals.upsert(keyval3)
-
-    (keyvals.get(algoid, modelset, "foo") must beSome("2")) and
-      (keyvals.get(algoid, modelset, "bar") must beSome("3")) and
-      (keyvals.get(otherAlgoid, modelset, "foo") must beNone) and
-      (keyvals.get(otherAlgoid, modelset, "bar") must beSome("4")) and
-      (keyvals.get(notExistsAlgoid, modelset, "bar") must beNone)
-  }
-}
diff --git a/commons/src/test/scala/io/prediction/commons/settings/AlgoInfosSpec.scala b/commons/src/test/scala/io/prediction/commons/settings/AlgoInfosSpec.scala
deleted file mode 100644
index cdfb9db..0000000
--- a/commons/src/test/scala/io/prediction/commons/settings/AlgoInfosSpec.scala
+++ /dev/null
@@ -1,339 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Spec
-
-import org.specs2._
-import org.specs2.specification.Step
-import com.mongodb.casbah.Imports._
-
-class AlgoInfosSpec extends Specification {
-  def is = s2"""
-
-  PredictionIO AlgoInfos Specification
-
-    Algos can be implemented by:
-    - MongoAlgoInfos ${mongoAlgoInfos}
-
-  """
-
-  def mongoAlgoInfos = s2"""
-
-    MongoAlgoInfos should" ^
-    - behave like any AlgoInfos implementation ${algoinfos(newMongoAlgoInfos)}
-    - (database cleanup) ${Step(Spec.mongoClient(mongoDbName).dropDatabase())}
-
-  """
-
-  def algoinfos(algoinfos: AlgoInfos) = s2"""
-
-    insert and get info of an algo ${insertAndGet(algoinfos)}
-    get info of algos by their engine type ${getByEngineInfoId(algoinfos)}
-    update info of an algo ${update(algoinfos)}
-    delete info of an algo ${delete(algoinfos)}
-    backup and restore existing algoinfos ${backuprestore(algoinfos)}
-
-  """
-
-  val mongoDbName = "predictionio_mongoalgoinfos_test"
-  def newMongoAlgoInfos = new mongodb.MongoAlgoInfos(Spec.mongoClient(mongoDbName))
-
-  def insertAndGet(algoinfos: AlgoInfos) = {
-    val ai = AlgoInfo(
-      id = "pdio-knnitembased",
-      name = "kNN Item Based Collaborative Filtering",
-      description = Some("This item-based k-NearestNeighbor algorithm predicts user preferences based on previous behaviors of users on similar items."),
-      batchcommands = Some(Seq(
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.DataPreparator --hdfs --dbType $appdataDbType$ --dbName $appdataDbName$ --dbHost $appdataDbHost$ --dbPort $appdataDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$",
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.KNNItemBased --hdfs --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --measureParam $measureParam$ --priorCountParam $priorCountParam$ --priorCorrelParam $priorCorrelParam$ --minNumRatersParam $minNumRatersParam$ --maxNumRatersParam $maxNumRatersParam$ --minIntersectionParam $minIntersectionParam$ --minNumRatedSimParam $minNumRatedSimParam$ --numRecommendations $numRecommendations$ --unseenOnly $unseenOnly$",
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.ModelConstructor --hdfs --dbType $modeldataDbType$ --dbName $modeldataDbName$ --dbHost $modeldataDbHost$ --dbPort $modeldataDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --modelSet $modelset$")),
-      offlineevalcommands = Some(Seq(
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.DataPreparator --hdfs --dbType $appdataTrainingDbType$ --dbName $appdataTrainingDbName$ --dbHost $appdataTrainingDbHost$ --dbPort $appdataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$",
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.KNNItemBased --hdfs --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ --measureParam $measureParam$ --priorCountParam $priorCountParam$ --priorCorrelParam $priorCorrelParam$ --minNumRatersParam $minNumRatersParam$ --maxNumRatersParam $maxNumRatersParam$ --minIntersectionParam $minIntersectionParam$ --minNumRatedSimParam $minNumRatedSimParam$ --numRecommendations $numRecommendations$ --unseenOnly $unseenOnly$",
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.ModelConstructor --hdfs --dbType $modeldataTrainingDbType$ --dbName $modeldataTrainingDbName$ --dbHost $modeldataTrainingDbHost$ --dbPort $modeldataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ --modelSet false")),
-      params = Map(
-        "foo" -> Param(
-          id = "foo",
-          name = "foo",
-          description = None,
-          defaultvalue = 0,
-          constraint = ParamIntegerConstraint(min = Some(0), max = Some(10)),
-          ui = ParamUI(
-            uitype = "selection",
-            selections = Some(Seq(
-              ParamSelectionUI("0", "0"),
-              ParamSelectionUI("2", "2"),
-              ParamSelectionUI("4", "4"),
-              ParamSelectionUI("6", "6"),
-              ParamSelectionUI("8", "8"),
-              ParamSelectionUI("10", "10")))),
-          scopes = Some(Set("dead", "beef")))),
-      paramsections = Seq(
-        ParamSection(
-          name = "foo",
-          description = None,
-          subsections = None,
-          params = None),
-        ParamSection(
-          name = "bar",
-          description = Some("deadbeef"),
-          subsections = Some(Seq(
-            ParamSection("baz", "norma", None, None, None),
-            ParamSection("jack", "normal", None, None, None))),
-          params = Some(Seq("this", "that")))),
-      paramorder = Seq(
-        "measureParam",
-        "priorCountParam",
-        "priorCorrelParam",
-        "minNumRatersParam",
-        "maxNumRatersParam",
-        "minIntersectionParam",
-        "minNumRatedSimParam",
-        "viewParam",
-        "likeParam",
-        "dislikeParam",
-        "conversionParam",
-        "conflictParam"),
-      engineinfoid = "itemrec",
-      techreq = Seq("Hadoop"),
-      datareq = Seq("Users, Items, and U2I Actions such as Like, Buy and Rate."))
-    algoinfos.insert(ai)
-    algoinfos.get(ai.id) must beSome(ai)
-  }
-
-  def getByEngineInfoId(algoinfos: AlgoInfos) = {
-    algoinfos.insert(AlgoInfo(
-      id = "pdio-is1",
-      name = "kNN Item Based Collaborative Filtering",
-      description = Some("This item-based k-NearestNeighbor algorithm predicts user preferences based on previous behaviors of users on similar items."),
-      batchcommands = Some(Seq(
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.DataPreparator --hdfs --dbType $appdataDbType$ --dbName $appdataDbName$ --dbHost $appdataDbHost$ --dbPort $appdataDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$",
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.KNNItemBased --hdfs --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --measureParam $measureParam$ --priorCountParam $priorCountParam$ --priorCorrelParam $priorCorrelParam$ --minNumRatersParam $minNumRatersParam$ --maxNumRatersParam $maxNumRatersParam$ --minIntersectionParam $minIntersectionParam$ --minNumRatedSimParam $minNumRatedSimParam$ --numRecommendations $numRecommendations$ --unseenOnly $unseenOnly$",
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.ModelConstructor --hdfs --dbType $modeldataDbType$ --dbName $modeldataDbName$ --dbHost $modeldataDbHost$ --dbPort $modeldataDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --modelSet $modelset$")),
-      offlineevalcommands = Some(Seq(
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.DataPreparator --hdfs --dbType $appdataTrainingDbType$ --dbName $appdataTrainingDbName$ --dbHost $appdataTrainingDbHost$ --dbPort $appdataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$",
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.KNNItemBased --hdfs --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ --measureParam $measureParam$ --priorCountParam $priorCountParam$ --priorCorrelParam $priorCorrelParam$ --minNumRatersParam $minNumRatersParam$ --maxNumRatersParam $maxNumRatersParam$ --minIntersectionParam $minIntersectionParam$ --minNumRatedSimParam $minNumRatedSimParam$ --numRecommendations $numRecommendations$ --unseenOnly $unseenOnly$",
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.ModelConstructor --hdfs --dbType $modeldataTrainingDbType$ --dbName $modeldataTrainingDbName$ --dbHost $modeldataTrainingDbHost$ --dbPort $modeldataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ --modelSet false")),
-      params = Map(),
-      paramsections = Seq(),
-      paramorder = Seq(
-        "measureParam",
-        "priorCountParam",
-        "priorCorrelParam",
-        "minNumRatersParam",
-        "maxNumRatersParam",
-        "minIntersectionParam",
-        "minNumRatedSimParam",
-        "viewParam",
-        "likeParam",
-        "dislikeParam",
-        "conversionParam",
-        "conflictParam"),
-      engineinfoid = "itemsim",
-      techreq = Seq("Hadoop"),
-      datareq = Seq("Users, Items, and U2I Actions such as Like, Buy and Rate.")))
-    algoinfos.insert(AlgoInfo(
-      id = "pdio-is2",
-      name = "kNN Item Based Collaborative Filtering",
-      description = Some("This item-based k-NearestNeighbor algorithm predicts user preferences based on previous behaviors of users on similar items."),
-      batchcommands = Some(Seq(
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.DataPreparator --hdfs --dbType $appdataDbType$ --dbName $appdataDbName$ --dbHost $appdataDbHost$ --dbPort $appdataDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$",
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.KNNItemBased --hdfs --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --measureParam $measureParam$ --priorCountParam $priorCountParam$ --priorCorrelParam $priorCorrelParam$ --minNumRatersParam $minNumRatersParam$ --maxNumRatersParam $maxNumRatersParam$ --minIntersectionParam $minIntersectionParam$ --minNumRatedSimParam $minNumRatedSimParam$ --numRecommendations $numRecommendations$ --unseenOnly $unseenOnly$",
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.ModelConstructor --hdfs --dbType $modeldataDbType$ --dbName $modeldataDbName$ --dbHost $modeldataDbHost$ --dbPort $modeldataDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --modelSet $modelset$")),
-      offlineevalcommands = Some(Seq(
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.DataPreparator --hdfs --dbType $appdataTrainingDbType$ --dbName $appdataTrainingDbName$ --dbHost $appdataTrainingDbHost$ --dbPort $appdataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$",
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.KNNItemBased --hdfs --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ --measureParam $measureParam$ --priorCountParam $priorCountParam$ --priorCorrelParam $priorCorrelParam$ --minNumRatersParam $minNumRatersParam$ --maxNumRatersParam $maxNumRatersParam$ --minIntersectionParam $minIntersectionParam$ --minNumRatedSimParam $minNumRatedSimParam$ --numRecommendations $numRecommendations$ --unseenOnly $unseenOnly$",
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.ModelConstructor --hdfs --dbType $modeldataTrainingDbType$ --dbName $modeldataTrainingDbName$ --dbHost $modeldataTrainingDbHost$ --dbPort $modeldataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ --modelSet false")),
-      params = Map(),
-      paramsections = Seq(),
-      paramorder = Seq(
-        "measureParam",
-        "priorCountParam",
-        "priorCorrelParam",
-        "minNumRatersParam",
-        "maxNumRatersParam",
-        "minIntersectionParam",
-        "minNumRatedSimParam",
-        "viewParam",
-        "likeParam",
-        "dislikeParam",
-        "conversionParam",
-        "conflictParam"),
-      engineinfoid = "itemsim",
-      techreq = Seq("Hadoop"),
-      datareq = Seq("Users, Items, and U2I Actions such as Like, Buy and Rate.")))
-    algoinfos.getByEngineInfoId("itemsim").size must beEqualTo(2)
-  }
-
-  def update(algoinfos: AlgoInfos) = {
-    val u1 = AlgoInfo(
-      id = "pdio-u1",
-      name = "kNN Item Based Collaborative Filtering",
-      description = Some("This item-based k-NearestNeighbor algorithm predicts user preferences based on previous behaviors of users on similar items."),
-      batchcommands = Some(Seq(
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.DataPreparator --hdfs --dbType $appdataDbType$ --dbName $appdataDbName$ --dbHost $appdataDbHost$ --dbPort $appdataDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$",
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.KNNItemBased --hdfs --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --measureParam $measureParam$ --priorCountParam $priorCountParam$ --priorCorrelParam $priorCorrelParam$ --minNumRatersParam $minNumRatersParam$ --maxNumRatersParam $maxNumRatersParam$ --minIntersectionParam $minIntersectionParam$ --minNumRatedSimParam $minNumRatedSimParam$ --numRecommendations $numRecommendations$ --unseenOnly $unseenOnly$",
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.ModelConstructor --hdfs --dbType $modeldataDbType$ --dbName $modeldataDbName$ --dbHost $modeldataDbHost$ --dbPort $modeldataDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --modelSet $modelset$")),
-      offlineevalcommands = Some(Seq(
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.DataPreparator --hdfs --dbType $appdataTrainingDbType$ --dbName $appdataTrainingDbName$ --dbHost $appdataTrainingDbHost$ --dbPort $appdataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$",
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.KNNItemBased --hdfs --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ --measureParam $measureParam$ --priorCountParam $priorCountParam$ --priorCorrelParam $priorCorrelParam$ --minNumRatersParam $minNumRatersParam$ --maxNumRatersParam $maxNumRatersParam$ --minIntersectionParam $minIntersectionParam$ --minNumRatedSimParam $minNumRatedSimParam$ --numRecommendations $numRecommendations$ --unseenOnly $unseenOnly$",
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.ModelConstructor --hdfs --dbType $modeldataTrainingDbType$ --dbName $modeldataTrainingDbName$ --dbHost $modeldataTrainingDbHost$ --dbPort $modeldataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ --modelSet false")),
-      params = Map(),
-      paramsections = Seq(),
-      paramorder = Seq(
-        "measureParam",
-        "priorCountParam",
-        "priorCorrelParam",
-        "minNumRatersParam",
-        "maxNumRatersParam",
-        "minIntersectionParam",
-        "minNumRatedSimParam",
-        "viewParam",
-        "likeParam",
-        "dislikeParam",
-        "conversionParam",
-        "conflictParam"),
-      engineinfoid = "itemrec",
-      techreq = Seq("Hadoop"),
-      datareq = Seq("Users, Items, and U2I Actions such as Like, Buy and Rate."))
-    algoinfos.insert(u1)
-
-    val u2 = u1.copy(techreq = Seq("GraphLab"))
-    algoinfos.update(u2)
-    algoinfos.get(u2.id) must beSome(u2)
-  }
-
-  def delete(algoinfos: AlgoInfos) = {
-    algoinfos.insert(AlgoInfo(
-      id = "pdio-d1",
-      name = "kNN Item Based Collaborative Filtering",
-      description = Some("This item-based k-NearestNeighbor algorithm predicts user preferences based on previous behaviors of users on similar items."),
-      batchcommands = Some(Seq(
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.DataPreparator --hdfs --dbType $appdataDbType$ --dbName $appdataDbName$ --dbHost $appdataDbHost$ --dbPort $appdataDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$",
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.KNNItemBased --hdfs --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --measureParam $measureParam$ --priorCountParam $priorCountParam$ --priorCorrelParam $priorCorrelParam$ --minNumRatersParam $minNumRatersParam$ --maxNumRatersParam $maxNumRatersParam$ --minIntersectionParam $minIntersectionParam$ --minNumRatedSimParam $minNumRatedSimParam$ --numRecommendations $numRecommendations$ --unseenOnly $unseenOnly$",
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.ModelConstructor --hdfs --dbType $modeldataDbType$ --dbName $modeldataDbName$ --dbHost $modeldataDbHost$ --dbPort $modeldataDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --modelSet $modelset$")),
-      offlineevalcommands = Some(Seq(
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.DataPreparator --hdfs --dbType $appdataTrainingDbType$ --dbName $appdataTrainingDbName$ --dbHost $appdataTrainingDbHost$ --dbPort $appdataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$",
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.KNNItemBased --hdfs --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ --measureParam $measureParam$ --priorCountParam $priorCountParam$ --priorCorrelParam $priorCorrelParam$ --minNumRatersParam $minNumRatersParam$ --maxNumRatersParam $maxNumRatersParam$ --minIntersectionParam $minIntersectionParam$ --minNumRatedSimParam $minNumRatedSimParam$ --numRecommendations $numRecommendations$ --unseenOnly $unseenOnly$",
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.ModelConstructor --hdfs --dbType $modeldataTrainingDbType$ --dbName $modeldataTrainingDbName$ --dbHost $modeldataTrainingDbHost$ --dbPort $modeldataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ --modelSet false")),
-      params = Map(),
-      paramsections = Seq(),
-      paramorder = Seq(
-        "measureParam",
-        "priorCountParam",
-        "priorCorrelParam",
-        "minNumRatersParam",
-        "maxNumRatersParam",
-        "minIntersectionParam",
-        "minNumRatedSimParam",
-        "viewParam",
-        "likeParam",
-        "dislikeParam",
-        "conversionParam",
-        "conflictParam"),
-      engineinfoid = "itemrec",
-      techreq = Seq("Hadoop"),
-      datareq = Seq("Users, Items, and U2I Actions such as Like, Buy and Rate.")))
-    algoinfos.delete("pdio-d1")
-    algoinfos.get("pdio-d1") must beNone
-  }
-
-  def backuprestore(algoinfos: AlgoInfos) = {
-    val ai = AlgoInfo(
-      id = "pdio-br",
-      name = "kNN Item Based Collaborative Filtering",
-      description = Some("This item-based k-NearestNeighbor algorithm predicts user preferences based on previous behaviors of users on similar items."),
-      batchcommands = Some(Seq(
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.DataPreparator --hdfs --dbType $appdataDbType$ --dbName $appdataDbName$ --dbHost $appdataDbHost$ --dbPort $appdataDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$",
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.KNNItemBased --hdfs --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --measureParam $measureParam$ --priorCountParam $priorCountParam$ --priorCorrelParam $priorCorrelParam$ --minNumRatersParam $minNumRatersParam$ --maxNumRatersParam $maxNumRatersParam$ --minIntersectionParam $minIntersectionParam$ --minNumRatedSimParam $minNumRatedSimParam$ --numRecommendations $numRecommendations$ --unseenOnly $unseenOnly$",
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.ModelConstructor --hdfs --dbType $modeldataDbType$ --dbName $modeldataDbName$ --dbHost $modeldataDbHost$ --dbPort $modeldataDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --modelSet $modelset$")),
-      offlineevalcommands = Some(Seq(
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.DataPreparator --hdfs --dbType $appdataTrainingDbType$ --dbName $appdataTrainingDbName$ --dbHost $appdataTrainingDbHost$ --dbPort $appdataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$",
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.KNNItemBased --hdfs --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ --measureParam $measureParam$ --priorCountParam $priorCountParam$ --priorCorrelParam $priorCorrelParam$ --minNumRatersParam $minNumRatersParam$ --maxNumRatersParam $maxNumRatersParam$ --minIntersectionParam $minIntersectionParam$ --minNumRatedSimParam $minNumRatedSimParam$ --numRecommendations $numRecommendations$ --unseenOnly $unseenOnly$",
-        "$hadoop$ jar $jar$ io.prediction.algorithms.scalding.itemrec.knnitembased.ModelConstructor --hdfs --dbType $modeldataTrainingDbType$ --dbName $modeldataTrainingDbName$ --dbHost $modeldataTrainingDbHost$ --dbPort $modeldataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ --modelSet false")),
-      params = Map(
-        "foo" -> Param(
-          id = "foo",
-          name = "foo",
-          description = None,
-          defaultvalue = 0,
-          constraint = ParamIntegerConstraint(min = Some(0), max = Some(10)),
-          ui = ParamUI(
-            uitype = "selection",
-            selections = Some(Seq(
-              ParamSelectionUI("0", "0"),
-              ParamSelectionUI("2", "2"),
-              ParamSelectionUI("4", "4"),
-              ParamSelectionUI("6", "6"),
-              ParamSelectionUI("8", "8"),
-              ParamSelectionUI("10", "10")))),
-          scopes = Some(Set("dead", "beef"))),
-        "bar" -> Param(
-          id = "bar",
-          name = "bar",
-          description = Some("random description"),
-          defaultvalue = false,
-          constraint = ParamBooleanConstraint(),
-          ui = ParamUI(
-            uitype = "slider",
-            slidermin = Some(10),
-            slidermax = Some(20),
-            sliderstep = Some(2)),
-          scopes = None),
-        "dead" -> Param(
-          id = "dead",
-          name = "dead",
-          description = None,
-          defaultvalue = "dead",
-          constraint = ParamStringConstraint(),
-          ui = ParamUI(),
-          scopes = None),
-        "beef" -> Param(
-          id = "beef",
-          name = "beef",
-          description = None,
-          defaultvalue = 3.14,
-          constraint = ParamDoubleConstraint(),
-          ui = ParamUI(),
-          scopes = None)),
-      paramsections = Seq(
-        ParamSection(
-          name = "foo",
-          description = None,
-          subsections = None,
-          params = None),
-        ParamSection(
-          name = "bar",
-          description = Some("deadbeef"),
-          subsections = Some(Seq(
-            ParamSection("baz", "normal", None, None, None),
-            ParamSection("jack", "normal", None, None, None))),
-          params = Some(Seq("this", "that")))),
-      paramorder = Seq(
-        "measureParam",
-        "priorCountParam",
-        "priorCorrelParam",
-        "minNumRatersParam",
-        "maxNumRatersParam",
-        "minIntersectionParam",
-        "minNumRatedSimParam",
-        "viewParam",
-        "likeParam",
-        "dislikeParam",
-        "conversionParam",
-        "conflictParam"),
-      engineinfoid = "itemrec",
-      techreq = Seq("Hadoop"),
-      datareq = Seq("Users, Items, and U2I Actions such as Like, Buy and Rate."))
-    algoinfos.insert(ai)
-    val fn = "algoinfos.json"
-    val fos = new java.io.FileOutputStream(fn)
-    try {
-      fos.write(algoinfos.backup())
-    } finally {
-      fos.close()
-    }
-    algoinfos.restore(scala.io.Source.fromFile(fn)(scala.io.Codec.UTF8).mkString.getBytes("UTF-8")) map { ralgoinfos =>
-      ralgoinfos must contain(ai)
-    } getOrElse 1 === 2
-  }
-}
diff --git a/commons/src/test/scala/io/prediction/commons/settings/AlgosSpec.scala b/commons/src/test/scala/io/prediction/commons/settings/AlgosSpec.scala
deleted file mode 100644
index 3df36d9..0000000
--- a/commons/src/test/scala/io/prediction/commons/settings/AlgosSpec.scala
+++ /dev/null
@@ -1,429 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Spec
-
-import org.specs2._
-import org.specs2.specification.Step
-
-import com.mongodb.casbah.Imports._
-import com.github.nscala_time.time.Imports._
-
-class AlgosSpec extends Specification {
-  def is = s2"""
-
-  PredictionIO Algos Specification
-
-    Algos can be implemented by:
-    - MongoAlgos ${mongoAlgos}
-
-  """
-
-  def mongoAlgos = s2"""
-
-    MongoAlgos should
-    - behave like any Algos implementation ${algos(newMongoAlgos)}
-    - (database cleanup) ${Step(Spec.mongoClient(mongoDbName).dropDatabase())}
-
-  """
-
-  def algos(algos: Algos) = s2"""
-
-    create an algo ${insert(algos)}
-    get two algos by engineid ${getByEngineid(algos)}
-    get a deployed algo by engineid ${getDeployedByEngineid(algos)}
-    get two algos by offlineevalid ${getByOfflineEvalid(algos)}
-    get an auto tune subject ${getTuneSubjectByOfflineTuneid(algos)}
-    get by id and engineid ${getByIdAndEngineid(algos)}
-    update an algo ${update(algos)}
-    delete an algo ${delete(algos)}
-    checking existence of algo ${existsByEngineidAndName(algos)}
-    backup and restore existing algos ${backuprestore(algos)}
-
-  """
-
-  val mongoDbName = "predictionio_mongoalgos_test"
-  def newMongoAlgos = new mongodb.MongoAlgos(Spec.mongoClient(mongoDbName))
-
-  def insert(algos: Algos) = {
-    val algo = Algo(
-      id = 0,
-      engineid = 123,
-      name = "insert",
-      infoid = "abc",
-      command = "insert",
-      params = Map("foo" -> "bar"),
-      settings = Map("dead" -> "beef"),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now.hour(4).minute(56).second(35),
-      status = "apple",
-      offlineevalid = None,
-      offlinetuneid = Some(134),
-      loop = None,
-      paramset = Some(4)
-    )
-    val insertid = algos.insert(algo)
-    algos.get(insertid) must beSome(algo.copy(id = insertid))
-  }
-
-  def getByEngineid(algos: Algos) = {
-    val algo1 = Algo(
-      id = 0,
-      engineid = 234,
-      name = "getByEngineid1",
-      infoid = "apple",
-      command = "getByEngineid1",
-      params = Map("baz" -> "bah"),
-      settings = Map("qwe" -> "rty"),
-      modelset = false,
-      createtime = DateTime.now,
-      updatetime = DateTime.now.hour(1).minute(2).second(3),
-      status = "orange",
-      offlineevalid = Some(2),
-      offlinetuneid = None,
-      loop = Some(4),
-      paramset = Some(123)
-    )
-    val algo2 = Algo(
-      id = 0,
-      engineid = 234,
-      name = "getByEngineid2",
-      infoid = "abc2",
-      command = "getByEngineid2",
-      params = Map("az" -> "ba"),
-      settings = Map("we" -> "rt"),
-      modelset = false,
-      createtime = DateTime.now.hour(4).minute(5).second(6),
-      updatetime = DateTime.now,
-      status = "abcdef",
-      offlineevalid = None,
-      offlinetuneid = Some(3),
-      loop = Some(5),
-      paramset = None
-    )
-    val id1 = algos.insert(algo1)
-    val id2 = algos.insert(algo2)
-    val algo12 = algos.getByEngineid(234)
-    val algo121 = algo12.next()
-    val algo122 = algo12.next()
-    algo121 must be equalTo (algo1.copy(id = id1)) and
-      (algo122 must be equalTo (algo2.copy(id = id2)))
-  }
-
-  def getDeployedByEngineid(algos: Algos) = {
-    val algo1 = Algo(
-      id = 0,
-      engineid = 567,
-      name = "getDeployedByEngineid1",
-      infoid = "def",
-      command = "getDeployedByEngineid1",
-      params = Map("baz" -> "bah"),
-      settings = Map("qwe" -> "rty"),
-      modelset = false,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "good",
-      offlineevalid = Some(2),
-      offlinetuneid = Some(33),
-      loop = None,
-      paramset = Some(6)
-    )
-    val algo2 = Algo(
-      id = 0,
-      engineid = 567,
-      name = "getDeployedByEngineid2",
-      infoid = "id3",
-      command = "getDeployedByEngineid2",
-      params = Map("az" -> "ba"),
-      settings = Map("we" -> "rt"),
-      modelset = false,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed", // NOTE!
-      offlineevalid = None,
-      offlinetuneid = Some(44),
-      loop = Some(3),
-      paramset = Some(56)
-    )
-    val id1 = algos.insert(algo1)
-    val id2 = algos.insert(algo2)
-    val algo12 = algos.getDeployedByEngineid(567)
-    algo12.next must be equalTo (algo2.copy(id = id2)) and
-      (algo12.hasNext must beFalse)
-  }
-
-  def getByOfflineEvalid(algos: Algos) = {
-    val algo1 = Algo(
-      id = 0,
-      engineid = 234,
-      name = "getByOfflineEvalid1",
-      infoid = "banana",
-      command = "getByOfflineEvalid1",
-      params = Map("baz1" -> "bah1"),
-      settings = Map("qwe1" -> "rty1"),
-      modelset = false,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "sleep",
-      offlineevalid = Some(20),
-      offlinetuneid = None,
-      loop = None,
-      paramset = Some(155)
-    )
-    val algo2 = Algo(
-      id = 0,
-      engineid = 233,
-      name = "getByOfflineEvalid2",
-      infoid = "banana2",
-      command = "getByOfflineEvalid2",
-      params = Map("az2" -> "ba2"),
-      settings = Map("we2" -> "rt2"),
-      modelset = false,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "start",
-      offlineevalid = Some(20),
-      offlinetuneid = Some(21),
-      loop = Some(14),
-      paramset = Some(1)
-    )
-    val id1 = algos.insert(algo1)
-    val id2 = algos.insert(algo2)
-    val algo12 = algos.getByOfflineEvalid(20)
-    val algo121 = algo12.next()
-    val algo122 = algo12.next()
-    algo121 must be equalTo (algo1.copy(id = id1)) and
-      (algo122 must be equalTo (algo2.copy(id = id2)))
-  }
-
-  def getTuneSubjectByOfflineTuneid(algos: Algos) = {
-    val algo1 = Algo(
-      id = 0,
-      engineid = 678,
-      name = "getTuneSubjectByTuneid1",
-      infoid = "def",
-      command = "getTuneSubjectByTuneid1",
-      params = Map("baz" -> "bah"),
-      settings = Map("qwe" -> "rty"),
-      modelset = false,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "good",
-      offlineevalid = Some(2),
-      offlinetuneid = Some(567),
-      loop = None,
-      paramset = Some(6)
-    )
-    val algo2 = Algo(
-      id = 0,
-      engineid = 678,
-      name = "getTuneSubjectByTuneid2",
-      infoid = "id3",
-      command = "getTuneSubjectByTuneid2",
-      params = Map("az" -> "ba"),
-      settings = Map("we" -> "rt"),
-      modelset = false,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed", // NOTE!
-      offlineevalid = None,
-      offlinetuneid = Some(567),
-      loop = None,
-      paramset = None
-    )
-    val id1 = algos.insert(algo1)
-    val id2 = algos.insert(algo2)
-    algos.getTuneSubjectByOfflineTuneid(567) must beSome(algo2.copy(id = id2))
-  }
-
-  def getByIdAndEngineid(algos: Algos) = {
-    val obj1 = Algo(
-      id = 0,
-      engineid = 2345,
-      name = "getByIdAndEngineid",
-      infoid = "apple",
-      command = "getByIdAndEngineid",
-      params = Map("baz" -> "bah"),
-      settings = Map("qwe" -> "rty"),
-      modelset = false,
-      createtime = DateTime.now,
-      updatetime = DateTime.now.hour(1).minute(2).second(3),
-      status = "orange",
-      offlineevalid = Some(2),
-      offlinetuneid = None,
-      loop = Some(4),
-      paramset = Some(123)
-    )
-    val obj2 = obj1.copy()
-    val obj3 = obj1.copy(engineid = 2346, name = "getByIdAndEngineid3")
-
-    val id1 = algos.insert(obj1)
-    val id2 = algos.insert(obj2)
-    val id3 = algos.insert(obj3)
-    val algo1 = algos.getByIdAndEngineid(id1, 2345)
-    val algo1b = algos.getByIdAndEngineid(id1, 2346)
-    val algo2 = algos.getByIdAndEngineid(id2, 2345)
-    val algo2b = algos.getByIdAndEngineid(id2, 2346)
-    val algo3b = algos.getByIdAndEngineid(id3, 2345)
-    val algo3 = algos.getByIdAndEngineid(id3, 2346)
-
-    algo1 must beSome(obj1.copy(id = id1)) and
-      (algo1b must beNone) and
-      (algo2 must beSome(obj2.copy(id = id2))) and
-      (algo2b must beNone) and
-      (algo3 must beSome(obj3.copy(id = id3))) and
-      (algo3b must beNone)
-  }
-
-  def update(algos: Algos) = {
-    val algo = Algo(
-      id = 0,
-      engineid = 345,
-      name = "update",
-      infoid = "food",
-      command = "update",
-      params = Map("az" -> "ba"),
-      settings = Map("we" -> "rt"),
-      modelset = false,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "abc",
-      offlineevalid = None,
-      offlinetuneid = None,
-      loop = None,
-      paramset = None
-    )
-    val updateid = algos.insert(algo)
-    val updatedAlgo = algo.copy(
-      id = updateid,
-      name = "updated",
-      infoid = "food2",
-      command = "updated",
-      params = Map("def" -> "ghi"),
-      settings = Map(),
-      updatetime = DateTime.now.hour(2).minute(45).second(10),
-      status = "ready",
-      offlineevalid = Some(3),
-      offlinetuneid = Some(4),
-      loop = Some(10),
-      paramset = Some(9)
-    )
-    algos.update(updatedAlgo)
-    algos.get(updateid) must beSome(updatedAlgo)
-  }
-
-  def delete(algos: Algos) = {
-    val id = algos.insert(Algo(
-      id = 0,
-      engineid = 456,
-      name = "delete",
-      infoid = "abc4",
-      command = "delete",
-      params = Map("az" -> "ba"),
-      settings = Map("we" -> "rt"),
-      modelset = false,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "ok",
-      offlineevalid = None,
-      offlinetuneid = Some(34),
-      loop = None,
-      paramset = Some(42)
-    ))
-    algos.delete(id)
-    algos.get(id) must beNone
-  }
-
-  def existsByEngineidAndName(algos: Algos) = {
-
-    val algo1 = Algo(
-      id = 0,
-      engineid = 456,
-      name = "existsByEngineidAndName-1",
-      infoid = "abcdef",
-      command = "delete",
-      params = Map("az" -> "ba"),
-      settings = Map("we" -> "rt"),
-      modelset = false,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "food",
-      offlineevalid = None,
-      offlinetuneid = None,
-      loop = None,
-      paramset = None
-    )
-
-    val id1 = algos.insert(algo1)
-
-    // algo with offlineevalid, existence is ignored
-    algos.insert(algo1.copy(
-      name = "existsByEngineidAndName-1a",
-      offlineevalid = Some(5)
-    ))
-    // algo with offlinetuneid, existence is not ignored
-    algos.insert(algo1.copy(
-      name = "existsByEngineidAndName-1b",
-      offlinetuneid = Some(6)
-    ))
-    algos.existsByEngineidAndName(456, "existsByEngineidAndName-1") must beTrue and // match engineid and name
-      (algos.existsByEngineidAndName(456, "existsByEngineidAndName-2") must beFalse) and // same engineid, diff name
-      (algos.existsByEngineidAndName(457, "existsByEngineidAndName-1") must beFalse) and // diff engineid, same name
-      (algos.existsByEngineidAndName(456, "existsByEngineidAndName-1a") must beFalse) and // algo with offlineevalid
-      (algos.existsByEngineidAndName(456, "existsByEngineidAndName-1b") must beTrue) // algo with offlinetuneid
-  }
-
-  def backuprestore(algos: Algos) = {
-    val algo1 = Algo(
-      id = 0,
-      engineid = 456,
-      name = "backuprestore-1",
-      infoid = "abcdef",
-      command = "delete",
-      params = Map("az" -> "ba"),
-      settings = Map("we" -> "rt"),
-      modelset = false,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "food",
-      offlineevalid = None,
-      offlinetuneid = Some(3),
-      loop = None,
-      paramset = None,
-      lasttraintime = Some(DateTime.now))
-    val algo2 = Algo(
-      id = 0,
-      engineid = 5839,
-      name = "backuprestore-2",
-      infoid = "abcdef",
-      command = "delete",
-      params = Map("az" -> "ba", "deadbeef" -> 3.14),
-      settings = Map(),
-      modelset = false,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "tuned",
-      offlineevalid = Some(43),
-      offlinetuneid = Some(3),
-      loop = None,
-      paramset = Some(5))
-    val id1 = algos.insert(algo1)
-    val id2 = algos.insert(algo2)
-    val ralgo1 = algo1.copy(id = id1)
-    val ralgo2 = algo2.copy(id = id2)
-    val fn = "algos.json"
-    val fos = new java.io.FileOutputStream(fn)
-    try {
-      fos.write(algos.backup())
-    } finally {
-      fos.close()
-    }
-    algos.restore(scala.io.Source.fromFile(fn)(scala.io.Codec.UTF8).mkString.getBytes("UTF-8")) map { ralgos =>
-      val falgo1 = ralgos.find(_.id == id1).get
-      val falgo2 = ralgos.find(_.id == id2).get
-      algos.update(falgo1)
-      algos.update(falgo2)
-      (algos.get(id1) must beSome(ralgo1)) and (algos.get(id2) must beSome(ralgo2))
-    } getOrElse 1 === 2
-  }
-}
diff --git a/commons/src/test/scala/io/prediction/commons/settings/AppsSpec.scala b/commons/src/test/scala/io/prediction/commons/settings/AppsSpec.scala
deleted file mode 100644
index a96cdf5..0000000
--- a/commons/src/test/scala/io/prediction/commons/settings/AppsSpec.scala
+++ /dev/null
@@ -1,179 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Spec
-
-import org.specs2._
-import org.specs2.specification.Step
-import com.mongodb.casbah.Imports._
-
-class AppsSpec extends Specification {
-  def is = s2"""
-
-  PredictionIO Apps Specification
-
-    Apps can be implemented by:
-    - MongoApps ${mongoApps}
-
-  """
-
-  def mongoApps = s2"""
-
-    MongoApps should
-    - behave like any Apps implementation ${apps(newMongoApps)}
-    - (database cleanup) ${Step(Spec.mongoClient(mongoDbName).dropDatabase())}
-
-  """
-
-  def apps(apps: Apps) = s2"""
-
-    get two apps by user ID ${getByUserid(apps)}
-    get an app by its appkey ${getByAppkey(apps)}
-    get an app by a non-existing appkey and fail ${getByAppkeyNonExist(apps)}
-    get an app by its appkey and user ID ${getByAppkeyAndUserid(apps)}
-    get an app by its appkey and a non-existing user ID and fail ${getByAppkeyAndUseridNonExist(apps)}
-    get an app by its ID and user ID ${getByIdAndUserid(apps)}
-    get an app by a non-existing ID and user ID and fail ${getByIdAndUseridNonExist(apps)}
-    delete an app by its ID and user ID ${deleteByIdAndUserid(apps)}
-    check existence of an app by its ID, appkey and user ID ${existsByIdAndAppkeyAndUserid(apps)}
-    updating an app ${update(apps)}
-    updating an app's appkey ${updateAppkeyByAppkeyAndUserid(apps)}
-    updating an app's timezone ${updateTimezoneByAppkeyAndUserid(apps)}
-    backup and restore apps ${backuprestore(apps)}
-
-  """
-
-  val mongoDbName = "predictionio_mongoapps_test"
-  def newMongoApps = new mongodb.MongoApps(Spec.mongoClient(mongoDbName))
-
-  def dummyApp(id: Int, userid: Int, dummy: String) = App(
-    id = id,
-    userid = userid,
-    appkey = dummy,
-    display = dummy,
-    url = None,
-    cat = None,
-    desc = None,
-    timezone = "UTC"
-  )
-
-  def getByUserid(apps: Apps) = {
-    val userid = 47838
-    val dummy1 = dummyApp(0, userid, "getByUserid1")
-    val dummy2 = dummyApp(0, userid, "getByUserid2")
-    val id1 = apps.insert(dummy1)
-    val id2 = apps.insert(dummy2)
-    val app12 = apps.getByUserid(userid)
-    val app1 = app12.next()
-    val app2 = app12.next()
-    (app1 must be equalTo (dummy1.copy(id = id1))) and
-      (app2 must be equalTo (dummy2.copy(id = id2)))
-  }
-
-  def getByAppkey(apps: Apps) = {
-    val userid = 2345
-    val dummy = dummyApp(0, userid, "getByAppkey")
-    val id = apps.insert(dummy)
-    apps.getByAppkey("getByAppkey") must beSome(dummy.copy(id = id))
-  }
-
-  def getByAppkeyNonExist(apps: Apps) = {
-    apps.getByAppkey("getByAppkeyNonExist") must beNone
-  }
-
-  def getByAppkeyAndUserid(apps: Apps) = {
-    val name = "getByAppkeyAndUserid"
-    val userid = 689
-    val dummy = dummyApp(0, userid, name)
-    val id = apps.insert(dummy)
-    apps.getByAppkeyAndUserid(name, userid) must beSome(dummy.copy(id = id))
-  }
-
-  def getByAppkeyAndUseridNonExist(apps: Apps) = {
-    val userid = 203
-    val id = apps.insert(dummyApp(0, userid, "getByAppkeyAndUseridNonExist"))
-    apps.getByAppkeyAndUserid("getByAppkeyAndUseridNonExist", 2849) must beNone
-  }
-
-  def getByIdAndUserid(apps: Apps) = {
-    val name = "getByIdAndUserid"
-    val userid = 12
-    val dummy = dummyApp(0, userid, name)
-    val id = apps.insert(dummy)
-    apps.getByIdAndUserid(id, userid) must beSome(dummy.copy(id = id))
-  }
-
-  def getByIdAndUseridNonExist(apps: Apps) = {
-    val name = "getByIdAndUseridNonExist"
-    val userid = 23
-    val id = apps.insert(dummyApp(0, userid, name))
-    apps.getByIdAndUserid(0, userid) must beNone
-  }
-
-  def deleteByIdAndUserid(apps: Apps) = {
-    val name = "deleteByIdAndUserid"
-    val userid = 34
-    val id = apps.insert(dummyApp(0, userid, name))
-    apps.deleteByIdAndUserid(id, userid)
-    apps.getByIdAndUserid(id, userid) must beNone
-  }
-
-  def existsByIdAndAppkeyAndUserid(apps: Apps) = {
-    val name = "existsByIdAndAppkeyAndUserid"
-    val userid = 45
-    val id = apps.insert(dummyApp(0, userid, name))
-    apps.existsByIdAndAppkeyAndUserid(id, name, userid) must beTrue
-  }
-
-  def update(apps: Apps) = {
-    val name = "update"
-    val userid = 56
-    val id = apps.insert(dummyApp(0, userid, name))
-    val updated = dummyApp(id, 67, "updated")
-    apps.update(updated)
-    apps.getByIdAndUserid(id, 67) must beSome(updated)
-  }
-
-  def updateAppkeyByAppkeyAndUserid(apps: Apps) = {
-    val name = "updateAppkeyByAppkeyAndUserid"
-    val userid = 78
-    val id = apps.insert(dummyApp(0, userid, name))
-    val updated = dummyApp(id, 67, "updated")
-    apps.updateAppkeyByAppkeyAndUserid(name, userid, "updatedAppkey")
-    apps.existsByIdAndAppkeyAndUserid(id, "updatedAppkey", userid) must beTrue
-  }
-
-  def updateTimezoneByAppkeyAndUserid(apps: Apps) = {
-    val name = "updateTimezoneByAppkeyAndUserid"
-    val userid = 89
-    val id = apps.insert(dummyApp(0, userid, name))
-    val updated = App(
-      id = id,
-      userid = userid,
-      appkey = name,
-      display = name,
-      url = None,
-      cat = None,
-      desc = None,
-      timezone = "US/Pacific"
-    )
-    apps.updateTimezoneByAppkeyAndUserid(name, userid, "US/Pacific")
-    apps.getByAppkey(name) must beSome(updated)
-  }
-
-  def backuprestore(apps: Apps) = {
-    val name = "backuprestore"
-    val userid = 90
-    val app1 = dummyApp(0, userid, name)
-    val id1 = apps.insert(app1)
-    val fn = "apps.json"
-    val fos = new java.io.FileOutputStream(fn)
-    try {
-      fos.write(apps.backup())
-    } finally {
-      fos.close()
-    }
-    apps.restore(scala.io.Source.fromFile(fn)(scala.io.Codec.UTF8).mkString.getBytes("UTF-8")) map { data =>
-      data must contain(app1.copy(id = id1))
-    } getOrElse 1 === 2
-  }
-}
diff --git a/commons/src/test/scala/io/prediction/commons/settings/EngineInfosSpec.scala b/commons/src/test/scala/io/prediction/commons/settings/EngineInfosSpec.scala
deleted file mode 100644
index ac44310..0000000
--- a/commons/src/test/scala/io/prediction/commons/settings/EngineInfosSpec.scala
+++ /dev/null
@@ -1,109 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Spec
-
-import org.specs2._
-import org.specs2.specification.Step
-import com.mongodb.casbah.Imports._
-
-class EngineInfosSpec extends Specification {
-  def is = s2"""
-
-  PredictionIO EngineInfos Specification
-
-    EngineInfos can be implemented by:
-    - MongoEngineInfos ${mongoEngineInfos}
-
-  """
-
-  def mongoEngineInfos = s2"""
-
-    MongoEngineInfos should
-    - behave like any EngineInfos implementation ${engineInfos(newMongoEngineInfos)}
-    - (database cleanup) ${Step(Spec.mongoClient(mongoDbName).dropDatabase())}
-
-  """
-
-  def engineInfos(engineInfos: EngineInfos) = s2"""
-
-    create and get an engine info ${insertAndGet(engineInfos)}
-    update an engine info ${update(engineInfos)}
-    delete an engine info ${delete(engineInfos)}
-    backup and restore existing engine info ${backuprestore(engineInfos)}
-
-  """
-
-  val mongoDbName = "predictionio_mongoengineinfos_test"
-  def newMongoEngineInfos = new mongodb.MongoEngineInfos(Spec.mongoClient(mongoDbName))
-
-  def insertAndGet(engineInfos: EngineInfos) = {
-    val itemrec = EngineInfo(
-      id = "itemrec",
-      name = "Item Recommendation Engine",
-      description = Some("Recommend interesting items to each user personally."),
-      params = Map[String, Param]("numRecs" -> Param(id = "numRecs", name = "", description = None, defaultvalue = 500, constraint = ParamIntegerConstraint(), ui = ParamUI(), scopes = None)),
-      paramsections = Seq(),
-      defaultalgoinfoid = "mahout-itembased",
-      defaultofflineevalmetricinfoid = "metric-x",
-      defaultofflineevalsplitterinfoid = "splitter-y")
-    engineInfos.insert(itemrec)
-    engineInfos.get("itemrec") must beSome(itemrec)
-  }
-
-  def update(engineInfos: EngineInfos) = {
-    val itemsim = EngineInfo(
-      id = "itemsim",
-      name = "Items Similarity Prediction Engine",
-      description = Some("Discover similar items."),
-      params = Map[String, Param](),
-      paramsections = Seq(),
-      defaultalgoinfoid = "knnitembased",
-      defaultofflineevalmetricinfoid = "metric-x",
-      defaultofflineevalsplitterinfoid = "splitter-y")
-    engineInfos.insert(itemsim)
-    val updatedItemsim = itemsim.copy(
-      defaultalgoinfoid = "mahout-itembasedcf",
-      defaultofflineevalmetricinfoid = "metric-apple",
-      defaultofflineevalsplitterinfoid = "splitter-orange")
-    engineInfos.update(updatedItemsim)
-    engineInfos.get("itemsim") must beSome(updatedItemsim)
-  }
-
-  def delete(engineInfos: EngineInfos) = {
-    val foo = EngineInfo(
-      id = "foo",
-      name = "bar",
-      description = None,
-      params = Map[String, Param](),
-      paramsections = Seq(),
-      defaultalgoinfoid = "baz",
-      defaultofflineevalmetricinfoid = "food",
-      defaultofflineevalsplitterinfoid = "yummy")
-    engineInfos.insert(foo)
-    engineInfos.delete("foo")
-    engineInfos.get("foo") must beNone
-  }
-
-  def backuprestore(engineInfos: EngineInfos) = {
-    val baz = EngineInfo(
-      id = "baz",
-      name = "beef",
-      description = Some("dead"),
-      params = Map[String, Param]("abc" -> Param(id = "abc", name = "", description = None, defaultvalue = 123.4, constraint = ParamDoubleConstraint(), ui = ParamUI(), scopes = None)),
-      paramsections = Seq(),
-      defaultalgoinfoid = "bar",
-      defaultofflineevalmetricinfoid = "yummy",
-      defaultofflineevalsplitterinfoid = "food")
-    engineInfos.insert(baz)
-    val fn = "engineinfos.json"
-    val fos = new java.io.FileOutputStream(fn)
-    try {
-      fos.write(engineInfos.backup())
-    } finally {
-      fos.close()
-    }
-    engineInfos.restore(scala.io.Source.fromFile(fn)(scala.io.Codec.UTF8).mkString.getBytes("UTF-8")) map { rengineinfos =>
-      rengineinfos must contain(baz)
-    } getOrElse 1 === 2
-  }
-}
diff --git a/commons/src/test/scala/io/prediction/commons/settings/EnginesSpec.scala b/commons/src/test/scala/io/prediction/commons/settings/EnginesSpec.scala
deleted file mode 100644
index dd30e1f..0000000
--- a/commons/src/test/scala/io/prediction/commons/settings/EnginesSpec.scala
+++ /dev/null
@@ -1,180 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Spec
-
-import org.specs2._
-import org.specs2.specification.Step
-import com.mongodb.casbah.Imports._
-
-class EnginesSpec extends Specification {
-  def is = s2"""
-
-  PredictionIO Engines Specification
-
-    Engines can be implemented by:
-    - MongoEngines ${mongoEngines}
-
-  """
-
-  def mongoEngines = s2"""
-
-    MongoEngines should
-    - behave like any Engines implementation ${engines(newMongoEngines)}
-    - (database cleanup) ${Step(Spec.mongoClient(mongoDbName).dropDatabase())}
-
-  """
-
-  def engines(engines: Engines) = s2"""
-
-    create an engine ${insert(engines)}
-    get two engines ${getByAppid(engines)}
-    get by id and appid ${getByIdAndAppid(engines)}
-    update an engine ${update(engines)}
-    delete an engine ${deleteByIdAndAppid(engines)}
-    checking existence of engines ${existsByAppidAndName(engines)}
-    backup and restore existing engines ${backuprestore(engines)}
-
-  """
-
-  val mongoDbName = "predictionio_mongoengines_test"
-  def newMongoEngines = new mongodb.MongoEngines(Spec.mongoClient(mongoDbName))
-
-  def insert(engines: Engines) = {
-    val engine = Engine(
-      id = 0,
-      appid = 123,
-      name = "insert",
-      infoid = "insert",
-      itypes = Option(List("foo", "bar")),
-      params = Map()
-    )
-    val engineid = engines.insert(engine)
-    engines.get(engineid) must beSome(engine.copy(id = engineid))
-  }
-
-  def getByAppid(engines: Engines) = {
-    val obj1 = Engine(
-      id = 0,
-      appid = 234,
-      name = "getByAppid1",
-      infoid = "getByAppid1",
-      itypes = Option(List("foo", "bar")),
-      params = Map("apple" -> "red")
-    )
-    val obj2 = Engine(
-      id = 0,
-      appid = 234,
-      name = "getByAppid2",
-      infoid = "getByAppid2",
-      itypes = None,
-      params = Map("foo2" -> "bar2")
-    )
-    val id1 = engines.insert(obj1)
-    val id2 = engines.insert(obj2)
-    val engine12 = engines.getByAppid(234)
-    val engine1 = engine12.next()
-    val engine2 = engine12.next()
-    engine1 must be equalTo (obj1.copy(id = id1)) and
-      (engine2 must be equalTo (obj2.copy(id = id2)))
-  }
-
-  def getByIdAndAppid(engines: Engines) = {
-    val obj1 = Engine(
-      id = 0,
-      appid = 2345,
-      name = "getByIdAndAppid",
-      infoid = "getByIdAndAppid",
-      itypes = Option(List("foo", "bar")),
-      params = Map("apple" -> "red")
-    )
-    val obj2 = obj1.copy()
-
-    val obj3 = obj1.copy(appid = 2346, name = "getByIdAndAppid3")
-
-    val id1 = engines.insert(obj1)
-    val id2 = engines.insert(obj2)
-    val id3 = engines.insert(obj3)
-    val engine1 = engines.getByIdAndAppid(id1, 2345)
-    val engine1b = engines.getByIdAndAppid(id1, 2346)
-    val engine2 = engines.getByIdAndAppid(id2, 2345)
-    val engine2b = engines.getByIdAndAppid(id2, 2346)
-    val engine3b = engines.getByIdAndAppid(id3, 2345)
-    val engine3 = engines.getByIdAndAppid(id3, 2346)
-
-    engine1 must beSome(obj1.copy(id = id1)) and
-      (engine1b must beNone) and
-      (engine2 must beSome(obj2.copy(id = id2))) and
-      (engine2b must beNone) and
-      (engine3 must beSome(obj3.copy(id = id3))) and
-      (engine3b must beNone)
-  }
-
-  def update(engines: Engines) = {
-    val id = engines.insert(Engine(
-      id = 0,
-      appid = 345,
-      name = "update",
-      infoid = "update",
-      itypes = Some(List("foo", "bar")),
-      params = Map()
-    ))
-    val updatedEngine = Engine(
-      id = id,
-      appid = 345,
-      name = "updated",
-      infoid = "updated",
-      itypes = Some(List("foo", "baz")),
-      params = Map("set1" -> "dat1", "set2" -> "dat2")
-    )
-    engines.update(updatedEngine)
-    engines.getByAppidAndName(345, "updated") must beSome(updatedEngine)
-  }
-
-  def deleteByIdAndAppid(engines: Engines) = {
-    val id = engines.insert(Engine(
-      id = 0,
-      appid = 456,
-      name = "deleteByIdAndAppid",
-      infoid = "deleteByIdAndAppid",
-      itypes = Some(List("foo", "bar")),
-      params = Map("x" -> "y")
-    ))
-    engines.deleteByIdAndAppid(id, 456)
-    engines.getByAppidAndName(456, "deleteByIdAndAppid") must beNone
-  }
-
-  def existsByAppidAndName(engines: Engines) = {
-    val id = engines.insert(Engine(
-      id = 0,
-      appid = 567,
-      name = "existsByAppidAndName",
-      infoid = "existsByAppidAndName",
-      itypes = None,
-      params = Map()
-    ))
-    engines.existsByAppidAndName(567, "existsByAppidAndName") must beTrue and
-      (engines.existsByAppidAndName(568, "foobar") must beFalse)
-  }
-
-  def backuprestore(engines: Engines) = {
-    val eng = Engine(
-      id = 0,
-      appid = 678,
-      name = "backuprestore",
-      infoid = "backuprestore",
-      itypes = Some(Seq("dead", "beef")),
-      params = Map("foo" -> "bar")
-    )
-    val eid = engines.insert(eng)
-    val fn = "engines.json"
-    val fos = new java.io.FileOutputStream(fn)
-    try {
-      fos.write(engines.backup())
-    } finally {
-      fos.close()
-    }
-    engines.restore(scala.io.Source.fromFile(fn)(scala.io.Codec.UTF8).mkString.getBytes("UTF-8")) map { rengines =>
-      rengines must contain(eng.copy(id = eid))
-    } getOrElse 1 === 2
-  }
-}
diff --git a/commons/src/test/scala/io/prediction/commons/settings/OfflineEvalMetricInfosSpec.scala b/commons/src/test/scala/io/prediction/commons/settings/OfflineEvalMetricInfosSpec.scala
deleted file mode 100644
index df6265b..0000000
--- a/commons/src/test/scala/io/prediction/commons/settings/OfflineEvalMetricInfosSpec.scala
+++ /dev/null
@@ -1,261 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Spec
-
-import org.specs2._
-import org.specs2.specification.Step
-import com.mongodb.casbah.Imports._
-
-class OfflineEvalMetricInfosSpec extends Specification {
-  def is = s2"""
-
-  PredictionIO OfflineEvalMetricInfos Specification
-
-    OfflineEvalMetricInfos can be implemented by:
-    - MongoOfflineEvalMetricInfos ${mongoOfflineEvalMetricInfos}
-
-  """
-
-  def mongoOfflineEvalMetricInfos = s2"""
-
-    MongoOfflineEvalMetricInfos should
-    - behave like any OfflineEvalMetricInfos implementation ${metricInfos(newMongoOfflineEvalMetricInfos)}
-    - (database cleanup) ${Step(Spec.mongoClient(mongoDbName).dropDatabase())}
-
-  """
-
-  def metricInfos(metricInfos: OfflineEvalMetricInfos) = s2"""
-
-    create and get an metric info ${insertAndGet(metricInfos)}
-    get metric info by engine info id ${getByEngineinfoid(metricInfos)}
-    update an metric info ${update(metricInfos)}
-    delete an metric info ${delete(metricInfos)}
-    backup and restore metric infos ${backuprestore(metricInfos)}
-
-  """
-
-  val mongoDbName = "predictionio_mongometricinfos_test"
-  def newMongoOfflineEvalMetricInfos = new mongodb.MongoOfflineEvalMetricInfos(Spec.mongoClient(mongoDbName))
-
-  def insertAndGet(metricInfos: OfflineEvalMetricInfos) = {
-    val mapk = OfflineEvalMetricInfo(
-      id = "map-k",
-      name = "Mean Average Precision",
-      description = None,
-      engineinfoids = Seq("itemrec"),
-      commands = Some(Seq(
-        "$hadoop$ jar $pdioEvalJar$ io.prediction.metrics.scalding.itemrec.map.MAPAtKDataPreparator --hdfs --test_dbType $appdataTestDbType$ --test_dbName $appdataTestDbName$ --test_dbHost $appdataTestDbHost$ --test_dbPort $appdataTestDbPort$ --training_dbType $appdataTrainingDbType$ --training_dbName $appdataTrainingDbName$ --training_dbHost $appdataTrainingDbHost$ --training_dbPort $appdataTrainingDbPort$ --modeldata_dbType $modeldataTrainingDbType$ --modeldata_dbName $modeldataTrainingDbName$ --modeldata_dbHost $modeldataTrainingDbHost$ --modeldata_dbPort $modeldataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --kParam $kParam$ --goalParam $goalParam$",
-        "java -Dio.prediction.base=$base$ $configFile$ -Devalid=$evalid$ -Dalgoid=$algoid$ -Dk=$kParam$ -Dmetricid=$metricid$ -Dhdfsroot=$hdfsRoot$ -jar $topkJar$",
-        "$hadoop$ jar $pdioEvalJar$ io.prediction.metrics.scalding.itemrec.map.MAPAtK --hdfs --dbType $settingsDbType$ --dbName $settingsDbName$ --dbHost $settingsDbHost$ --dbPort $settingsDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --kParam $kParam$")),
-      params = Map(
-        "k" -> Param(
-          id = "k",
-          name = "k parameter",
-          description = Some("Averaging window size"),
-          defaultvalue = 20,
-          constraint = ParamIntegerConstraint(min = Some(0), max = Some(100)),
-          ui = ParamUI(
-            uitype = "text"))),
-      paramsections = Seq(
-        ParamSection(
-          name = "foo",
-          params = Some(Seq("k")))),
-      paramorder = Seq("k"))
-    metricInfos.insert(mapk)
-    metricInfos.get("map-k") must beSome(mapk)
-  }
-
-  def getByEngineinfoid(metricInfos: OfflineEvalMetricInfos) = {
-    val mapkA = OfflineEvalMetricInfo(
-      id = "map-k-a",
-      name = "Mean Average Precision A",
-      description = None,
-      engineinfoids = Seq("engine1"),
-      commands = Some(Seq(
-        "$hadoop$ jar $pdioEvalJar$ io.prediction.metrics.scalding.itemrec.map.MAPAtKDataPreparator --hdfs --test_dbType $appdataTestDbType$ --test_dbName $appdataTestDbName$ --test_dbHost $appdataTestDbHost$ --test_dbPort $appdataTestDbPort$ --training_dbType $appdataTrainingDbType$ --training_dbName $appdataTrainingDbName$ --training_dbHost $appdataTrainingDbHost$ --training_dbPort $appdataTrainingDbPort$ --modeldata_dbType $modeldataTrainingDbType$ --modeldata_dbName $modeldataTrainingDbName$ --modeldata_dbHost $modeldataTrainingDbHost$ --modeldata_dbPort $modeldataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --kParam $kParam$ --goalParam $goalParam$",
-        "java -Dio.prediction.base=$base$ $configFile$ -Devalid=$evalid$ -Dalgoid=$algoid$ -Dk=$kParam$ -Dmetricid=$metricid$ -Dhdfsroot=$hdfsRoot$ -jar $topkJar$",
-        "$hadoop$ jar $pdioEvalJar$ io.prediction.metrics.scalding.itemrec.map.MAPAtK --hdfs --dbType $settingsDbType$ --dbName $settingsDbName$ --dbHost $settingsDbHost$ --dbPort $settingsDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --kParam $kParam$")),
-      params = Map(
-        "k" -> Param(
-          id = "k",
-          name = "k parameter",
-          description = Some("Averaging window size"),
-          defaultvalue = 20,
-          constraint = ParamIntegerConstraint(min = Some(0), max = Some(100)),
-          ui = ParamUI(
-            uitype = "text"))),
-      paramsections = Seq(
-        ParamSection(
-          name = "foo",
-          params = Some(Seq("k")))),
-      paramorder = Seq("k"))
-
-    val mapkB = mapkA.copy(
-      id = "map-k-b",
-      name = "Mean Average Precision B",
-      engineinfoids = Seq("engine1")
-    )
-
-    val mapkC = mapkA.copy(
-      id = "map-k-c",
-      name = "Mean Average Precision C",
-      engineinfoids = Seq("engine2")
-    )
-
-    val mapkD = mapkA.copy(
-      id = "map-k-D",
-      name = "Mean Average Precision D",
-      engineinfoids = Seq("engine3", "engine1")
-    )
-
-    metricInfos.insert(mapkA)
-    metricInfos.insert(mapkB)
-    metricInfos.insert(mapkC)
-    metricInfos.insert(mapkD)
-
-    val engine1Metrics = metricInfos.getByEngineinfoid("engine1")
-
-    val engine1Metric1 = engine1Metrics(0)
-    val engine1Metric2 = engine1Metrics(1)
-    val engine1Metric3 = engine1Metrics(2)
-
-    val engine2Metrics = metricInfos.getByEngineinfoid("engine2")
-
-    val engine2Metric1 = engine2Metrics(0)
-
-    val engine3Metrics = metricInfos.getByEngineinfoid("engine3")
-
-    val engine3Metric1 = engine3Metrics(0)
-
-    engine1Metrics.length must be equalTo (3) and
-      (engine1Metric1 must be equalTo (mapkA)) and
-      (engine1Metric2 must be equalTo (mapkB)) and
-      (engine1Metric3 must be equalTo (mapkD)) and
-      (engine2Metrics.length must be equalTo (1)) and
-      (engine2Metric1 must be equalTo (mapkC)) and
-      (engine3Metrics.length must be equalTo (1)) and
-      (engine3Metric1 must be equalTo (mapkD))
-
-  }
-
-  def update(metricInfos: OfflineEvalMetricInfos) = {
-    val mapk = OfflineEvalMetricInfo(
-      id = "u-map-k",
-      name = "Mean Average Precision",
-      description = None,
-      engineinfoids = Seq("itemrec"),
-      commands = Some(Seq(
-        "$hadoop$ jar $pdioEvalJar$ io.prediction.metrics.scalding.itemrec.map.MAPAtKDataPreparator --hdfs --test_dbType $appdataTestDbType$ --test_dbName $appdataTestDbName$ --test_dbHost $appdataTestDbHost$ --test_dbPort $appdataTestDbPort$ --training_dbType $appdataTrainingDbType$ --training_dbName $appdataTrainingDbName$ --training_dbHost $appdataTrainingDbHost$ --training_dbPort $appdataTrainingDbPort$ --modeldata_dbType $modeldataTrainingDbType$ --modeldata_dbName $modeldataTrainingDbName$ --modeldata_dbHost $modeldataTrainingDbHost$ --modeldata_dbPort $modeldataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --kParam $kParam$ --goalParam $goalParam$",
-        "java -Dio.prediction.base=$base$ $configFile$ -Devalid=$evalid$ -Dalgoid=$algoid$ -Dk=$kParam$ -Dmetricid=$metricid$ -Dhdfsroot=$hdfsRoot$ -jar $topkJar$",
-        "$hadoop$ jar $pdioEvalJar$ io.prediction.metrics.scalding.itemrec.map.MAPAtK --hdfs --dbType $settingsDbType$ --dbName $settingsDbName$ --dbHost $settingsDbHost$ --dbPort $settingsDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --kParam $kParam$")),
-      params = Map(
-        "k" -> Param(
-          id = "k",
-          name = "k parameter",
-          description = Some("Averaging window size"),
-          defaultvalue = 20,
-          constraint = ParamIntegerConstraint(min = Some(0), max = Some(100)),
-          ui = ParamUI(
-            uitype = "text"))),
-      paramsections = Seq(
-        ParamSection(
-          name = "foo",
-          params = Some(Seq("k")))),
-      paramorder = Seq("k"))
-    metricInfos.insert(mapk)
-    val updatedMapk = mapk.copy(
-      commands = Some(Seq(
-        "cmd1",
-        "cmd2",
-        "cmd3")),
-      params = Map(
-        "k" -> Param(
-          id = "k",
-          name = "k parameter",
-          description = Some("Averaging window size"),
-          defaultvalue = 20,
-          constraint = ParamIntegerConstraint(min = Some(0), max = Some(100)),
-          ui = ParamUI(
-            uitype = "text")),
-        "f" -> Param(
-          id = "f",
-          name = "f parameter",
-          description = Some("FooBar"),
-          defaultvalue = 33,
-          constraint = ParamIntegerConstraint(min = Some(1), max = Some(2)),
-          ui = ParamUI(
-            uitype = "text"))),
-      paramsections = Seq(
-        ParamSection(
-          name = "apple section",
-          params = Some(Seq("f", "k")))),
-      paramorder = Seq("f", "k"))
-
-    metricInfos.update(updatedMapk)
-    metricInfos.get("u-map-k") must beSome(updatedMapk)
-  }
-
-  def delete(metricInfos: OfflineEvalMetricInfos) = {
-    val mapk = OfflineEvalMetricInfo(
-      id = "foo",
-      name = "Mean Average Precision",
-      description = None,
-      engineinfoids = Seq("itemrec"),
-      commands = Some(Seq(
-        "$hadoop$ jar $pdioEvalJar$ io.prediction.metrics.scalding.itemrec.map.MAPAtKDataPreparator --hdfs --test_dbType $appdataTestDbType$ --test_dbName $appdataTestDbName$ --test_dbHost $appdataTestDbHost$ --test_dbPort $appdataTestDbPort$ --training_dbType $appdataTrainingDbType$ --training_dbName $appdataTrainingDbName$ --training_dbHost $appdataTrainingDbHost$ --training_dbPort $appdataTrainingDbPort$ --modeldata_dbType $modeldataTrainingDbType$ --modeldata_dbName $modeldataTrainingDbName$ --modeldata_dbHost $modeldataTrainingDbHost$ --modeldata_dbPort $modeldataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --kParam $kParam$ --goalParam $goalParam$",
-        "java -Dio.prediction.base=$base$ $configFile$ -Devalid=$evalid$ -Dalgoid=$algoid$ -Dk=$kParam$ -Dmetricid=$metricid$ -Dhdfsroot=$hdfsRoot$ -jar $topkJar$",
-        "$hadoop$ jar $pdioEvalJar$ io.prediction.metrics.scalding.itemrec.map.MAPAtK --hdfs --dbType $settingsDbType$ --dbName $settingsDbName$ --dbHost $settingsDbHost$ --dbPort $settingsDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --kParam $kParam$")),
-      params = Map("k" -> Param(
-        id = "k",
-        name = "k parameter",
-        description = Some("Averaging window size"),
-        defaultvalue = 20,
-        constraint = ParamIntegerConstraint(min = Some(0), max = Some(100)),
-        ui = ParamUI(
-          uitype = "text"))),
-      paramsections = Seq(
-        ParamSection(
-          name = "foo",
-          params = Some(Seq("k")))),
-      paramorder = Seq("k"))
-    metricInfos.insert(mapk)
-    metricInfos.delete("foo")
-    metricInfos.get("foo") must beNone
-  }
-
-  def backuprestore(metricInfos: OfflineEvalMetricInfos) = {
-    val mapkbk = OfflineEvalMetricInfo(
-      id = "backup",
-      name = "Mean Average Precision",
-      description = None,
-      engineinfoids = Seq("itemrec"),
-      commands = Some(Seq(
-        "$hadoop$ jar $pdioEvalJar$ io.prediction.metrics.scalding.itemrec.map.MAPAtKDataPreparator --hdfs --test_dbType $appdataTestDbType$ --test_dbName $appdataTestDbName$ --test_dbHost $appdataTestDbHost$ --test_dbPort $appdataTestDbPort$ --training_dbType $appdataTrainingDbType$ --training_dbName $appdataTrainingDbName$ --training_dbHost $appdataTrainingDbHost$ --training_dbPort $appdataTrainingDbPort$ --modeldata_dbType $modeldataTrainingDbType$ --modeldata_dbName $modeldataTrainingDbName$ --modeldata_dbHost $modeldataTrainingDbHost$ --modeldata_dbPort $modeldataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --kParam $kParam$ --goalParam $goalParam$",
-        "java -Dio.prediction.base=$base$ $configFile$ -Devalid=$evalid$ -Dalgoid=$algoid$ -Dk=$kParam$ -Dmetricid=$metricid$ -Dhdfsroot=$hdfsRoot$ -jar $topkJar$",
-        "$hadoop$ jar $pdioEvalJar$ io.prediction.metrics.scalding.itemrec.map.MAPAtK --hdfs --dbType $settingsDbType$ --dbName $settingsDbName$ --dbHost $settingsDbHost$ --dbPort $settingsDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --kParam $kParam$")),
-      params = Map("k" -> Param(
-        id = "k",
-        name = "k parameter",
-        description = Some("Averaging window size"),
-        defaultvalue = 20,
-        constraint = ParamIntegerConstraint(min = Some(0), max = Some(100)),
-        ui = ParamUI(
-          uitype = "text"))),
-      paramsections = Seq(
-        ParamSection(
-          name = "foo",
-          params = Some(Seq("k")))),
-      paramorder = Seq("k"))
-    metricInfos.insert(mapkbk)
-    val fn = "metricinfos.json"
-    val fos = new java.io.FileOutputStream(fn)
-    try {
-      fos.write(metricInfos.backup())
-    } finally {
-      fos.close()
-    }
-    metricInfos.restore(scala.io.Source.fromFile(fn)(scala.io.Codec.UTF8).mkString.getBytes("UTF-8")) map { data =>
-      data must contain(mapkbk)
-    } getOrElse 1 === 2
-  }
-}
diff --git a/commons/src/test/scala/io/prediction/commons/settings/OfflineEvalMetricsSpec.scala b/commons/src/test/scala/io/prediction/commons/settings/OfflineEvalMetricsSpec.scala
deleted file mode 100644
index 6e8864b..0000000
--- a/commons/src/test/scala/io/prediction/commons/settings/OfflineEvalMetricsSpec.scala
+++ /dev/null
@@ -1,158 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Spec
-
-import org.specs2._
-import org.specs2.specification.Step
-import com.mongodb.casbah.Imports._
-
-class OfflineEvalMetricsSpec extends Specification {
-  def is = s2"""
-
-  PredictionIO OfflineEvalMetrics Specification
-
-    OfflineEvalMetrics can be implemented by:
-    - MongoOfflineEvalMetrics ${mongoOfflineEvalMetrics}
-
-  """
-
-  def mongoOfflineEvalMetrics = s2"""
-
-    MongoOfflineEvalMetrics should
-    - behave like any OfflineEvalMetrics implementation ${offlineEvalMetricsTest(newMongoOfflineEvalMetrics)}
-    - (database cleanup) ${Step(Spec.mongoClient(mongoDbName).dropDatabase())}
-
-  """
-
-  def offlineEvalMetricsTest(offlineEvalMetrics: OfflineEvalMetrics) = s2"""
-
-    create an OfflineEvalMetric ${insert(offlineEvalMetrics)}
-    get two OfflineEvalMetrics ${getByEvalid(offlineEvalMetrics)}
-    update an OfflineEvalMetric ${update(offlineEvalMetrics)}
-    delete an OfflineEvalMetric ${delete(offlineEvalMetrics)}
-    backup and restore OfflineEvalMetrics ${backuprestore(offlineEvalMetrics)}
-
-  """
-
-  val mongoDbName = "predictionio_mongoofflineevalmetrics_test"
-  def newMongoOfflineEvalMetrics = new mongodb.MongoOfflineEvalMetrics(Spec.mongoClient(mongoDbName))
-
-  /**
-   * insert and get by id
-   */
-  def insert(offlineEvalMetrics: OfflineEvalMetrics) = {
-    val obj = OfflineEvalMetric(
-      id = -1,
-      infoid = "metric-insert1",
-      evalid = 42,
-      params = Map(("abc" -> 3), ("bar" -> "foo1 foo2"))
-    )
-
-    val insertid = offlineEvalMetrics.insert(obj)
-    offlineEvalMetrics.get(insertid) must beSome(obj.copy(id = insertid))
-  }
-
-  /**
-   * insert a few and get by engineid
-   */
-  def getByEvalid(offlineEvalMetrics: OfflineEvalMetrics) = {
-    val obj1 = OfflineEvalMetric(
-      id = -1,
-      infoid = "metric-getByEvalid1",
-      evalid = 15,
-      params = Map(("abc1" -> 6), ("bar1" -> "foo1 foo2"), ("bar1b" -> "foo1b"))
-    )
-    val obj2 = OfflineEvalMetric(
-      id = -1,
-      infoid = "metric-getByEvalid2",
-      evalid = 15,
-      params = Map(("abc2" -> 0), ("bar2" -> "foox"))
-    )
-
-    val id1 = offlineEvalMetrics.insert(obj1)
-    val id2 = offlineEvalMetrics.insert(obj2)
-
-    val it = offlineEvalMetrics.getByEvalid(15)
-
-    val it1 = it.next()
-    val it2 = it.next()
-    val left = it.hasNext // make sure it has 2 only
-
-    it1 must be equalTo (obj1.copy(id = id1)) and
-      (it2 must be equalTo (obj2.copy(id = id2))) and
-      (left must be_==(false))
-
-  }
-
-  /**
-   * insert one and then update with new data and get back
-   */
-  def update(offlineEvalMetrics: OfflineEvalMetrics) = {
-    val obj1 = OfflineEvalMetric(
-      id = -1,
-      infoid = "metric-update1",
-      evalid = 16,
-      params = Map(("def" -> "a1 a2 a3"), ("def2" -> 1), ("def3" -> "food"))
-    )
-
-    val updateid = offlineEvalMetrics.insert(obj1)
-    val data1 = offlineEvalMetrics.get(updateid)
-
-    val obj2 = obj1.copy(
-      id = updateid,
-      infoid = "metric-update2",
-      evalid = 99,
-      params = Map()
-    )
-
-    offlineEvalMetrics.update(obj2)
-
-    val data2 = offlineEvalMetrics.get(updateid)
-
-    data1 must beSome(obj1.copy(id = updateid)) and
-      (data2 must beSome(obj2))
-
-  }
-
-  /**
-   * insert one and delete and get back
-   */
-  def delete(offlineEvalMetrics: OfflineEvalMetrics) = {
-    val obj1 = OfflineEvalMetric(
-      id = -1,
-      infoid = "metric-delete1",
-      evalid = 3,
-      params = Map(("x" -> 1))
-    )
-
-    val id1 = offlineEvalMetrics.insert(obj1)
-    val data1 = offlineEvalMetrics.get(id1)
-
-    offlineEvalMetrics.delete(id1)
-    val data2 = offlineEvalMetrics.get(id1)
-
-    data1 must beSome(obj1.copy(id = id1)) and
-      (data2 must beNone)
-
-  }
-
-  def backuprestore(offlineEvalMetrics: OfflineEvalMetrics) = {
-    val obj1 = OfflineEvalMetric(
-      id = -1,
-      infoid = "metric-backuprestore",
-      evalid = 45,
-      params = Map("foo" -> "bar", "pi" -> 3.14))
-    val id1 = offlineEvalMetrics.insert(obj1)
-    val fn = "metrics.json"
-    val fos = new java.io.FileOutputStream(fn)
-    try {
-      fos.write(offlineEvalMetrics.backup())
-    } finally {
-      fos.close()
-    }
-    offlineEvalMetrics.restore(scala.io.Source.fromFile(fn)(scala.io.Codec.UTF8).mkString.getBytes("UTF-8")) map { data =>
-      data must contain(obj1.copy(id = id1))
-    } getOrElse 1 === 2
-  }
-
-}
diff --git a/commons/src/test/scala/io/prediction/commons/settings/OfflineEvalResultsSpec.scala b/commons/src/test/scala/io/prediction/commons/settings/OfflineEvalResultsSpec.scala
deleted file mode 100644
index 6955c40..0000000
--- a/commons/src/test/scala/io/prediction/commons/settings/OfflineEvalResultsSpec.scala
+++ /dev/null
@@ -1,188 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Spec
-
-import org.specs2._
-import org.specs2.specification.Step
-import com.mongodb.casbah.Imports._
-
-class OfflineEvalResultsSpec extends Specification {
-  def is = s2"""
-
-  PredictionIO OfflineEvalResults Specification
-
-    OfflineEvalResults can be implemented by:
-    - MongoOfflineEvalResults ${mongoOfflineEvalResults}
-
-  """
-
-  def mongoOfflineEvalResults = s2"""
-
-    MongoOfflineEvalResults should
-    - behave like any OfflineEvalResults implementation ${offlineEvalResultsTest(newMongoOfflineEvalResults)}
-    - (database cleanup) ${Step(Spec.mongoClient(mongoDbName).dropDatabase())}
-
-  """
-
-  def offlineEvalResultsTest(offlineEvalResults: OfflineEvalResults) = s2"""
-
-    get two OfflineEvalResults by evalid ${getByEvalid(offlineEvalResults)}
-    delete two OfflineEvalResults by evalid ${deleteByEvalid(offlineEvalResults)}
-    backup and restore OfflineEvalResults ${backuprestore(offlineEvalResults)}
-
-  """
-
-  val mongoDbName = "predictionio_mongoofflineevalresults_test"
-  def newMongoOfflineEvalResults = new mongodb.MongoOfflineEvalResults(Spec.mongoClient(mongoDbName))
-
-  /**
-   * save a few and get by evalid
-   */
-  def getByEvalid(offlineEvalResults: OfflineEvalResults) = {
-    val obj1 = OfflineEvalResult(
-      evalid = 16,
-      metricid = 2,
-      algoid = 3,
-      score = 0.09876,
-      iteration = 1,
-      splitset = "test"
-    )
-    val obj2 = OfflineEvalResult(
-      evalid = 16,
-      metricid = 2,
-      algoid = 3,
-      score = 0.123,
-      iteration = 2, // only this is diff from obj1
-      splitset = "test"
-    )
-    val obj3 = OfflineEvalResult(
-      evalid = 16,
-      metricid = 2,
-      algoid = 3,
-      score = 0.123,
-      iteration = 2,
-      splitset = "validation" // only this is diff from obj2
-    )
-    val obj4 = OfflineEvalResult(
-      evalid = 2,
-      metricid = 3,
-      algoid = 4,
-      score = 0.567,
-      iteration = 3,
-      splitset = ""
-    )
-
-    val id1 = offlineEvalResults.save(obj1)
-    val id2 = offlineEvalResults.save(obj2)
-    val id3 = offlineEvalResults.save(obj3)
-    val id4 = offlineEvalResults.save(obj4)
-
-    val it = offlineEvalResults.getByEvalid(16).toSeq
-
-    /*
-    val itData1 = it.next()
-    val itData2 = it.next()
-    val itData3 = it.next()
-    */
-
-    val it2 = offlineEvalResults.getByEvalidAndMetricidAndAlgoid(2, 3, 4).toSeq
-
-    //val it2Data1 = it2.next()
-
-    /*
-    itData1 must be equalTo (obj1) and
-      (itData2 must be equalTo (obj2)) and
-      (itData3 must be equalTo (obj3)) and
-      (it.hasNext must be_==(false)) and // make sure it has 2 only
-      (it2Data1 must equalTo(obj4)) and
-      (it2.hasNext must be_==(false))
-      */
-    it must contain(obj1) and (it must contain(obj2)) and
-      (it must contain(obj3)) and (it.size must be_==(3)) and
-      (it2 must contain(obj4)) and (it2.size must be_==(1))
-  }
-
-  /**
-   * save a few and delete by evalid and get back
-   */
-  def deleteByEvalid(offlineEvalResults: OfflineEvalResults) = {
-    val obj1 = OfflineEvalResult(
-      evalid = 25,
-      metricid = 6,
-      algoid = 8,
-      score = 0.7601,
-      iteration = 1,
-      splitset = "abc"
-    )
-    val obj2 = OfflineEvalResult(
-      evalid = 7,
-      metricid = 1,
-      algoid = 9,
-      score = 0.001,
-      iteration = 2,
-      splitset = ""
-    )
-    val obj3 = OfflineEvalResult(
-      evalid = 25,
-      metricid = 33,
-      algoid = 41,
-      score = 0.999,
-      iteration = 1,
-      splitset = "efg"
-    )
-
-    val id1 = offlineEvalResults.save(obj1)
-    val id2 = offlineEvalResults.save(obj2)
-    val id3 = offlineEvalResults.save(obj3)
-
-    val it1 = offlineEvalResults.getByEvalid(25)
-
-    val it1Data1 = it1.next()
-    val it1Data2 = it1.next()
-
-    offlineEvalResults.deleteByEvalid(25)
-
-    val it2 = offlineEvalResults.getByEvalid(25)
-    val it3 = offlineEvalResults.getByEvalid(7) // others shouldn't be deleted
-    val it3Data1 = it3.next()
-
-    it1Data1 must be equalTo (obj1) and
-      (it1Data2 must be equalTo (obj3)) and
-      (it1.hasNext must be_==(false)) and //make sure it has 2 only
-      (it2.hasNext must be_==(false))
-    (it3Data1 must be equalTo (obj2)) and
-      (it3.hasNext must be_==(false))
-
-  }
-
-  def backuprestore(offlineEvalResults: OfflineEvalResults) = {
-    val obj1 = OfflineEvalResult(
-      evalid = 26,
-      metricid = 6,
-      algoid = 10,
-      score = 0.7601,
-      iteration = 1,
-      splitset = "abc"
-    )
-    val obj2 = OfflineEvalResult(
-      evalid = 8,
-      metricid = 1,
-      algoid = 11,
-      score = 0.001,
-      iteration = 2,
-      splitset = ""
-    )
-    offlineEvalResults.save(obj1)
-    offlineEvalResults.save(obj2)
-    val fn = "results.json"
-    val fos = new java.io.FileOutputStream(fn)
-    try {
-      fos.write(offlineEvalResults.backup())
-    } finally {
-      fos.close()
-    }
-    offlineEvalResults.restore(scala.io.Source.fromFile(fn)(scala.io.Codec.UTF8).mkString.getBytes("UTF-8")) map { data =>
-      (data must contain(obj1)) and (data must contain(obj2))
-    } getOrElse 1 === 2
-  }
-}
diff --git a/commons/src/test/scala/io/prediction/commons/settings/OfflineEvalSplitterInfosSpec.scala b/commons/src/test/scala/io/prediction/commons/settings/OfflineEvalSplitterInfosSpec.scala
deleted file mode 100644
index 3df48c8..0000000
--- a/commons/src/test/scala/io/prediction/commons/settings/OfflineEvalSplitterInfosSpec.scala
+++ /dev/null
@@ -1,262 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Spec
-
-import org.specs2._
-import org.specs2.specification.Step
-import com.mongodb.casbah.Imports._
-
-class OfflineEvalSplitterInfosSpec extends Specification {
-  def is = s2"""
-
-    PredictionIO OfflineEvalSplitterInfos Specification
-
-    OfflineEvalSplitterInfos can be implemented by:
-    1. MongoOfflineEvalSplitterInfos ${mongoOfflineEvalSplitterInfos}
-
-  """
-
-  def mongoOfflineEvalSplitterInfos = s2"""
-
-    MongoOfflineEvalSplitterInfos should
-    behave like any OfflineEvalSplitterInfos implementation ${offlineEvalSplitterInfos(newMongoOfflineEvalSplitterInfos)}
-    ${Step(Spec.mongoClient(mongoDbName).dropDatabase())}
-
-  """
-
-  def offlineEvalSplitterInfos(
-    offlineEvalSplitterInfos: OfflineEvalSplitterInfos) = s2"""
-
-    create and get an splitter info ${insertAndGet(offlineEvalSplitterInfos)}
-    get splitter info by engine info id ${getByEngineinfoid(offlineEvalSplitterInfos)}
-    update an splitter info ${update(offlineEvalSplitterInfos)}
-    delete an splitter info ${delete(offlineEvalSplitterInfos)}
-    backup and restore splitter info ${backuprestore(offlineEvalSplitterInfos)}
-
-  """
-
-  val mongoDbName = "predictionio_mongoofflineevalsplitterinfos_test"
-  def newMongoOfflineEvalSplitterInfos =
-    new mongodb.MongoOfflineEvalSplitterInfos(Spec.mongoClient(mongoDbName))
-
-  def insertAndGet(offlineEvalSplitterInfos: OfflineEvalSplitterInfos) = {
-    val mapk = OfflineEvalSplitterInfo(
-      id = "map-k",
-      name = "Mean Average Precision",
-      description = None,
-      engineinfoids = Seq("itemrec"),
-      commands = Some(Seq(
-        "$hadoop$ jar $pdioEvalJar$ io.prediction.metrics.scalding.itemrec.map.MAPAtKDataPreparator --hdfs --test_dbType $appdataTestDbType$ --test_dbName $appdataTestDbName$ --test_dbHost $appdataTestDbHost$ --test_dbPort $appdataTestDbPort$ --training_dbType $appdataTrainingDbType$ --training_dbName $appdataTrainingDbName$ --training_dbHost $appdataTrainingDbHost$ --training_dbPort $appdataTrainingDbPort$ --modeldata_dbType $modeldataTrainingDbType$ --modeldata_dbName $modeldataTrainingDbName$ --modeldata_dbHost $modeldataTrainingDbHost$ --modeldata_dbPort $modeldataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --kParam $kParam$ --goalParam $goalParam$",
-        "java -Dio.prediction.base=$base$ $configFile$ -Devalid=$evalid$ -Dalgoid=$algoid$ -Dk=$kParam$ -Dmetricid=$metricid$ -Dhdfsroot=$hdfsRoot$ -jar $topkJar$",
-        "$hadoop$ jar $pdioEvalJar$ io.prediction.metrics.scalding.itemrec.map.MAPAtK --hdfs --dbType $settingsDbType$ --dbName $settingsDbName$ --dbHost $settingsDbHost$ --dbPort $settingsDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --kParam $kParam$")),
-      params = Map(
-        "k" -> Param(
-          id = "k",
-          name = "k parameter",
-          description = Some("Averaging window size"),
-          defaultvalue = 20,
-          constraint = ParamIntegerConstraint(min = Some(0), max = Some(100)),
-          ui = ParamUI(
-            uitype = "text"))),
-      paramsections = Seq(
-        ParamSection(
-          name = "foo",
-          params = Some(Seq("k")))),
-      paramorder = Seq("k"))
-    offlineEvalSplitterInfos.insert(mapk)
-    offlineEvalSplitterInfos.get("map-k") must beSome(mapk)
-  }
-
-  def getByEngineinfoid(offlineEvalSplitterInfos: OfflineEvalSplitterInfos) = {
-    val mapkA = OfflineEvalSplitterInfo(
-      id = "map-k-a",
-      name = "Mean Average Precision A",
-      description = None,
-      engineinfoids = Seq("engine1"),
-      commands = Some(Seq(
-        "$hadoop$ jar $pdioEvalJar$ io.prediction.metrics.scalding.itemrec.map.MAPAtKDataPreparator --hdfs --test_dbType $appdataTestDbType$ --test_dbName $appdataTestDbName$ --test_dbHost $appdataTestDbHost$ --test_dbPort $appdataTestDbPort$ --training_dbType $appdataTrainingDbType$ --training_dbName $appdataTrainingDbName$ --training_dbHost $appdataTrainingDbHost$ --training_dbPort $appdataTrainingDbPort$ --modeldata_dbType $modeldataTrainingDbType$ --modeldata_dbName $modeldataTrainingDbName$ --modeldata_dbHost $modeldataTrainingDbHost$ --modeldata_dbPort $modeldataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --kParam $kParam$ --goalParam $goalParam$",
-        "java -Dio.prediction.base=$base$ $configFile$ -Devalid=$evalid$ -Dalgoid=$algoid$ -Dk=$kParam$ -Dmetricid=$metricid$ -Dhdfsroot=$hdfsRoot$ -jar $topkJar$",
-        "$hadoop$ jar $pdioEvalJar$ io.prediction.metrics.scalding.itemrec.map.MAPAtK --hdfs --dbType $settingsDbType$ --dbName $settingsDbName$ --dbHost $settingsDbHost$ --dbPort $settingsDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --kParam $kParam$")),
-      params = Map(
-        "k" -> Param(
-          id = "k",
-          name = "k parameter",
-          description = Some("Averaging window size"),
-          defaultvalue = 20,
-          constraint = ParamIntegerConstraint(min = Some(0), max = Some(100)),
-          ui = ParamUI(
-            uitype = "text"))),
-      paramsections = Seq(
-        ParamSection(
-          name = "foo",
-          params = Some(Seq("k")))),
-      paramorder = Seq("k"))
-
-    val mapkB = mapkA.copy(
-      id = "map-k-b",
-      name = "Mean Average Precision B",
-      engineinfoids = Seq("engine1")
-    )
-
-    val mapkC = mapkA.copy(
-      id = "map-k-c",
-      name = "Mean Average Precision C",
-      engineinfoids = Seq("engine2")
-    )
-
-    val mapkD = mapkA.copy(
-      id = "map-k-D",
-      name = "Mean Average Precision D",
-      engineinfoids = Seq("engine3", "engine1")
-    )
-
-    offlineEvalSplitterInfos.insert(mapkA)
-    offlineEvalSplitterInfos.insert(mapkB)
-    offlineEvalSplitterInfos.insert(mapkC)
-    offlineEvalSplitterInfos.insert(mapkD)
-
-    val engine1Splitters = offlineEvalSplitterInfos.getByEngineinfoid("engine1")
-
-    val engine1Splitter1 = engine1Splitters(0)
-    val engine1Splitter2 = engine1Splitters(1)
-    val engine1Splitter3 = engine1Splitters(2)
-
-    val engine2Splitters = offlineEvalSplitterInfos.getByEngineinfoid("engine2")
-
-    val engine2Splitter1 = engine2Splitters(0)
-
-    val engine3Splitters = offlineEvalSplitterInfos.getByEngineinfoid("engine3")
-
-    val engine3Splitter1 = engine3Splitters(0)
-
-    engine1Splitters.length must be equalTo (3) and
-      (engine1Splitters must containTheSameElementsAs(Seq(mapkA, mapkB,
-        mapkD))) and
-      (engine2Splitters.length must be equalTo (1)) and
-      (engine2Splitter1 must be equalTo (mapkC)) and
-      (engine3Splitters.length must be equalTo (1)) and
-      (engine3Splitter1 must be equalTo (mapkD))
-
-  }
-
-  def update(offlineEvalSplitterInfos: OfflineEvalSplitterInfos) = {
-    val mapk = OfflineEvalSplitterInfo(
-      id = "u-map-k",
-      name = "Mean Average Precision",
-      description = None,
-      engineinfoids = Seq("itemrec"),
-      commands = Some(Seq(
-        "$hadoop$ jar $pdioEvalJar$ io.prediction.metrics.scalding.itemrec.map.MAPAtKDataPreparator --hdfs --test_dbType $appdataTestDbType$ --test_dbName $appdataTestDbName$ --test_dbHost $appdataTestDbHost$ --test_dbPort $appdataTestDbPort$ --training_dbType $appdataTrainingDbType$ --training_dbName $appdataTrainingDbName$ --training_dbHost $appdataTrainingDbHost$ --training_dbPort $appdataTrainingDbPort$ --modeldata_dbType $modeldataTrainingDbType$ --modeldata_dbName $modeldataTrainingDbName$ --modeldata_dbHost $modeldataTrainingDbHost$ --modeldata_dbPort $modeldataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --kParam $kParam$ --goalParam $goalParam$",
-        "java -Dio.prediction.base=$base$ $configFile$ -Devalid=$evalid$ -Dalgoid=$algoid$ -Dk=$kParam$ -Dmetricid=$metricid$ -Dhdfsroot=$hdfsRoot$ -jar $topkJar$",
-        "$hadoop$ jar $pdioEvalJar$ io.prediction.metrics.scalding.itemrec.map.MAPAtK --hdfs --dbType $settingsDbType$ --dbName $settingsDbName$ --dbHost $settingsDbHost$ --dbPort $settingsDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --kParam $kParam$")),
-      params = Map(
-        "k" -> Param(
-          id = "k",
-          name = "k parameter",
-          description = Some("Averaging window size"),
-          defaultvalue = 20,
-          constraint = ParamIntegerConstraint(min = Some(0), max = Some(100)),
-          ui = ParamUI(
-            uitype = "text"))),
-      paramsections = Seq(
-        ParamSection(
-          name = "foo",
-          params = Some(Seq("k")))),
-      paramorder = Seq("k"))
-    offlineEvalSplitterInfos.insert(mapk)
-    val updatedMapk = mapk.copy(
-      commands = Some(Seq(
-        "cmd1",
-        "cmd2",
-        "cmd3")),
-      params = Map(
-        "k" -> Param(
-          id = "k",
-          name = "k parameter",
-          description = Some("Averaging window size"),
-          defaultvalue = 20,
-          constraint = ParamIntegerConstraint(min = Some(0), max = Some(100)),
-          ui = ParamUI(
-            uitype = "text")),
-        "f" -> Param(
-          id = "f",
-          name = "f parameter",
-          description = Some("FooBar"),
-          defaultvalue = 33,
-          constraint = ParamIntegerConstraint(min = Some(1), max = Some(2)),
-          ui = ParamUI(
-            uitype = "text"))),
-      paramsections = Seq(
-        ParamSection(
-          name = "apple section",
-          params = Some(Seq("f", "k")))),
-      paramorder = Seq("f", "k"))
-
-    offlineEvalSplitterInfos.update(updatedMapk)
-    offlineEvalSplitterInfos.get("u-map-k") must beSome(updatedMapk)
-  }
-
-  def delete(offlineEvalSplitterInfos: OfflineEvalSplitterInfos) = {
-    val mapk = OfflineEvalSplitterInfo(
-      id = "foo",
-      name = "Mean Average Precision",
-      description = None,
-      engineinfoids = Seq("itemrec"),
-      commands = Some(Seq(
-        "$hadoop$ jar $pdioEvalJar$ io.prediction.metrics.scalding.itemrec.map.MAPAtKDataPreparator --hdfs --test_dbType $appdataTestDbType$ --test_dbName $appdataTestDbName$ --test_dbHost $appdataTestDbHost$ --test_dbPort $appdataTestDbPort$ --training_dbType $appdataTrainingDbType$ --training_dbName $appdataTrainingDbName$ --training_dbHost $appdataTrainingDbHost$ --training_dbPort $appdataTrainingDbPort$ --modeldata_dbType $modeldataTrainingDbType$ --modeldata_dbName $modeldataTrainingDbName$ --modeldata_dbHost $modeldataTrainingDbHost$ --modeldata_dbPort $modeldataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --kParam $kParam$ --goalParam $goalParam$",
-        "java -Dio.prediction.base=$base$ $configFile$ -Devalid=$evalid$ -Dalgoid=$algoid$ -Dk=$kParam$ -Dmetricid=$metricid$ -Dhdfsroot=$hdfsRoot$ -jar $topkJar$",
-        "$hadoop$ jar $pdioEvalJar$ io.prediction.metrics.scalding.itemrec.map.MAPAtK --hdfs --dbType $settingsDbType$ --dbName $settingsDbName$ --dbHost $settingsDbHost$ --dbPort $settingsDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --kParam $kParam$")),
-      params = Map("k" -> Param(
-        id = "k",
-        name = "k parameter",
-        description = Some("Averaging window size"),
-        defaultvalue = 20,
-        constraint = ParamIntegerConstraint(min = Some(0), max = Some(100)),
-        ui = ParamUI(
-          uitype = "text"))),
-      paramsections = Seq(
-        ParamSection(
-          name = "foo",
-          params = Some(Seq("k")))),
-      paramorder = Seq("k"))
-    offlineEvalSplitterInfos.insert(mapk)
-    offlineEvalSplitterInfos.delete("foo")
-    offlineEvalSplitterInfos.get("foo") must beNone
-  }
-
-  def backuprestore(offlineEvalSplitterInfos: OfflineEvalSplitterInfos) = {
-    val mapkbk = OfflineEvalSplitterInfo(
-      id = "backup",
-      name = "Mean Average Precision",
-      description = None,
-      engineinfoids = Seq("itemrec"),
-      commands = Some(Seq(
-        "$hadoop$ jar $pdioEvalJar$ io.prediction.metrics.scalding.itemrec.map.MAPAtKDataPreparator --hdfs --test_dbType $appdataTestDbType$ --test_dbName $appdataTestDbName$ --test_dbHost $appdataTestDbHost$ --test_dbPort $appdataTestDbPort$ --training_dbType $appdataTrainingDbType$ --training_dbName $appdataTrainingDbName$ --training_dbHost $appdataTrainingDbHost$ --training_dbPort $appdataTrainingDbPort$ --modeldata_dbType $modeldataTrainingDbType$ --modeldata_dbName $modeldataTrainingDbName$ --modeldata_dbHost $modeldataTrainingDbHost$ --modeldata_dbPort $modeldataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --kParam $kParam$ --goalParam $goalParam$",
-        "java -Dio.prediction.base=$base$ $configFile$ -Devalid=$evalid$ -Dalgoid=$algoid$ -Dk=$kParam$ -Dmetricid=$metricid$ -Dhdfsroot=$hdfsRoot$ -jar $topkJar$",
-        "$hadoop$ jar $pdioEvalJar$ io.prediction.metrics.scalding.itemrec.map.MAPAtK --hdfs --dbType $settingsDbType$ --dbName $settingsDbName$ --dbHost $settingsDbHost$ --dbPort $settingsDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --kParam $kParam$")),
-      params = Map("k" -> Param(
-        id = "k",
-        name = "k parameter",
-        description = Some("Averaging window size"),
-        defaultvalue = 20,
-        constraint = ParamIntegerConstraint(min = Some(0), max = Some(100)),
-        ui = ParamUI(
-          uitype = "text"))),
-      paramsections = Seq(
-        ParamSection(
-          name = "foo",
-          params = Some(Seq("k")))),
-      paramorder = Seq("k"))
-    offlineEvalSplitterInfos.insert(mapkbk)
-    val fn = "splitterinfos.json"
-    val fos = new java.io.FileOutputStream(fn)
-    try {
-      fos.write(offlineEvalSplitterInfos.backup())
-    } finally {
-      fos.close()
-    }
-    offlineEvalSplitterInfos.restore(scala.io.Source.fromFile(fn)(scala.io.Codec.UTF8).mkString.getBytes("UTF-8")) map { data =>
-      data must contain(mapkbk)
-    } getOrElse 1 === 2
-  }
-}
diff --git a/commons/src/test/scala/io/prediction/commons/settings/OfflineEvalSplittersSpec.scala b/commons/src/test/scala/io/prediction/commons/settings/OfflineEvalSplittersSpec.scala
deleted file mode 100644
index 5ff37b0..0000000
--- a/commons/src/test/scala/io/prediction/commons/settings/OfflineEvalSplittersSpec.scala
+++ /dev/null
@@ -1,135 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Spec
-
-import org.specs2._
-import org.specs2.specification.Step
-import com.mongodb.casbah.Imports._
-
-class OfflineEvalSplittersSpec extends Specification {
-  def is = s2"""
-
-  PredictionIO OfflineEvalSplitters Specification
-
-    OfflineEvalSplitters can be implemented by:
-    - MongoOfflineEvalSplitters ${mongoOfflineEvalSplitters}
-
-  """
-
-  def mongoOfflineEvalSplitters = s2"""
-
-    MongoOfflineEvalSplitters should" ^
-    - behave like any OfflineEvalSplitters implementation ${offlineEvalSplitters(newMongoOfflineEvalSplitters)}
-    - (database cleanup) ${Step(Spec.mongoClient(mongoDbName).dropDatabase())}
-
-  """
-
-  def offlineEvalSplitters(splitters: OfflineEvalSplitters) = s2"""
-
-    create an OfflineEvalSplitter ${insert(splitters)}
-    get two OfflineEvalSplitters ${getByEvalid(splitters)}
-    update an OfflineEvalSplitter ${update(splitters)}
-    delete an OfflineEvalSplitter ${delete(splitters)}
-    backup and restore OfflineEvalSplitters ${backuprestore(splitters)}
-
-  """
-
-  val mongoDbName = "predictionio_mongoofflineevalsplitters_test"
-  def newMongoOfflineEvalSplitters = new mongodb.MongoOfflineEvalSplitters(Spec.mongoClient(mongoDbName))
-
-  def insert(splitters: OfflineEvalSplitters) = {
-    val splitter = OfflineEvalSplitter(
-      id = 0,
-      evalid = 123,
-      name = "insert",
-      infoid = "insert",
-      settings = Map())
-    val i = splitters.insert(splitter)
-    splitters.get(i) must beSome(splitter.copy(id = i))
-  }
-
-  /**
-   * insert a few and get by evalid
-   */
-  def getByEvalid(splitters: OfflineEvalSplitters) = {
-    val obj1 = OfflineEvalSplitter(
-      id = -1,
-      evalid = 15,
-      name = "abc",
-      infoid = "splitter-getByEvalid1",
-      settings = Map(("abc1" -> 6), ("bar1" -> "foo1 foo2"), ("bar1b" -> "foo1b"))
-    )
-    val obj2 = OfflineEvalSplitter(
-      id = -1,
-      evalid = 15,
-      name = "def",
-      infoid = "splitter-getByEvalid2",
-      settings = Map(("abc2" -> 0), ("bar2" -> "foox"))
-    )
-
-    val id1 = splitters.insert(obj1)
-    val id2 = splitters.insert(obj2)
-
-    val it = splitters.getByEvalid(15)
-
-    val it1 = it.next()
-    val it2 = it.next()
-    val left = it.hasNext // make sure it has 2 only
-
-    it1 must be equalTo (obj1.copy(id = id1)) and
-      (it2 must be equalTo (obj2.copy(id = id2))) and
-      (left must be_==(false))
-
-  }
-
-  def update(splitters: OfflineEvalSplitters) = {
-    val id = splitters.insert(OfflineEvalSplitter(
-      id = 0,
-      evalid = 345,
-      name = "update",
-      infoid = "update",
-      settings = Map()
-    ))
-    val updatedSplitter = OfflineEvalSplitter(
-      id = id,
-      evalid = 345,
-      name = "updated",
-      infoid = "updated",
-      settings = Map("set1" -> "dat1", "set2" -> "dat2")
-    )
-    splitters.update(updatedSplitter)
-    splitters.get(id) must beSome(updatedSplitter)
-  }
-
-  def delete(splitters: OfflineEvalSplitters) = {
-    val id = splitters.insert(OfflineEvalSplitter(
-      id = 0,
-      evalid = 456,
-      name = "deleteByIdAndAppid",
-      infoid = "deleteByIdAndAppid",
-      settings = Map("x" -> "y")
-    ))
-    splitters.delete(id)
-    splitters.get(id) must beNone
-  }
-
-  def backuprestore(splitters: OfflineEvalSplitters) = {
-    val obj = OfflineEvalSplitter(
-      id = 0,
-      evalid = 567,
-      name = "backuprestore",
-      infoid = "backuprestore",
-      settings = Map("x" -> "y"))
-    val sid = splitters.insert(obj)
-    val fn = "splitters.json"
-    val fos = new java.io.FileOutputStream(fn)
-    try {
-      fos.write(splitters.backup())
-    } finally {
-      fos.close()
-    }
-    splitters.restore(scala.io.Source.fromFile(fn)(scala.io.Codec.UTF8).mkString.getBytes("UTF-8")) map { data =>
-      data must contain(obj.copy(id = sid))
-    } getOrElse 1 === 2
-  }
-}
diff --git a/commons/src/test/scala/io/prediction/commons/settings/OfflineEvalsSpec.scala b/commons/src/test/scala/io/prediction/commons/settings/OfflineEvalsSpec.scala
deleted file mode 100644
index 190b4ce..0000000
--- a/commons/src/test/scala/io/prediction/commons/settings/OfflineEvalsSpec.scala
+++ /dev/null
@@ -1,262 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Spec
-
-import org.specs2._
-import org.specs2.specification.Step
-
-import com.mongodb.casbah.Imports._
-import com.github.nscala_time.time.Imports._
-
-class OfflineEvalsSpec extends Specification {
-  def is = s2"""
-
-  PredictionIO OfflineEvals Specification
-
-    OfflineEvals can be implemented by:
-    - MongoOfflineEvals ${mongoOfflineEvals}
-
-  """
-
-  def mongoOfflineEvals = s2"""
-
-    MongoOfflineEvals should
-    - behave like any OfflineEvals implementation ${offlineEvalsTest(newMongoOfflineEvals)}
-    - (database cleanup) ${Step(Spec.mongoClient(mongoDbName).dropDatabase())}
-
-  """
-
-  def offlineEvalsTest(offlineEvals: OfflineEvals) = s2"""
-
-    create an OfflineEval ${insert(offlineEvals)}
-    get two OfflineEvals by Engineid ${getByEngineid(offlineEvals)}
-    get two OfflineEvals by Tuneid ${getByTuneid(offlineEvals)}
-    get by id and engineid ${getByIdAndEngineid(offlineEvals)}
-    update an OfflineEval ${update(offlineEvals)}
-    delete an OfflineEval ${delete(offlineEvals)}
-    backup and restore OfflineEvals ${backuprestore(offlineEvals)}
-
-  """
-
-  val mongoDbName = "predictionio_mongoofflineevals_test"
-  def newMongoOfflineEvals = new mongodb.MongoOfflineEvals(Spec.mongoClient(mongoDbName))
-
-  /**
-   * insert and get by id
-   */
-  def insert(offlineEvals: OfflineEvals) = {
-    val eval1 = OfflineEval(
-      id = -1,
-      engineid = 4,
-      name = "offline-eval-insert1",
-      tuneid = None,
-      createtime = Some(DateTime.now),
-      starttime = Some(DateTime.now),
-      endtime = None
-    )
-
-    val insertid = offlineEvals.insert(eval1)
-    offlineEvals.get(insertid) must beSome(eval1.copy(id = insertid))
-  }
-
-  /**
-   * insert a few and get by engineid
-   */
-  def getByEngineid(offlineEvals: OfflineEvals) = {
-    val eval1 = OfflineEval(
-      id = -1,
-      engineid = 11,
-      name = "offline-eval-getByEngineid1",
-      tuneid = Some(3),
-      createtime = None,
-      starttime = None,
-      endtime = None
-    )
-    val eval2 = OfflineEval(
-      id = -1,
-      engineid = 11,
-      name = "offline-eval-getByEngineid2",
-      tuneid = None,
-      createtime = Some(DateTime.now.hour(1).minute(12).second(34)),
-      starttime = Some(DateTime.now.hour(2).minute(45).second(10)),
-      endtime = Some(DateTime.now.hour(4).minute(56).second(35))
-    )
-
-    val id1 = offlineEvals.insert(eval1)
-    val id2 = offlineEvals.insert(eval2)
-
-    val it = offlineEvals.getByEngineid(11)
-
-    val it1 = it.next()
-    val it2 = it.next()
-    val left = it.hasNext // make sure it has 2 only
-
-    it1 must be equalTo (eval1.copy(id = id1)) and
-      (it2 must be equalTo (eval2.copy(id = id2))) and
-      (left must be_==(false))
-
-  }
-
-  /**
-   * insert a few and get by offline tune id
-   */
-  def getByTuneid(offlineEvals: OfflineEvals) = {
-    val eval1 = OfflineEval(
-      id = -1,
-      engineid = 12,
-      name = "offline-eval-getByEngineid1",
-      tuneid = Some(31),
-      createtime = None,
-      starttime = None,
-      endtime = None
-    )
-    val eval2 = OfflineEval(
-      id = -1,
-      engineid = 12,
-      name = "offline-eval-getByEngineid2",
-      tuneid = Some(31),
-      createtime = Some(DateTime.now.hour(1).minute(12).second(34)),
-      starttime = Some(DateTime.now.hour(2).minute(45).second(10)),
-      endtime = Some(DateTime.now.hour(4).minute(56).second(35))
-    )
-    val eval3 = OfflineEval(
-      id = -1,
-      engineid = 12,
-      name = "offline-eval-getByEngineid2",
-      tuneid = Some(32), // note: this one has different tuneid
-      createtime = Some(DateTime.now.hour(1).minute(12).second(34)),
-      starttime = Some(DateTime.now.hour(2).minute(45).second(10)),
-      endtime = Some(DateTime.now.hour(4).minute(56).second(35))
-    )
-
-    val id1 = offlineEvals.insert(eval1)
-    val id2 = offlineEvals.insert(eval2)
-    val id3 = offlineEvals.insert(eval3)
-
-    val it = offlineEvals.getByTuneid(31)
-
-    val it1 = it.next()
-    val it2 = it.next()
-    val left = it.hasNext // make sure it has 2 only
-
-    it1 must be equalTo (eval1.copy(id = id1)) and
-      (it2 must be equalTo (eval2.copy(id = id2))) and
-      (left must be_==(false))
-
-  }
-
-  def getByIdAndEngineid(offlineEvals: OfflineEvals) = {
-    val obj1 = OfflineEval(
-      id = -1,
-      engineid = 2345,
-      name = "getByIdAndEngineid",
-      tuneid = Some(3),
-      createtime = None,
-      starttime = None,
-      endtime = None
-    )
-    val obj2 = obj1.copy()
-    val obj3 = obj1.copy(engineid = 2346, name = "getByIdAndEngineid3")
-
-    val id1 = offlineEvals.insert(obj1)
-    val id2 = offlineEvals.insert(obj2)
-    val id3 = offlineEvals.insert(obj3)
-    val eval1 = offlineEvals.getByIdAndEngineid(id1, 2345)
-    val eval1b = offlineEvals.getByIdAndEngineid(id1, 2346)
-    val eval2 = offlineEvals.getByIdAndEngineid(id2, 2345)
-    val eval2b = offlineEvals.getByIdAndEngineid(id2, 2346)
-    val eval3b = offlineEvals.getByIdAndEngineid(id3, 2345)
-    val eval3 = offlineEvals.getByIdAndEngineid(id3, 2346)
-
-    eval1 must beSome(obj1.copy(id = id1)) and
-      (eval1b must beNone) and
-      (eval2 must beSome(obj2.copy(id = id2))) and
-      (eval2b must beNone) and
-      (eval3 must beSome(obj3.copy(id = id3))) and
-      (eval3b must beNone)
-  }
-
-  /**
-   * insert one and then update with new data and get back
-   */
-  def update(offlineEvals: OfflineEvals) = {
-    val eval1 = OfflineEval(
-      id = -1,
-      engineid = 9,
-      name = "offline-eval-update1",
-      tuneid = None,
-      createtime = None,
-      starttime = Some(DateTime.now.hour(3).minute(15).second(8)),
-      endtime = None
-    )
-
-    val updateid = offlineEvals.insert(eval1)
-    val data1 = offlineEvals.get(updateid)
-
-    val eval2 = eval1.copy(
-      id = updateid,
-      engineid = 10,
-      name = "new-offline-eval-update1",
-      tuneid = Some(44),
-      createtime = Some(DateTime.now.hour(1).minute(2).second(3)),
-      starttime = None,
-      endtime = Some(DateTime.now)
-    )
-    offlineEvals.update(eval2)
-
-    val data2 = offlineEvals.get(updateid)
-
-    data1 must beSome(eval1.copy(id = updateid)) and
-      (data2 must beSome(eval2))
-  }
-
-  /**
-   * insert one and delete and get back
-   */
-  def delete(offlineEvals: OfflineEvals) = {
-    val eval1 = OfflineEval(
-      id = -1,
-      engineid = 18,
-      name = "offline-eval-delete",
-      tuneid = None,
-      createtime = Some(DateTime.now),
-      starttime = Some(DateTime.now),
-      endtime = None
-    )
-
-    val id1 = offlineEvals.insert(eval1)
-    val data1 = offlineEvals.get(id1)
-
-    offlineEvals.delete(id1)
-    val data2 = offlineEvals.get(id1)
-
-    data1 must beSome(eval1.copy(id = id1)) and
-      (data2 must beNone)
-  }
-
-  def backuprestore(offlineEvals: OfflineEvals) = {
-    val eval1 = OfflineEval(
-      id = -1,
-      engineid = 20,
-      name = "backuprestore",
-      tuneid = None,
-      createtime = Some(DateTime.now),
-      starttime = Some(DateTime.now),
-      endtime = None
-    )
-    val id1 = offlineEvals.insert(eval1)
-    val fn = "evals.json"
-    val fos = new java.io.FileOutputStream(fn)
-    try {
-      fos.write(offlineEvals.backup())
-    } finally {
-      fos.close()
-    }
-    offlineEvals.restore(scala.io.Source.fromFile(fn)(scala.io.Codec.UTF8).mkString.getBytes("UTF-8")) map { data =>
-      // For some reason inserting Joda DateTime to DB and getting them back will make test pass
-      val feval1 = data.find(_.id == id1).get
-      offlineEvals.update(feval1)
-      offlineEvals.get(id1) must beSome(eval1.copy(id = id1))
-    } getOrElse 1 === 2
-  }
-}
diff --git a/commons/src/test/scala/io/prediction/commons/settings/OfflineTunesSpec.scala b/commons/src/test/scala/io/prediction/commons/settings/OfflineTunesSpec.scala
deleted file mode 100644
index f5bce27..0000000
--- a/commons/src/test/scala/io/prediction/commons/settings/OfflineTunesSpec.scala
+++ /dev/null
@@ -1,137 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Spec
-
-import org.specs2._
-import org.specs2.specification.Step
-
-import com.mongodb.casbah.Imports._
-import com.github.nscala_time.time.Imports._
-
-class OfflineTunesSpec extends Specification {
-  def is = s2"""
-
-  PredictionIO OfflineTunes Specification
-
-    OfflineTunes can be implemented by:
-    - MongoOfflineTunes ${mongoOfflineTunes}
-
-  """
-
-  def mongoOfflineTunes = s2"""
-
-    MongoOfflineTunes should
-    - behave like any OfflinTunes implementation ${offlineTunesTest(newMongoOfflineTunes)}
-    - (database cleanup) ${Step(Spec.mongoClient(mongoDbName).dropDatabase())}
-
-  """
-
-  def offlineTunesTest(offlineTunes: OfflineTunes) = s2"""
-
-    create an OfflineTune ${insert(offlineTunes)}
-    update an OfflineTune ${update(offlineTunes)}
-    delete an OfflineTune ${delete(offlineTunes)}
-    backup and restore OfflineTunes ${backuprestore(offlineTunes)}
-
-  """
-
-  val mongoDbName = "predictionio_mongoofflinetunes_test"
-  def newMongoOfflineTunes = new mongodb.MongoOfflineTunes(Spec.mongoClient(mongoDbName))
-
-  /**
-   * insert and get by id
-   */
-  def insert(offlineTunes: OfflineTunes) = {
-    val tune1 = OfflineTune(
-      id = -1,
-      engineid = 4,
-      loops = 1,
-      createtime = Some(DateTime.now),
-      starttime = Some(DateTime.now),
-      endtime = None
-    )
-
-    val insertid = offlineTunes.insert(tune1)
-    offlineTunes.get(insertid) must beSome(tune1.copy(id = insertid))
-  }
-
-  /**
-   * insert one and then update with new data and get back
-   */
-  def update(offlineTunes: OfflineTunes) = {
-    val tune1 = OfflineTune(
-      id = -1,
-      engineid = 9,
-      loops = 2,
-      createtime = None,
-      starttime = Some(DateTime.now.hour(3).minute(15).second(8)),
-      endtime = None
-    )
-
-    val updateid = offlineTunes.insert(tune1)
-    val data1 = offlineTunes.get(updateid)
-
-    val tune2 = tune1.copy(
-      id = updateid,
-      engineid = 10,
-      loops = 10,
-      createtime = Some(DateTime.now.hour(1).minute(2).second(3)),
-      starttime = None,
-      endtime = Some(DateTime.now)
-    )
-    offlineTunes.update(tune2)
-
-    val data2 = offlineTunes.get(updateid)
-
-    data1 must beSome(tune1.copy(id = updateid)) and
-      (data2 must beSome(tune2))
-  }
-
-  /**
-   * insert one and delete and get back
-   */
-  def delete(offlineTunes: OfflineTunes) = {
-    val tune1 = OfflineTune(
-      id = -1,
-      engineid = 18,
-      loops = 11,
-      createtime = Some(DateTime.now),
-      starttime = Some(DateTime.now),
-      endtime = None
-    )
-
-    val id1 = offlineTunes.insert(tune1)
-    val data1 = offlineTunes.get(id1)
-
-    offlineTunes.delete(id1)
-    val data2 = offlineTunes.get(id1)
-
-    data1 must beSome(tune1.copy(id = id1)) and
-      (data2 must beNone)
-  }
-
-  def backuprestore(offlineTunes: OfflineTunes) = {
-    val tune1 = OfflineTune(
-      id = -1,
-      engineid = 18,
-      loops = 11,
-      createtime = Some(DateTime.now),
-      starttime = Some(DateTime.now),
-      endtime = None
-    )
-    val id1 = offlineTunes.insert(tune1)
-    val fn = "tunes.json"
-    val fos = new java.io.FileOutputStream(fn)
-    try {
-      fos.write(offlineTunes.backup())
-    } finally {
-      fos.close()
-    }
-    offlineTunes.restore(scala.io.Source.fromFile(fn)(scala.io.Codec.UTF8).mkString.getBytes("UTF-8")) map { data =>
-      // For some reason inserting Joda DateTime to DB and getting them back will make test pass
-      val ftune1 = data.find(_.id == id1).get
-      offlineTunes.update(ftune1)
-      offlineTunes.get(id1) must beSome(tune1.copy(id = id1))
-    } getOrElse 1 === 2
-  }
-}
diff --git a/commons/src/test/scala/io/prediction/commons/settings/ParamGenInfosSpec.scala b/commons/src/test/scala/io/prediction/commons/settings/ParamGenInfosSpec.scala
deleted file mode 100644
index ce4202a..0000000
--- a/commons/src/test/scala/io/prediction/commons/settings/ParamGenInfosSpec.scala
+++ /dev/null
@@ -1,122 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Spec
-
-import org.specs2._
-import org.specs2.specification.Step
-import com.mongodb.casbah.Imports._
-
-class ParamGenInfosSpec extends Specification {
-  def is = s2"""
-
-  PredictionIO ParamGenInfos Specification
-
-    ParamGenInfos can be implemented by:
-    - MongoParamGenInfos ${mongoParamGenInfos}
-
-  """
-
-  def mongoParamGenInfos = s2"""
-
-    MongoParamGenInfos should
-    - behave like any ParamGenInfos implementation ${paramGenInfos(newMongoParamGenInfos)}
-    - (database cleanup) ${Step(Spec.mongoClient(mongoDbName).dropDatabase())}
-
-  """
-
-  def paramGenInfos(paramGenInfos: ParamGenInfos) = s2"""
-
-    create and get a parameter generator info ${insertAndGet(paramGenInfos)}
-    update a parameter generator info ${update(paramGenInfos)}
-    delete a parameter generator info ${delete(paramGenInfos)}
-    backup and restore parameter generator info ${backuprestore(paramGenInfos)}
-
-  """
-
-  val mongoDbName = "predictionio_mongoparamgeninfos_test"
-  def newMongoParamGenInfos = new mongodb.MongoParamGenInfos(Spec.mongoClient(mongoDbName))
-
-  def insertAndGet(paramGenInfos: ParamGenInfos) = {
-    val mapk = ParamGenInfo(
-      id = "map-k",
-      name = "Mean Average Precision",
-      description = None,
-      commands = Some(Seq(
-        "$hadoop$ jar $pdioEvalJar$ io.prediction.metrics.scalding.itemrec.map.MAPAtKDataPreparator --hdfs --test_dbType $appdataTestDbType$ --test_dbName $appdataTestDbName$ --test_dbHost $appdataTestDbHost$ --test_dbPort $appdataTestDbPort$ --training_dbType $appdataTrainingDbType$ --training_dbName $appdataTrainingDbName$ --training_dbHost $appdataTrainingDbHost$ --training_dbPort $appdataTrainingDbPort$ --modeldata_dbType $modeldataTrainingDbType$ --modeldata_dbName $modeldataTrainingDbName$ --modeldata_dbHost $modeldataTrainingDbHost$ --modeldata_dbPort $modeldataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --kParam $kParam$ --goalParam $goalParam$",
-        "java -Dio.prediction.base=$base$ $configFile$ -Devalid=$evalid$ -Dalgoid=$algoid$ -Dk=$kParam$ -Dmetricid=$metricid$ -Dhdfsroot=$hdfsRoot$ -jar $topkJar$",
-        "$hadoop$ jar $pdioEvalJar$ io.prediction.metrics.scalding.itemrec.map.MAPAtK --hdfs --dbType $settingsDbType$ --dbName $settingsDbName$ --dbHost $settingsDbHost$ --dbPort $settingsDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --kParam $kParam$")),
-      paramdefaults = Map("k" -> 20),
-      paramnames = Map("k" -> "k"),
-      paramdescription = Map("k" -> "Averaging window size"),
-      paramorder = Seq("k"))
-    paramGenInfos.insert(mapk)
-    paramGenInfos.get("map-k") must beSome(mapk)
-  }
-
-  def update(paramGenInfos: ParamGenInfos) = {
-    val mapk = ParamGenInfo(
-      id = "u-map-k",
-      name = "Mean Average Precision",
-      description = None,
-      commands = Some(Seq(
-        "$hadoop$ jar $pdioEvalJar$ io.prediction.metrics.scalding.itemrec.map.MAPAtKDataPreparator --hdfs --test_dbType $appdataTestDbType$ --test_dbName $appdataTestDbName$ --test_dbHost $appdataTestDbHost$ --test_dbPort $appdataTestDbPort$ --training_dbType $appdataTrainingDbType$ --training_dbName $appdataTrainingDbName$ --training_dbHost $appdataTrainingDbHost$ --training_dbPort $appdataTrainingDbPort$ --modeldata_dbType $modeldataTrainingDbType$ --modeldata_dbName $modeldataTrainingDbName$ --modeldata_dbHost $modeldataTrainingDbHost$ --modeldata_dbPort $modeldataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --kParam $kParam$ --goalParam $goalParam$",
-        "java -Dio.prediction.base=$base$ $configFile$ -Devalid=$evalid$ -Dalgoid=$algoid$ -Dk=$kParam$ -Dmetricid=$metricid$ -Dhdfsroot=$hdfsRoot$ -jar $topkJar$",
-        "$hadoop$ jar $pdioEvalJar$ io.prediction.metrics.scalding.itemrec.map.MAPAtK --hdfs --dbType $settingsDbType$ --dbName $settingsDbName$ --dbHost $settingsDbHost$ --dbPort $settingsDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --kParam $kParam$")),
-      paramdefaults = Map("k" -> 20),
-      paramnames = Map("k" -> "k"),
-      paramdescription = Map("k" -> "Averaging window size"),
-      paramorder = Seq("k"))
-    paramGenInfos.insert(mapk)
-    val updatedMapk = mapk.copy(
-      paramdefaults = mapk.paramdefaults ++ Map("f" -> 20),
-      paramnames = mapk.paramnames ++ Map("f" -> "Foo"),
-      paramdescription = mapk.paramdescription ++ Map("f" -> "FooBar"),
-      paramorder = Seq("f", "k"))
-    paramGenInfos.update(updatedMapk)
-    paramGenInfos.get("u-map-k") must beSome(updatedMapk)
-  }
-
-  def delete(paramGenInfos: ParamGenInfos) = {
-    val mapk = ParamGenInfo(
-      id = "foo",
-      name = "Mean Average Precision",
-      description = None,
-      commands = Some(Seq(
-        "$hadoop$ jar $pdioEvalJar$ io.prediction.metrics.scalding.itemrec.map.MAPAtKDataPreparator --hdfs --test_dbType $appdataTestDbType$ --test_dbName $appdataTestDbName$ --test_dbHost $appdataTestDbHost$ --test_dbPort $appdataTestDbPort$ --training_dbType $appdataTrainingDbType$ --training_dbName $appdataTrainingDbName$ --training_dbHost $appdataTrainingDbHost$ --training_dbPort $appdataTrainingDbPort$ --modeldata_dbType $modeldataTrainingDbType$ --modeldata_dbName $modeldataTrainingDbName$ --modeldata_dbHost $modeldataTrainingDbHost$ --modeldata_dbPort $modeldataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --kParam $kParam$ --goalParam $goalParam$",
-        "java -Dio.prediction.base=$base$ $configFile$ -Devalid=$evalid$ -Dalgoid=$algoid$ -Dk=$kParam$ -Dmetricid=$metricid$ -Dhdfsroot=$hdfsRoot$ -jar $topkJar$",
-        "$hadoop$ jar $pdioEvalJar$ io.prediction.metrics.scalding.itemrec.map.MAPAtK --hdfs --dbType $settingsDbType$ --dbName $settingsDbName$ --dbHost $settingsDbHost$ --dbPort $settingsDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --kParam $kParam$")),
-      paramdefaults = Map("k" -> 20),
-      paramnames = Map("k" -> "k"),
-      paramdescription = Map("k" -> "Averaging window size"),
-      paramorder = Seq("k"))
-    paramGenInfos.insert(mapk)
-    paramGenInfos.delete("foo")
-    paramGenInfos.get("foo") must beNone
-  }
-
-  def backuprestore(paramGenInfos: ParamGenInfos) = {
-    val mapkbk = ParamGenInfo(
-      id = "backup",
-      name = "Mean Average Precision",
-      description = None,
-      commands = Some(Seq(
-        "$hadoop$ jar $pdioEvalJar$ io.prediction.metrics.scalding.itemrec.map.MAPAtKDataPreparator --hdfs --test_dbType $appdataTestDbType$ --test_dbName $appdataTestDbName$ --test_dbHost $appdataTestDbHost$ --test_dbPort $appdataTestDbPort$ --training_dbType $appdataTrainingDbType$ --training_dbName $appdataTrainingDbName$ --training_dbHost $appdataTrainingDbHost$ --training_dbPort $appdataTrainingDbPort$ --modeldata_dbType $modeldataTrainingDbType$ --modeldata_dbName $modeldataTrainingDbName$ --modeldata_dbHost $modeldataTrainingDbHost$ --modeldata_dbPort $modeldataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --kParam $kParam$ --goalParam $goalParam$",
-        "java -Dio.prediction.base=$base$ $configFile$ -Devalid=$evalid$ -Dalgoid=$algoid$ -Dk=$kParam$ -Dmetricid=$metricid$ -Dhdfsroot=$hdfsRoot$ -jar $topkJar$",
-        "$hadoop$ jar $pdioEvalJar$ io.prediction.metrics.scalding.itemrec.map.MAPAtK --hdfs --dbType $settingsDbType$ --dbName $settingsDbName$ --dbHost $settingsDbHost$ --dbPort $settingsDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --kParam $kParam$")),
-      paramdefaults = Map("k" -> 20),
-      paramnames = Map("k" -> "k"),
-      paramdescription = Map("k" -> "Averaging window size"),
-      paramorder = Seq("k"))
-    paramGenInfos.insert(mapkbk)
-    val fn = "paramgeninfos.json"
-    val fos = new java.io.FileOutputStream(fn)
-    try {
-      fos.write(paramGenInfos.backup())
-    } finally {
-      fos.close()
-    }
-    paramGenInfos.restore(scala.io.Source.fromFile(fn)(scala.io.Codec.UTF8).mkString.getBytes("UTF-8")) map { data =>
-      data must contain(mapkbk)
-    } getOrElse 1 === 2
-  }
-}
diff --git a/commons/src/test/scala/io/prediction/commons/settings/ParamGensSpec.scala b/commons/src/test/scala/io/prediction/commons/settings/ParamGensSpec.scala
deleted file mode 100644
index a92a0ea..0000000
--- a/commons/src/test/scala/io/prediction/commons/settings/ParamGensSpec.scala
+++ /dev/null
@@ -1,166 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Spec
-
-import org.specs2._
-import org.specs2.specification.Step
-import com.mongodb.casbah.Imports._
-
-class ParamGensSpec extends Specification {
-  def is = s2"""
-
-  PredictionIO ParamGens Specification
-
-    ParamGens can be implemented by:
-    - MongoParamGens ${mongoParamGens}
-
-  """
-
-  def mongoParamGens = s2"""
-
-    MongoParamGens should
-    - behave like any ParamGens implementation ${paramGensTest(newMongoParamGens)}
-    - (database cleanup) ${Step(Spec.mongoClient(mongoDbName).dropDatabase())}
-
-  """
-
-  def paramGensTest(paramGens: ParamGens) = s2"""
-
-    create an ParamGen ${insert(paramGens)}
-    update an ParamGen ${update(paramGens)}
-    get two ParamGens by Tuneid ${getByTuneid(paramGens)}
-    delete an ParamGen ${delete(paramGens)}
-    backup and restore ParamGens ${backuprestore(paramGens)}
-
-  """
-
-  val mongoDbName = "predictionio_mongoparamgens_test"
-  def newMongoParamGens = new mongodb.MongoParamGens(Spec.mongoClient(mongoDbName))
-
-  /**
-   * insert and get by id
-   */
-  def insert(paramGens: ParamGens) = {
-    val obj = ParamGen(
-      id = -1,
-      infoid = "paramGen-insert1",
-      tuneid = 42,
-      params = Map(("abc" -> 3), ("bar" -> "foo1 foo2"))
-    )
-
-    val insertid = paramGens.insert(obj)
-    paramGens.get(insertid) must beSome(obj.copy(id = insertid))
-  }
-
-  /**
-   * insert one and then update with new data and get back
-   */
-  def update(paramGens: ParamGens) = {
-    val obj1 = ParamGen(
-      id = -1,
-      infoid = "paramGen-update1",
-      tuneid = 16,
-      params = Map(("def" -> "a1 a2 a3"), ("def2" -> 1), ("def3" -> "food"))
-    )
-
-    val updateid = paramGens.insert(obj1)
-    val data1 = paramGens.get(updateid)
-
-    val obj2 = obj1.copy(
-      id = updateid,
-      infoid = "paramGen-update2",
-      tuneid = 99,
-      params = Map()
-    )
-
-    paramGens.update(obj2)
-
-    val data2 = paramGens.get(updateid)
-
-    data1 must beSome(obj1.copy(id = updateid)) and
-      (data2 must beSome(obj2))
-
-  }
-
-  /**
-   * insert a few and get by offline tune id
-   */
-  def getByTuneid(paramGens: ParamGens) = {
-    val obj1 = ParamGen(
-      id = -1,
-      infoid = "paramGen-update1",
-      tuneid = 121,
-      params = Map(("def" -> "a1 a2 a3"), ("def2" -> 1), ("def3" -> "food"))
-    )
-    val obj2 = ParamGen(
-      id = -1,
-      infoid = "paramGen-update1",
-      tuneid = 121,
-      params = Map(("def" -> "a1 a3 a4"), ("def2" -> 1), ("def3" -> "food"))
-    )
-    val obj3 = ParamGen(
-      id = -1,
-      infoid = "paramGen-update1",
-      tuneid = 122, // diff tuneid
-      params = Map(("def" -> "a1 a2 a3"), ("def2" -> 1), ("def3" -> "food"))
-    )
-
-    val id1 = paramGens.insert(obj1)
-    val id2 = paramGens.insert(obj2)
-    val id3 = paramGens.insert(obj3)
-
-    val it = paramGens.getByTuneid(121)
-
-    val it1 = it.next()
-    val it2 = it.next()
-    val left = it.hasNext // make sure it has 2 only
-
-    it1 must be equalTo (obj1.copy(id = id1)) and
-      (it2 must be equalTo (obj2.copy(id = id2))) and
-      (left must be_==(false))
-
-  }
-
-  /**
-   * insert one and delete and get back
-   */
-  def delete(paramGens: ParamGens) = {
-    val obj1 = ParamGen(
-      id = -1,
-      infoid = "paramGen-delete1",
-      tuneid = 3,
-      params = Map(("x" -> 1))
-    )
-
-    val id1 = paramGens.insert(obj1)
-    val data1 = paramGens.get(id1)
-
-    paramGens.delete(id1)
-    val data2 = paramGens.get(id1)
-
-    data1 must beSome(obj1.copy(id = id1)) and
-      (data2 must beNone)
-
-  }
-
-  def backuprestore(paramGens: ParamGens) = {
-    val obj1 = ParamGen(
-      id = -1,
-      infoid = "paramGen-backuprestore",
-      tuneid = 345,
-      params = Map("dead" -> "beef")
-    )
-
-    val id1 = paramGens.insert(obj1)
-    val fn = "paramgens.json"
-    val fos = new java.io.FileOutputStream(fn)
-    try {
-      fos.write(paramGens.backup())
-    } finally {
-      fos.close()
-    }
-    paramGens.restore(scala.io.Source.fromFile(fn)(scala.io.Codec.UTF8).mkString.getBytes("UTF-8")) map { data =>
-      data must contain(obj1.copy(id = id1))
-    } getOrElse 1 === 2
-  }
-}
diff --git a/commons/src/test/scala/io/prediction/commons/settings/SystemInfosSpec.scala b/commons/src/test/scala/io/prediction/commons/settings/SystemInfosSpec.scala
deleted file mode 100644
index 4fc3355..0000000
--- a/commons/src/test/scala/io/prediction/commons/settings/SystemInfosSpec.scala
+++ /dev/null
@@ -1,86 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Spec
-
-import org.specs2._
-import org.specs2.specification.Step
-import com.mongodb.casbah.Imports._
-
-class SystemInfosSpec extends Specification {
-  def is = s2"""
-
-  PredictionIO SystemInfos Specification
-
-    SystemInfos can be implemented by:
-    - MongoSystemInfos ${mongoSystemInfos}
-
-  """
-
-  def mongoSystemInfos = s2"""
-
-    MongoSystemInfos should
-    - behave like any SystemInfos implementation ${systemInfos(newMongoSystemInfos)}
-    - (database cleanup) ${Step(Spec.mongoClient(mongoDbName).dropDatabase())}
-
-  """
-
-  def systemInfos(systemInfos: SystemInfos) = s2"""
-
-    create and get a system info entry ${insertAndGet(systemInfos)}
-    update a system info entry ${update(systemInfos)}
-    delete a system info entry ${delete(systemInfos)}
-    backup and restore system info entries ${backuprestore(systemInfos)}
-
-  """
-
-  val mongoDbName = "predictionio_mongosysteminfos_test"
-  def newMongoSystemInfos = new mongodb.MongoSystemInfos(Spec.mongoClient(mongoDbName))
-
-  def insertAndGet(systemInfos: SystemInfos) = {
-    val version = SystemInfo(
-      id = "version",
-      value = "0.4-SNAPSHOT",
-      description = Some("PredictionIO Version"))
-    systemInfos.insert(version)
-    systemInfos.get("version") must beSome(version).eventually
-  }
-
-  def update(systemInfos: SystemInfos) = {
-    val build = SystemInfo(
-      id = "build",
-      value = "123",
-      description = None)
-    systemInfos.insert(build)
-    val updatedBuild = build.copy(value = "124")
-    systemInfos.update(updatedBuild)
-    systemInfos.get("build") must beSome(updatedBuild)
-  }
-
-  def delete(systemInfos: SystemInfos) = {
-    val foo = SystemInfo(
-      id = "foo",
-      value = "bar",
-      description = None)
-    systemInfos.insert(foo)
-    systemInfos.delete("foo")
-    systemInfos.get("foo") must beNone
-  }
-
-  def backuprestore(systemInfos: SystemInfos) = {
-    val rev = SystemInfo(
-      id = "rev",
-      value = "321",
-      description = Some("software revision"))
-    systemInfos.insert(rev)
-    val fn = "systeminfos.json"
-    val fos = new java.io.FileOutputStream(fn)
-    try {
-      fos.write(systemInfos.backup())
-    } finally {
-      fos.close()
-    }
-    systemInfos.restore(scala.io.Source.fromFile(fn)(scala.io.Codec.UTF8).mkString.getBytes("UTF-8")) map { data =>
-      data must contain(rev)
-    } getOrElse 1 === 2
-  }
-}
diff --git a/commons/src/test/scala/io/prediction/commons/settings/UsersSpec.scala b/commons/src/test/scala/io/prediction/commons/settings/UsersSpec.scala
deleted file mode 100644
index 0e14f21..0000000
--- a/commons/src/test/scala/io/prediction/commons/settings/UsersSpec.scala
+++ /dev/null
@@ -1,269 +0,0 @@
-package io.prediction.commons.settings
-
-import io.prediction.commons.Spec
-
-import org.specs2._
-import org.specs2.specification.Step
-import com.mongodb.casbah.Imports._
-
-class UsersSpec extends Specification {
-  def is = s2"""
-
-  PredictionIO Users Specification
-
-    Users can be implemented by:
-    - MongoUsers $mongoUsers
-
-  """
-
-  def mongoUsers = s2"""
-
-    MongoUsers should
-    - behave like any Users implementation ${users(newMongoUsers)}
-    - (database cleanup) ${Step(Spec.mongoClient(mongoDbName).dropDatabase())}
-
-  """
-
-  def users(users: Users) = s2"""
-
-    inserting a user ${insert(users)}
-    looking up an existing e-mail ${emailExists(users)}
-    looking up a non-existing e-mail should fail ${emailExistsNonExist(users)}
-    looking up an existing ID and e-mail combo ${idAndEmailExists(users)}
-    looking up a non-existing ID and e-mail combo should fail ${idAndEmailExistsNonExist(users)}
-    getting a user by ID ${get(users)}
-    getting a user by e-mail ${getByEmail(users)}
-    authenticating a non-existing user and fail ${authenticateNonExist(users)}
-    authenticating an unconfirmed user and fail ${authenticateUnconfirmed(users)}
-    authenticating a confirmed user ${authenticate(users)}
-    authenticating by e-mail a non-existing user and fail ${authenticateByEmailNonExist(users)}
-    authenticating by e-mail an unconfirmed user and fail ${authenticateByEmailUnconfirmed(users)}
-    authenticating by e-mail a confirmed user ${authenticateByEmail(users)}
-    confirming a non-existing user and fail ${confirmNonExist(users)}
-    confirming an unconfirmed user ${confirm(users)}
-    updating a user's e-mail by ID ${updateEmail(users)}
-    updating a user's password by ID ${updatePassword(users)}
-    updating a user's password by e-mail ${updatePasswordByEmail(users)}
-    updating a user ${update(users)}
-    backup and restore users ${backuprestore(users)}
-
-  """
-
-  val mongoDbName = "predictionio_mongousers_test"
-  def newMongoUsers = new mongodb.MongoUsers(Spec.mongoClient(mongoDbName))
-
-  def insert(users: Users) = {
-    val name = "insert"
-    users.insert(
-      email = name + "@prediction.io",
-      password = name,
-      firstname = name,
-      lastname = Option(name),
-      confirm = name
-    )
-    users.emailExists(name + "@prediction.io") must beTrue
-  }
-
-  def get(users: Users) = {
-    val name = "get"
-    val id = users.insert(
-      email = name + "@prediction.io",
-      password = name,
-      firstname = name,
-      lastname = Option(name),
-      confirm = name
-    )
-    users.get(id) must beSome(User(id, name, Option(name), name + "@prediction.io", name, Some(name)))
-  }
-
-  def getByEmail(users: Users) = {
-    val name = "getByEmail"
-    val id = users.insert(
-      email = name + "@prediction.io",
-      password = name,
-      firstname = name,
-      lastname = None,
-      confirm = name
-    )
-    users.getByEmail(name + "@prediction.io") must beSome(User(id, name, None, name + "@prediction.io", name, Some(name)))
-  }
-
-  def emailExists(users: Users) = {
-    val dummy = "emailExists"
-    val email = dummy + "@prediction.io"
-    users.insert(
-      email = email,
-      password = dummy,
-      firstname = dummy,
-      lastname = None,
-      confirm = dummy
-    )
-    users.emailExists(email) must beTrue
-  }
-
-  def emailExistsNonExist(users: Users) = {
-    users.emailExists("nonexist@prediction.io") must beFalse
-  }
-
-  def idAndEmailExists(users: Users) = {
-    val name = "idAndEmailExists"
-    val id = users.insert(
-      email = name + "@prediction.io",
-      password = name,
-      firstname = name,
-      lastname = Option(name),
-      confirm = name
-    )
-    users.idAndEmailExists(id, name + "@prediction.io") must beTrue
-  }
-
-  def idAndEmailExistsNonExist(users: Users) = {
-    users.idAndEmailExists(4789, "nonexist@prediction.io") must beFalse
-  }
-
-  def authenticateNonExist(users: Users) = {
-    users.authenticate(342, "bar") must beFalse
-  }
-
-  def authenticateUnconfirmed(users: Users) = {
-    val name = "authenticateUnconfirmed"
-    val id = users.insert(
-      email = name + "@prediction.io",
-      password = name,
-      firstname = name,
-      lastname = Option(name),
-      confirm = name
-    )
-    users.authenticate(id, name) must beFalse
-  }
-
-  def authenticate(users: Users) = {
-    val name = "authenticate"
-    val id = users.insert(
-      email = name + "@prediction.io",
-      password = name,
-      firstname = name,
-      lastname = Option(name),
-      confirm = name
-    )
-    users.confirm(name)
-    users.authenticate(id, name) must beTrue
-  }
-
-  def authenticateByEmailNonExist(users: Users) = {
-    users.authenticateByEmail("foo", "bar") must beNone
-  }
-
-  def authenticateByEmailUnconfirmed(users: Users) = {
-    val name = "authenticateByEmailUnconfirmed"
-    users.insert(
-      email = name + "@prediction.io",
-      password = name,
-      firstname = name,
-      lastname = Option(name),
-      confirm = name
-    )
-    users.authenticateByEmail(name + "@predictionio", name) must beNone
-  }
-
-  def authenticateByEmail(users: Users) = {
-    val name = "authenticateByEmail"
-    val id = users.insert(
-      email = name + "@prediction.io",
-      password = name,
-      firstname = name,
-      lastname = Option(name),
-      confirm = name
-    )
-    users.confirm(name)
-    users.authenticateByEmail(name + "@prediction.io", name) must beSome(id)
-  }
-
-  def confirmNonExist(users: Users) = {
-    users.confirm("fakecode") must beNone
-  }
-
-  def confirm(users: Users) = {
-    val name = "confirm"
-    val id = users.insert(
-      email = name + "@prediction.io",
-      password = name,
-      firstname = name,
-      lastname = None,
-      confirm = name
-    )
-    users.confirm(name) must beSome(User(id, name, None, name + "@prediction.io", name, Some(name)))
-  }
-
-  def updateEmail(users: Users) = {
-    val id = users.insert(
-      email = "updateEmail@prediction.io",
-      password = "updateEmail",
-      firstname = "updateEmail",
-      lastname = None,
-      confirm = "updateEmail"
-    )
-    users.updateEmail(id, "updateEmailUpdated@prediction.io")
-    users.get(id) must beSome(User(id, "updateEmail", None, "updateEmailUpdated@prediction.io", "updateEmail", Some("updateEmail")))
-  }
-
-  def updatePassword(users: Users) = {
-    val id = users.insert(
-      email = "updatePassword@prediction.io",
-      password = "updatePassword",
-      firstname = "updatePassword",
-      lastname = None,
-      confirm = "updatePassword"
-    )
-    users.confirm("updatePassword")
-    users.updatePassword(id, "updatePasswordUpdated")
-    users.authenticate(id, "updatePasswordUpdated") must beTrue
-  }
-
-  def updatePasswordByEmail(users: Users) = {
-    val id = users.insert(
-      email = "updatePasswordByEmail@prediction.io",
-      password = "updatePasswordByEmail",
-      firstname = "updatePasswordByEmail",
-      lastname = None,
-      confirm = "updatePasswordByEmail"
-    )
-    users.confirm("updatePasswordByEmail")
-    users.updatePasswordByEmail("updatePasswordByEmail@prediction.io", "updatePasswordByEmailUpdated")
-    users.authenticate(id, "updatePasswordByEmailUpdated") must beTrue
-  }
-
-  def update(users: Users) = {
-    val id = users.insert(
-      email = "update@prediction.io",
-      password = "update",
-      firstname = "update",
-      lastname = None,
-      confirm = "update"
-    )
-    val updatedUser = User(id, "updated", None, "updated@prediction.io")
-    users.update(updatedUser)
-    users.get(id) must beSome(updatedUser)
-  }
-
-  def backuprestore(users: Users) = {
-    val user1 = User(0, "english中文", None, "backuprestore@prediction.io", "password", Some("backuprestore"))
-    val id1 = users.insert(
-      email = user1.email,
-      password = user1.password,
-      firstname = user1.firstName,
-      lastname = user1.lastName,
-      confirm = user1.confirm.get
-    )
-    val fn = "users.json"
-    val fos = new java.io.FileOutputStream(fn)
-    try {
-      fos.write(users.backup())
-    } finally {
-      fos.close()
-    }
-    users.restore(scala.io.Source.fromFile(fn)(scala.io.Codec.UTF8).mkString.getBytes("UTF-8")) map { data =>
-      data must contain(user1.copy(id = id1))
-    } getOrElse 1 === 2
-  }
-}
diff --git a/dist/bin/common.sh b/dist/bin/common.sh
deleted file mode 100644
index 31f8dcd..0000000
--- a/dist/bin/common.sh
+++ /dev/null
@@ -1,52 +0,0 @@
-# PredictionIO Shared Shell Code
-
-# This script should be sourced with $BASE set to the base of the binary package
-
-VERSION=0.7.3
-
-# Play framework related
-PLAY_OPTS=""
-PLAY_START_OPTS="-Dio.prediction.base=$BASE -Dsbt.log.noformat=true -Dconfig.file=$BASE/conf/predictionio.conf"
-
-# Log related
-LOGDIR="$BASE/logs"
-
-# Play apps related
-ADMIN_PORT=9000
-API_PORT=8000
-SCHEDULER_PORT=7000
-
-ADMIN_DIR="$BASE/servers/admin"
-API_DIR="$BASE/servers/api"
-SCHEDULER_DIR="$BASE/servers/scheduler"
-
-ADMIN_OUT="$LOGDIR/admin.out"
-API_OUT="$LOGDIR/api.out"
-SCHEDULER_OUT="$LOGDIR/scheduler.out"
-
-ADMIN_ERR="$LOGDIR/admin.err"
-API_ERR="$LOGDIR/api.err"
-SCHEDULER_ERR="$LOGDIR/scheduler.err"
-
-# Kill the whole shell when Ctrl+C is pressed
-trap "exit 1" INT
-
-# Stop Play server
-stop_play () {
-	PLAY_NAME=$1
-	PLAY_DIR=$2
-	PLAY_OUT=$3
-	mkdir -p `dirname $PLAY_OUT`
-	echo "Trying to stop ${PLAY_NAME} server... \c"
-	echo "Trying to stop ${PLAY_NAME} server at: `date`" >>"$PLAY_OUT"
-	PID_FILE="${BASE}/${PLAY_NAME}.pid"
-	#if [ -e $PLAY_DIR/RUNNING_PID ] ; then
-	if [ -e $PID_FILE ] ; then
-		#kill -TERM `cat ${PLAY_DIR}/RUNNING_PID`
-		kill -TERM `cat $PID_FILE`
-		echo "stopped"
-	else
-		#echo "cannot find ${PLAY_DIR}/RUNNING_PID (server may not be running)"
-		echo "cannot find $PID_FILE (server may not be running)"
-	fi
-}
diff --git a/dist/bin/setup-vendors.sh b/dist/bin/setup-vendors.sh
deleted file mode 100755
index a9fc9f9..0000000
--- a/dist/bin/setup-vendors.sh
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/usr/bin/env sh
-
-# PredictionIO Third Party Software Installation
-
-# Get the absolute path of the build script
-SCRIPT="$0"
-while [ -h "$SCRIPT" ] ; do
-	SCRIPT=`readlink "$SCRIPT"`
-done
-
-# Get the base directory of the repo
-DIR=`dirname $SCRIPT`/..
-cd $DIR
-BASE=`pwd`
-
-. "$BASE/bin/common.sh"
-. "$BASE/bin/vendors.sh"
-
-# Detect existing installations in search path
-if vendor_graphchi_exists ; then
-	echo "Found GraphChi C++ Collaborative Filtering Toolkit in vendors area. Assuming it has been installed."
-else
-	echo "Cannot find GraphChi C++ Collaborative Filtering Toolkit from vendors area. Installing it from the Internet."
-	install_graphchi "$VENDORS_PATH"
-fi
-
-# Detect existing installations in search path
-if [ $(process_exists "mongod") -gt "0" ] ; then
-	echo "mongod is running. Skipping MongoDB installation."
-elif command_exists "mongod" ; then
-	echo "Found mongod in search path. Assuming MongoDB has been installed."
-elif vendor_mongodb_exists ; then
-	echo "Found mongod in vendors area. Assuming MongoDB has been installed."
-else
-	while true; do
-		read -p "Cannot find mongod from process list, search path, nor vendors area. Do you want to automatically install $VENDOR_MONGODB_NAME? [y/n] " yn
-		case $yn in
-			[Yy]* ) install_mongodb "$VENDORS_PATH"; break;;
-			[Nn]* ) break;;
-			* ) echo "Please answer 'y' or 'n'.";;
-		esac
-	done
-fi
-
-# Detect existing installations in search path
-if command_exists "hadoop" ; then
-	echo "Found hadoop in search path. Assuming Apache Hadoop has been installed."
-elif vendor_hadoop_exists ; then
-	echo "Found hadoop in vendors area. Assuming Apache Hadoop has been installed."
-else
-	while true; do
-		read -p "Cannot find hadoop from search path nor vendors area. Do you want to automatically install $VENDOR_HADOOP_NAME? (Please make sure you can SSH to the localhost without a password.) [y/n] " yn
-		case $yn in
-			[Yy]* ) install_hadoop "$VENDORS_PATH"; break;;
-			[Nn]* ) break;;
-			* ) echo "Please answer 'y' or 'n'.";;
-		esac
-	done
-fi
diff --git a/dist/bin/setup.sh b/dist/bin/setup.sh
deleted file mode 100755
index f991e97..0000000
--- a/dist/bin/setup.sh
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/env sh
-
-# PredictionIO Software Installation
-
-# Get the absolute path of the build script
-SCRIPT="$0"
-while [ -h "$SCRIPT" ] ; do
-	SCRIPT=`readlink "$SCRIPT"`
-done
-
-# Get the base directory of the repo
-DIR=`dirname $SCRIPT`/..
-cd $DIR
-BASE=`pwd`
-
-. "$BASE/bin/common.sh"
-. "$BASE/bin/vendors.sh"
-
-# MongoDB
-if vendor_mongodb_exists ; then
-	while true; do
-		echo "Note: MongoDB connectivity is required to run setup."
-		read -p "Found MongoDB in vendors area. Do you want to start it? [y/n] " yn
-		case $yn in
-			[Yy]* ) start_mongodb; break;;
-			[Nn]* ) break;;
-			* ) echo "Please answer 'y' or 'n'.";;
-		esac
-	done
-fi
-
-$BASE/bin/conncheck
-
-# Initialize settings
-echo "Initializing PredictionIO Settings Database..."
-$BASE/bin/settingsinit conf/init.json
diff --git a/dist/bin/start-admin.sh b/dist/bin/start-admin.sh
deleted file mode 100755
index 55f757f..0000000
--- a/dist/bin/start-admin.sh
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/env sh
-
-# PredictionIO Admin Server Startup Script
-
-set -e
-
-# Get the absolute path of the build script
-SCRIPT="$0"
-while [ -h "$SCRIPT" ] ; do
-    SCRIPT=`readlink "$SCRIPT"`
-done
-
-# Get the base directory of the repo
-DIR=`dirname $SCRIPT`/..
-cd $DIR
-BASE=`pwd`
-
-. "$BASE/bin/common.sh"
-. "$BASE/bin/vendors.sh"
-
-mkdir -p "$LOGDIR"
-
-SERVER_WAIT=1
-SERVER_RETRY=20
-
-$BASE/bin/conncheck
-
-# Admin server
-echo "Trying to start admin server... \c"
-echo "Trying to start admin server at: `date`" >>"$ADMIN_OUT"
-$BASE/bin/predictionio-admin $PLAY_START_OPTS -Dhttp.port=$ADMIN_PORT -Dlogger.file=$BASE/conf/admin-logger.xml -Dpidfile.path=$BASE/admin.pid >>"$ADMIN_OUT" 2>>"$ADMIN_ERR" &
-SERVER_TRY=1
-while [ $SERVER_TRY -le $SERVER_RETRY ] ; do
-    sleep $SERVER_WAIT
-    if [ $(curl --write-out %{http_code} --silent --output /dev/null "localhost:$ADMIN_PORT") -eq 303 ] ; then
-        echo "started"
-        SERVER_TRY=$SERVER_RETRY
-    elif [ $SERVER_TRY -eq $SERVER_RETRY ] ; then
-        echo "failed ($ADMIN_PORT unreachable)"
-        exit 1
-    fi
-    SERVER_TRY=$((SERVER_TRY+1))
-done
diff --git a/dist/bin/start-all.sh b/dist/bin/start-all.sh
deleted file mode 100755
index f35c1b6..0000000
--- a/dist/bin/start-all.sh
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/env sh
-
-# PredictionIO Startup Script
-
-set -e
-
-# Get the absolute path of the build script
-SCRIPT="$0"
-while [ -h "$SCRIPT" ] ; do
-    SCRIPT=`readlink "$SCRIPT"`
-done
-
-# Get the base directory of the repo
-DIR=`dirname $SCRIPT`/..
-cd $DIR
-BASE=`pwd`
-
-. "$BASE/bin/common.sh"
-. "$BASE/bin/vendors.sh"
-
-mkdir -p "$LOGDIR"
-
-SERVER_WAIT=1
-SERVER_RETRY=20
-
-# MongoDB
-if vendor_mongodb_exists ; then
-    while true; do
-        read -p "Found MongoDB in vendors area. Do you want to start it? [y/n] " yn
-        case $yn in
-            [Yy]* ) start_mongodb; break;;
-            [Nn]* ) break;;
-            * ) echo "Please answer 'y' or 'n'.";;
-        esac
-    done
-fi
-
-$BASE/bin/conncheck
-
-$BASE/bin/start-admin.sh
-$BASE/bin/start-api.sh
-$BASE/bin/start-scheduler.sh
-
-# Apache Hadoop
-if vendor_hadoop_exists ; then
-    while true; do
-        read -p "Found Hadoop in vendors area. Do you want to start it? [y/n] " yn
-        case $yn in
-            [Yy]* ) start_hadoop; break;;
-            [Nn]* ) break;;
-            * ) echo "Please answer 'y' or 'n'.";;
-        esac
-    done
-fi
diff --git a/dist/bin/start-api.sh b/dist/bin/start-api.sh
deleted file mode 100755
index 2ddbba7..0000000
--- a/dist/bin/start-api.sh
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/env sh
-
-# PredictionIO API Server Startup Script
-
-set -e
-
-# Get the absolute path of the build script
-SCRIPT="$0"
-while [ -h "$SCRIPT" ] ; do
-    SCRIPT=`readlink "$SCRIPT"`
-done
-
-# Get the base directory of the repo
-DIR=`dirname $SCRIPT`/..
-cd $DIR
-BASE=`pwd`
-
-. "$BASE/bin/common.sh"
-. "$BASE/bin/vendors.sh"
-
-mkdir -p "$LOGDIR"
-
-SERVER_WAIT=1
-SERVER_RETRY=20
-
-$BASE/bin/conncheck
-
-# API server
-echo "Trying to start API server... \c"
-echo "Trying to start API server at: `date`" >>"$API_OUT"
-$BASE/bin/predictionio-api $PLAY_START_OPTS -Dhttp.port=$API_PORT -Dlogger.file=$BASE/conf/api-logger.xml -Dpidfile.path=$BASE/api.pid >>"$API_OUT" 2>>"$API_ERR" &
-SERVER_TRY=1
-while [ $SERVER_TRY -le $SERVER_RETRY ] ; do
-    sleep $SERVER_WAIT
-    if [ $(curl --write-out %{http_code} --silent --output /dev/null "localhost:$API_PORT") -eq 200 ] ; then
-        echo "started"
-        SERVER_TRY=$SERVER_RETRY
-    elif [ $SERVER_TRY -eq $SERVER_RETRY ] ; then
-        echo "failed ($API_PORT unreachable)"
-        exit 1
-    fi
-    SERVER_TRY=$((SERVER_TRY+1))
-done
diff --git a/dist/bin/start-scheduler.sh b/dist/bin/start-scheduler.sh
deleted file mode 100755
index 994f217..0000000
--- a/dist/bin/start-scheduler.sh
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/env sh
-
-# PredictionIO Startup Script
-
-set -e
-
-# Get the absolute path of the build script
-SCRIPT="$0"
-while [ -h "$SCRIPT" ] ; do
-    SCRIPT=`readlink "$SCRIPT"`
-done
-
-# Get the base directory of the repo
-DIR=`dirname $SCRIPT`/..
-cd $DIR
-BASE=`pwd`
-
-. "$BASE/bin/common.sh"
-. "$BASE/bin/vendors.sh"
-
-mkdir -p "$LOGDIR"
-
-SERVER_WAIT=1
-SERVER_RETRY=20
-
-$BASE/bin/conncheck
-
-# Scheduler server
-echo "Trying to start scheduler server... \c"
-echo "Trying to start scheduler server at: `date`" >>"$SCHEDULER_OUT"
-$BASE/bin/predictionio-scheduler $PLAY_START_OPTS -Dhttp.port=$SCHEDULER_PORT -Dlogger.file=$BASE/conf/scheduler-logger.xml -Dpidfile.path=$BASE/scheduler.pid -Dorg.quartz.properties=$BASE/conf/quartz.properties >>"$SCHEDULER_OUT" 2>>"$SCHEDULER_ERR" &
-SERVER_TRY=1
-while [ $SERVER_TRY -le $SERVER_RETRY ] ; do
-    sleep $SERVER_WAIT
-    if [ $(curl --write-out %{http_code} --silent --output /dev/null "localhost:$SCHEDULER_PORT") -eq 200 ] ; then
-        echo "started"
-        SERVER_TRY=$SERVER_RETRY
-    elif [ $SERVER_TRY -eq $SERVER_RETRY ] ; then
-        echo "failed ($SCHEDULER_PORT unreachable)"
-        exit 1
-    fi
-    SERVER_TRY=$((SERVER_TRY+1))
-done
diff --git a/dist/bin/stop-admin.sh b/dist/bin/stop-admin.sh
deleted file mode 100755
index 0c15e0e..0000000
--- a/dist/bin/stop-admin.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/env sh
-
-# PredictionIO Admin Server Shutdown Script
-
-# Get the absolute path of the build script
-SCRIPT="$0"
-while [ -h "$SCRIPT" ] ; do
-	SCRIPT=`readlink "$SCRIPT"`
-done
-
-# Get the base directory of the repo
-DIR=`dirname $SCRIPT`/..
-cd $DIR
-BASE=`pwd`
-
-. "$BASE/bin/common.sh"
-
-stop_play "admin" $ADMIN_DIR $ADMIN_OUT
diff --git a/dist/bin/stop-all.sh b/dist/bin/stop-all.sh
deleted file mode 100755
index a9183d1..0000000
--- a/dist/bin/stop-all.sh
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/env sh
-
-# PredictionIO Shutdown Script
-
-# Get the absolute path of the build script
-SCRIPT="$0"
-while [ -h "$SCRIPT" ] ; do
-	SCRIPT=`readlink "$SCRIPT"`
-done
-
-# Get the base directory of the repo
-DIR=`dirname $SCRIPT`/..
-cd $DIR
-BASE=`pwd`
-
-. "$BASE/bin/common.sh"
-. "$BASE/bin/vendors.sh"
-
-# Admin server
-$BASE/bin/stop-admin.sh
-
-# API server
-$BASE/bin/stop-api.sh
-
-# Scheduler server
-$BASE/bin/stop-scheduler.sh
-
-# Apache Hadoop
-if vendor_hadoop_exists ; then
-	echo ""
-	while true; do
-		read -p "Found Hadoop in vendors area. Do you want to stop it? [y/n] " yn
-		case $yn in
-			[Yy]* ) stop_hadoop; break;;
-			[Nn]* ) break;;
-			* ) echo "Please answer 'y' or 'n'.";;
-		esac
-	done
-fi
-
-echo ""
-echo "Note: You must stop any running MongoDB processes manually."
diff --git a/dist/bin/stop-api.sh b/dist/bin/stop-api.sh
deleted file mode 100755
index 094627e..0000000
--- a/dist/bin/stop-api.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/env sh
-
-# PredictionIO API Server Shutdown Script
-
-# Get the absolute path of the build script
-SCRIPT="$0"
-while [ -h "$SCRIPT" ] ; do
-	SCRIPT=`readlink "$SCRIPT"`
-done
-
-# Get the base directory of the repo
-DIR=`dirname $SCRIPT`/..
-cd $DIR
-BASE=`pwd`
-
-. "$BASE/bin/common.sh"
-
-stop_play "api" $API_DIR $API_OUT
diff --git a/dist/bin/stop-scheduler.sh b/dist/bin/stop-scheduler.sh
deleted file mode 100755
index 066ef97..0000000
--- a/dist/bin/stop-scheduler.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/env sh
-
-# PredictionIO Scheduler Server Shutdown Script
-
-# Get the absolute path of the build script
-SCRIPT="$0"
-while [ -h "$SCRIPT" ] ; do
-	SCRIPT=`readlink "$SCRIPT"`
-done
-
-# Get the base directory of the repo
-DIR=`dirname $SCRIPT`/..
-cd $DIR
-BASE=`pwd`
-
-. "$BASE/bin/common.sh"
-
-stop_play "scheduler" $SCHEDULER_DIR $SCHEDULER_OUT
diff --git a/dist/bin/vendors.sh b/dist/bin/vendors.sh
deleted file mode 100644
index ada3039..0000000
--- a/dist/bin/vendors.sh
+++ /dev/null
@@ -1,127 +0,0 @@
-#!/usr/bin/env sh
-
-# PredictionIO Third Party Software Utilities
-
-# This script should be sourced with $BASE set to the base of the binary package
-
-# Utilities
-command_exists () {
-	command -v "$1" >/dev/null 2>&1
-}
-
-ostype () {
-	case $(uname) in
-		Linux*)
-			echo "linux";;
-		Darwin*)
-			echo "osx";;
-	esac
-}
-
-hosttype () {
-	case $(uname -m) in
-		i[3456]86)
-			echo "i686";;
-		x86_64)
-			echo "x86_64";;
-	esac
-}
-
-OS=$(ostype)
-ARCH=$(hosttype)
-
-process_exists () {
-	echo $(ps -ef | grep "$1" | grep -v "grep" | wc -l)
-}
-
-# Third party software
-VENDORS_PATH="$BASE/vendors"
-
-VENDOR_GRAPHCHI_VERSION="0a6545ccb7"
-VENDOR_HADOOP_VERSION="1.2.1"
-VENDOR_MONGODB_VERSION="2.4.9"
-
-VENDOR_GRAPHCHI_PATH="$VENDORS_PATH/graphchi-cpp-cf-$OS-$ARCH-$VENDOR_GRAPHCHI_VERSION"
-VENDOR_HADOOP_PATH="$VENDORS_PATH/hadoop-$VENDOR_HADOOP_VERSION"
-VENDOR_MONGODB_PATH="$VENDORS_PATH/mongodb-$OS-$ARCH-$VENDOR_MONGODB_VERSION"
-
-VENDOR_GRAPHCHI_NAME="GraphChi C++ Collaborative Filtering Toolkit $VENDOR_GRAPHCHI_VERSION"
-VENDOR_HADOOP_NAME="Apache Hadoop $VENDOR_HADOOP_VERSION"
-VENDOR_MONGODB_NAME="MongoDB $VENDOR_MONGODB_VERSION"
-
-install_graphchi () {
-	local FN="graphchi-cpp-cf-$OS-$ARCH-$VENDOR_GRAPHCHI_VERSION.tar.gz"
-	local URL="http://download.prediction.io/graphchi-cpp-cf/$FN"
-	echo "Going to download and install $VENDOR_GRAPHCHI_NAME ($URL)..."
-	local VENDORS_PATH=$1
-	mkdir -p $VENDORS_PATH
-	cd $VENDORS_PATH
-	curl -O $URL
-	tar zxvf $FN
-	cp $VENDOR_GRAPHCHI_PATH/* $BASE/bin
-}
-
-install_mongodb () {
-	local FN="mongodb-$OS-$ARCH-$VENDOR_MONGODB_VERSION.tgz"
-	local URL="http://fastdl.mongodb.org/$OS/$FN"
-	echo "Going to download and install $VENDOR_MONGODB_NAME ($URL)..."
-	local VENDORS_PATH=$1
-	mkdir -p $VENDORS_PATH
-	cd $VENDORS_PATH
-	curl -O $URL
-	tar zxvf $FN
-}
-
-install_hadoop () {
-	while true; do
-		read -p "Please supply the absolute path to your Java installation: " JAVA_HOME
-		if [ $JAVA_HOME ] && [ -d $JAVA_HOME ] && [ -x "$JAVA_HOME/bin/java" ] ; then
-			echo "Using directory $JAVA_HOME as your Java installation..."
-			break
-		else
-			echo "Please provide a valid Java installation directory"
-		fi
-	done
-	echo "Going to download and install $VENDOR_HADOOP_NAME..."
-	local VENDORS_PATH=$1
-	mkdir -p $VENDORS_PATH
-	cd $VENDORS_PATH
-	curl -O http://archive.apache.org/dist/hadoop/common/hadoop-$VENDOR_HADOOP_VERSION/hadoop-$VENDOR_HADOOP_VERSION-bin.tar.gz
-	tar zxvf hadoop-$VENDOR_HADOOP_VERSION-bin.tar.gz
-	echo "Configuring Hadoop in pseudo-distributed mode..."
-	cp ../conf/hadoop/* $VENDOR_HADOOP_PATH/conf
-	echo "export JAVA_HOME=$JAVA_HOME" >> $VENDOR_HADOOP_PATH/conf/hadoop-env.sh
-	echo "Configuring PredictionIO to use Hadoop in vendors area..."
-	echo "io.prediction.commons.settings.hadoop.home=$VENDOR_HADOOP_PATH" >> ../conf/predictionio.conf
-	echo "Trying to format HDFS..."
-	$VENDOR_HADOOP_PATH/bin/hadoop namenode -format
-}
-
-start_mongodb () {
-	echo "Going to start MongoDB..."
-	mkdir -p "$VENDORS_PATH/mongodb/data"
-	mkdir -p "$VENDORS_PATH/mongodb/logs"
-	$VENDOR_MONGODB_PATH/bin/mongod --config conf/mongodb/mongodb.conf >/dev/null 2>&1 &
-}
-
-start_hadoop () {
-	echo "Going to start Hadoop..."
-	$VENDOR_HADOOP_PATH/bin/start-all.sh
-}
-
-stop_hadoop () {
-	echo "Going to stop Hadoop..."
-	$VENDOR_HADOOP_PATH/bin/stop-all.sh
-}
-
-vendor_graphchi_exists () {
-	[ -e "$VENDOR_GRAPHCHI_PATH/als" ]
-}
-
-vendor_mongodb_exists () {
-	[ -e "$VENDOR_MONGODB_PATH/bin/mongod" ]
-}
-
-vendor_hadoop_exists () {
-	[ -e "$VENDOR_HADOOP_PATH/bin/hadoop" ]
-}
diff --git a/dist/conf/admin-logger.xml b/dist/conf/admin-logger.xml
deleted file mode 100644
index 5a266cb..0000000
--- a/dist/conf/admin-logger.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<configuration>
-
-  <conversionRule conversionWord="coloredLevel" converterClass="play.api.Logger$ColoredLevel" />
-
-  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
-     <file>${application.home}/logs/admin.log</file>
-     <encoder>
-       <pattern>%date - [%level] - from %logger in %thread %n%message%n%xException%n</pattern>
-     </encoder>
-   </appender>
-
-  <logger name="play" level="INFO" />
-  <logger name="application" level="INFO" />
-
-  <root level="ERROR">
-    <appender-ref ref="FILE" />
-  </root>
-
-</configuration>
diff --git a/dist/conf/api-logger.xml b/dist/conf/api-logger.xml
deleted file mode 100644
index 94bfbaf..0000000
--- a/dist/conf/api-logger.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<configuration>
-
-  <conversionRule conversionWord="coloredLevel" converterClass="play.api.Logger$ColoredLevel" />
-
-  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
-     <file>${application.home}/logs/api.log</file>
-     <encoder>
-       <pattern>%date - [%level] - from %logger in %thread %n%message%n%xException%n</pattern>
-     </encoder>
-   </appender>
-
-  <logger name="play" level="INFO" />
-  <logger name="application" level="INFO" />
-
-  <root level="ERROR">
-    <appender-ref ref="FILE" />
-  </root>
-
-</configuration>
diff --git a/dist/conf/graphchi.cnf b/dist/conf/graphchi.cnf
deleted file mode 100644
index 8274e64..0000000
--- a/dist/conf/graphchi.cnf
+++ /dev/null
@@ -1,29 +0,0 @@
-
-# GraphChi configuration.
-# Commandline parameters override values in the configuration file.
-# execthreads=2
-loadthreads = 4
-niothreads = 2
-
-# Good for 8gigs
-#membudget_mb = 2000
-#cachesize_mb = 1000
-
-# Good for 4 gigs
-membudget_mb = 800
-cachesize_mb = 0
-
-# I/O settings
-io.blocksize = 1048576 
-mmap = 0  # Use mmaped files where applicable
-
-
-# Comma-delimited list of metrics output reporters.
-# Can be "console", "file" or "html"
-metrics.reporter = console,file,html
-metrics.reporter.filename = graphchi_metrics.txt
-metrics.reporter.htmlfile = graphchi_metrics.html
-
-
-
-
diff --git a/dist/conf/hadoop/core-site.xml b/dist/conf/hadoop/core-site.xml
deleted file mode 100644
index 03a2e8c..0000000
--- a/dist/conf/hadoop/core-site.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<configuration>
-	<property>
-		<name>fs.default.name</name>
-		<value>hdfs://localhost:9001</value>
-	</property>
-</configuration>
diff --git a/dist/conf/hadoop/hdfs-site.xml b/dist/conf/hadoop/hdfs-site.xml
deleted file mode 100644
index 84f3842..0000000
--- a/dist/conf/hadoop/hdfs-site.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<configuration>
-	<property>
-		<name>dfs.replication</name>
-		<value>1</value>
-	</property>
-</configuration>
diff --git a/dist/conf/hadoop/mapred-site.xml b/dist/conf/hadoop/mapred-site.xml
deleted file mode 100644
index bd0de19..0000000
--- a/dist/conf/hadoop/mapred-site.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<configuration>
-	<property>
-		<name>mapred.job.tracker</name>
-		<value>localhost:9002</value>
-	</property>
-</configuration>
\ No newline at end of file
diff --git a/dist/conf/init.json b/dist/conf/init.json
deleted file mode 100644
index 064bf1e..0000000
--- a/dist/conf/init.json
+++ /dev/null
@@ -1,7158 +0,0 @@
-{
-    "systeminfos": {
-        "version": {
-            "value": "0.7.3",
-            "description": "PredictionIO version"
-        },
-        "jars.pdioItemrecAlgo": {
-            "value": "predictionio-process-hadoop-scalding-assembly-0.7.3.jar"
-        },
-        "jars.pdioItemsimAlgo": {
-            "value": "predictionio-process-hadoop-scalding-assembly-0.7.3.jar"
-        },
-        "jars.pdioItemrecEval": {
-            "value": "predictionio-process-hadoop-scalding-assembly-0.7.3.jar"
-        },
-        "jars.pdioItemsimEval": {
-            "value": "predictionio-process-hadoop-scalding-assembly-0.7.3.jar"
-        },
-        "jars.pdioCommonsEval": {
-            "value": "predictionio-process-hadoop-scalding-assembly-0.7.3.jar"
-        }
-    },
-    "engineinfos": {
-        "itemrec": {
-            "name": "Item Recommendation Engine",
-            "description": "<h6>Recommend interesting items to each user personally.</h6><p>Sample Use Cases</p><ul><li>recommend top N items to users personally</li><li>predict users' future preferences</li><li>help users to discover new topics they may be interested in</li><li>personalize content</li><li>optimize sales</li></ul>",
-            "defaultalgoinfoid": "pio-itemrec-single-mahout-knnitembased",
-            "defaultofflineevalmetricinfoid": "pio-itemrec-single-map_k",
-            "defaultofflineevalsplitterinfoid": "pio-single-trainingtestsplit",
-            "params": {
-                "serendipity": {
-                    "name": "Serendipity",
-                    "description": "Preference for surprising discovery",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "defaultvalue": 0,
-                    "ui": {
-                        "uitype": "slider",
-                        "slidermin": 0,
-                        "slidermax": 10,
-                        "sliderstep": 1
-                    }
-                },
-                "freshness": {
-                    "name": "Freshness",
-                    "description": "Preference for newer items",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "defaultvalue": 0,
-                    "ui": {
-                        "uitype": "slider",
-                        "slidermin": 0,
-                        "slidermax": 10,
-                        "sliderstep": 1
-                    }
-                },
-                "freshnessTimeUnit": {
-                    "name": "Time Unit for Freshness",
-                    "description": "The time unit in seconds for freshness prioritization. As an example, if you set this to one day (86400), and freshness is set to 10, items that are one day old would have their score degraded by a bit more than 60%.",
-                    "constraint": {
-                        "paramtype": "long"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 86400
-                },
-                "unseenonly": {
-                    "name": "",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "boolean"
-                    },
-                    "defaultvalue": false,
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "Recommend Unseen Only",
-                                "value": "true"
-                            },
-                            {
-                                "name": "Recommend Any Items",
-                                "value": "false"
-                            }
-                        ]
-                    }
-                },
-                "seenActions": {
-                    "name": "",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "defaultvalue": "",
-                    "ui": {
-                        "uitype": "text"
-                    }
-                },
-                "goal": {
-                    "name": "Recommend items that users will",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "defaultvalue": "rate3",
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "rate = 5",
-                                "value": "rate5"
-                            },
-                            {
-                                "name": "rate >= 4",
-                                "value": "rate4"
-                            },
-                            {
-                                "name": "rate >= 3",
-                                "value": "rate3"
-                            },
-                            {
-                                "name": "like",
-                                "value": "like"
-                            },
-                            {
-                                "name": "conversion",
-                                "value": "conversion"
-                            },
-                            {
-                                "name": "view",
-                                "value": "view"
-                            }
-                        ]
-                    }
-                },
-                "numRecommendations": {
-                    "name": "",
-                    "description": "Number of recommendations to be generated for each user",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "defaultvalue": 50,
-                    "ui": {
-                        "uitype": "text"
-                    }
-                },
-                "dedupByAttribute": {
-                    "name": "Dedup By Attribute",
-                    "description": "When specified, the engine returns at most 1 item per custom attribute value.",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "defaultvalue": "",
-                    "ui": {
-                        "uitype": ""
-                    }
-                }
-            },
-            "paramsections": [
-                {
-                    "name": "Recommendation Preferences",
-                    "sectiontype": "normal",
-                    "description": "You could adjust the following parameters using the sliders. Higher value means more important to your App.",
-                    "params": [
-                        "freshness",
-                        "freshnessTimeUnit",
-                        "serendipity"
-                    ],
-                    "subsections": [
-                        {
-                            "name": "Unseen Items Only",
-                            "sectiontype": "normal",
-                            "description": "Should the system recommend items that users have seen before?",
-                            "params": [
-                                "unseenonly"
-                            ]
-                        },
-                        {
-                            "name": "Seen Actions",
-                            "sectiontype": "normal",
-                            "description": "Actions to be treated as seen (space-separated string, e.g. 'like rate'). If empty, all actions will be treated as seen.",
-                            "params": [
-                                "seenActions"
-                            ]
-                        },
-                        {
-                            "name": "Number of Recommendations",
-                            "sectiontype": "normal",
-                            "params": [
-                                "numRecommendations"
-                            ]
-                        },
-                        {
-                            "name": "Dedup by Custom Attribute",
-                            "sectiontype": "normal",
-                            "description": "Only return at most one item per attribute value.",
-                            "params": [
-                                "dedupByAttribute"
-                            ]
-                        }
-                    ]
-                },
-                {
-                    "name": "Recommendation Goal",
-                    "sectiontype": "normal",
-                    "description": "Please define the goal to be maximized. Algorithms will be evaluated based on the goal defined here.",
-                    "params": [
-                        "goal"
-                    ]
-                }
-            ]
-        },
-        "itemrank": {
-            "name": "Item Ranking Engine",
-            "description": "<h6>Rank given items to each user personally.</h6><p>Sample Use Cases</p><ul><li>prioritize a set of items to users personally</li><li>reorder menu items to users personally</li></ul>",
-            "defaultalgoinfoid": "pio-itemrank-single-mahout-knnitembased",
-            "defaultofflineevalmetricinfoid": "pio-itemrec-single-map_k",
-            "defaultofflineevalsplitterinfoid": "pio-single-trainingtestsplit",
-            "params": {
-                "freshness": {
-                    "name": "Freshness",
-                    "description": "Preference for newer items",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "defaultvalue": 0,
-                    "ui": {
-                        "uitype": "slider",
-                        "slidermin": 0,
-                        "slidermax": 10,
-                        "sliderstep": 1
-                    }
-                },
-                "freshnessTimeUnit": {
-                    "name": "Time Unit for Freshness",
-                    "description": "The time unit in seconds for freshness prioritization. As an example, if you set this to one day (86400), and freshness is set to 10, items that are one day old would have their score degraded by a bit more than 60%.",
-                    "constraint": {
-                        "paramtype": "long"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 86400
-                }
-            },
-            "paramsections": [
-                {
-                    "name": "Recommendation Preferences",
-                    "sectiontype": "normal",
-                    "description": "You could adjust the following parameters using the sliders. Higher value means more important to your App.",
-                    "params": [
-                        "freshness",
-                        "freshnessTimeUnit"
-                    ]
-                }
-            ]
-        },
-        "itemsim": {
-            "name": "Item Similarity Engine",
-            "description": "<h6>Discover similar items.</h6><p>Sample Use Cases</p><ul><li>predict what else would a user like if this user likes a, i.e. \"People who like this also like....\"</li><li>automatic item grouping</li></ul>",
-            "defaultalgoinfoid": "pio-itemsim-single-mahout-itemsimcf",
-            "defaultofflineevalmetricinfoid": "pio-itemsim-single-ismap_k",
-            "defaultofflineevalsplitterinfoid": "pio-single-trainingtestsplit",
-            "params": {
-                "serendipity": {
-                    "name": "Serendipity",
-                    "description": "Preference for surprising discovery",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "defaultvalue": 0,
-                    "ui": {
-                        "uitype": "slider",
-                        "slidermin": 0,
-                        "slidermax": 10,
-                        "sliderstep": 1
-                    }
-                },
-                "freshness": {
-                    "name": "Freshness",
-                    "description": "Preference for newer items",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "defaultvalue": 0,
-                    "ui": {
-                        "uitype": "slider",
-                        "slidermin": 0,
-                        "slidermax": 10,
-                        "sliderstep": 1
-                    }
-                },
-                "freshnessTimeUnit": {
-                    "name": "Time Unit for Freshness",
-                    "description": "The time unit in seconds for freshness prioritization. As an example, if you set this to one day (86400), and freshness is set to 10, items that are one day old would have their score degraded by a bit more than 60%.",
-                    "constraint": {
-                        "paramtype": "long"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 86400
-                },
-                "goal": {
-                    "name": "Recommendation Goal",
-                    "description": "Goal to be maximized",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "defaultvalue": "rate3",
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "rate = 5",
-                                "value": "rate5"
-                            },
-                            {
-                                "name": "rate >= 4",
-                                "value": "rate4"
-                            },
-                            {
-                                "name": "rate >= 3",
-                                "value": "rate3"
-                            },
-                            {
-                                "name": "like",
-                                "value": "like"
-                            },
-                            {
-                                "name": "conversion",
-                                "value": "conversion"
-                            },
-                            {
-                                "name": "view",
-                                "value": "view"
-                            }
-                        ]
-                    }
-                },
-                "numSimilarItems": {
-                    "name": "",
-                    "description": "Number of similar items to be generated for each item.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "defaultvalue": 50,
-                    "ui": {
-                        "uitype": "text"
-                    }
-                },
-                "dedupByAttribute": {
-                    "name": "Dedup By Attribute",
-                    "description": "When specified, the engine returns at most 1 item per custom attribute value.",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "defaultvalue": "",
-                    "ui": {
-                        "uitype": ""
-                    }
-                }
-            },
-            "paramsections": [
-                {
-                    "name": "Prediction Preferences",
-                    "sectiontype": "normal",
-                    "description": "You could adjust the following parameters using the sliders. Higher value means more important to your App.",
-                    "params": [
-                        "freshness",
-                        "freshnessTimeUnit",
-                        "serendipity"
-                    ],
-                    "subsections": [
-                        {
-                            "name": "Number of Similar Items",
-                            "sectiontype": "normal",
-                            "params": [
-                                "numSimilarItems"
-                            ]
-                        },
-                        {
-                            "name": "Dedup by Custom Attribute",
-                            "sectiontype": "normal",
-                            "description": "Only return at most one item per attribute value.",
-                            "params": [
-                                "dedupByAttribute"
-                            ]
-                        }
-                    ]
-                },
-                {
-                    "name": "Prediction Goal",
-                    "sectiontype": "normal",
-                    "description": "Please define the goal to be maximized. Algorithms will be evaluated based on the goal defined here.",
-                    "params": [
-                        "goal"
-                    ]
-                }
-            ]
-        }
-    },
-    "algoinfos": {
-        "pio-itemrec-single-random": {
-            "name": "Random Rank (Single Machine)",
-            "description": "Predict user preferences randomly.",
-            "batchcommands": [
-                "$base$/bin/random --appid $appid$ --engineid $engineid$ --algoid $algoid$ --numPredictions $numRecommendations$ --modelSet $modelset$ --recommendationTime $recommendationTime$"
-            ],
-            "offlineevalcommands": [
-                "$base$/bin/random --appid $appid$ --engineid $engineid$ --algoid $algoid$ --numPredictions $numRecommendations$ --modelSet false --recommendationTime $recommendationTime$ --evalid $evalid$"
-            ],
-            "paramorder": [],
-            "engineinfoid": "itemrec",
-            "techreq": [],
-            "datareq": [
-                "Users and Items."
-            ],
-            "params": {},
-            "paramsections": []
-        },
-        "pio-itemsim-single-random": {
-            "name": "Random Rank (Single Machine)",
-            "description": "Predict user preferences randomly.",
-            "batchcommands": [
-                "$base$/bin/random --appid $appid$ --engineid $engineid$ --algoid $algoid$ --numPredictions $numSimilarItems$ --modelSet $modelset$ --recommendationTime $recommendationTime$"
-            ],
-            "offlineevalcommands": [
-                "$base$/bin/random --appid $appid$ --engineid $engineid$ --algoid $algoid$ --numPredictions $numSimilarItems$ --modelSet false --recommendationTime $recommendationTime$ --evalid $evalid$"
-            ],
-            "paramorder": [],
-            "engineinfoid": "itemsim",
-            "techreq": [],
-            "datareq": [
-                "Users and Items."
-            ],
-            "params": {},
-            "paramsections": []
-        },
-        "pio-itemrec-distributed-random": {
-            "name": "Random Rank",
-            "description": "Predict user preferences randomly.",
-            "batchcommands": [
-                "$hadoop$ jar $base$/lib/$pdioItemrecAlgo$ io.prediction.algorithms.scalding.itemrec.randomrank.RandomRank --hdfs --training_dbType $appdataDbType$ --training_dbName $appdataDbName$ --training_dbHost $appdataDbHost$ --training_dbPort $appdataDbPort$ --modeldata_dbType $modeldataDbType$ --modeldata_dbName $modeldataDbName$ --modeldata_dbHost $modeldataDbHost$ --modeldata_dbPort $modeldataDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --numRecommendations $numRecommendations$ --modelSet $modelset$ --recommendationTime $recommendationTime$"
-            ],
-            "offlineevalcommands": [
-                "$hadoop$ jar $base$/lib/$pdioItemrecAlgo$ io.prediction.algorithms.scalding.itemrec.randomrank.RandomRank --hdfs --training_dbType $appdataTrainingDbType$ --training_dbName $appdataTrainingDbName$ --training_dbHost $appdataTrainingDbHost$ --training_dbPort $appdataTrainingDbPort$ --modeldata_dbType $modeldataTrainingDbType$ --modeldata_dbName $modeldataTrainingDbName$ --modeldata_dbHost $modeldataTrainingDbHost$ --modeldata_dbPort $modeldataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --numRecommendations $numRecommendations$ --modelSet false --recommendationTime $recommendationTime$ --evalid $evalid$"
-            ],
-            "paramorder": [],
-            "engineinfoid": "itemrec",
-            "techreq": [
-                "Hadoop"
-            ],
-            "datareq": [
-                "Users and Items."
-            ],
-            "params": {},
-            "paramsections": []
-        },
-        "pio-itemrec-distributed-latest": {
-            "name": "Latest Rank",
-            "description": "Recommend latest items to users.",
-            "batchcommands": [
-                "$hadoop$ jar $base$/lib/$pdioItemrecAlgo$ io.prediction.algorithms.scalding.itemrec.latestrank.LatestRank --hdfs --training_dbType $appdataDbType$ --training_dbName $appdataDbName$ --training_dbHost $appdataDbHost$ --training_dbPort $appdataDbPort$ --modeldata_dbType $modeldataDbType$ --modeldata_dbName $modeldataDbName$ --modeldata_dbHost $modeldataDbHost$ --modeldata_dbPort $modeldataDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --numRecommendations $numRecommendations$ --modelSet $modelset$ --recommendationTime $recommendationTime$"
-            ],
-            "offlineevalcommands": [
-                "$hadoop$ jar $base$/lib/$pdioItemrecAlgo$ io.prediction.algorithms.scalding.itemrec.latestrank.LatestRank --hdfs --training_dbType $appdataTrainingDbType$ --training_dbName $appdataTrainingDbName$ --training_dbHost $appdataTrainingDbHost$ --training_dbPort $appdataTrainingDbPort$ --modeldata_dbType $modeldataTrainingDbType$ --modeldata_dbName $modeldataTrainingDbName$ --modeldata_dbHost $modeldataTrainingDbHost$ --modeldata_dbPort $modeldataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --numRecommendations $numRecommendations$ --modelSet false --recommendationTime $recommendationTime$ --evalid $evalid$"
-            ],
-            "paramorder": [],
-            "engineinfoid": "itemrec",
-            "techreq": [
-                "Hadoop"
-            ],
-            "datareq": [
-                "Users and Items with starttime."
-            ],
-            "params": {},
-            "paramsections": []
-        },
-        "pio-itemrec-single-graphchi-als": {
-            "name": "GraphChi's Alternating Least Squares Collaborative Filtering",
-            "description": "Predict user preferences based on matrix factorization.",
-            "batchcommands": [
-                "$base$/bin/itemrec.generic.dataprep --outputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --recommendationTime $recommendationTime$ --matrixMarket true --seenActions $seenActions$",
-                "$base$/bin/als --training=$localTempDir$ratings.mm --D=$d$ --lambda=$lambda$ --minval=1 --maxval=5 --max_iter=$maxIter$ --halt_on_rmse_increase=$haltRMSEInc$ --quiet=1",
-                "$base$/bin/itemrec.graphchi.modelcon --inputDir $localTempDir$ --appid $appid$ --algoid $algoid$ --modelSet $modelset$ --unseenOnly $unseenOnly$ --numRecommendations $numRecommendations$"
-            ],
-            "offlineevalcommands": [
-                "$base$/bin/itemrec.generic.dataprep --outputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --recommendationTime $recommendationTime$ --matrixMarket true --seenActions $seenActions$",
-                "$base$/bin/als --training=$localTempDir$ratings.mm --D=$d$ --lambda=$lambda$ --minval=1 --maxval=5 --max_iter=$maxIter$ --halt_on_rmse_increase=$haltRMSEInc$ --quiet=1",
-                "$base$/bin/itemrec.graphchi.modelcon --inputDir $localTempDir$ --appid $appid$ --algoid $algoid$ --evalid $evalid$ --modelSet false --unseenOnly $unseenOnly$ --numRecommendations $numRecommendations$"
-            ],
-            "paramorder": [
-                "d",
-                "lambda",
-                "maxIter",
-                "haltRMSEInc",
-                "viewParam",
-                "likeParam",
-                "dislikeParam",
-                "conversionParam",
-                "conflictParam"
-            ],
-            "engineinfoid": "itemrec",
-            "techreq": [
-                "GraphChi"
-            ],
-            "datareq": [
-                "Users, Items, and U2I Actions such as Like, Conversion and Rate."
-            ],
-            "params": {
-                "d": {
-                    "name": "Number of Factorized Features",
-                    "description": "Width of the factorized matrix.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 20
-                },
-                "dMin": {
-                    "name": "Number of Factorized Features (Min)",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 2
-                },
-                "dMax": {
-                    "name": "Number of Factorized Features (Max)",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 30
-                },
-                "lambda": {
-                    "name": "Lambda",
-                    "description": "Regularization parameter to avoid overfitting.",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.065
-                },
-                "lambdaMin": {
-                    "name": "Lambda (Min)",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.01
-                },
-                "lambdaMax": {
-                    "name": "Lambda (Max)",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.1
-                },
-                "maxIter": {
-                    "name": "Maximum Number of Iterations",
-                    "description": "Maximum number of training iterations allowed.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 6
-                },
-                "maxIterMin": {
-                    "name": "Maximum Number of Iterations (Min)",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1
-                },
-                "maxIterMax": {
-                    "name": "Maximum Number of Iterations (Max)",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 20
-                },
-                "haltRMSEInc": {
-                    "name": "Halt on RMSE Increase",
-                    "description": "Stop execution when validation error goes up. Run at least the number of iterations specified in the flag.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0
-                },
-                "haltRMSEIncMin": {
-                    "name": "Halt on RMSE Increase (Min)",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0
-                },
-                "haltRMSEIncMax": {
-                    "name": "Halt on RMSE Increase (Max)",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 20
-                },
-                "viewParam": {
-                    "name": "View Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "3"
-                },
-                "likeParam": {
-                    "name": "Like Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "5"
-                },
-                "dislikeParam": {
-                    "name": "Dislike Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "1"
-                },
-                "conversionParam": {
-                    "name": "Conversion Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "4"
-                },
-                "conflictParam": {
-                    "name": "Override",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "Use the latest action",
-                                "value": "latest"
-                            },
-                            {
-                                "name": "Use the highest preference score one",
-                                "value": "highest"
-                            },
-                            {
-                                "name": "Use the lowest preference score one",
-                                "value": "lowest"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "latest"
-                }
-            },
-            "paramsections": [
-                {
-                    "name": "Parameter Settings",
-                    "sectiontype": "normal",
-                    "subsections": [
-                        {
-                            "name": "Numeric Parameters",
-                            "sectiontype": "tuning",
-                            "params": [
-                                "d",
-                                "lambda",
-                                "maxIter",
-                                "haltRMSEInc"
-                            ]
-                        }
-                    ]
-                },
-                {
-                    "name": "User Actions Representation Settings",
-                    "sectiontype": "normal",
-                    "subsections": [
-                        {
-                            "name": "User Action Scores",
-                            "sectiontype": "normal",
-                            "description": "Define the preference score represented by each user action from 1 to 5. 5 is the most preferred, 1 is the least preferred. 3 is neutral.",
-                            "params": [
-                                "viewParam",
-                                "likeParam",
-                                "dislikeParam",
-                                "conversionParam"
-                            ]
-                        },
-                        {
-                            "name": "Overriding",
-                            "sectiontype": "normal",
-                            "description": "When there are conflicting actions, e.g. a user gives an item a rating 5 but later dislikes it, determine which action will be considered as final preference.",
-                            "params": [
-                                "conflictParam"
-                            ]
-                        }
-                    ]
-                }
-            ]
-        },
-        "pio-itemrec-single-graphchi-als_coord": {
-            "name": "GraphChi's CCD++ Alternating Least Squares Collaborative Filtering with Parallel Coordinate Descent",
-            "description": "Predict user preferences based on matrix factorization.",
-            "batchcommands": [
-                "$base$/bin/itemrec.generic.dataprep --outputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --recommendationTime $recommendationTime$ --matrixMarket true --seenActions $seenActions$",
-                "$base$/bin/als_coord --training=$localTempDir$ratings.mm --D=$d$ --lambda=$lambda$ --minval=1 --maxval=5 --max_iter=$maxIter$ --halt_on_rmse_increase=$haltRMSEInc$ --quiet=1",
-                "$base$/bin/itemrec.graphchi.modelcon --inputDir $localTempDir$ --appid $appid$ --algoid $algoid$ --modelSet $modelset$ --unseenOnly $unseenOnly$ --numRecommendations $numRecommendations$"
-            ],
-            "offlineevalcommands": [
-                "$base$/bin/itemrec.generic.dataprep --outputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --recommendationTime $recommendationTime$ --matrixMarket true --seenActions $seenActions$",
-                "$base$/bin/als_coord --training=$localTempDir$ratings.mm --D=$d$ --lambda=$lambda$ --minval=1 --maxval=5 --max_iter=$maxIter$ --halt_on_rmse_increase=$haltRMSEInc$ --quiet=1",
-                "$base$/bin/itemrec.graphchi.modelcon --inputDir $localTempDir$ --appid $appid$ --algoid $algoid$ --evalid $evalid$ --modelSet false --unseenOnly $unseenOnly$ --numRecommendations $numRecommendations$"
-            ],
-            "paramorder": [
-                "d",
-                "lambda",
-                "maxIter",
-                "haltRMSEInc",
-                "viewParam",
-                "likeParam",
-                "dislikeParam",
-                "conversionParam",
-                "conflictParam"
-            ],
-            "engineinfoid": "itemrec",
-            "techreq": [
-                "GraphChi"
-            ],
-            "datareq": [
-                "Users, Items, and U2I Actions such as Like, Conversion and Rate."
-            ],
-            "params": {
-                "d": {
-                    "name": "Number of Factorized Features",
-                    "description": "Width of the factorized matrix.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 20
-                },
-                "dMin": {
-                    "name": "Number of Factorized Features (Min)",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 2
-                },
-                "dMax": {
-                    "name": "Number of Factorized Features (Max)",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 30
-                },
-                "lambda": {
-                    "name": "Lambda",
-                    "description": "Regularization parameter to avoid overfitting.",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.065
-                },
-                "lambdaMin": {
-                    "name": "Lambda (Min)",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.01
-                },
-                "lambdaMax": {
-                    "name": "Lambda (Max)",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.1
-                },
-                "maxIter": {
-                    "name": "Maximum Number of Iterations",
-                    "description": "Maximum number of training iterations allowed.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 6
-                },
-                "maxIterMin": {
-                    "name": "Maximum Number of Iterations (Min)",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1
-                },
-                "maxIterMax": {
-                    "name": "Maximum Number of Iterations (Max)",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 20
-                },
-                "haltRMSEInc": {
-                    "name": "Halt on RMSE Increase",
-                    "description": "Stop execution when validation error goes up. Run at least the number of iterations specified in the flag.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0
-                },
-                "haltRMSEIncMin": {
-                    "name": "Halt on RMSE Increase (Min)",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0
-                },
-                "haltRMSEIncMax": {
-                    "name": "Halt on RMSE Increase (Max)",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 20
-                },
-                "viewParam": {
-                    "name": "View Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "3"
-                },
-                "likeParam": {
-                    "name": "Like Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "5"
-                },
-                "dislikeParam": {
-                    "name": "Dislike Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "1"
-                },
-                "conversionParam": {
-                    "name": "Conversion Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "4"
-                },
-                "conflictParam": {
-                    "name": "Override",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "Use the latest action",
-                                "value": "latest"
-                            },
-                            {
-                                "name": "Use the highest preference score one",
-                                "value": "highest"
-                            },
-                            {
-                                "name": "Use the lowest preference score one",
-                                "value": "lowest"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "latest"
-                }
-            },
-            "paramsections": [
-                {
-                    "name": "Parameter Settings",
-                    "sectiontype": "normal",
-                    "subsections": [
-                        {
-                            "name": "Numeric Parameters",
-                            "sectiontype": "tuning",
-                            "params": [
-                                "d",
-                                "lambda",
-                                "maxIter",
-                                "haltRMSEInc"
-                            ]
-                        }
-                    ]
-                },
-                {
-                    "name": "User Actions Representation Settings",
-                    "sectiontype": "normal",
-                    "subsections": [
-                        {
-                            "name": "User Action Scores",
-                            "sectiontype": "normal",
-                            "description": "Define the preference score represented by each user action from 1 to 5. 5 is the most preferred, 1 is the least preferred. 3 is neutral.",
-                            "params": [
-                                "viewParam",
-                                "likeParam",
-                                "dislikeParam",
-                                "conversionParam"
-                            ]
-                        },
-                        {
-                            "name": "Overriding",
-                            "sectiontype": "normal",
-                            "description": "When there are conflicting actions, e.g. a user gives an item a rating 5 but later dislikes it, determine which action will be considered as final preference.",
-                            "params": [
-                                "conflictParam"
-                            ]
-                        }
-                    ]
-                }
-            ]
-        },
-        "pio-itemrec-single-graphchi-sgd": {
-            "name": "GraphChi's Stochastic Gradient Descent",
-            "description": "Predict user preferences based on matrix factorization.",
-            "batchcommands": [
-                "$base$/bin/itemrec.generic.dataprep --outputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --recommendationTime $recommendationTime$ --matrixMarket true --seenActions $seenActions$",
-                "$base$/bin/sgd --training=$localTempDir$ratings.mm --D=$d$ --sgd_lambda=$lambda$ --sgd_gamma=$gamma$ --sgd_step_dec=$stepDec$ --minval=1 --maxval=5 --max_iter=$maxIter$ --halt_on_rmse_increase=$haltRMSEInc$ --quiet=1",
-                "$base$/bin/itemrec.graphchi.modelcon --inputDir $localTempDir$ --appid $appid$ --algoid $algoid$ --modelSet $modelset$ --unseenOnly $unseenOnly$ --numRecommendations $numRecommendations$"
-            ],
-            "offlineevalcommands": [
-                "$base$/bin/itemrec.generic.dataprep --outputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --recommendationTime $recommendationTime$ --matrixMarket true --seenActions $seenActions$",
-                "$base$/bin/sgd --training=$localTempDir$ratings.mm --D=$d$ --sgd_lambda=$lambda$ --sgd_gamma=$gamma$ --sgd_step_dec=$stepDec$ --minval=1 --maxval=5 --max_iter=$maxIter$ --halt_on_rmse_increase=$haltRMSEInc$ --quiet=1",
-                "$base$/bin/itemrec.graphchi.modelcon --inputDir $localTempDir$ --appid $appid$ --algoid $algoid$ --evalid $evalid$ --modelSet false --unseenOnly $unseenOnly$ --numRecommendations $numRecommendations$"
-            ],
-            "paramorder": [
-                "d",
-                "lambda",
-                "gamma",
-                "stepDec",
-                "maxIter",
-                "haltRMSEInc",
-                "viewParam",
-                "likeParam",
-                "dislikeParam",
-                "conversionParam",
-                "conflictParam"
-            ],
-            "engineinfoid": "itemrec",
-            "techreq": [
-                "GraphChi"
-            ],
-            "datareq": [
-                "Users, Items, and U2I Actions such as Like, Conversion and Rate."
-            ],
-            "params": {
-                "d": {
-                    "name": "Number of Factorized Features",
-                    "description": "Width of the factorized matrix.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 20
-                },
-                "dMin": {
-                    "name": "Number of Factorized Features (Min)",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 2
-                },
-                "dMax": {
-                    "name": "Number of Factorized Features (Max)",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 30
-                },
-                "lambda": {
-                    "name": "Lambda",
-                    "description": "Regularization parameter to avoid overfitting.",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1E-4
-                },
-                "lambdaMin": {
-                    "name": "Lambda (Min)",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1E-5
-                },
-                "lambdaMax": {
-                    "name": "Lambda (Max)",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1E-3
-                },
-                "gamma": {
-                    "name": "Gamma",
-                    "description": "Gradient step size.",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1E-4
-                },
-                "gammaMin": {
-                    "name": "Gamma (Min)",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1E-5
-                },
-                "gammaMax": {
-                    "name": "Gamma (Max)",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1E-3
-                },
-                "stepDec": {
-                    "name": "Step Decrement",
-                    "description": "Multiplicative step decrement.",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.9
-                },
-                "stepDecMin": {
-                    "name": "Step Decrement (Min)",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.8
-                },
-                "stepDecMax": {
-                    "name": "Step Decrement (Max)",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.99
-                },
-                "maxIter": {
-                    "name": "Maximum Number of Iterations",
-                    "description": "Maximum number of training iterations allowed.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 6
-                },
-                "maxIterMin": {
-                    "name": "Maximum Number of Iterations (Min)",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1
-                },
-                "maxIterMax": {
-                    "name": "Maximum Number of Iterations (Max)",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 20
-                },
-                "haltRMSEInc": {
-                    "name": "Halt on RMSE Increase",
-                    "description": "Stop execution when validation error goes up. Run at least the number of iterations specified in the flag.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0
-                },
-                "haltRMSEIncMin": {
-                    "name": "Halt on RMSE Increase (Min)",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0
-                },
-                "haltRMSEIncMax": {
-                    "name": "Halt on RMSE Increase (Max)",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 20
-                },
-                "viewParam": {
-                    "name": "View Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "3"
-                },
-                "likeParam": {
-                    "name": "Like Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "5"
-                },
-                "dislikeParam": {
-                    "name": "Dislike Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "1"
-                },
-                "conversionParam": {
-                    "name": "Conversion Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "4"
-                },
-                "conflictParam": {
-                    "name": "Override",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "Use the latest action",
-                                "value": "latest"
-                            },
-                            {
-                                "name": "Use the highest preference score one",
-                                "value": "highest"
-                            },
-                            {
-                                "name": "Use the lowest preference score one",
-                                "value": "lowest"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "latest"
-                }
-            },
-            "paramsections": [
-                {
-                    "name": "Parameter Settings",
-                    "sectiontype": "normal",
-                    "subsections": [
-                        {
-                            "name": "Numeric Parameters",
-                            "sectiontype": "tuning",
-                            "params": [
-                                "d",
-                                "lambda",
-                                "gamma",
-                                "stepDec",
-                                "maxIter",
-                                "haltRMSEInc"
-                            ]
-                        }
-                    ]
-                },
-                {
-                    "name": "User Actions Representation Settings",
-                    "sectiontype": "normal",
-                    "subsections": [
-                        {
-                            "name": "User Action Scores",
-                            "sectiontype": "normal",
-                            "description": "Define the preference score represented by each user action from 1 to 5. 5 is the most preferred, 1 is the least preferred. 3 is neutral.",
-                            "params": [
-                                "viewParam",
-                                "likeParam",
-                                "dislikeParam",
-                                "conversionParam"
-                            ]
-                        },
-                        {
-                            "name": "Overriding",
-                            "sectiontype": "normal",
-                            "description": "When there are conflicting actions, e.g. a user gives an item a rating 5 but later dislikes it, determine which action will be considered as final preference.",
-                            "params": [
-                                "conflictParam"
-                            ]
-                        }
-                    ]
-                }
-            ]
-        },
-        "pio-itemrec-single-graphchi-climf": {
-            "name": "GraphChi's CLiMF algorithm",
-            "description": "Predict user preferences based on matrix factorization and optimizing MRR (mean reciprocal rank)",
-            "batchcommands": [
-                "$base$/bin/itemrec.generic.dataprep --outputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --recommendationTime $recommendationTime$ --matrixMarket true --seenActions $seenActions$",
-                "$base$/bin/climf --training=$localTempDir$ratings.mm --D=$d$ --binary_relevance_thresh=$relevanceThresh$ --halt_on_mrr_decrease=$haltMRRDec$ --num_ratings=$numRatings$ --sgd_lambda=$lambda$ --sgd_gamma=$gamma$ --sgd_step_dec=$stepDec$ --minval=1 --maxval=5 --max_iter=$maxIter$ --quiet=1",
-                "$base$/bin/itemrec.graphchi.modelcon --inputDir $localTempDir$ --appid $appid$ --algoid $algoid$ --modelSet $modelset$ --unseenOnly $unseenOnly$ --numRecommendations $numRecommendations$"
-            ],
-            "offlineevalcommands": [
-                "$base$/bin/itemrec.generic.dataprep --outputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --recommendationTime $recommendationTime$ --matrixMarket true --seenActions $seenActions$",
-                "$base$/bin/climf --training=$localTempDir$ratings.mm --D=$d$ --binary_relevance_thresh=$relevanceThresh$ --halt_on_mrr_decrease=$haltMRRDec$ --num_ratings=$numRatings$ --sgd_lambda=$lambda$ --sgd_gamma=$gamma$ --sgd_step_dec=$stepDec$ --minval=1 --maxval=5 --max_iter=$maxIter$ --quiet=1",
-                "$base$/bin/itemrec.graphchi.modelcon --inputDir $localTempDir$ --appid $appid$ --algoid $algoid$ --evalid $evalid$ --modelSet false --unseenOnly $unseenOnly$ --numRecommendations $numRecommendations$"
-            ],
-            "paramorder": [
-                "d",
-                "relevanceThresh",
-                "haltMRRDec",
-                "numRatings",
-                "lambda",
-                "gamma",
-                "stepDec",
-                "maxIter",
-                "viewParam",
-                "likeParam",
-                "dislikeParam",
-                "conversionParam",
-                "conflictParam"
-            ],
-            "engineinfoid": "itemrec",
-            "techreq": [
-                "GraphChi"
-            ],
-            "datareq": [
-                "Users, Items, and U2I Actions such as Like, Conversion and Rate."
-            ],
-            "params": {
-                "d": {
-                    "name": "Number of Factorized Features",
-                    "description": "Width of the factorized matrix.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 20
-                },
-                "dMin": {
-                    "name": "Number of Factorized Features (Min)",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 2
-                },
-                "dMax": {
-                    "name": "Number of Factorized Features (Max)",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 30
-                },
-                "relevanceThresh": {
-                    "name": "Binary Relevant Threshold",
-                    "description": "Consider the item liked/relevant if rating is at least this value.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0
-                },
-                "relevanceThreshMin": {
-                    "name": "Binary Relevant Threshold (Min)",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0
-                },
-                "relevanceThreshMax": {
-                    "name": "Binary Relevant Threshold (Max)",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 3
-                },
-                "haltMRRDec": {
-                    "name": "Halt on MRR Decrease",
-                    "description": "Halt if the training set objective (smoothed MRR) decreases.",
-                    "constraint": {
-                        "paramtype": "boolean"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "True",
-                                "value": "true"
-                            },
-                            {
-                                "name": "False",
-                                "value": "false"
-                            }
-                        ]
-                    },
-                    "defaultvalue": false
-                },
-                "numRatings": {
-                    "name": "Number of Ratings",
-                    "description": "Consider this many top predicted items when computing actual MRR on validation set.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 10000
-                },
-                "numRatingsMin": {
-                    "name": "Number of Ratings (Min)",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 10
-                },
-                "numRatingsMax": {
-                    "name": "Number of Ratings (Max)",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 10000
-                },
-                "lambda": {
-                    "name": "Lambda",
-                    "description": "Regularization parameter to avoid overfitting.",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1E-6
-                },
-                "lambdaMin": {
-                    "name": "Lambda (Min)",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1E-7
-                },
-                "lambdaMax": {
-                    "name": "Lambda (Max)",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1E-5
-                },
-                "gamma": {
-                    "name": "Gamma",
-                    "description": "Gradient step size.",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1E-6
-                },
-                "gammaMin": {
-                    "name": "Gamma (Min)",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1E-7
-                },
-                "gammaMax": {
-                    "name": "Gamma (Max)",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1E-5
-                },
-                "maxIter": {
-                    "name": "Maximum Number of Iterations",
-                    "description": "Maximum number of training iterations allowed.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 6
-                },
-                "maxIterMin": {
-                    "name": "Maximum Number of Iterations (Min)",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1
-                },
-                "maxIterMax": {
-                    "name": "Maximum Number of Iterations (Max)",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 20
-                },
-                "stepDec": {
-                    "name": "Step Decrement",
-                    "description": "Multiplicative step decrement.",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.9
-                },
-                "stepDecMin": {
-                    "name": "Step Decrement (Min)",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.8
-                },
-                "stepDecMax": {
-                    "name": "Step Decrement (Max)",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.99
-                },
-                "viewParam": {
-                    "name": "View Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "3"
-                },
-                "likeParam": {
-                    "name": "Like Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "5"
-                },
-                "dislikeParam": {
-                    "name": "Dislike Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "1"
-                },
-                "conversionParam": {
-                    "name": "Conversion Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "4"
-                },
-                "conflictParam": {
-                    "name": "Override",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "Use the latest action",
-                                "value": "latest"
-                            },
-                            {
-                                "name": "Use the highest preference score one",
-                                "value": "highest"
-                            },
-                            {
-                                "name": "Use the lowest preference score one",
-                                "value": "lowest"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "latest"
-                }
-            },
-            "paramsections": [
-                {
-                    "name": "Parameter Settings",
-                    "sectiontype": "normal",
-                    "subsections": [
-                        {
-                            "name": "Boolean Parameter",
-                            "sectiontype": "normal",
-                            "params": [
-                                "haltMRRDec"
-                            ]
-                        },
-                        {
-                            "name": "Numeric Parameters",
-                            "sectiontype": "tuning",
-                            "params": [
-                                "d",
-                                "relevanceThresh",
-                                "numRatings",
-                                "lambda",
-                                "gamma",
-                                "stepDec",
-                                "maxIter"
-                            ]
-                        }
-                    ]
-                },
-                {
-                    "name": "User Actions Representation Settings",
-                    "sectiontype": "normal",
-                    "subsections": [
-                        {
-                            "name": "User Action Scores",
-                            "sectiontype": "normal",
-                            "description": "Define the preference score represented by each user action from 1 to 5. 5 is the most preferred, 1 is the least preferred. 3 is neutral.",
-                            "params": [
-                                "viewParam",
-                                "likeParam",
-                                "dislikeParam",
-                                "conversionParam"
-                            ]
-                        },
-                        {
-                            "name": "Overriding",
-                            "sectiontype": "normal",
-                            "description": "When there are conflicting actions, e.g. a user gives an item a rating 5 but later dislikes it, determine which action will be considered as final preference.",
-                            "params": [
-                                "conflictParam"
-                            ]
-                        }
-                    ]
-                }
-            ]
-        },
-        "pio-itemrec-distributed-mahout-itembased": {
-            "name": "Mahout's Threshold Item Based Collaborative Filtering",
-            "description": "Predicts user preferences based on previous behaviors of users on similar items.",
-            "batchcommands": [
-                "$base$/bin/quiet.sh $hadoop$ fs -rmr $mahoutTempDir$",
-                "$base$/bin/quiet.sh $hadoop$ fs -rmr $algoDir$",
-                "$base$/bin/quiet.sh rm -rf $localTempDir$",
-                "$hadoop$ jar $base$/lib/$pdioItemrecAlgo$ $hadoopOptions$ io.prediction.algorithms.scalding.mahout.itemrec.DataCopy --hdfs --dbType $appdataDbType$ --dbName $appdataDbName$ --dbHost $appdataDbHost$ --dbPort $appdataDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --recommendationTime $recommendationTime$ --unseenOnly $unseenOnly$ --seenActions $seenActions$",
-                "$hadoop$ jar $base$/lib/$pdioItemrecAlgo$ $hadoopOptions$ io.prediction.algorithms.scalding.mahout.itemrec.DataPreparator --hdfs --dbType $appdataDbType$ --dbName $appdataDbName$ --dbHost $appdataDbHost$ --dbPort $appdataDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --recommendationTime $recommendationTime$ --unseenOnly $unseenOnly$ --seenActions $seenActions$",
-                "$hadoop$ fs -getmerge $dataFilePrefix$recommendItems.csv $localTempDir$recommendItemsM.csv",
-                "$hadoop$ fs -copyFromLocal $localTempDir$recommendItemsM.csv $dataFilePrefix$recommendItemsM.csv",
-                "$hadoop$ jar $mahoutCoreJob$ org.apache.mahout.cf.taste.hadoop.item.RecommenderJob $hadoopOptions$ --input $dataFilePrefix$ratings.csv --itemsFile $dataFilePrefix$recommendItemsM.csv --output $algoFilePrefix$predicted.tsv --tempDir $mahoutTempDir$ --numRecommendations $numRecommendations$ --booleanData $booleanData$ --maxPrefsPerUser $maxPrefsPerUser$ --minPrefsPerUser $minPrefsPerUser$ --maxSimilaritiesPerItem $maxSimilaritiesPerItem$ --maxPrefsInItemSimilarity $maxPrefsInItemSimilarity$ --similarityClassname $similarityClassname$ --threshold $threshold$ --filterFile $dataFilePrefix$seen.csv --includeRatedItem true",
-                "$hadoop$ jar $base$/lib/$pdioItemrecAlgo$ $hadoopOptions$ io.prediction.algorithms.scalding.mahout.itemrec.ModelConstructor --hdfs --dbType $modeldataDbType$ --dbName $modeldataDbName$ --dbHost $modeldataDbHost$ --dbPort $modeldataDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --modelSet $modelset$ --numRecommendations $numRecommendations$"
-            ],
-            "offlineevalcommands": [
-                "$base$/bin/quiet.sh $hadoop$ fs -rmr $mahoutTempDir$",
-                "$base$/bin/quiet.sh $hadoop$ fs -rmr $algoDir$",
-                "$base$/bin/quiet.sh rm -rf $localTempDir$",
-                "$hadoop$ jar $base$/lib/$pdioItemrecAlgo$ $hadoopOptions$ io.prediction.algorithms.scalding.mahout.itemrec.DataCopy --hdfs --dbType $appdataTrainingDbType$ --dbName $appdataTrainingDbName$ --dbHost $appdataTrainingDbHost$ --dbPort $appdataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --recommendationTime $recommendationTime$ --unseenOnly $unseenOnly$ --seenActions $seenActions$",
-                "$hadoop$ jar $base$/lib/$pdioItemrecAlgo$ $hadoopOptions$ io.prediction.algorithms.scalding.mahout.itemrec.DataPreparator --hdfs --dbType $appdataTrainingDbType$ --dbName $appdataTrainingDbName$ --dbHost $appdataTrainingDbHost$ --dbPort $appdataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --recommendationTime $recommendationTime$ --unseenOnly $unseenOnly$ --seenActions $seenActions$",
-                "$hadoop$ fs -getmerge $dataFilePrefix$recommendItems.csv $localTempDir$recommendItemsM.csv",
-                "$hadoop$ fs -copyFromLocal $localTempDir$recommendItemsM.csv $dataFilePrefix$recommendItemsM.csv",
-                "$hadoop$ jar $mahoutCoreJob$ org.apache.mahout.cf.taste.hadoop.item.RecommenderJob $hadoopOptions$ --input $dataFilePrefix$ratings.csv --itemsFile $dataFilePrefix$recommendItemsM.csv --output $algoFilePrefix$predicted.tsv --tempDir $mahoutTempDir$ --numRecommendations $numRecommendations$ --booleanData $booleanData$ --maxPrefsPerUser $maxPrefsPerUser$ --minPrefsPerUser $minPrefsPerUser$ --maxSimilaritiesPerItem $maxSimilaritiesPerItem$ --maxPrefsInItemSimilarity $maxPrefsInItemSimilarity$ --similarityClassname $similarityClassname$ --threshold $threshold$ --filterFile $dataFilePrefix$seen.csv --includeRatedItem true",
-                "$hadoop$ jar $base$/lib/$pdioItemrecAlgo$ $hadoopOptions$ io.prediction.algorithms.scalding.mahout.itemrec.ModelConstructor --hdfs --dbType $modeldataTrainingDbType$ --dbName $modeldataTrainingDbName$ --dbHost $modeldataTrainingDbHost$ --dbPort $modeldataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ --modelSet $modelset$ --numRecommendations $numRecommendations$"
-            ],
-            "paramorder": [
-                "booleanData",
-                "maxPrefsPerUser",
-                "minPrefsPerUser",
-                "maxSimilaritiesPerItem",
-                "maxPrefsInItemSimilarity",
-                "similarityClassname",
-                "threshold",
-                "viewParam",
-                "likeParam",
-                "dislikeParam",
-                "conversionParam",
-                "conflictParam"
-            ],
-            "engineinfoid": "itemrec",
-            "techreq": [
-                "Hadoop"
-            ],
-            "datareq": [
-                "Users, Items, and U2I Actions such as Like, Conversion and Rate."
-            ],
-            "params": {
-                "booleanData": {
-                    "name": "Boolean Data",
-                    "description": "Treat input data as having no preference values.",
-                    "constraint": {
-                        "paramtype": "boolean"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "True",
-                                "value": "true"
-                            },
-                            {
-                                "name": "False",
-                                "value": "false"
-                            }
-                        ]
-                    },
-                    "defaultvalue": false
-                },
-                "maxPrefsPerUser": {
-                    "name": "Max Num of Preferences per User",
-                    "description": "Maximum number of preferences considered per user in final recommendation phase.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 10
-                },
-                "minPrefsPerUser": {
-                    "name": "Min Num of Preferences per User",
-                    "description": "Ignore users with less preferences than this.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1
-                },
-                "maxSimilaritiesPerItem": {
-                    "name": "Max Num of Similarities per Item",
-                    "description": "Maximum number of similarities considered per item.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 100
-                },
-                "maxPrefsInItemSimilarity": {
-                    "name": "Max Num of Preferences per User in Item Similarity",
-                    "description": "Max number of preferences to consider per user in the item similarity computation phase, users with more preferences will be sampled down.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1000
-                },
-                "similarityClassname": {
-                    "name": "Distance Function",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "Co-occurrence",
-                                "value": "SIMILARITY_COOCCURRENCE"
-                            },
-                            {
-                                "name": "Log-Likelihood",
-                                "value": "SIMILARITY_LOGLIKELIHOOD"
-                            },
-                            {
-                                "name": "Tanimoto Coefficient",
-                                "value": "SIMILARITY_TANIMOTO_COEFFICIENT"
-                            },
-                            {
-                                "name": "City Block",
-                                "value": "SIMILARITY_CITY_BLOCK"
-                            },
-                            {
-                                "name": "Cosine Similarity",
-                                "value": "SIMILARITY_COSINE"
-                            },
-                            {
-                                "name": "Pearson Correlation",
-                                "value": "SIMILARITY_PEARSON_CORRELATION"
-                            },
-                            {
-                                "name": "Euclidean Distance",
-                                "value": "SIMILARITY_EUCLIDEAN_DISTANCE"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "SIMILARITY_LOGLIKELIHOOD"
-                },
-                "threshold": {
-                    "name": "Threshold",
-                    "description": "Discard item pairs with a similarity value below this.",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 5e-324
-                },
-                "viewParam": {
-                    "name": "View Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "3"
-                },
-                "likeParam": {
-                    "name": "Like Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "5"
-                },
-                "dislikeParam": {
-                    "name": "Dislike Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "1"
-                },
-                "conversionParam": {
-                    "name": "Conversion Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "4"
-                },
-                "conflictParam": {
-                    "name": "Override",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "Use the latest action",
-                                "value": "latest"
-                            },
-                            {
-                                "name": "Use the highest preference score one",
-                                "value": "highest"
-                            },
-                            {
-                                "name": "Use the lowest preference score one",
-                                "value": "lowest"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "latest"
-                },
-                "thresholdMin": {
-                    "name": "thresholdMin",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 5e-324
-                },
-                "thresholdMax": {
-                    "name": "thresholdMax",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.15
-                },
-                "maxPrefsPerUserMin": {
-                    "name": "maxPrefsPerUserMin",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 10
-                },
-                "maxPrefsPerUserMax": {
-                    "name": "maxPrefsPerUserMax",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 50
-                },
-                "minPrefsPerUserMin": {
-                    "name": "minPrefsPerUserMin",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1
-                },
-                "minPrefsPerUserMax": {
-                    "name": "minPrefsPerUserMax",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 5
-                },
-                "maxSimilaritiesPerItemMin": {
-                    "name": "maxSimilaritiesPerItemMin",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 50
-                },
-                "maxSimilaritiesPerItemMax": {
-                    "name": "maxSimilaritiesPerItemMax",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 150
-                },
-                "maxPrefsInItemSimilarityMin": {
-                    "name": "maxPrefsInItemSimilarityMin",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 500
-                },
-                "maxPrefsInItemSimilarityMax": {
-                    "name": "maxPrefsInItemSimilarityMax",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1500
-                }
-            },
-            "paramsections": [
-                {
-                    "name": "Parameter Settings",
-                    "sectiontype": "normal",
-                    "subsections": [
-                        {
-                            "name": "Item Similarity Measurement",
-                            "sectiontype": "normal",
-                            "params": [
-                                "similarityClassname"
-                            ]
-                        },
-                        {
-                            "name": "Advanced Parameters",
-                            "sectiontype": "normal",
-                            "params": [
-                                "booleanData"
-                            ]
-                        },
-                        {
-                            "name": "Numeric Parameters",
-                            "sectiontype": "tuning",
-                            "params": [
-                                "threshold",
-                                "maxPrefsPerUser",
-                                "minPrefsPerUser",
-                                "maxSimilaritiesPerItem",
-                                "maxPrefsInItemSimilarity"
-                            ]
-                        }
-                    ]
-                },
-                {
-                    "name": "User Actions Representation Settings",
-                    "sectiontype": "normal",
-                    "subsections": [
-                        {
-                            "name": "User Action Scores",
-                            "sectiontype": "normal",
-                            "description": "Define the preference score represented by each user action from 1 to 5. 5 is the most preferred, 1 is the least preferred. 3 is neutral.",
-                            "params": [
-                                "viewParam",
-                                "likeParam",
-                                "dislikeParam",
-                                "conversionParam"
-                            ]
-                        },
-                        {
-                            "name": "Overriding",
-                            "sectiontype": "normal",
-                            "description": "When there are conflicting actions, e.g. a user gives an item a rating 5 but later dislikes it, determine which action will be considered as final preference.",
-                            "params": [
-                                "conflictParam"
-                            ]
-                        }
-                    ]
-                }
-            ]
-        },
-        "pio-itemrec-distributed-mahout-parallelals": {
-            "name": "Mahout's Parallel ALS-WR",
-            "description": "Predicts user preferences based on previous behaviors of users.",
-            "batchcommands": [
-                "$base$/bin/quiet.sh $hadoop$ fs -rmr $mahoutTempDir$",
-                "$base$/bin/quiet.sh $hadoop$ fs -rmr $algoDir$",
-                "$hadoop$ jar $base$/lib/$pdioItemrecAlgo$ $hadoopOptions$ io.prediction.algorithms.scalding.mahout.itemrec.DataCopy --hdfs --dbType $appdataDbType$ --dbName $appdataDbName$ --dbHost $appdataDbHost$ --dbPort $appdataDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --unseenOnly $unseenOnly$ --seenActions $seenActions$",
-                "$hadoop$ jar $base$/lib/$pdioItemrecAlgo$ $hadoopOptions$ io.prediction.algorithms.scalding.mahout.itemrec.DataPreparator --hdfs --dbType $appdataDbType$ --dbName $appdataDbName$ --dbHost $appdataDbHost$ --dbPort $appdataDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --unseenOnly $unseenOnly$ --seenActions $seenActions$",
-                "$hadoop$ jar $mahoutCoreJob$ org.apache.mahout.cf.taste.hadoop.als.ParallelALSFactorizationJob $hadoopOptions$ --input $dataFilePrefix$ratings.csv --output $algoFilePrefix$matrix --tempDir $mahoutTempDir$ --lambda $lambda$ --implicitFeedback $implicitFeedback$ --numFeatures $numFeatures$ --numIterations $numIterations$",
-                "$hadoop$ jar $mahoutCoreJob$ org.apache.mahout.cf.taste.hadoop.als.RecommenderJob $hadoopOptions$ --input $algoFilePrefix$matrix/userRatings --userFeatures $algoFilePrefix$matrix/U --itemFeatures $algoFilePrefix$matrix/M --output $algoFilePrefix$predicted.tsv --tempDir $mahoutTempDir$ --numRecommendations $numRecommendations$ --maxRating 5",
-                "$hadoop$ jar $base$/lib/$pdioItemrecAlgo$ $hadoopOptions$ io.prediction.algorithms.scalding.mahout.itemrec.ParallelALSModelConstructor --hdfs --dbType $modeldataDbType$ --dbName $modeldataDbName$ --dbHost $modeldataDbHost$ --dbPort $modeldataDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --modelSet $modelset$ --unseenOnly $unseenOnly$ --numRecommendations $numRecommendations$ --recommendationTime $recommendationTime$ --implicitFeedback $implicitFeedback$"
-            ],
-            "offlineevalcommands": [
-                "$base$/bin/quiet.sh $hadoop$ fs -rmr $mahoutTempDir$",
-                "$base$/bin/quiet.sh $hadoop$ fs -rmr $algoDir$",
-                "$hadoop$ jar $base$/lib/$pdioItemrecAlgo$ $hadoopOptions$ io.prediction.algorithms.scalding.mahout.itemrec.DataCopy --hdfs --dbType $appdataTrainingDbType$ --dbName $appdataTrainingDbName$ --dbHost $appdataTrainingDbHost$ --dbPort $appdataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --unseenOnly $unseenOnly$ --seenActions $seenActions$",
-                "$hadoop$ jar $base$/lib/$pdioItemrecAlgo$ $hadoopOptions$ io.prediction.algorithms.scalding.mahout.itemrec.DataPreparator --hdfs --dbType $appdataTrainingDbType$ --dbName $appdataTrainingDbName$ --dbHost $appdataTrainingDbHost$ --dbPort $appdataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --unseenOnly $unseenOnly$ --seenActions $seenActions$",
-                "$hadoop$ jar $mahoutCoreJob$ org.apache.mahout.cf.taste.hadoop.als.ParallelALSFactorizationJob $hadoopOptions$ --input $dataFilePrefix$ratings.csv --output $algoFilePrefix$matrix --tempDir $mahoutTempDir$ --lambda $lambda$ --implicitFeedback $implicitFeedback$ --numFeatures $numFeatures$ --numIterations $numIterations$",
-                "$hadoop$ jar $mahoutCoreJob$ org.apache.mahout.cf.taste.hadoop.als.RecommenderJob $hadoopOptions$ --input $algoFilePrefix$matrix/userRatings --userFeatures $algoFilePrefix$matrix/U --itemFeatures $algoFilePrefix$matrix/M --output $algoFilePrefix$predicted.tsv --tempDir $mahoutTempDir$ --numRecommendations $numRecommendations$ --maxRating 5",
-                "$hadoop$ jar $base$/lib/$pdioItemrecAlgo$ $hadoopOptions$ io.prediction.algorithms.scalding.mahout.itemrec.ParallelALSModelConstructor --hdfs --dbType $modeldataTrainingDbType$ --dbName $modeldataTrainingDbName$ --dbHost $modeldataTrainingDbHost$ --dbPort $modeldataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ --modelSet $modelset$ --unseenOnly $unseenOnly$ --numRecommendations $numRecommendations$ --recommendationTime $recommendationTime$ --implicitFeedback $implicitFeedback$"
-            ],
-            "paramorder": [
-                "lambda",
-                "implicitFeedback",
-                "alpha",
-                "numFeatures",
-                "numIterations",
-                "viewParam",
-                "likeParam",
-                "dislikeParam",
-                "conversionParam",
-                "conflictParam"
-            ],
-            "engineinfoid": "itemrec",
-            "techreq": [
-                "Hadoop"
-            ],
-            "datareq": [
-                "Users, Items, and U2I Actions such as Like, Conversion and Rate."
-            ],
-            "params": {
-                "lambda": {
-                    "name": "Lambda",
-                    "description": "Regularization parameter to avoid overfitting.",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.03
-                },
-                "implicitFeedback": {
-                    "name": "Implicit Feedback",
-                    "description": "Whether data consists of implicit data.",
-                    "constraint": {
-                        "paramtype": "boolean"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "True",
-                                "value": "true"
-                            },
-                            {
-                                "name": "False",
-                                "value": "false"
-                            }
-                        ]
-                    },
-                    "defaultvalue": false
-                },
-                "alpha": {
-                    "name": "Alpha",
-                    "description": "Confidence parameter will be ignored if Implicit Feedback is false.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 40
-                },
-                "numFeatures": {
-                    "name": "Number of Factorized Features",
-                    "description": "Dimension of the factorized feature space.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 3
-                },
-                "numIterations": {
-                    "name": "Number of Iterations",
-                    "description": "Number of training iteration.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 5
-                },
-                "viewParam": {
-                    "name": "View Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "3"
-                },
-                "likeParam": {
-                    "name": "Like Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "5"
-                },
-                "dislikeParam": {
-                    "name": "Dislike Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "1"
-                },
-                "conversionParam": {
-                    "name": "Conversion Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "4"
-                },
-                "conflictParam": {
-                    "name": "Override",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "Use the latest action",
-                                "value": "latest"
-                            },
-                            {
-                                "name": "Use the highest preference score one",
-                                "value": "highest"
-                            },
-                            {
-                                "name": "Use the lowest preference score one",
-                                "value": "lowest"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "latest"
-                },
-                "lambdaMin": {
-                    "name": "lambdaMin",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.01
-                },
-                "lambdaMax": {
-                    "name": "lambdaMax",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.1
-                },
-                "alphaMin": {
-                    "name": "alphaMin",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 10
-                },
-                "alphaMax": {
-                    "name": "alphaMax",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 50
-                },
-                "numFeaturesMin": {
-                    "name": "numFeaturesMin",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 2
-                },
-                "numFeaturesMax": {
-                    "name": "numFeaturesMax",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 10
-                },
-                "numIterationsMin": {
-                    "name": "numIterationsMin",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1
-                },
-                "numIterationsMax": {
-                    "name": "numIterationsMax",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 20
-                }
-            },
-            "paramsections": [
-                {
-                    "name": "Parameter Settings",
-                    "sectiontype": "normal",
-                    "params": [
-                        "implicitFeedback"
-                    ],
-                    "subsections": [
-                        {
-                            "name": "Numeric Parameters",
-                            "sectiontype": "tuning",
-                            "params": [
-                                "lambda",
-                                "alpha",
-                                "numFeatures",
-                                "numIterations"
-                            ]
-                        }
-                    ]
-                },
-                {
-                    "name": "User Actions Representation Settings",
-                    "sectiontype": "normal",
-                    "subsections": [
-                        {
-                            "name": "User Action Scores",
-                            "sectiontype": "normal",
-                            "description": "Define the preference score represented by each user action from 1 to 5. 5 is the most preferred, 1 is the least preferred. 3 is neutral.",
-                            "params": [
-                                "viewParam",
-                                "likeParam",
-                                "dislikeParam",
-                                "conversionParam"
-                            ]
-                        },
-                        {
-                            "name": "Overriding",
-                            "sectiontype": "normal",
-                            "description": "When there are conflicting actions, e.g. a user gives an item a rating 5 but later dislikes it, determine which action will be considered as final preference.",
-                            "params": [
-                                "conflictParam"
-                            ]
-                        }
-                    ]
-                }
-            ]
-        },
-        "pio-itemrec-single-mahout-knnitembased": {
-            "name": "Mahout's kNN Item Based Collaborative Filtering (extension to GenericItemBased) (Single Machine)",
-            "description": "Predicts user preferences based on previous behaviors of users on similar items (Single Machine).",
-            "batchcommands": [
-                "$base$/bin/itemrec.generic.dataprep --outputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --recommendationTime $recommendationTime$ --matrixMarket false --seenActions $seenActions$",
-                "$base$/bin/itemrec.mahout.mahoutjob io.prediction.algorithms.mahout.itemrec.knnitembased.KNNItemBasedJob --input $localTempDir$ratings.csv --itemsFile $localTempDir$itemsIndex.tsv --output $localTempDir$predicted.tsv --outputSim $localTempDir$itemSim.csv --appid $appid$ --engineid $engineid$ --algoid $algoid$ --booleanData $booleanData$ --numRecommendations $numRecommendations$ --itemSimilarity $itemSimilarity$ --weighted $weighted$ --nearestN $nearestN$ --threshold $threshold$ --preComputeItemSim $preComputeItemSim$ --similarItemsPerItem $similarItemsPerItem$ --unseenOnly $unseenOnly$ --seenFile $localTempDir$seen.csv --freshness $freshness$ --recommendationTime $recommendationTime$ --freshnessTimeUnit $freshnessTimeUnit$",
-                "$base$/bin/itemrec.mahout.modelcon --inputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --modelSet $modelset$ --numRecommendations $numRecommendations$ --booleanData $booleanData$"
-            ],
-            "offlineevalcommands": [
-                "$base$/bin/itemrec.generic.dataprep --outputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --recommendationTime $recommendationTime$ --matrixMarket false --seenActions $seenActions$",
-                "$base$/bin/itemrec.mahout.mahoutjob io.prediction.algorithms.mahout.itemrec.knnitembased.KNNItemBasedJob --input $localTempDir$ratings.csv --itemsFile $localTempDir$itemsIndex.tsv --output $localTempDir$predicted.tsv --outputSim $localTempDir$itemSim.csv --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ --booleanData $booleanData$ --numRecommendations $numRecommendations$ --itemSimilarity $itemSimilarity$ --weighted $weighted$ --nearestN $nearestN$ --threshold $threshold$ --preComputeItemSim $preComputeItemSim$ --similarItemsPerItem $similarItemsPerItem$ --unseenOnly $unseenOnly$ --seenFile $localTempDir$seen.csv --freshness $freshness$ --recommendationTime $recommendationTime$ --freshnessTimeUnit $freshnessTimeUnit$",
-                "$base$/bin/itemrec.mahout.modelcon --inputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ --modelSet $modelset$ --numRecommendations $numRecommendations$ --booleanData $booleanData$"
-            ],
-            "paramorder": [
-                "booleanData",
-                "itemSimilarity",
-                "weighted",
-                "nearestN",
-                "threshold",
-                "preComputeItemSim",
-                "similarItemsPerItem",
-                "viewParam",
-                "likeParam",
-                "dislikeParam",
-                "conversionParam",
-                "conflictParam"
-            ],
-            "engineinfoid": "itemrec",
-            "techreq": [],
-            "datareq": [
-                "Users, Items, and U2I Actions such as Like, Conversion and Rate."
-            ],
-            "capabilities": ["freshness"],
-            "params": {
-                "booleanData": {
-                    "name": "Boolean Data",
-                    "description": "Treat input data as having no preference values.",
-                    "constraint": {
-                        "paramtype": "boolean"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "True",
-                                "value": "true"
-                            },
-                            {
-                                "name": "False",
-                                "value": "false"
-                            }
-                        ]
-                    },
-                    "defaultvalue": false
-                },
-                "itemSimilarity": {
-                    "name": "Item Similarity",
-                    "description": "Item Similarity Measure.",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "City Block",
-                                "value": "CityBlockSimilarity"
-                            },
-                            {
-                                "name": "Euclidean Distance",
-                                "value": "EuclideanDistanceSimilarity"
-                            },
-                            {
-                                "name": "Log-Likelihood",
-                                "value": "LogLikelihoodSimilarity"
-                            },
-                            {
-                                "name": "Pearson Correlation",
-                                "value": "PearsonCorrelationSimilarity"
-                            },
-                            {
-                                "name": "Tanimoto Coefficient",
-                                "value": "TanimotoCoefficientSimilarity"
-                            },
-                            {
-                                "name": "Uncentered Cosine",
-                                "value": "UncenteredCosineSimilarity"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "LogLikelihoodSimilarity"
-                },
-                "weighted": {
-                    "name": "Weighted",
-                    "description": "The Similarity score is weighted (only applied to Euclidean Distance, Pearson Correlation, Uncentered Cosine item similarity).",
-                    "constraint": {
-                        "paramtype": "boolean"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "True",
-                                "value": "true"
-                            },
-                            {
-                                "name": "False",
-                                "value": "false"
-                            }
-                        ]
-                    },
-                    "defaultvalue": false
-                },
-                "viewParam": {
-                    "name": "View Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "3"
-                },
-                "nearestN": {
-                    "name": "Nearest K",
-                    "description": "K-nearest rated item neighbors.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 10
-                },
-                "threshold": {
-                    "name": "Threshold",
-                    "description": "Similarity threshold.",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 5e-324
-                },
-                "preComputeItemSim": {
-                    "name": "Pre-Compute Item Similarity",
-                    "description": "Pre-compute item similarity for better run time performance (but use more storage space and memory).",
-                    "constraint": {
-                        "paramtype": "boolean"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "True",
-                                "value": "true"
-                            },
-                            {
-                                "name": "False",
-                                "value": "false"
-                            }
-                        ]
-                    },
-                    "defaultvalue": false
-                },
-                "similarItemsPerItem": {
-                    "name": "Number of Similar Items per Items",
-                    "description": "Number of Similar items in pre-computed item similarity. Only applicable when Pre-Compute Item Similarity = true. Should set this cautiously if you have large number of items (>100K). Storage space needed is about number of items * number of similar items * 30Bytes. Also, the pre-computed similarity will be loaded into memory.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 100
-                },
-                "likeParam": {
-                    "name": "Like Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "5"
-                },
-                "dislikeParam": {
-                    "name": "Dislike Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "1"
-                },
-                "conversionParam": {
-                    "name": "Conversion Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "4"
-                },
-                "conflictParam": {
-                    "name": "Override",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "Use the latest action",
-                                "value": "latest"
-                            },
-                            {
-                                "name": "Use the highest preference score one",
-                                "value": "highest"
-                            },
-                            {
-                                "name": "Use the lowest preference score one",
-                                "value": "lowest"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "latest"
-                },
-                "nearestNMin": {
-                    "name": "nearestNMin",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 5
-                },
-                "nearestNMax": {
-                    "name": "nearestNMax",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 15
-                },
-                "thresholdMin": {
-                    "name": "thresholdMin",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 5e-324
-                },
-                "thresholdMax": {
-                    "name": "thresholdMax",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.2
-                }
-            },
-            "paramsections": [
-                {
-                    "name": "Parameter Settings",
-                    "sectiontype": "normal",
-                    "subsections": [
-                        {
-                            "name": "Item Similarity Measurement",
-                            "sectiontype": "normal",
-                            "params": [
-                                "itemSimilarity"
-                            ]
-                        },
-                        {
-                            "name": "Advanced Parameters",
-                            "sectiontype": "normal",
-                            "params": [
-                                "booleanData",
-                                "weighted",
-                                "preComputeItemSim",
-                                "similarItemsPerItem"
-                            ]
-                        },
-                        {
-                            "name": "Numeric Parameters",
-                            "sectiontype": "tuning",
-                            "params": [
-                                "nearestN",
-                                "threshold"
-                            ]
-                        }
-                    ]
-                },
-                {
-                    "name": "User Actions Representation Settings",
-                    "sectiontype": "normal",
-                    "subsections": [
-                        {
-                            "name": "User Action Scores",
-                            "sectiontype": "normal",
-                            "description": "Define the preference score represented by each user action from 1 to 5. 5 is the most preferred, 1 is the least preferred. 3 is neutral.",
-                            "params": [
-                                "viewParam",
-                                "likeParam",
-                                "dislikeParam",
-                                "conversionParam"
-                            ]
-                        },
-                        {
-                            "name": "Overriding",
-                            "sectiontype": "normal",
-                            "description": "When there are conflicting actions, e.g. a user gives an item a rating 5 but later dislikes it, determine which action will be considered as final preference.",
-                            "params": [
-                                "conflictParam"
-                            ]
-                        }
-                    ]
-                }
-            ]
-        },
-        "pio-itemrec-single-mahout-knnuserbased": {
-            "name": "Mahout's kNN User Based Collaborative Filtering (Single Machine)",
-            "description": "Predicts user preferences based on previous behaviors of users who are the k-nearest neighbors (Single Machine).",
-            "batchcommands": [
-                "$base$/bin/itemrec.generic.dataprep --outputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --recommendationTime $recommendationTime$ --matrixMarket false --seenActions $seenActions$",
-                "$base$/bin/itemrec.mahout.mahoutjob io.prediction.algorithms.mahout.itemrec.knnuserbased.KNNUserBasedJob --input $localTempDir$ratings.csv --itemsFile $localTempDir$itemsIndex.tsv --output $localTempDir$predicted.tsv --appid $appid$ --engineid $engineid$ --algoid $algoid$ --booleanData $booleanData$ --numRecommendations $numRecommendations$ --unseenOnly $unseenOnly$ --seenFile $localTempDir$seen.csv --nearestN $nearestN$ --userSimilarity $userSimilarity$ --weighted $weighted$ --minSimilarity $minSimilarity$ --samplingRate $samplingRate$ --freshness $freshness$ --recommendationTime $recommendationTime$ --freshnessTimeUnit $freshnessTimeUnit$",
-                "$base$/bin/itemrec.mahout.modelcon --inputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --modelSet $modelset$ --numRecommendations $numRecommendations$ --booleanData $booleanData$"
-            ],
-            "offlineevalcommands": [
-                "$base$/bin/itemrec.generic.dataprep --outputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --recommendationTime $recommendationTime$ --matrixMarket false --seenActions $seenActions$",
-                "$base$/bin/itemrec.mahout.mahoutjob io.prediction.algorithms.mahout.itemrec.knnuserbased.KNNUserBasedJob --input $localTempDir$ratings.csv --itemsFile $localTempDir$itemsIndex.tsv --output $localTempDir$predicted.tsv --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ --booleanData $booleanData$ --numRecommendations $numRecommendations$ --unseenOnly $unseenOnly$ --seenFile $localTempDir$seen.csv --nearestN $nearestN$ --userSimilarity $userSimilarity$ --weighted $weighted$ --minSimilarity $minSimilarity$ --samplingRate $samplingRate$ --freshness $freshness$ --recommendationTime $recommendationTime$ --freshnessTimeUnit $freshnessTimeUnit$",
-                "$base$/bin/itemrec.mahout.modelcon --inputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ --modelSet $modelset$ --numRecommendations $numRecommendations$ --booleanData $booleanData$"
-            ],
-            "paramorder": [
-                "booleanData",
-                "nearestN",
-                "userSimilarity",
-                "weighted",
-                "minSimilarity",
-                "samplingRate",
-                "viewParam",
-                "likeParam",
-                "dislikeParam",
-                "conversionParam",
-                "conflictParam"
-            ],
-            "engineinfoid": "itemrec",
-            "techreq": [],
-            "datareq": [
-                "Users, Items, and U2I Actions such as Like, Conversion and Rate."
-            ],
-            "capabilities": ["freshness"],
-            "params": {
-                "booleanData": {
-                    "name": "Boolean Data",
-                    "description": "Treat input data as having no preference values.",
-                    "constraint": {
-                        "paramtype": "boolean"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "True",
-                                "value": "true"
-                            },
-                            {
-                                "name": "False",
-                                "value": "false"
-                            }
-                        ]
-                    },
-                    "defaultvalue": false
-                },
-                "nearestN": {
-                    "name": "Nearest K",
-                    "description": "K-nearest neighbors to a given user.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 10
-                },
-                "userSimilarity": {
-                    "name": "User Similarity",
-                    "description": "User Similarity Measure.",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "City Block",
-                                "value": "CityBlockSimilarity"
-                            },
-                            {
-                                "name": "Euclidean Distance",
-                                "value": "EuclideanDistanceSimilarity"
-                            },
-                            {
-                                "name": "Log-Likelihood",
-                                "value": "LogLikelihoodSimilarity"
-                            },
-                            {
-                                "name": "Pearson Correlation",
-                                "value": "PearsonCorrelationSimilarity"
-                            },
-                            {
-                                "name": "Spearman Correlation",
-                                "value": "SpearmanCorrelationSimilarity"
-                            },
-                            {
-                                "name": "Tanimoto Coefficient",
-                                "value": "TanimotoCoefficientSimilarity"
-                            },
-                            {
-                                "name": "Uncentered Cosine",
-                                "value": "UncenteredCosineSimilarity"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "PearsonCorrelationSimilarity"
-                },
-                "weighted": {
-                    "name": "Weighted",
-                    "description": "The Similarity score is weighted (only applied to Euclidean Distance, Pearson Correlation, Uncentered Cosine user similarity).",
-                    "constraint": {
-                        "paramtype": "boolean"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "True",
-                                "value": "true"
-                            },
-                            {
-                                "name": "False",
-                                "value": "false"
-                            }
-                        ]
-                    },
-                    "defaultvalue": false
-                },
-                "minSimilarity": {
-                    "name": "Minimal Similarity",
-                    "description": "Minimal similarity required for neighbors.",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 5e-324
-                },
-                "samplingRate": {
-                    "name": "Sampling Rate",
-                    "description": "Must be greater > 0 and <= 1. Percentage of users to consider when building neighborhood. Decrease to trade quality for performance.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1
-                },
-                "viewParam": {
-                    "name": "View Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "3"
-                },
-                "likeParam": {
-                    "name": "Like Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "5"
-                },
-                "dislikeParam": {
-                    "name": "Dislike Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "1"
-                },
-                "conversionParam": {
-                    "name": "Conversion Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "4"
-                },
-                "conflictParam": {
-                    "name": "Override",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "Use the latest action",
-                                "value": "latest"
-                            },
-                            {
-                                "name": "Use the highest preference score one",
-                                "value": "highest"
-                            },
-                            {
-                                "name": "Use the lowest preference score one",
-                                "value": "lowest"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "latest"
-                },
-                "nearestNMin": {
-                    "name": "nearestNMin",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 5
-                },
-                "nearestNMax": {
-                    "name": "nearestNMax",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 15
-                },
-                "minSimilarityMin": {
-                    "name": "minSimilarityMin",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 5e-324
-                },
-                "minSimilarityMax": {
-                    "name": "minSimilarityMax",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.2
-                },
-                "samplingRateMin": {
-                    "name": "samplingRateMin",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.5
-                },
-                "samplingRateMax": {
-                    "name": "samplingRateMax",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1
-                }
-            },
-            "paramsections": [
-                {
-                    "name": "Parameter Settings",
-                    "sectiontype": "normal",
-                    "subsections": [
-                        {
-                            "name": "User Similarity Measurement",
-                            "sectiontype": "normal",
-                            "params": [
-                                "userSimilarity"
-                            ]
-                        },
-                        {
-                            "name": "Advanced Parameters",
-                            "sectiontype": "normal",
-                            "params": [
-                                "booleanData",
-                                "weighted"
-                            ]
-                        },
-                        {
-                            "name": "Numeric Parameters",
-                            "sectiontype": "tuning",
-                            "params": [
-                                "nearestN",
-                                "minSimilarity",
-                                "samplingRate"
-                            ]
-                        }
-                    ]
-                },
-                {
-                    "name": "User Actions Representation Settings",
-                    "sectiontype": "normal",
-                    "subsections": [
-                        {
-                            "name": "User Action Scores",
-                            "sectiontype": "normal",
-                            "description": "Define the preference score represented by each user action from 1 to 5. 5 is the most preferred, 1 is the least preferred. 3 is neutral.",
-                            "params": [
-                                "viewParam",
-                                "likeParam",
-                                "dislikeParam",
-                                "conversionParam"
-                            ]
-                        },
-                        {
-                            "name": "Overriding",
-                            "sectiontype": "normal",
-                            "description": "When there are conflicting actions, e.g. a user gives an item a rating 5 but later dislikes it, determine which action will be considered as final preference.",
-                            "params": [
-                                "conflictParam"
-                            ]
-                        }
-                    ]
-                }
-            ]
-        },
-        "pio-itemrec-single-mahout-thresholduserbased": {
-            "name": "Mahout's Threshold User Based Collaborative Filtering (Single Machine)",
-            "description": "Predicts user preferences based on previous behaviors of users whose similarity meets or exceeds a certain threshold (Single Machine).",
-            "batchcommands": [
-                "$base$/bin/itemrec.generic.dataprep --outputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --recommendationTime $recommendationTime$ --matrixMarket false --seenActions $seenActions$",
-                "$base$/bin/itemrec.mahout.mahoutjob io.prediction.algorithms.mahout.itemrec.thresholduserbased.ThresholdUserBasedJob --input $localTempDir$ratings.csv --itemsFile $localTempDir$itemsIndex.tsv --output $localTempDir$predicted.tsv --appid $appid$ --engineid $engineid$ --algoid $algoid$ --booleanData $booleanData$ --numRecommendations $numRecommendations$ --unseenOnly $unseenOnly$ --seenFile $localTempDir$seen.csv --threshold $threshold$ --userSimilarity $userSimilarity$ --weighted $weighted$ --samplingRate $samplingRate$ --freshness $freshness$ --recommendationTime $recommendationTime$ --freshnessTimeUnit $freshnessTimeUnit$",
-                "$base$/bin/itemrec.mahout.modelcon --inputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --modelSet $modelset$ --numRecommendations $numRecommendations$ --booleanData $booleanData$"
-            ],
-            "offlineevalcommands": [
-                "$base$/bin/itemrec.generic.dataprep --outputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --recommendationTime $recommendationTime$ --matrixMarket false --seenActions $seenActions$",
-                "$base$/bin/itemrec.mahout.mahoutjob io.prediction.algorithms.mahout.itemrec.thresholduserbased.ThresholdUserBasedJob --input $localTempDir$ratings.csv --itemsFile $localTempDir$itemsIndex.tsv --output $localTempDir$predicted.tsv --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ --booleanData $booleanData$ --numRecommendations $numRecommendations$ --unseenOnly $unseenOnly$ --seenFile $localTempDir$seen.csv --threshold $threshold$ --userSimilarity $userSimilarity$ --weighted $weighted$ --samplingRate $samplingRate$ --freshness $freshness$ --recommendationTime $recommendationTime$ --freshnessTimeUnit $freshnessTimeUnit$",
-                "$base$/bin/itemrec.mahout.modelcon --inputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ --modelSet $modelset$ --numRecommendations $numRecommendations$ --booleanData $booleanData$"
-            ],
-            "paramorder": [
-                "booleanData",
-                "threshold",
-                "userSimilarity",
-                "weighted",
-                "samplingRate",
-                "viewParam",
-                "likeParam",
-                "dislikeParam",
-                "conversionParam",
-                "conflictParam"
-            ],
-            "engineinfoid": "itemrec",
-            "techreq": [],
-            "datareq": [
-                "Users, Items, and U2I Actions such as Like, Conversion and Rate."
-            ],
-            "capabilities": ["freshness"],
-            "params": {
-                "booleanData": {
-                    "name": "Boolean Data",
-                    "description": "Treat input data as having no preference values.",
-                    "constraint": {
-                        "paramtype": "boolean"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "True",
-                                "value": "true"
-                            },
-                            {
-                                "name": "False",
-                                "value": "false"
-                            }
-                        ]
-                    },
-                    "defaultvalue": false
-                },
-                "threshold": {
-                    "name": "Threshold",
-                    "description": "Similarity threshold.",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 5e-324
-                },
-                "userSimilarity": {
-                    "name": "User Similarity",
-                    "description": "User Similarity Measure.",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "City Block",
-                                "value": "CityBlockSimilarity"
-                            },
-                            {
-                                "name": "Euclidean Distance",
-                                "value": "EuclideanDistanceSimilarity"
-                            },
-                            {
-                                "name": "Log-Likelihood",
-                                "value": "LogLikelihoodSimilarity"
-                            },
-                            {
-                                "name": "Pearson Correlation",
-                                "value": "PearsonCorrelationSimilarity"
-                            },
-                            {
-                                "name": "Spearman Correlation",
-                                "value": "SpearmanCorrelationSimilarity"
-                            },
-                            {
-                                "name": "Tanimoto Coefficient",
-                                "value": "TanimotoCoefficientSimilarity"
-                            },
-                            {
-                                "name": "Uncentered Cosine",
-                                "value": "UncenteredCosineSimilarity"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "PearsonCorrelationSimilarity"
-                },
-                "weighted": {
-                    "name": "Weighted",
-                    "description": "The Similarity score is weighted (only applied to Euclidean Distance, Pearson Correlation, Uncentered Cosine user similarity).",
-                    "constraint": {
-                        "paramtype": "boolean"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "True",
-                                "value": "true"
-                            },
-                            {
-                                "name": "False",
-                                "value": "false"
-                            }
-                        ]
-                    },
-                    "defaultvalue": false
-                },
-                "samplingRate": {
-                    "name": "Sampling Rate",
-                    "description": "Must be greater > 0 and <= 1. Percentage of users to consider when building neighborhood. Decrease to trade quality for performance.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1
-                },
-                "viewParam": {
-                    "name": "View Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "3"
-                },
-                "likeParam": {
-                    "name": "Like Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "5"
-                },
-                "dislikeParam": {
-                    "name": "Dislike Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "1"
-                },
-                "conversionParam": {
-                    "name": "Conversion Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "4"
-                },
-                "conflictParam": {
-                    "name": "Override",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "Use the latest action",
-                                "value": "latest"
-                            },
-                            {
-                                "name": "Use the highest preference score one",
-                                "value": "highest"
-                            },
-                            {
-                                "name": "Use the lowest preference score one",
-                                "value": "lowest"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "latest"
-                },
-                "thresholdMin": {
-                    "name": "thresholdMin",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 5e-324
-                },
-                "thresholdMax": {
-                    "name": "thresholdMax",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.2
-                },
-                "samplingRateMin": {
-                    "name": "samplingRateMin",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.5
-                },
-                "samplingRateMax": {
-                    "name": "samplingRateMax",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1
-                }
-            },
-            "paramsections": [
-                {
-                    "name": "Parameter Settings",
-                    "sectiontype": "normal",
-                    "subsections": [
-                        {
-                            "name": "User Similarity Measurement",
-                            "sectiontype": "normal",
-                            "params": [
-                                "userSimilarity"
-                            ]
-                        },
-                        {
-                            "name": "Advanced Parameters",
-                            "sectiontype": "normal",
-                            "params": [
-                                "booleanData",
-                                "weighted"
-                            ]
-                        },
-                        {
-                            "name": "Numeric Parameters",
-                            "sectiontype": "tuning",
-                            "params": [
-                                "threshold",
-                                "samplingRate"
-                            ]
-                        }
-                    ]
-                },
-                {
-                    "name": "User Actions Representation Settings",
-                    "sectiontype": "normal",
-                    "subsections": [
-                        {
-                            "name": "User Action Scores",
-                            "sectiontype": "normal",
-                            "description": "Define the preference score represented by each user action from 1 to 5. 5 is the most preferred, 1 is the least preferred. 3 is neutral.",
-                            "params": [
-                                "viewParam",
-                                "likeParam",
-                                "dislikeParam",
-                                "conversionParam"
-                            ]
-                        },
-                        {
-                            "name": "Overriding",
-                            "sectiontype": "normal",
-                            "description": "When there are conflicting actions, e.g. a user gives an item a rating 5 but later dislikes it, determine which action will be considered as final preference.",
-                            "params": [
-                                "conflictParam"
-                            ]
-                        }
-                    ]
-                }
-            ]
-        },
-        "pio-itemrec-single-mahout-alswr": {
-            "name": "Mahout's ALS-WR (Single Machine)",
-            "description": "Predict user preferences using matrix factorization (Single Machine).",
-            "batchcommands": [
-                "$base$/bin/itemrec.generic.dataprep --outputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --recommendationTime $recommendationTime$ --matrixMarket false --seenActions $seenActions$",
-                "$base$/bin/itemrec.mahout.mahoutjob io.prediction.algorithms.mahout.itemrec.alswr.ALSWRJob --input $localTempDir$ratings.csv --itemsFile $localTempDir$itemsIndex.tsv --output $localTempDir$predicted.tsv --appid $appid$ --engineid $engineid$ --algoid $algoid$ --numRecommendations $numRecommendations$ --unseenOnly $unseenOnly$ --seenFile $localTempDir$seen.csv --numFeatures $numFeatures$ --lambda $lambda$ --numIterations $numIterations$ --freshness $freshness$ --recommendationTime $recommendationTime$ --freshnessTimeUnit $freshnessTimeUnit$",
-                "$base$/bin/itemrec.mahout.modelcon --inputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --modelSet $modelset$ --numRecommendations $numRecommendations$"
-            ],
-            "offlineevalcommands": [
-                "$base$/bin/itemrec.generic.dataprep --outputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --recommendationTime $recommendationTime$ --matrixMarket false --seenActions $seenActions$",
-                "$base$/bin/itemrec.mahout.mahoutjob io.prediction.algorithms.mahout.itemrec.alswr.ALSWRJob --input $localTempDir$ratings.csv --itemsFile $localTempDir$itemsIndex.tsv --output $localTempDir$predicted.tsv --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ --numRecommendations $numRecommendations$ --unseenOnly $unseenOnly$ --seenFile $localTempDir$seen.csv --numFeatures $numFeatures$ --lambda $lambda$ --numIterations $numIterations$ --freshness $freshness$ --recommendationTime $recommendationTime$ --freshnessTimeUnit $freshnessTimeUnit$",
-                "$base$/bin/itemrec.mahout.modelcon --inputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ --modelSet $modelset$ --numRecommendations $numRecommendations$"
-            ],
-            "paramorder": [
-                "numFeatures",
-                "lambda",
-                "numIterations",
-                "viewParam",
-                "likeParam",
-                "dislikeParam",
-                "conversionParam",
-                "conflictParam"
-            ],
-            "engineinfoid": "itemrec",
-            "techreq": [],
-            "datareq": [
-                "Users, Items, and U2I Actions such as Like, Conversion and Rate."
-            ],
-            "capabilities": ["freshness"],
-            "params": {
-                "numFeatures": {
-                    "name": "Number of Factorized Features",
-                    "description": "Dimension of the factorized feature space.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 3
-                },
-                "lambda": {
-                    "name": "Lambda",
-                    "description": "Regularization param to avoid overfitting.",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.03
-                },
-                "numIterations": {
-                    "name": "Number of Iterations",
-                    "description": "Number of training iteration.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 3
-                },
-                "viewParam": {
-                    "name": "View Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "3"
-                },
-                "likeParam": {
-                    "name": "Like Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "5"
-                },
-                "dislikeParam": {
-                    "name": "Dislike Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "1"
-                },
-                "conversionParam": {
-                    "name": "Conversion Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "4"
-                },
-                "conflictParam": {
-                    "name": "Override",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "Use the latest action",
-                                "value": "latest"
-                            },
-                            {
-                                "name": "Use the highest preference score one",
-                                "value": "highest"
-                            },
-                            {
-                                "name": "Use the lowest preference score one",
-                                "value": "lowest"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "latest"
-                },
-                "numFeaturesMin": {
-                    "name": "numFeaturesMin",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 2
-                },
-                "numFeaturesMax": {
-                    "name": "numFeaturesMax",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 10
-                },
-                "lambdaMin": {
-                    "name": "lambdaMin",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.01
-                },
-                "lambdaMax": {
-                    "name": "lambdaMax",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.1
-                },
-                "numIterationsMin": {
-                    "name": "numIterationsMin",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1
-                },
-                "numIterationsMax": {
-                    "name": "numIterationsMax",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 20
-                }
-            },
-            "paramsections": [
-                {
-                    "name": "Parameter Settings",
-                    "sectiontype": "normal",
-                    "subsections": [
-                        {
-                            "name": "",
-                            "sectiontype": "tuning",
-                            "params": [
-                                "numFeatures",
-                                "lambda",
-                                "numIterations"
-                            ]
-                        }
-                    ]
-                },
-                {
-                    "name": "User Actions Representation Settings",
-                    "sectiontype": "normal",
-                    "subsections": [
-                        {
-                            "name": "User Action Scores",
-                            "sectiontype": "normal",
-                            "description": "Define the preference score represented by each user action from 1 to 5. 5 is the most preferred, 1 is the least preferred. 3 is neutral.",
-                            "params": [
-                                "viewParam",
-                                "likeParam",
-                                "dislikeParam",
-                                "conversionParam"
-                            ]
-                        },
-                        {
-                            "name": "Overriding",
-                            "sectiontype": "normal",
-                            "description": "When there are conflicting actions, e.g. a user gives an item a rating 5 but later dislikes it, determine which action will be considered as final preference.",
-                            "params": [
-                                "conflictParam"
-                            ]
-                        }
-                    ]
-                }
-            ]
-        },
-        "pio-itemrec-single-mahout-svdsgd": {
-            "name": "Mahout's SVD-RatingSGD Recommender (Single Machine)",
-            "description": "Predict user preferences using matrix factorization (Single Machine).",
-            "batchcommands": [
-                "$base$/bin/itemrec.generic.dataprep --outputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --recommendationTime $recommendationTime$ --matrixMarket false --seenActions $seenActions$",
-                "$base$/bin/itemrec.mahout.mahoutjob io.prediction.algorithms.mahout.itemrec.svdsgd.SVDSGDJob --input $localTempDir$ratings.csv --itemsFile $localTempDir$itemsIndex.tsv --output $localTempDir$predicted.tsv --appid $appid$ --engineid $engineid$ --algoid $algoid$ --numRecommendations $numRecommendations$ --unseenOnly $unseenOnly$ --seenFile $localTempDir$seen.csv --numFeatures $numFeatures$ --learningRate $learningRate$ --preventOverfitting $preventOverfitting$ --randomNoise $randomNoise$ --numIterations $numIterations$ --learningRateDecay $learningRateDecay$ --freshness $freshness$ --recommendationTime $recommendationTime$ --freshnessTimeUnit $freshnessTimeUnit$",
-                "$base$/bin/itemrec.mahout.modelcon --inputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --modelSet $modelset$ --numRecommendations $numRecommendations$"
-            ],
-            "offlineevalcommands": [
-                "$base$/bin/itemrec.generic.dataprep --outputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --recommendationTime $recommendationTime$ --matrixMarket false --seenActions $seenActions$",
-                "$base$/bin/itemrec.mahout.mahoutjob io.prediction.algorithms.mahout.itemrec.svdsgd.SVDSGDJob --input $localTempDir$ratings.csv --itemsFile $localTempDir$itemsIndex.tsv --output $localTempDir$predicted.tsv --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ --numRecommendations $numRecommendations$ --unseenOnly $unseenOnly$ --seenFile $localTempDir$seen.csv --numFeatures $numFeatures$ --learningRate $learningRate$ --preventOverfitting $preventOverfitting$ --randomNoise $randomNoise$ --numIterations $numIterations$ --learningRateDecay $learningRateDecay$ --freshness $freshness$ --recommendationTime $recommendationTime$ --freshnessTimeUnit $freshnessTimeUnit$",
-                "$base$/bin/itemrec.mahout.modelcon --inputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ --modelSet $modelset$ --numRecommendations $numRecommendations$"
-            ],
-            "paramorder": [
-                "numFeatures",
-                "learningRate",
-                "preventOverfitting",
-                "randomNoise",
-                "numIterations",
-                "learningRateDecay",
-                "viewParam",
-                "likeParam",
-                "dislikeParam",
-                "conversionParam",
-                "conflictParam"
-            ],
-            "engineinfoid": "itemrec",
-            "techreq": [],
-            "datareq": [
-                "Users, Items, and U2I Actions such as Like, Conversion and Rate."
-            ],
-            "capabilities": ["freshness"],
-            "params": {
-                "numFeatures": {
-                    "name": "Number of Factorized Features",
-                    "description": "Dimension of the factorized feature space.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 3
-                },
-                "learningRate": {
-                    "name": "Learning Rate",
-                    "description": "Learning rate (step size).",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.01
-                },
-                "preventOverfitting": {
-                    "name": "Prevent Overfitting",
-                    "description": "Parameter used to prevent overfitting.",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.1
-                },
-                "randomNoise": {
-                    "name": "Random Noise",
-                    "description": "Standard deviation for random initialization of feature.",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.01
-                },
-                "numIterations": {
-                    "name": "Number of Iterations",
-                    "description": "Number of training iterations.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 3
-                },
-                "learningRateDecay": {
-                    "name": "Learning Rate Decay",
-                    "description": "Multiplicative decay factor for Learning Rate.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1
-                },
-                "viewParam": {
-                    "name": "View Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "3"
-                },
-                "likeParam": {
-                    "name": "Like Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "5"
-                },
-                "dislikeParam": {
-                    "name": "Dislike Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "1"
-                },
-                "conversionParam": {
-                    "name": "Conversion Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "4"
-                },
-                "conflictParam": {
-                    "name": "Override",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "Use the latest action",
-                                "value": "latest"
-                            },
-                            {
-                                "name": "Use the highest preference score one",
-                                "value": "highest"
-                            },
-                            {
-                                "name": "Use the lowest preference score one",
-                                "value": "lowest"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "latest"
-                },
-                "numFeaturesMin": {
-                    "name": "numFeaturesMin",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 2
-                },
-                "numFeaturesMax": {
-                    "name": "numFeaturesMax",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 10
-                },
-                "learningRateMin": {
-                    "name": "learningRateMin",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.01
-                },
-                "learningRateMax": {
-                    "name": "learningRateMax",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.05
-                },
-                "preventOverfittingMin": {
-                    "name": "preventOverfittingMin",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.1
-                },
-                "preventOverfittingMax": {
-                    "name": "preventOverfittingMax",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.5
-                },
-                "randomNoiseMin": {
-                    "name": "randomNoiseMin",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.01
-                },
-                "randomNoiseMax": {
-                    "name": "randomNoiseMax",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.05
-                },
-                "numIterationsMin": {
-                    "name": "numIterationsMin",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1
-                },
-                "numIterationsMax": {
-                    "name": "numIterationsMax",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 10
-                },
-                "learningRateDecayMin": {
-                    "name": "learningRateDecayMin",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1
-                },
-                "learningRateDecayMax": {
-                    "name": "learningRateDecayMax",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1
-                }
-            },
-            "paramsections": [
-                {
-                    "name": "Parameter Settings",
-                    "sectiontype": "normal",
-                    "subsections": [
-                        {
-                            "name": "Numeric Parameters",
-                            "sectiontype": "tuning",
-                            "params": [
-                                "numFeatures",
-                                "learningRate",
-                                "preventOverfitting",
-                                "randomNoise",
-                                "numIterations",
-                                "learningRateDecay"
-                            ]
-                        }
-                    ]
-                },
-                {
-                    "name": "User Actions Representation Settings",
-                    "sectiontype": "normal",
-                    "subsections": [
-                        {
-                            "name": "User Action Scores",
-                            "sectiontype": "normal",
-                            "description": "Define the preference score represented by each user action from 1 to 5. 5 is the most preferred, 1 is the least preferred. 3 is neutral.",
-                            "params": [
-                                "viewParam",
-                                "likeParam",
-                                "dislikeParam",
-                                "conversionParam"
-                            ]
-                        },
-                        {
-                            "name": "Overriding",
-                            "sectiontype": "normal",
-                            "description": "When there are conflicting actions, e.g. a user gives an item a rating 5 but later dislikes it, determine which action will be considered as final preference.",
-                            "params": [
-                                "conflictParam"
-                            ]
-                        }
-                    ]
-                }
-            ]
-        },
-        "pio-itemrec-single-mahout-svdplusplus": {
-            "name": "Mahout's SVDPlusPlus Recommender (Single Machine)",
-            "description": "Predict user preferences using matrix factorization (Single Machine).",
-            "batchcommands": [
-                "$base$/bin/itemrec.generic.dataprep --outputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --recommendationTime $recommendationTime$ --matrixMarket false --seenActions $seenActions$",
-                "$base$/bin/itemrec.mahout.mahoutjob io.prediction.algorithms.mahout.itemrec.svdplusplus.SVDPlusPlusJob --input $localTempDir$ratings.csv --itemsFile $localTempDir$itemsIndex.tsv --output $localTempDir$predicted.tsv --appid $appid$ --engineid $engineid$ --algoid $algoid$ --numRecommendations $numRecommendations$ --unseenOnly $unseenOnly$ --seenFile $localTempDir$seen.csv --numFeatures $numFeatures$ --learningRate $learningRate$ --preventOverfitting $preventOverfitting$ --randomNoise $randomNoise$ --numIterations $numIterations$ --learningRateDecay $learningRateDecay$ --freshness $freshness$ --recommendationTime $recommendationTime$ --freshnessTimeUnit $freshnessTimeUnit$",
-                "$base$/bin/itemrec.mahout.modelcon --inputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --modelSet $modelset$ --numRecommendations $numRecommendations$"
-            ],
-            "offlineevalcommands": [
-                "$base$/bin/itemrec.generic.dataprep --outputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --recommendationTime $recommendationTime$ --matrixMarket false --seenActions $seenActions$",
-                "$base$/bin/itemrec.mahout.mahoutjob io.prediction.algorithms.mahout.itemrec.svdplusplus.SVDPlusPlusJob --input $localTempDir$ratings.csv --itemsFile $localTempDir$itemsIndex.tsv --output $localTempDir$predicted.tsv --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ --numRecommendations $numRecommendations$ --unseenOnly $unseenOnly$ --seenFile $localTempDir$seen.csv --numFeatures $numFeatures$ --learningRate $learningRate$ --preventOverfitting $preventOverfitting$ --randomNoise $randomNoise$ --numIterations $numIterations$ --learningRateDecay $learningRateDecay$ --freshness $freshness$ --recommendationTime $recommendationTime$ --freshnessTimeUnit $freshnessTimeUnit$",
-                "$base$/bin/itemrec.mahout.modelcon --inputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ --modelSet $modelset$ --numRecommendations $numRecommendations$"
-            ],
-            "paramorder": [
-                "numFeatures",
-                "learningRate",
-                "preventOverfitting",
-                "randomNoise",
-                "numIterations",
-                "learningRateDecay",
-                "viewParam",
-                "likeParam",
-                "dislikeParam",
-                "conversionParam",
-                "conflictParam"
-            ],
-            "engineinfoid": "itemrec",
-            "techreq": [],
-            "datareq": [
-                "Users, Items, and U2I Actions such as Like, Conversion and Rate."
-            ],
-            "capabilities": ["freshness"],
-            "params": {
-                "numFeatures": {
-                    "name": "Number of Factorized Features",
-                    "description": "Dimension of the factorized feature space.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 3
-                },
-                "learningRate": {
-                    "name": "Learning Rate",
-                    "description": "Learning rate (step size).",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.01
-                },
-                "preventOverfitting": {
-                    "name": "Prevent Overfitting",
-                    "description": "Parameter used to prevent overfitting.",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.1
-                },
-                "randomNoise": {
-                    "name": "Random Noise",
-                    "description": "Standard deviation for random initialization of feature.",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.01
-                },
-                "numIterations": {
-                    "name": "Number of Iterations",
-                    "description": "Number of training iterations.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 3
-                },
-                "learningRateDecay": {
-                    "name": "Learning Rate Decay",
-                    "description": "Multiplicative decay factor for Learning Rate.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1
-                },
-                "viewParam": {
-                    "name": "View Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "3"
-                },
-                "likeParam": {
-                    "name": "Like Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "5"
-                },
-                "dislikeParam": {
-                    "name": "Dislike Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "1"
-                },
-                "conversionParam": {
-                    "name": "Conversion Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "4"
-                },
-                "conflictParam": {
-                    "name": "Override",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "Use the latest action",
-                                "value": "latest"
-                            },
-                            {
-                                "name": "Use the highest preference score one",
-                                "value": "highest"
-                            },
-                            {
-                                "name": "Use the lowest preference score one",
-                                "value": "lowest"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "latest"
-                },
-                "numFeaturesMin": {
-                    "name": "numFeaturesMin",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 2
-                },
-                "numFeaturesMax": {
-                    "name": "numFeaturesMax",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 10
-                },
-                "learningRateMin": {
-                    "name": "learningRateMin",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.01
-                },
-                "learningRateMax": {
-                    "name": "learningRateMax",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.05
-                },
-                "preventOverfittingMin": {
-                    "name": "preventOverfittingMin",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.1
-                },
-                "preventOverfittingMax": {
-                    "name": "preventOverfittingMax",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.5
-                },
-                "randomNoiseMin": {
-                    "name": "randomNoiseMin",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.01
-                },
-                "randomNoiseMax": {
-                    "name": "randomNoiseMax",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.05
-                },
-                "numIterationsMin": {
-                    "name": "numIterationsMin",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1
-                },
-                "numIterationsMax": {
-                    "name": "numIterationsMax",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 10
-                },
-                "learningRateDecayMin": {
-                    "name": "learningRateDecayMin",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1
-                },
-                "learningRateDecayMax": {
-                    "name": "learningRateDecayMax",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1
-                }
-            },
-            "paramsections": [
-                {
-                    "name": "Parameter Settings",
-                    "sectiontype": "normal",
-                    "subsections": [
-                        {
-                            "name": "Numeric Parameters",
-                            "sectiontype": "tuning",
-                            "params": [
-                                "numFeatures",
-                                "learningRate",
-                                "preventOverfitting",
-                                "randomNoise",
-                                "numIterations",
-                                "learningRateDecay"
-                            ]
-                        }
-                    ]
-                },
-                {
-                    "name": "User Actions Representation Settings",
-                    "sectiontype": "normal",
-                    "subsections": [
-                        {
-                            "name": "User Action Scores",
-                            "sectiontype": "normal",
-                            "description": "Define the preference score represented by each user action from 1 to 5. 5 is the most preferred, 1 is the least preferred. 3 is neutral.",
-                            "params": [
-                                "viewParam",
-                                "likeParam",
-                                "dislikeParam",
-                                "conversionParam"
-                            ]
-                        },
-                        {
-                            "name": "Overriding",
-                            "sectiontype": "normal",
-                            "description": "When there are conflicting actions, e.g. a user gives an item a rating 5 but later dislikes it, determine which action will be considered as final preference.",
-                            "params": [
-                                "conflictParam"
-                            ]
-                        }
-                    ]
-                }
-            ]
-        },
-        "pio-itemrec-single-featurebased_batch": {
-            "name": "Feature Based, Batch Mode. (Experimental)",
-            "description": "Item recommendation based on item's feature vector (itypes). This engine build a user preference model based on high ratings items (rate > 3).",
-            "batchcommands": [
-                "$base$/bin/itemrec.featurebased.Batch --appid $appid$ --algoid $algoid$ --modelSet $modelset$ --numRecommendations $numRecommendations$ --featureItypes $featureItypes$ $itypes$"
-            ],
-            "offlineevalcommands": [
-                "$base$/bin/itemrec.featurebased.Batch --appid $appid$ --algoid $algoid$ --modelSet $modelset$ --numRecommendations $numRecommendations$ --featureItypes $featureItypes$"
-            ],
-            "paramorder": [],
-            "engineinfoid": "itemrec",
-            "techreq": [],
-            "datareq": [
-              "Users, Items, and U2I Actions."
-            ],
-            "params": {
-              "featureItypes": {
-                "name": "Feature Itypes",
-                "description": "A comma-delimited list of itypes that is used to construct the preference model. If not specified, all itypes found in items will be used.",
-                "constraint": {
-                  "paramtype": "string"
-                },
-                "ui": {
-                  "uitype": "text"
-                },
-                "defaultvalue": ""
-              }
-            },
-            "paramsections": [
-              {
-                "name": "Parameter Settings",
-                "sectiontype": "normal",
-                "params": [
-                  "featureItypes"
-                ]
-              }
-            ]
-        },
-        "pio-itemrec-single-featurebased_realtime": {
-            "name": "Feature Based, Realtime Mode. (Experimental)",
-            "description": "Item recommendation based on item's feature vector (itypes). This engine build a user preference model based on high ratings items (rate > 3).",
-            "batchcommands": [
-                "$base$/bin/itemrec.featurebased.Realtime --appid $appid$ --algoid $algoid$ --modelSet $modelset$ --numRecommendations $numRecommendations$ --featureItypes $featureItypes$ $itypes$"
-            ],
-            "offlineevalcommands": [
-                "$base$/bin/itemrec.featurebased.Realtime --appid $appid$ --algoid $algoid$ --modelSet $modelset$ --numRecommendations $numRecommendations$ --whiteItypes $whiteItypes$"
-            ],
-            "paramorder": [],
-            "engineinfoid": "itemrec",
-            "techreq": [],
-            "datareq": [
-              "Users, Items, and U2I Actions."
-            ],
-            "params": {
-              "featureItypes": {
-                "name": "Feature Itypes",
-                "description": "A comma-delimited list of itypes that is used to construct the preference model. If not specified, all itypes found in items will be used.",
-                "constraint": {
-                  "paramtype": "string"
-                },
-                "ui": {
-                  "uitype": "text"
-                },
-                "defaultvalue": ""
-              }
-            },
-            "paramsections": [
-              {
-                "name": "Parameter Settings",
-                "sectiontype": "normal",
-                "params": [
-                  "featureItypes"
-                ]
-              }
-            ]
-        },
-        "pio-itemsim-distributed-random": {
-            "name": "Random Rank",
-            "description": "Predict item similarities randomly.",
-            "batchcommands": [
-                "$hadoop$ jar $base$/lib/$pdioItemsimAlgo$ io.prediction.algorithms.scalding.itemsim.randomrank.RandomRank --hdfs --training_dbType $appdataDbType$ --training_dbName $appdataDbName$ --training_dbHost $appdataDbHost$ --training_dbPort $appdataDbPort$ --modeldata_dbType $modeldataDbType$ --modeldata_dbName $modeldataDbName$ --modeldata_dbHost $modeldataDbHost$ --modeldata_dbPort $modeldataDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --numSimilarItems $numSimilarItems$ --modelSet $modelset$ --recommendationTime $recommendationTime$"
-            ],
-            "offlineevalcommands": [
-                "$hadoop$ jar $base$/lib/$pdioItemsimAlgo$ io.prediction.algorithms.scalding.itemsim.randomrank.RandomRank --hdfs --training_dbType $appdataTrainingDbType$ --training_dbName $appdataTrainingDbName$ --training_dbHost $appdataTrainingDbHost$ --training_dbPort $appdataTrainingDbPort$ --modeldata_dbType $modeldataTrainingDbType$ --modeldata_dbName $modeldataTrainingDbName$ --modeldata_dbHost $modeldataTrainingDbHost$ --modeldata_dbPort $modeldataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --numSimilarItems $numSimilarItems$ --modelSet false --evalid $evalid$ --recommendationTime $recommendationTime$"
-            ],
-            "paramorder": [],
-            "engineinfoid": "itemsim",
-            "techreq": [
-                "Hadoop"
-            ],
-            "datareq": [
-                "Items."
-            ],
-            "params": {},
-            "paramsections": []
-        },
-        "pio-itemsim-distributed-latest": {
-            "name": "Latest Rank",
-            "description": "Consider latest items as most similar.",
-            "batchcommands": [
-                "$hadoop$ jar $base$/lib/$pdioItemsimAlgo$ io.prediction.algorithms.scalding.itemsim.latestrank.LatestRank --hdfs --training_dbType $appdataDbType$ --training_dbName $appdataDbName$ --training_dbHost $appdataDbHost$ --training_dbPort $appdataDbPort$ --modeldata_dbType $modeldataDbType$ --modeldata_dbName $modeldataDbName$ --modeldata_dbHost $modeldataDbHost$ --modeldata_dbPort $modeldataDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --numSimilarItems $numSimilarItems$ --modelSet $modelset$ --recommendationTime $recommendationTime$"
-            ],
-            "offlineevalcommands": [
-                "$hadoop$ jar $base$/lib/$pdioItemsimAlgo$ io.prediction.algorithms.scalding.itemsim.latestrank.LatestRank --hdfs --training_dbType $appdataTrainingDbType$ --training_dbName $appdataTrainingDbName$ --training_dbHost $appdataTrainingDbHost$ --training_dbPort $appdataTrainingDbPort$ --modeldata_dbType $modeldataTrainingDbType$ --modeldata_dbName $modeldataTrainingDbName$ --modeldata_dbHost $modeldataTrainingDbHost$ --modeldata_dbPort $modeldataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --numSimilarItems $numSimilarItems$ --modelSet false --evalid $evalid$ --recommendationTime $recommendationTime$"
-            ],
-            "paramorder": [],
-            "engineinfoid": "itemsim",
-            "techreq": [
-                "Hadoop"
-            ],
-            "datareq": [
-                "Items with starttime."
-            ],
-            "params": {},
-            "paramsections": []
-        },
-        "pio-itemsim-single-mahout-itemsimcf": {
-            "name": "Mahout's Item Similarity Collaborative Filtering (Single Machine)",
-            "description": "This algorithm predicts similar items which the user may also like (Single Machine).",
-            "batchcommands": [
-                "$base$/bin/itemsim.generic.dataprep --outputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --recommendationTime $recommendationTime$ --matrixMarket false",
-                "$base$/bin/itemsim.mahout.mahoutjob io.prediction.algorithms.mahout.itemsim.itemsimcf.ItemSimCFJob --input $localTempDir$ratings.csv --output $localTempDir$similarities.tsv --itemsFile $localTempDir$validItemsIndex.tsv --appid $appid$ --engineid $engineid$ --algoid $algoid$ --booleanData $booleanData$ --numSimilarItems $numSimilarItems$ --itemSimilarity $itemSimilarity$ --weighted $weighted$ --freshness $freshness$ --recommendationTime $recommendationTime$ --freshnessTimeUnit $freshnessTimeUnit$",
-                "$base$/bin/itemsim.mahout.modelcon --inputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --modelSet $modelset$ --numSimilarItems $numSimilarItems$"
-            ],
-            "offlineevalcommands": [
-                "$base$/bin/itemsim.generic.dataprep --outputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --recommendationTime $recommendationTime$ --matrixMarket false",
-                "$base$/bin/itemsim.mahout.mahoutjob io.prediction.algorithms.mahout.itemsim.itemsimcf.ItemSimCFJob  --input $localTempDir$ratings.csv --output $localTempDir$similarities.tsv --itemsFile $localTempDir$validItemsIndex.tsv --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ --booleanData $booleanData$ --numSimilarItems $numSimilarItems$ --itemSimilarity $itemSimilarity$ --weighted $weighted$ --freshness $freshness$ --recommendationTime $recommendationTime$ --freshnessTimeUnit $freshnessTimeUnit$",
-                "$base$/bin/itemsim.mahout.modelcon --inputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ --modelSet $modelset$ --numSimilarItems $numSimilarItems$"
-            ],
-            "paramorder": [
-                "booleanData",
-                "itemSimilarity",
-                "weighted",
-                "viewParam",
-                "likeParam",
-                "dislikeParam",
-                "conversionParam",
-                "conflictParam"
-            ],
-            "engineinfoid": "itemsim",
-            "techreq": [],
-            "datareq": [
-                "Users, Items, and U2I Actions such as Like, Conversion and Rate."
-            ],
-            "capabilities": [
-                "freshness"
-            ],
-            "params": {
-                "booleanData": {
-                    "name": "Boolean Data",
-                    "description": "Treat input data as having no preference values.",
-                    "constraint": {
-                        "paramtype": "boolean"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "True",
-                                "value": "true"
-                            },
-                            {
-                                "name": "False",
-                                "value": "false"
-                            }
-                        ]
-                    },
-                    "defaultvalue": false
-                },
-                "itemSimilarity": {
-                    "name": "Item Similarity",
-                    "description": "Item Similarity Measure.",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "City Block",
-                                "value": "CityBlockSimilarity"
-                            },
-                            {
-                                "name": "Euclidean Distance",
-                                "value": "EuclideanDistanceSimilarity"
-                            },
-                            {
-                                "name": "Log-Likelihood",
-                                "value": "LogLikelihoodSimilarity"
-                            },
-                            {
-                                "name": "Pearson Correlation",
-                                "value": "PearsonCorrelationSimilarity"
-                            },
-                            {
-                                "name": "Tanimoto Coefficient",
-                                "value": "TanimotoCoefficientSimilarity"
-                            },
-                            {
-                                "name": "Uncentered Cosine",
-                                "value": "UncenteredCosineSimilarity"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "LogLikelihoodSimilarity"
-                },
-                "weighted": {
-                    "name": "Weighted",
-                    "description": "The Similarity score is weighted (only applied to Euclidean Distance, Pearson Correlation, Uncentered Cosine item similarity).",
-                    "constraint": {
-                        "paramtype": "boolean"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "True",
-                                "value": "true"
-                            },
-                            {
-                                "name": "False",
-                                "value": "false"
-                            }
-                        ]
-                    },
-                    "defaultvalue": false
-                },
-                "viewParam": {
-                    "name": "View Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "3"
-                },
-                "likeParam": {
-                    "name": "Like Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "5"
-                },
-                "dislikeParam": {
-                    "name": "Dislike Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "1"
-                },
-                "conversionParam": {
-                    "name": "Conversion Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "4"
-                },
-                "conflictParam": {
-                    "name": "Override",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "Use the latest action",
-                                "value": "latest"
-                            },
-                            {
-                                "name": "Use the highest preference score one",
-                                "value": "highest"
-                            },
-                            {
-                                "name": "Use the lowest preference score one",
-                                "value": "lowest"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "latest"
-                }
-            },
-            "paramsections": [
-                {
-                    "name": "Parameter Settings",
-                    "sectiontype": "normal",
-                    "subsections": [
-                        {
-                            "name": "Item Similarity Measurement",
-                            "sectiontype": "normal",
-                            "params": [
-                                "itemSimilarity"
-                            ]
-                        },
-                        {
-                            "name": "Advanced Parameters",
-                            "sectiontype": "normal",
-                            "params": [
-                                "booleanData",
-                                "weighted"
-                            ]
-                        }
-                    ]
-                },
-                {
-                    "name": "User Actions Representation Settings",
-                    "sectiontype": "normal",
-                    "subsections": [
-                        {
-                            "name": "User Action Scores",
-                            "sectiontype": "normal",
-                            "description": "Define the preference score represented by each user action from 1 to 5. 5 is the most preferred, 1 is the least preferred. 3 is neutral.",
-                            "params": [
-                                "viewParam",
-                                "likeParam",
-                                "dislikeParam",
-                                "conversionParam"
-                            ]
-                        },
-                        {
-                            "name": "Overriding",
-                            "sectiontype": "normal",
-                            "description": "When there are conflicting actions, e.g. a user gives an item a rating 5 but later dislikes it, determine which action will be considered as final preference.",
-                            "params": [
-                                "conflictParam"
-                            ]
-                        }
-                    ]
-                }
-            ]
-        },
-        "pio-itemsim-distributed-mahout-itemsimcf": {
-            "name": "Mahout's Item Similarity Collaborative Filtering",
-            "description": "This algorithm predicts similar items which the user may also like.",
-            "batchcommands": [
-                "$base$/bin/quiet.sh $hadoop$ fs -rmr $mahoutTempDir$",
-                "$base$/bin/quiet.sh $hadoop$ fs -rmr $algoDir$",
-                "$hadoop$ jar $base$/lib/$pdioItemsimAlgo$ $hadoopOptions$ io.prediction.algorithms.scalding.mahout.itemsim.DataCopy --hdfs --dbType $appdataDbType$ --dbName $appdataDbName$ --dbHost $appdataDbHost$ --dbPort $appdataDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$",
-                "$hadoop$ jar $base$/lib/$pdioItemsimAlgo$ $hadoopOptions$ io.prediction.algorithms.scalding.mahout.itemsim.DataPreparator --hdfs --dbType $appdataDbType$ --dbName $appdataDbName$ --dbHost $appdataDbHost$ --dbPort $appdataDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$",
-                "$hadoop$ jar $mahoutCoreJob$ org.apache.mahout.cf.taste.hadoop.similarity.item.ItemSimilarityJob $hadoopOptions$ --input $dataFilePrefix$ratings.csv --output $algoFilePrefix$similarities.tsv --tempDir $mahoutTempDir$ --maxSimilaritiesPerItem $numSimilarItems$ --booleanData $booleanData$ --maxPrefs $maxPrefs$ --minPrefsPerUser $minPrefsPerUser$ --similarityClassname $similarityClassname$ --threshold $threshold$",
-                "$hadoop$ jar $base$/lib/$pdioItemsimAlgo$ $hadoopOptions$ io.prediction.algorithms.scalding.mahout.itemsim.ModelConstructor --hdfs --dbType $modeldataDbType$ --dbName $modeldataDbName$ --dbHost $modeldataDbHost$ --dbPort $modeldataDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --modelSet $modelset$ --numSimilarItems $numSimilarItems$ --recommendationTime $recommendationTime$"
-            ],
-            "offlineevalcommands": [
-                "$base$/bin/quiet.sh $hadoop$ fs -rmr $mahoutTempDir$",
-                "$base$/bin/quiet.sh $hadoop$ fs -rmr $algoDir$",
-                "$hadoop$ jar $base$/lib/$pdioItemsimAlgo$ $hadoopOptions$ io.prediction.algorithms.scalding.mahout.itemsim.DataCopy --hdfs --dbType $appdataTrainingDbType$ --dbName $appdataTrainingDbName$ --dbHost $appdataTrainingDbHost$ --dbPort $appdataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$",
-                "$hadoop$ jar $base$/lib/$pdioItemsimAlgo$ $hadoopOptions$ io.prediction.algorithms.scalding.mahout.itemsim.DataPreparator --hdfs --dbType $appdataTrainingDbType$ --dbName $appdataTrainingDbName$ --dbHost $appdataTrainingDbHost$ --dbPort $appdataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$",
-                "$hadoop$ jar $mahoutCoreJob$ org.apache.mahout.cf.taste.hadoop.similarity.item.ItemSimilarityJob $hadoopOptions$ --input $dataFilePrefix$ratings.csv --output $algoFilePrefix$similarities.tsv --tempDir $mahoutTempDir$ --maxSimilaritiesPerItem $numSimilarItems$ --booleanData $booleanData$ --maxPrefs $maxPrefs$ --minPrefsPerUser $minPrefsPerUser$ --similarityClassname $similarityClassname$ --threshold $threshold$",
-                "$hadoop$ jar $base$/lib/$pdioItemsimAlgo$ $hadoopOptions$ io.prediction.algorithms.scalding.mahout.itemsim.ModelConstructor --hdfs --dbType $modeldataTrainingDbType$ --dbName $modeldataTrainingDbName$ --dbHost $modeldataTrainingDbHost$ --dbPort $modeldataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --evalid $evalid$ --modelSet $modelset$ --numSimilarItems $numSimilarItems$ --recommendationTime $recommendationTime$"
-            ],
-            "paramorder": [
-                "booleanData",
-                "maxPrefs",
-                "minPrefsPerUser",
-                "similarityClassname",
-                "threshold",
-                "viewParam",
-                "likeParam",
-                "dislikeParam",
-                "conversionParam",
-                "conflictParam"
-            ],
-            "engineinfoid": "itemsim",
-            "techreq": [
-                "Hadoop"
-            ],
-            "datareq": [
-                "Users, Items, and U2I Actions such as Like, Conversion and Rate."
-            ],
-            "params": {
-                "booleanData": {
-                    "name": "Boolean Data",
-                    "description": "Treat input data as having no preference values.",
-                    "constraint": {
-                        "paramtype": "boolean"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "True",
-                                "value": "true"
-                            },
-                            {
-                                "name": "False",
-                                "value": "false"
-                            }
-                        ]
-                    },
-                    "defaultvalue": false
-                },
-                "maxPrefs": {
-                    "name": "Max Num of Preferences per User",
-                    "description": "Maximum number of preferences considered per user in final recommendation phase.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1000
-                },
-                "minPrefsPerUser": {
-                    "name": "Min Num of Preferences per User",
-                    "description": "Ignore users with less preferences than this.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1
-                },
-                "similarityClassname": {
-                    "name": "Distance Function",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "Co-occurrence",
-                                "value": "SIMILARITY_COOCCURRENCE"
-                            },
-                            {
-                                "name": "Log-Likelihood",
-                                "value": "SIMILARITY_LOGLIKELIHOOD"
-                            },
-                            {
-                                "name": "Tanimoto Coefficient",
-                                "value": "SIMILARITY_TANIMOTO_COEFFICIENT"
-                            },
-                            {
-                                "name": "City Block",
-                                "value": "SIMILARITY_CITY_BLOCK"
-                            },
-                            {
-                                "name": "Cosine Similarity",
-                                "value": "SIMILARITY_COSINE"
-                            },
-                            {
-                                "name": "Pearson Correlation",
-                                "value": "SIMILARITY_PEARSON_CORRELATION"
-                            },
-                            {
-                                "name": "Euclidean Distance",
-                                "value": "SIMILARITY_EUCLIDEAN_DISTANCE"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "SIMILARITY_LOGLIKELIHOOD"
-                },
-                "threshold": {
-                    "name": "Threshold",
-                    "description": "Discard item pairs with a similarity value below this.",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 5e-324
-                },
-                "viewParam": {
-                    "name": "View Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "3"
-                },
-                "likeParam": {
-                    "name": "Like Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "5"
-                },
-                "dislikeParam": {
-                    "name": "Dislike Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "1"
-                },
-                "conversionParam": {
-                    "name": "Conversion Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "4"
-                },
-                "conflictParam": {
-                    "name": "Override",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "Use the latest action",
-                                "value": "latest"
-                            },
-                            {
-                                "name": "Use the highest preference score one",
-                                "value": "highest"
-                            },
-                            {
-                                "name": "Use the lowest preference score one",
-                                "value": "lowest"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "latest"
-                },
-                "thresholdMin": {
-                    "name": "thresholdMin",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 5e-324
-                },
-                "thresholdMax": {
-                    "name": "thresholdMax",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.15
-                },
-                "maxPrefsMin": {
-                    "name": "maxPrefsMin",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 500
-                },
-                "maxPrefsMax": {
-                    "name": "maxPrefsMax",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1500
-                },
-                "minPrefsPerUserMin": {
-                    "name": "minPrefsPerUserMin",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 1
-                },
-                "minPrefsPerUserMax": {
-                    "name": "minPrefsPerUserMax",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 5
-                }
-            },
-            "paramsections": [
-                {
-                    "name": "Parameter Settings",
-                    "sectiontype": "normal",
-                    "subsections": [
-                        {
-                            "name": "Item Similarity Measurement",
-                            "sectiontype": "normal",
-                            "params": [
-                                "similarityClassname"
-                            ]
-                        },
-                        {
-                            "name": "Advanced Parameters",
-                            "sectiontype": "normal",
-                            "params": [
-                                "booleanData"
-                            ]
-                        },
-                        {
-                            "name": "Numeric Parameters",
-                            "sectiontype": "tuning",
-                            "params": [
-                                "threshold",
-                                "maxPrefs",
-                                "minPrefsPerUser"
-                            ]
-                        }
-                    ]
-                },
-                {
-                    "name": "User Actions Representation Settings",
-                    "sectiontype": "normal",
-                    "subsections": [
-                        {
-                            "name": "User Action Scores",
-                            "sectiontype": "normal",
-                            "description": "Define the preference score represented by each user action from 1 to 5. 5 is the most preferred, 1 is the least preferred. 3 is neutral.",
-                            "params": [
-                                "viewParam",
-                                "likeParam",
-                                "dislikeParam",
-                                "conversionParam"
-                            ]
-                        },
-                        {
-                            "name": "Overriding",
-                            "sectiontype": "normal",
-                            "description": "When there are conflicting actions, e.g. a user gives an item a rating 5 but later dislikes it, determine which action will be considered as final preference.",
-                            "params": [
-                                "conflictParam"
-                            ]
-                        }
-                    ]
-                }
-            ]
-        },
-        "pio-itemrank-single-mahout-knnitembased": {
-            "name": "Mahout's kNN Item Based Collaborative Filtering (extension to GenericItemBased) (Single Machine)",
-            "description": "Predicts user preferences based on previous behaviors of users on similar items (Single Machine).",
-            "batchcommands": [
-                "$base$/bin/itemrec.generic.dataprep --outputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --recommendationTime $recommendationTime$ --matrixMarket false",
-                "$base$/bin/itemrec.mahout.mahoutjob io.prediction.algorithms.mahout.itemrec.knnitembased.KNNItemBasedJob --input $localTempDir$ratings.csv --itemsFile $localTempDir$itemsIndex.tsv --output $localTempDir$predicted.tsv --outputSim $localTempDir$itemSim.csv --appid $appid$ --engineid $engineid$ --algoid $algoid$ --booleanData $booleanData$ --numRecommendations $itemCount$ --itemSimilarity $itemSimilarity$ --weighted $weighted$ --nearestN $nearestN$ --threshold $threshold$ --preComputeItemSim $preComputeItemSim$ --similarItemsPerItem $similarItemsPerItem$ --freshness $freshness$ --recommendationTime $recommendationTime$ --freshnessTimeUnit $freshnessTimeUnit$",
-                "$base$/bin/itemrec.mahout.modelcon --inputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --modelSet $modelset$ --numRecommendations $itemCount$ --booleanData $booleanData$"
-            ],
-            "offlineevalcommands": [
-                "$base$/bin/itemrec.generic.dataprep --outputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ $itypes$ --viewParam $viewParam$ --likeParam $likeParam$ --dislikeParam $dislikeParam$ --conversionParam $conversionParam$ --conflictParam $conflictParam$ --recommendationTime $recommendationTime$ --matrixMarket false",
-                "$base$/bin/itemrec.mahout.mahoutjob io.prediction.algorithms.mahout.itemrec.knnitembased.KNNItemBasedJob --input $localTempDir$ratings.csv --itemsFile $localTempDir$itemsIndex.tsv --output $localTempDir$predicted.tsv --outputSim $localTempDir$itemSim.csv --appid $appid$ --engineid $engineid$ --algoid $algoid$ --booleanData $booleanData$ --numRecommendations $itemCount$ --itemSimilarity $itemSimilarity$ --weighted $weighted$ --nearestN $nearestN$ --threshold $threshold$ --preComputeItemSim $preComputeItemSim$ --similarItemsPerItem $similarItemsPerItem$ --freshness $freshness$ --recommendationTime $recommendationTime$ --freshnessTimeUnit $freshnessTimeUnit$",
-                "$base$/bin/itemrec.mahout.modelcon --inputDir $localTempDir$ --appid $appid$ --engineid $engineid$ --algoid $algoid$ --modelSet $modelset$ --numRecommendations $itemCount$ --booleanData $booleanData$"
-            ],
-            "paramorder": [
-                "booleanData",
-                "itemSimilarity",
-                "weighted",
-                "nearestN",
-                "threshold",
-                "preComputeItemSim",
-                "similarItemsPerItem",
-                "viewParam",
-                "likeParam",
-                "dislikeParam",
-                "conversionParam",
-                "conflictParam"
-            ],
-            "engineinfoid": "itemrank",
-            "techreq": [],
-            "datareq": [
-                "Users, Items, and U2I Actions such as Like, Conversion and Rate."
-            ],
-            "capabilities": ["freshness"],
-            "params": {
-                "booleanData": {
-                    "name": "Boolean Data",
-                    "description": "Treat input data as having no preference values.",
-                    "constraint": {
-                        "paramtype": "boolean"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "True",
-                                "value": "true"
-                            },
-                            {
-                                "name": "False",
-                                "value": "false"
-                            }
-                        ]
-                    },
-                    "defaultvalue": false
-                },
-                "itemSimilarity": {
-                    "name": "Item Similarity",
-                    "description": "Item Similarity Measure.",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "City Block",
-                                "value": "CityBlockSimilarity"
-                            },
-                            {
-                                "name": "Euclidean Distance",
-                                "value": "EuclideanDistanceSimilarity"
-                            },
-                            {
-                                "name": "Log-Likelihood",
-                                "value": "LogLikelihoodSimilarity"
-                            },
-                            {
-                                "name": "Pearson Correlation",
-                                "value": "PearsonCorrelationSimilarity"
-                            },
-                            {
-                                "name": "Tanimoto Coefficient",
-                                "value": "TanimotoCoefficientSimilarity"
-                            },
-                            {
-                                "name": "Uncentered Cosine",
-                                "value": "UncenteredCosineSimilarity"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "LogLikelihoodSimilarity"
-                },
-                "weighted": {
-                    "name": "Weighted",
-                    "description": "The Similarity score is weighted (only applied to Euclidean Distance, Pearson Correlation, Uncentered Cosine item similarity).",
-                    "constraint": {
-                        "paramtype": "boolean"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "True",
-                                "value": "true"
-                            },
-                            {
-                                "name": "False",
-                                "value": "false"
-                            }
-                        ]
-                    },
-                    "defaultvalue": false
-                },
-                "viewParam": {
-                    "name": "View Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "3"
-                },
-                "nearestN": {
-                    "name": "Nearest K",
-                    "description": "K-nearest rated item neighbors.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 10
-                },
-                "threshold": {
-                    "name": "Threshold",
-                    "description": "Similarity threshold.",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 5e-324
-                },
-                "preComputeItemSim": {
-                    "name": "Pre-Compute Item Similarity",
-                    "description": "Pre-compute item similarity for better run time performance (but use more storage space and memory).",
-                    "constraint": {
-                        "paramtype": "boolean"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "True",
-                                "value": "true"
-                            },
-                            {
-                                "name": "False",
-                                "value": "false"
-                            }
-                        ]
-                    },
-                    "defaultvalue": false
-                },
-                "similarItemsPerItem": {
-                    "name": "Number of Similar Items per Items",
-                    "description": "Number of Similar items in pre-computed item similarity. Only applicable when Pre-Compute Item Similarity = true. Should set this cautiously if you have large number of items (>100K). Storage space needed is about number of items * number of similar items * 30Bytes. Also, the pre-computed similarity will be loaded into memory.",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 100
-                },
-                "likeParam": {
-                    "name": "Like Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "5"
-                },
-                "dislikeParam": {
-                    "name": "Dislike Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "1"
-                },
-                "conversionParam": {
-                    "name": "Conversion Score",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "1",
-                                "value": "1"
-                            },
-                            {
-                                "name": "2",
-                                "value": "2"
-                            },
-                            {
-                                "name": "3",
-                                "value": "3"
-                            },
-                            {
-                                "name": "4",
-                                "value": "4"
-                            },
-                            {
-                                "name": "5",
-                                "value": "5"
-                            },
-                            {
-                                "name": "Ignore",
-                                "value": "ignore"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "4"
-                },
-                "conflictParam": {
-                    "name": "Override",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "string"
-                    },
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "Use the latest action",
-                                "value": "latest"
-                            },
-                            {
-                                "name": "Use the highest preference score one",
-                                "value": "highest"
-                            },
-                            {
-                                "name": "Use the lowest preference score one",
-                                "value": "lowest"
-                            }
-                        ]
-                    },
-                    "defaultvalue": "latest"
-                },
-                "nearestNMin": {
-                    "name": "nearestNMin",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 5
-                },
-                "nearestNMax": {
-                    "name": "nearestNMax",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 15
-                },
-                "thresholdMin": {
-                    "name": "thresholdMin",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 5e-324
-                },
-                "thresholdMax": {
-                    "name": "thresholdMax",
-                    "constraint": {
-                        "paramtype": "double"
-                    },
-                    "ui": {
-                        "uitype": "text"
-                    },
-                    "defaultvalue": 0.2
-                }
-            },
-            "paramsections": [
-                {
-                    "name": "Parameter Settings",
-                    "sectiontype": "normal",
-                    "subsections": [
-                        {
-                            "name": "Item Similarity Measurement",
-                            "sectiontype": "normal",
-                            "params": [
-                                "itemSimilarity"
-                            ]
-                        },
-                        {
-                            "name": "Advanced Parameters",
-                            "sectiontype": "normal",
-                            "params": [
-                                "booleanData",
-                                "weighted",
-                                "preComputeItemSim",
-                                "similarItemsPerItem"
-                            ]
-                        },
-                        {
-                            "name": "Numeric Parameters",
-                            "sectiontype": "tuning",
-                            "params": [
-                                "nearestN",
-                                "threshold"
-                            ]
-                        }
-                    ]
-                },
-                {
-                    "name": "User Actions Representation Settings",
-                    "sectiontype": "normal",
-                    "subsections": [
-                        {
-                            "name": "User Action Scores",
-                            "sectiontype": "normal",
-                            "description": "Define the preference score represented by each user action from 1 to 5. 5 is the most preferred, 1 is the least preferred. 3 is neutral.",
-                            "params": [
-                                "viewParam",
-                                "likeParam",
-                                "dislikeParam",
-                                "conversionParam"
-                            ]
-                        },
-                        {
-                            "name": "Overriding",
-                            "sectiontype": "normal",
-                            "description": "When there are conflicting actions, e.g. a user gives an item a rating 5 but later dislikes it, determine which action will be considered as final preference.",
-                            "params": [
-                                "conflictParam"
-                            ]
-                        }
-                    ]
-                }
-            ]
-        }
-    },
-    "offlineevalsplitterinfos": {
-        "pio-distributed-trainingtestsplit": {
-            "name": "Training/Test Data Splitter With Time Order Option",
-            "description": "Split data into training, validation and test sets",
-            "engineinfoids": [
-                "itemrec", "itemsim"
-            ],
-            "commands": [
-                "$base$/bin/u2itrainingtestsplit --hadoop $hadoop$ --pdioEvalJar $base$/lib/$pdioCommonsEval$ --sequenceNum $iteration$ --hdfs --dbType $appdataDbType$ --dbName $appdataDbName$ --dbHost $appdataDbHost$ --dbPort $appdataDbPort$ --training_dbType $appdataTrainingDbType$ --training_dbName $appdataTrainingDbName$ --training_dbHost $appdataTrainingDbHost$ --training_dbPort $appdataTrainingDbPort$ --validation_dbType $appdataValidationDbType$ --validation_dbName $appdataValidationDbName$ --validation_dbHost $appdataValidationDbHost$ --validation_dbPort $appdataValidationDbPort$ --test_dbType $appdataTestDbType$ --test_dbName $appdataTestDbName$ --test_dbHost $appdataTestDbHost$ --test_dbPort $appdataTestDbPort$ --hdfsRoot $hdfsRoot$ --localTempRoot $localTempRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ $itypes$ --trainingPercent $trainingPercent$ --validationPercent $validationPercent$ --testPercent $testPercent$ --timeorder $timeorder$"
-            ],
-            "params": {
-                "timeorder": {
-                    "name": "Data Selection",
-                    "description": "Random with Time Order means that data in Test Set is always newer than those in Train Set.",
-                    "constraint": {
-                        "paramtype": "boolean"
-                    },
-                    "defaultvalue": false,
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "Random Sampling",
-                                "value": "false"
-                            },
-                            {
-                                "name": "Random with Time Order",
-                                "value": "true"
-                            }
-                        ]
-                    }
-                }
-            },
-            "paramsections": [
-                {
-                    "name": "Parameters",
-                    "sectiontype": "normal",
-                    "description": "",
-                    "params": [
-                        "timeorder"
-                    ]
-                }
-            ],
-            "paramorder": [
-                "timeorder"
-            ]
-        },
-        "pio-single-trainingtestsplit": {
-            "name": "Training and Test Set Data Splitter for User-to-Item Actions (Single Machine)",
-            "description": "Split data into training, validation and test sets",
-            "engineinfoids": [
-                "itemrec", "itemsim"
-            ],
-            "commands": [
-                "$base$/bin/u2isplit --sequenceNum $iteration$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ $itypesCSV$ --trainingpercent $trainingPercent$ --validationpercent $validationPercent$ --testpercent $testPercent$ --timeorder $timeorder$"
-            ],
-            "params": {
-                "timeorder": {
-                    "name": "Data Selection",
-                    "description": "Random with Time Order means that data in Test Set is always newer than those in Train Set.",
-                    "constraint": {
-                        "paramtype": "boolean"
-                    },
-                    "defaultvalue": false,
-                    "ui": {
-                        "uitype": "selection",
-                        "selections": [
-                            {
-                                "name": "Random Sampling",
-                                "value": "false"
-                            },
-                            {
-                                "name": "Random with Time Order",
-                                "value": "true"
-                            }
-                        ]
-                    }
-                }
-            },
-            "paramsections": [
-                {
-                    "name": "Parameters",
-                    "sectiontype": "normal",
-                    "description": "",
-                    "params": [
-                        "timeorder"
-                    ]
-                }
-            ],
-            "paramorder": [
-                "timeorder"
-            ]
-        }
-    },
-    "offlineevalmetricinfos": {
-        "pio-itemrec-distributed-map_k": {
-            "name": "MAP@k",
-            "description": "Mean Average Precision",
-            "engineinfoids": [
-                "itemrec"
-            ],
-            "commands": [
-                "$hadoop$ jar $base$/lib/$pdioItemrecEval$ io.prediction.metrics.scalding.itemrec.map.MAPAtKDataPreparator --hdfs --test_dbType $appdataTestDbType$ --test_dbName $appdataTestDbName$ --test_dbHost $appdataTestDbHost$ --test_dbPort $appdataTestDbPort$ --training_dbType $appdataTrainingDbType$ --training_dbName $appdataTrainingDbName$ --training_dbHost $appdataTrainingDbHost$ --training_dbPort $appdataTrainingDbPort$ --modeldata_dbType $modeldataTrainingDbType$ --modeldata_dbName $modeldataTrainingDbName$ --modeldata_dbHost $modeldataTrainingDbHost$ --modeldata_dbPort $modeldataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --kParam $kParam$ --goalParam $goal$",
-                "$base$/bin/topk --enginetype itemrec --evalid $evalid$ --algoid $algoid$ --k $kParam$ --metricid $metricid$ --hdfsroot $hdfsRoot$",
-                "$hadoop$ jar $base$/lib/$pdioItemrecEval$ io.prediction.metrics.scalding.itemrec.map.MAPAtK --hdfs --dbType $settingsDbType$ --dbName $settingsDbName$ --dbHost $settingsDbHost$ --dbPort $settingsDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --iteration $iteration$ --splitset $splitset$ --kParam $kParam$"
-            ],
-            "params": {
-                "kParam": {
-                    "name": "k",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "defaultvalue": 20,
-                    "ui": {
-                        "uitype": "text"
-                    }
-                }
-            },
-            "paramsections": [
-                {
-                    "name": "Parameters",
-                    "sectiontype": "normal",
-                    "description": "",
-                    "params": [
-                        "kParam"
-                    ]
-                }
-            ],
-            "paramorder": [
-                "kParam"
-            ]
-        },
-        "pio-itemrec-single-map_k": {
-            "name": "MAP@k (Single Machine)",
-            "description": "Mean Average Precision",
-            "engineinfoids": [
-                "itemrec"
-            ],
-            "commands": [
-                "$base$/bin/topk --enginetype itemrec --evalid $evalid$ --algoid $algoid$ --k $k$ --metricid $metricid$ --hdfsroot $hdfsRoot$ --local",
-                "$base$/bin/mapatk --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --iteration $iteration$ --splitset $splitset$ --k $k$ --goal $goal$"
-            ],
-            "params": {
-                "k": {
-                    "name": "k",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "defaultvalue": 20,
-                    "ui": {
-                        "uitype": "text"
-                    }
-                }
-            },
-            "paramsections": [
-                {
-                    "name": "Parameters",
-                    "sectiontype": "normal",
-                    "description": "",
-                    "params": [
-                        "k"
-                    ]
-                }
-            ],
-            "paramorder": [
-                "k"
-            ]
-        },
-        "pio-itemsim-distributed-ismap_k": {
-            "name": "ISMAP@k",
-            "description": "Item Similarity Mean Average Precision",
-            "engineinfoids": [
-                "itemsim"
-            ],
-            "commands": [
-                "$hadoop$ jar $base$/lib/$pdioItemsimEval$ io.prediction.metrics.scalding.itemsim.ismap.ISMAPAtKDataPreparator --hdfs --test_dbType $appdataTestDbType$ --test_dbName $appdataTestDbName$ --test_dbHost $appdataTestDbHost$ --test_dbPort $appdataTestDbPort$ --training_dbType $appdataTrainingDbType$ --training_dbName $appdataTrainingDbName$ --training_dbHost $appdataTrainingDbHost$ --training_dbPort $appdataTrainingDbPort$ --modeldata_dbType $modeldataTrainingDbType$ --modeldata_dbName $modeldataTrainingDbName$ --modeldata_dbHost $modeldataTrainingDbHost$ --modeldata_dbPort $modeldataTrainingDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --kParam $kParam$ --goalParam $goal$",
-                "$base$/bin/topk --enginetype itemsim --evalid $evalid$ --algoid $algoid$ --k $kParam$ --metricid $metricid$ --hdfsroot $hdfsRoot$",
-                "$hadoop$ jar $base$/lib/$pdioItemsimEval$ io.prediction.metrics.scalding.itemsim.ismap.ISMAPAtK --hdfs --dbType $settingsDbType$ --dbName $settingsDbName$ --dbHost $settingsDbHost$ --dbPort $settingsDbPort$ --hdfsRoot $hdfsRoot$ --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --iteration $iteration$ --splitset $splitset$ --kParam $kParam$"
-            ],
-            "params": {
-                "kParam": {
-                    "name": "k",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "defaultvalue": 20,
-                    "ui": {
-                        "uitype": "text"
-                    }
-                }
-            },
-            "paramsections": [
-                {
-                    "name": "Parameters",
-                    "sectiontype": "normal",
-                    "description": "",
-                    "params": [
-                        "kParam"
-                    ]
-                }
-            ],
-            "paramorder": [
-                "kParam"
-            ]
-        },
-        "pio-itemsim-single-ismap_k": {
-            "name": "ISMAP@k (Single Machine)",
-            "description": "Item Similarity Mean Average Precision",
-            "engineinfoids": [
-                "itemsim"
-            ],
-            "commands": [
-                "$base$/bin/topk --enginetype itemsim --evalid $evalid$ --algoid $algoid$ --k $k$ --metricid $metricid$ --hdfsroot $hdfsRoot$ --local",
-                "$base$/bin/mapatk --appid $appid$ --engineid $engineid$ --evalid $evalid$ --metricid $metricid$ --algoid $algoid$ --iteration $iteration$ --splitset $splitset$ --k $k$ --goal $goal$"
-            ],
-            "params": {
-                "k": {
-                    "name": "k",
-                    "description": "",
-                    "constraint": {
-                        "paramtype": "integer"
-                    },
-                    "defaultvalue": 20,
-                    "ui": {
-                        "uitype": "text"
-                    }
-                }
-            },
-            "paramsections": [
-                {
-                    "name": "Parameters",
-                    "sectiontype": "normal",
-                    "description": "",
-                    "params": [
-                        "k"
-                    ]
-                }
-            ],
-            "paramorder": [
-                "k"
-            ]
-        }
-    },
-    "paramgeninfos": {
-        "pio-single-random": {
-            "name": "Random Search",
-            "description": "Random search within specified interval",
-            "commands": [
-                "$base$/bin/paramgen --evalids $evalids$ --algoid $algoid$ --loop $loop$ --paramsets $paramsets$"
-            ],
-            "paramorder": [],
-            "paramnames": {},
-            "paramdescription": {},
-            "paramdefaults": {}
-        }
-    }
-}
diff --git a/dist/conf/mongodb/mongodb.conf b/dist/conf/mongodb/mongodb.conf
deleted file mode 100644
index 2add8c5..0000000
--- a/dist/conf/mongodb/mongodb.conf
+++ /dev/null
@@ -1,3 +0,0 @@
-dbpath=vendors/mongodb/data
-logpath=vendors/mongodb/logs/mongodb.log
-logappend=true
diff --git a/dist/conf/predictionio.conf b/dist/conf/predictionio.conf
deleted file mode 100644
index e9f54a2..0000000
--- a/dist/conf/predictionio.conf
+++ /dev/null
@@ -1,96 +0,0 @@
-# This is the main configuration file for the application.
-# ~~~~~
-
-# Secret key
-# ~~~~~
-# The secret key is used to secure cryptographics functions.
-# If you deploy your application to several instances be sure to use the same key!
-application.secret="CR2H^VlZ3M3fu;/jDZ<_ZQI`nb[pQ7:TxyV/tACshUD;Udj^5b64F=/J08yTG1A2"
-
-# The application languages
-# ~~~~~
-application.langs="en"
-
-# Global object class
-# ~~~~~
-# Define the Global object class for this application.
-# Default to Global in the root package.
-# global=Global
-
-# Database configuration
-# ~~~~~
-# You can declare as many datasources as you want.
-# By convention, the default datasource is named `default`
-#
-# db.default.driver=org.h2.Driver
-# db.default.url="jdbc:h2:mem:play"
-# db.default.user=sa
-# db.default.password=
-
-# Evolutions
-# ~~~~~
-# You can disable evolutions if needed
-# evolutionplugin=disabled
-
-# Logger
-# ~~~~~
-# You can also configure logback (http://logback.qos.ch/), by providing a logger.xml file in the conf directory .
-
-# Root logger:
-logger.root=ERROR
-
-# Logger used by the framework:
-logger.play=INFO
-
-# Logger provided to your application:
-logger.application=DEBUG
-
-# Domains allowed to access your API server through cross-site scripts, comma-separated.
-# Default to all domains.
-# cors.allowed.domains = "*"
-
-# PredictionIO Commons Settings
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.host=localhost
-io.prediction.commons.settings.db.port=27017
-
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.host=localhost
-io.prediction.commons.appdata.db.port=27017
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.host=localhost
-io.prediction.commons.appdata.test.db.port=27017
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.host=localhost
-io.prediction.commons.appdata.training.db.port=27017
-
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.host=localhost
-io.prediction.commons.appdata.validation.db.port=27017
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.host=localhost
-io.prediction.commons.modeldata.db.port=27017
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.host=localhost
-io.prediction.commons.modeldata.training.db.port=27017
-
-# Mahout core job
-io.prediction.jars.mahoutCoreJob=${io.prediction.base}/vendors/mahout-distribution-0.9/pio-mahout-core-0.9-a91092c0e1-job.jar
-
-# PredictionIO Scheduler Threading
-io.prediction.scheduler.steps.fork-join-executor.parallelism-factor = 1.0
-io.prediction.scheduler.steps.fork-join-executor.parallelism-max = 1
-
-io.prediction.scheduler.child.java.opts="-Xmx1g"
-
-# Hadoop options passed by PredictionIO Scheduler
-io.prediction.scheduler.mapred.min.split.size=0
-io.prediction.scheduler.mapred.map.tasks=4
-io.prediction.scheduler.mapred.reduce.tasks=2
-
-# default local temporary space
-io.prediction.commons.settings.local.temp.root=${io.prediction.base}/tmp/
diff --git a/dist/conf/quartz.properties b/dist/conf/quartz.properties
deleted file mode 100644
index e5dfef6..0000000
--- a/dist/conf/quartz.properties
+++ /dev/null
@@ -1,13 +0,0 @@
-#============================================================================
-# Configure Main Scheduler Properties
-#============================================================================
-org.quartz.scheduler.instanceName = PredictionIOScheduler
-org.quartz.scheduler.instanceId = AUTO
-org.quartz.scheduler.skipUpdateCheck = true
-
-#============================================================================
-# Configure ThreadPool
-#============================================================================
-org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
-org.quartz.threadPool.threadCount = 1
-org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
diff --git a/dist/conf/scheduler-logger.xml b/dist/conf/scheduler-logger.xml
deleted file mode 100644
index 4a1eb7f..0000000
--- a/dist/conf/scheduler-logger.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<configuration>
-
-  <conversionRule conversionWord="coloredLevel" converterClass="play.api.Logger$ColoredLevel" />
-
-  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
-     <file>${application.home}/logs/scheduler.log</file>
-     <encoder>
-       <pattern>%date - [%level] - from %logger in %thread %n%message%n%xException%n</pattern>
-     </encoder>
-   </appender>
-
-  <logger name="play" level="INFO" />
-  <logger name="application" level="INFO" />
-  <logger name="org.quartz.core.QuartzScheduler" level="INFO" />
-  <logger name="org.quartz.simpl.RAMJobStore" level="INFO" />
-  <logger name="org.quartz.impl.StdSchedulerFactory" level="INFO" />
-
-  <root level="ERROR">
-    <appender-ref ref="FILE" />
-  </root>
-
-</configuration>
diff --git a/dist/conf/versions.json b/dist/conf/versions.json
deleted file mode 100644
index 6976cf1..0000000
--- a/dist/conf/versions.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-    "latest": "0.6.8",
-    "versions": {
-        "0.5.0": {
-            "binaries": "http://download.prediction.io/PredictionIO-0.5.0.zip",
-            "sources": "http://download.prediction.io/PredictionIO-0.5.0-sources.zip"
-        },
-        "0.5.1": {
-            "binaries": "http://download.prediction.io/PredictionIO-0.5.1.zip",
-            "sources": "http://download.prediction.io/PredictionIO-0.5.1-sources.zip"
-        },
-        "0.5.2": {
-            "binaries": "http://download.prediction.io/PredictionIO-0.5.2.zip",
-            "sources": "http://download.prediction.io/PredictionIO-0.5.2-sources.zip"
-        },
-        "0.6.0": {
-            "binaries": "http://download.prediction.io/PredictionIO-0.6.0.zip",
-            "sources": "http://download.prediction.io/PredictionIO-0.6.0-sources.zip"
-        }
-    }
-}
diff --git a/output/.gitignore b/output/.gitignore
deleted file mode 100644
index 069bbbe..0000000
--- a/output/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-/project/
-target/
diff --git a/output/build.sbt b/output/build.sbt
deleted file mode 100644
index 3b8d615..0000000
--- a/output/build.sbt
+++ /dev/null
@@ -1,7 +0,0 @@
-name := "predictionio-output"
-
-scalacOptions in (Compile, doc) ++= Opts.doc.title(
-  "PredictionIO Output API Documentation")
-
-libraryDependencies  ++= Seq(
-  "org.scalanlp" %% "breeze" % "0.7")
diff --git a/output/src/main/scala/io/prediction/output/AlgoOutputSelector.scala b/output/src/main/scala/io/prediction/output/AlgoOutputSelector.scala
deleted file mode 100644
index a825468..0000000
--- a/output/src/main/scala/io/prediction/output/AlgoOutputSelector.scala
+++ /dev/null
@@ -1,73 +0,0 @@
-package io.prediction.output
-
-import io.prediction.commons.settings._
-
-class AlgoOutputSelector(algos: Algos) {
-  val multipleAlgoErrorMsg = "Deploying multiple algorithms is not yet supported. No results can be returned."
-
-  def itemRecSelection(uid: String, n: Int, itypes: Option[Seq[String]], latlng: Option[Tuple2[Double, Double]], within: Option[Double], unit: Option[String])(implicit app: App, engine: Engine): Seq[String] = {
-    implicit val algo = itemRecAlgoSelection(engine)
-
-    itemrec.ItemRecAlgoOutput.output(uid, n, itypes, latlng, within, unit)
-  }
-
-  def itemRecAlgoSelection(engine: Engine): Algo = {
-    /** Check engine type. */
-    if (engine.infoid != "itemrec") throw new RuntimeException("Not an itemrec engine (id: %d, name: %s, type: %s)" format (engine.id, engine.name, engine.infoid))
-
-    val itemRecAlgos = algos.getDeployedByEngineid(engine.id)
-
-    if (!itemRecAlgos.hasNext) throw new RuntimeException("No deployed algorithm for specified engine (id: %d, name: %s, type: %s)" format (engine.id, engine.name, engine.infoid))
-
-    val algo = itemRecAlgos.next()
-
-    /** Multiple deployment not yet supported. */
-    if (itemRecAlgos.hasNext) throw new RuntimeException(multipleAlgoErrorMsg)
-
-    algo
-  }
-
-  def itemSimSelection(iid: String, n: Int, itypes: Option[Seq[String]], latlng: Option[Tuple2[Double, Double]], within: Option[Double], unit: Option[String])(implicit app: App, engine: Engine): Seq[String] = {
-    implicit val algo = itemSimAlgoSelection(engine)
-
-    itemsim.ItemSimAlgoOutput.output(iid, n, itypes, latlng, within, unit)
-  }
-
-  def itemSimAlgoSelection(engine: Engine): Algo = {
-    /** Check engine type. */
-    if (engine.infoid != "itemsim") throw new RuntimeException("Not an itemsim engine (id: %d, name: %s, type: %s)" format (engine.id, engine.name, engine.infoid))
-
-    val itemSimAlgos = algos.getDeployedByEngineid(engine.id)
-
-    if (!itemSimAlgos.hasNext) throw new RuntimeException("No deployed algorithm for specified engine (id: %d, name: %s, type: %s)" format (engine.id, engine.name, engine.infoid))
-
-    val algo = itemSimAlgos.next()
-
-    /** Multiple deployment not yet supported. */
-    if (itemSimAlgos.hasNext) throw new RuntimeException(multipleAlgoErrorMsg)
-
-    algo
-  }
-
-  def itemRankSelection(uid: String, iids: Seq[String])(implicit app: App, engine: Engine): Seq[String] = {
-    implicit val algo = itemRankAlgoSelection(engine)
-
-    itemrank.ItemRankAlgoOutput.output(uid, iids)
-  }
-
-  def itemRankAlgoSelection(engine: Engine): Algo = {
-    /** Check engine type. */
-    if (engine.infoid != "itemrank") throw new RuntimeException("Not an itemrank engine (id: %d, name: %s, type: %s)" format (engine.id, engine.name, engine.infoid))
-
-    val itemRankAlgos = algos.getDeployedByEngineid(engine.id)
-
-    if (!itemRankAlgos.hasNext) throw new RuntimeException("No deployed algorithm for specified engine (id: %d, name: %s, type: %s)" format (engine.id, engine.name, engine.infoid))
-
-    val algo = itemRankAlgos.next()
-
-    /** Multiple deployment not yet supported. */
-    if (itemRankAlgos.hasNext) throw new RuntimeException(multipleAlgoErrorMsg)
-
-    algo
-  }
-}
diff --git a/output/src/main/scala/io/prediction/output/itemrank/ItemRankAlgoOutput.scala b/output/src/main/scala/io/prediction/output/itemrank/ItemRankAlgoOutput.scala
deleted file mode 100644
index 86c2bbd..0000000
--- a/output/src/main/scala/io/prediction/output/itemrank/ItemRankAlgoOutput.scala
+++ /dev/null
@@ -1,93 +0,0 @@
-package io.prediction.output.itemrank
-
-import io.prediction.commons.Config
-import io.prediction.commons.appdata.{ Item, Items }
-import io.prediction.commons.modeldata.ItemRecScore
-import io.prediction.commons.settings.{ Algo, App, Engine, OfflineEval }
-
-import com.github.nscala_time.time.Imports._
-
-trait ItemRankAlgoOutput {
-  /** output the Seq of iids */
-  def output(uid: String, iids: Seq[String], instant: DateTime)(implicit app: App, algo: Algo,
-    offlineEval: Option[OfflineEval]): Seq[(String, Double)]
-}
-
-object ItemRankAlgoOutput {
-  val config = new Config
-
-  def freshnessOutput(output: Seq[(Item, Double)])(implicit app: App,
-    engine: Engine, items: Items) = {
-    val freshness = engine.params.get("freshness").map(_.asInstanceOf[Int])
-    val freshnessTimeUnit = engine.params.get("freshnessTimeUnit").map(
-      _.asInstanceOf[Long])
-    /** Freshness output. */
-    (freshness, freshnessTimeUnit) match {
-      case (Some(f), Some(ftu)) => if (f > 0) {
-        val recommendationTime = DateTime.now.millis
-        output.map { itemAndScore =>
-          val item = itemAndScore._1
-          item.starttime map { st =>
-            val timeDiff = (recommendationTime - st.millis) / 1000 / ftu
-            if (timeDiff > 0)
-              (itemAndScore._1, itemAndScore._2 * scala.math.exp(-timeDiff /
-                (11 - f)))
-            else
-              itemAndScore
-          } getOrElse itemAndScore
-        }.sortBy(t => t._2).reverse
-      } else output
-      case _ => output
-    }
-  }
-
-  /**
-   * The ItemRec output does the following in sequence:
-   *
-   * - determine capabilities that needs to be handled by the engine
-   * - compute the number of items for the engine to postprocess
-   * - perform mandatory filtering (geo, time)
-   * - perform postprocessing capabilities
-   * - output items
-   */
-  def output(uid: String, iids: Seq[String])(implicit app: App, engine: Engine,
-    algo: Algo, offlineEval: Option[OfflineEval] = None): Seq[String] = {
-    val algoInfos = config.getSettingsAlgoInfos
-    implicit val items = offlineEval map { _ =>
-      config.getAppdataTrainingItems
-    } getOrElse { config.getAppdataItems }
-
-    /**
-     * Determine capability of algo to see what this engine output layer needs
-     * to handle.
-     */
-    val engineCapabilities = Seq("freshness")
-    val algoCapabilities = algoInfos.get(algo.infoid).map(_.capabilities).
-      getOrElse(Seq())
-    val handledByEngine = engineCapabilities.filterNot(
-      algoCapabilities.contains(_))
-
-    // Time-dependent logic should reference to the same instant.
-    val instant = DateTime.now
-
-    /**
-     * If no recommendations found for this user, simply return the original
-     * list.
-     */
-    val ranked = ItemRankAllItemOutput.output(uid, iids, instant)
-    val (rankedIids, rankedScores) = ranked.unzip
-    val rankedIidsSet = rankedIids.toSet
-    val rankedItemsMap = items.getByIds(app.id, rankedIids).map(x => x.id -> x)
-      .toMap
-    val rankedItems = rankedIids.map(x => rankedItemsMap(x))
-    val unranked = iids.filterNot(x => rankedIidsSet(x))
-    val preFinalOutput = handledByEngine
-      .foldLeft(rankedItems.zip(rankedScores)) {
-        (output, cap) =>
-          cap match {
-            case "freshness" => freshnessOutput(output)
-          }
-      }
-    preFinalOutput.map(_._1.id) ++ unranked
-  }
-}
diff --git a/output/src/main/scala/io/prediction/output/itemrank/ItemRankAllItemOutput.scala b/output/src/main/scala/io/prediction/output/itemrank/ItemRankAllItemOutput.scala
deleted file mode 100644
index bcaa030..0000000
--- a/output/src/main/scala/io/prediction/output/itemrank/ItemRankAllItemOutput.scala
+++ /dev/null
@@ -1,30 +0,0 @@
-package io.prediction.output.itemrank
-
-import io.prediction.commons.Config
-import io.prediction.commons.settings.{ Algo, App, Engine, OfflineEval }
-
-import com.github.nscala_time.time.Imports._
-
-object ItemRankAllItemOutput extends ItemRankAlgoOutput {
-  val config = new Config
-
-  override def output(uid: String, iids: Seq[String],
-    instant: DateTime)(implicit app: App, algo: Algo,
-      offlineEval: Option[OfflineEval]): Seq[(String, Double)] = {
-    val itemRecScores = offlineEval map { _ =>
-      config.getModeldataTrainingItemRecScores
-    } getOrElse { config.getModeldataItemRecScores }
-    val allItemsForUid = itemRecScores.getByUid(uid)
-
-    /**
-     * Rank based on scores. If no recommendations found for this user,
-     * simply return the original list.
-     */
-    val n = iids.size
-    val iidsSet = iids.toSet
-    allItemsForUid map { allItems =>
-      allItems.iids.zip(allItems.scores).filter(p => iidsSet(p._1)).sortBy(_._2)
-        .reverse
-    } getOrElse Seq[(String, Double)]()
-  }
-}
diff --git a/output/src/main/scala/io/prediction/output/itemrec/ItemRecAlgoOutput.scala b/output/src/main/scala/io/prediction/output/itemrec/ItemRecAlgoOutput.scala
deleted file mode 100644
index 53c5e03..0000000
--- a/output/src/main/scala/io/prediction/output/itemrec/ItemRecAlgoOutput.scala
+++ /dev/null
@@ -1,188 +0,0 @@
-package io.prediction.output.itemrec
-
-import io.prediction.commons.Config
-import io.prediction.commons.appdata.{ Item, Items }
-import io.prediction.commons.modeldata.ItemRecScore
-import io.prediction.commons.settings.{ Algo, App, Engine, OfflineEval }
-
-import scala.util.Random
-import scala.collection.mutable
-
-import com.github.nscala_time.time.Imports._
-
-trait ItemRecAlgoOutput {
-  /** output the Seq of iids */
-  def output(uid: String, n: Int, itypes: Option[Seq[String]],
-    instant: DateTime)(
-      implicit app: App, algo: Algo,
-      offlineEval: Option[OfflineEval]): Seq[(String, Double)]
-}
-
-object ItemRecAlgoOutput {
-  val config = new Config
-
-  def serendipityN(n: Int)(implicit engine: Engine) = {
-    /** Serendipity settings. */
-    val serendipity = engine.params.get("serendipity").map(_.asInstanceOf[Int])
-
-    /**
-     * Serendipity value (s) from 0-10 in engine settings.
-     * Implemented as randomly picking items from top n*(s+1) results.
-     */
-    serendipity.map { s => n * (s + 1) }.getOrElse(n)
-  }
-
-  def serendipityOutput(output: Seq[(Item, Double)],
-    n: Int)(implicit engine: Engine) = {
-    val serendipity = engine.params.get("serendipity").map(_.asInstanceOf[Int])
-    /** Serendipity output. */
-    serendipity.map { s =>
-      if (s > 0)
-        Random.shuffle(output.take(n * (s + 1)))
-      else
-        output
-    } getOrElse output
-  }
-
-  def freshnessOutput(output: Seq[(Item, Double)])(implicit app: App,
-    engine: Engine, items: Items) = {
-    val freshness = engine.params.get("freshness").map(_.asInstanceOf[Int])
-    val freshnessTimeUnit = engine.params.get("freshnessTimeUnit").map(
-      _.asInstanceOf[Long])
-    /** Freshness output. */
-    (freshness, freshnessTimeUnit) match {
-      case (Some(f), Some(ftu)) => if (f > 0) {
-        val recommendationTime = DateTime.now.millis
-        output.map { itemAndScore =>
-          val item = itemAndScore._1
-          item.starttime map { st =>
-            val timeDiff = (recommendationTime - st.millis) / 1000 / ftu
-            if (timeDiff > 0)
-              (itemAndScore._1, itemAndScore._2 * scala.math.exp(-timeDiff /
-                (11 - f)))
-            else
-              itemAndScore
-          } getOrElse itemAndScore
-        }.sortBy(t => t._2).reverse
-      } else output
-      case _ => output
-    }
-  }
-
-  private def dedupByAttribute(output: Seq[(Item, Double)],
-    attribute: String) = {
-    val seenValueSet = mutable.Set[String]()
-    output.filter { itemAndScore =>
-      if (itemAndScore._1.attributes.isEmpty) {
-        false
-      } else if (!itemAndScore._1.attributes.get.contains(attribute)) {
-        // If item doesn't have the attribute, drop the item
-        false
-      } else {
-        val attributeValue = itemAndScore._1.attributes.get(attribute)
-          .asInstanceOf[String]
-        if (seenValueSet(attributeValue)) {
-          false
-        } else {
-          seenValueSet.add(attributeValue)
-          true
-        }
-      }
-    }
-  }
-
-  def dedupOutput(output: Seq[(Item, Double)])(implicit engine: Engine) = {
-    val attribute = engine.params.get("dedupByAttribute")
-      .map(_.asInstanceOf[String])
-
-    if (!attribute.isEmpty && attribute.get != "")
-      dedupByAttribute(output, attribute.get)
-    else
-      output
-  }
-
-  /**
-   * The ItemRec output does the following in sequence:
-   *
-   * - determine capabilities that needs to be handled by the engine
-   * - compute the number of items for the engine to postprocess
-   * - perform mandatory filtering (geo, time)
-   * - perform postprocessing capabilities
-   * - output items
-   */
-  def output(uid: String, n: Int, itypes: Option[Seq[String]],
-    latlng: Option[Tuple2[Double, Double]], within: Option[Double],
-    unit: Option[String])(implicit app: App, engine: Engine, algo: Algo,
-      offlineEval: Option[OfflineEval] = None): Seq[String] = {
-    val algoInfos = config.getSettingsAlgoInfos
-    implicit val items = offlineEval map { _ =>
-      config.getAppdataTrainingItems
-    } getOrElse { config.getAppdataItems }
-
-    /**
-     * Determine capability of algo to see what this engine output layer needs
-     * to handle.
-     */
-    val engineCapabilities = Seq("dedupByAttribute", "freshness", "serendipity")
-    val algoCapabilities = algoInfos.get(algo.infoid).map(_.capabilities).
-      getOrElse(Seq())
-    val handledByEngine = engineCapabilities.filterNot(
-      algoCapabilities.contains(_))
-
-    // Determine the number of items to process in the filtering stage.
-    val filterN = handledByEngine.foldLeft(n) { (n, cap) =>
-      if (cap == "serendipity") serendipityN(n) else n
-    }
-
-    // Time-dependent logic should reference to the same instant.
-    val instant = DateTime.now
-
-    /**
-     * At the moment, PredictionIO depends only on MongoDB for its model data
-     * storage. Since we are still using the legacy longitude-latitude format,
-     * the maximum number of documents that can be returned from a query with
-     * geospatial constraint is 100. A "manual join" is still feasible with this
-     * size.
-     */
-    val iidsAndScores =
-      latlng.map { ll =>
-        val geoItems = items.getByAppidAndLatlng(app.id, ll, within, unit)
-          .map(_.id).toSet
-        // use n = 0 to return all available iids for now
-        ItemRecCFAlgoOutput.output(uid, 0, itypes, instant).filter(t => geoItems(t._1))
-      }.getOrElse {
-        // use n = 0 to return all available iids for now
-        ItemRecCFAlgoOutput.output(uid, 0, itypes, instant)
-      }.toSeq
-    val iids = iidsAndScores map { _._1 }
-
-    /** Start and end time filtering. */
-    val itemsForTimeCheck = items.getByIds(app.id, iids)
-    // valid time and !inactive
-    val iidsWithValidMap = (itemsForTimeCheck filter { item =>
-      val validTime = (item.starttime, item.endtime) match {
-        case (Some(st), None) => instant >= st
-        case (None, Some(et)) => instant <= et
-        case (Some(st), Some(et)) => st <= instant && instant <= et
-        case _ => true
-      }
-      val inactive = item.inactive.getOrElse(false)
-      validTime && (!inactive)
-    }).map(item => (item.id, item)).toMap
-
-    val itemsAndScoresWithValid = iidsAndScores
-      .filter(t => iidsWithValidMap.contains(t._1))
-      .map(t => (iidsWithValidMap(t._1), t._2))
-
-    val finalOutput = handledByEngine.foldLeft(itemsAndScoresWithValid) {
-      (output, cap) =>
-        cap match {
-          case "dedupByAttribute" => dedupOutput(output)
-          case "freshness" => freshnessOutput(output)
-          case "serendipity" => serendipityOutput(output, n)
-        }
-    }
-
-    finalOutput.take(n).map(_._1.id)
-  }
-}
diff --git a/output/src/main/scala/io/prediction/output/itemrec/ItemRecAlgoRealtimeOutput.scala b/output/src/main/scala/io/prediction/output/itemrec/ItemRecAlgoRealtimeOutput.scala
deleted file mode 100644
index b89cf35..0000000
--- a/output/src/main/scala/io/prediction/output/itemrec/ItemRecAlgoRealtimeOutput.scala
+++ /dev/null
@@ -1,55 +0,0 @@
-package io.prediction.output.itemrec
-
-import io.prediction.commons.Config
-import io.prediction.commons.modeldata.ItemRecScore
-import io.prediction.commons.settings.{ Algo, App, OfflineEval }
-import com.github.nscala_time.time.Imports._
-
-object UserProfileRecommendationRealtimeOutput {
-  private val config = new Config
-  def output(uid: String, n: Int, itypes: Option[Seq[String]],
-    instant: DateTime)(implicit app: App, algo: Algo,
-      offlineEval: Option[OfflineEval]): Seq[(String, Double)] = {
-    // We ignore the parameter n here, since some items are filtered.
-    val itemRecScores = config.getModeldataItemRecScores
-    val itemRecScore = itemRecScores.getByUid(uid).get
-
-    val metadataKeyvals = config.getModeldataMetadataKeyvals
-    val optionalFeatureStr = metadataKeyvals.get(algo.id, algo.modelset, "features")
-    if (optionalFeatureStr.isEmpty) {
-      // When feature list not found in metadata, cannot recommendend items.
-      // TODO: Return better error message.
-      return Seq[(String, Double)]()
-    }
-    val features = optionalFeatureStr.get.split(',')
-    val featureScores = itemRecScore.scores
-    val featureScoreMap = features.zip(featureScores).toMap
-
-    val items = config.getAppdataItems
-    val itemList = items
-      .getByAppidAndItypesAndTime(app.id, itypes, Some(instant))
-      .filter(!_.inactive.getOrElse(false)) // Remove inactive items.
-      .toSeq
-
-    val itemScoreList = itemList.map { item =>
-      {
-        val score = item.itypes.map { itype =>
-          featureScoreMap.getOrElse(itype, 0).asInstanceOf[Double]
-        }.sum
-        (item, score)
-      }
-    }
-
-    itemScoreList.sortBy(_._2).map(e => (e._1.id, e._2))
-  }
-}
-
-object ItemRecAlgoRealtimeOutput {
-  private val config = new Config
-
-  def output(uid: String, n: Int, itypes: Option[Seq[String]],
-    instant: DateTime)(implicit app: App, algo: Algo, offlineEval: Option[OfflineEval]) = {
-    // Not handling offline eval
-    UserProfileRecommendationRealtimeOutput.output(uid, n, itypes, instant)
-  }
-}
diff --git a/output/src/main/scala/io/prediction/output/itemrec/ItemRecCFAlgoBatchOutput.scala b/output/src/main/scala/io/prediction/output/itemrec/ItemRecCFAlgoBatchOutput.scala
deleted file mode 100644
index 6ddfc73..0000000
--- a/output/src/main/scala/io/prediction/output/itemrec/ItemRecCFAlgoBatchOutput.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package io.prediction.output.itemrec
-
-import io.prediction.commons.Config
-import io.prediction.commons.modeldata.ItemRecScore
-import io.prediction.commons.settings.{ Algo, App, OfflineEval }
-import com.github.nscala_time.time.Imports._
-
-object ItemRecCFAlgoBatchOutput {
-  private val config = new Config
-
-  def output(uid: String, n: Int,
-    itypes: Option[Seq[String]], instant: DateTime)(
-      implicit app: App, algo: Algo,
-      offlineEval: Option[OfflineEval]): Seq[(String, Double)] = {
-    val itemRecScores = offlineEval map { _ =>
-      config.getModeldataTrainingItemRecScores
-    } getOrElse config.getModeldataItemRecScores
-    itemRecScores.getTopNIidsAndScores(uid, n, itypes)
-  }
-}
diff --git a/output/src/main/scala/io/prediction/output/itemrec/ItemRecCFAlgoOutput.scala b/output/src/main/scala/io/prediction/output/itemrec/ItemRecCFAlgoOutput.scala
deleted file mode 100644
index d242243..0000000
--- a/output/src/main/scala/io/prediction/output/itemrec/ItemRecCFAlgoOutput.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package io.prediction.output.itemrec
-
-import io.prediction.commons.modeldata.ItemRecScore
-import io.prediction.commons.settings.{ App, Algo, OfflineEval }
-import com.github.nscala_time.time.Imports._
-
-object ItemRecCFAlgoOutput extends ItemRecAlgoOutput {
-  override def output(uid: String, n: Int, itypes: Option[Seq[String]],
-    instant: DateTime)(implicit app: App, algo: Algo, offlineEval: Option[OfflineEval]): Seq[(String, Double)] = {
-    /** FIXME(someone). Ugly hack for realtime algorithms. **/
-    if (algo.infoid == "pio-itemrec-single-featurebased_realtime") {
-      ItemRecAlgoRealtimeOutput.output(uid, n, itypes, instant)
-    } else {
-      ItemRecCFAlgoBatchOutput.output(uid, n, itypes, instant)
-    }
-  }
-}
diff --git a/output/src/main/scala/io/prediction/output/itemsim/ItemSimAlgoOutput.scala b/output/src/main/scala/io/prediction/output/itemsim/ItemSimAlgoOutput.scala
deleted file mode 100644
index 18ffe8b..0000000
--- a/output/src/main/scala/io/prediction/output/itemsim/ItemSimAlgoOutput.scala
+++ /dev/null
@@ -1,175 +0,0 @@
-package io.prediction.output.itemsim
-
-import io.prediction.commons.Config
-import io.prediction.commons.appdata.{ Item, Items }
-import io.prediction.commons.modeldata.ItemSimScore
-import io.prediction.commons.settings.{ Algo, App, Engine, OfflineEval }
-
-import scala.util.Random
-import scala.collection.mutable
-
-import com.github.nscala_time.time.Imports._
-
-trait ItemSimAlgoOutput {
-  def output(iid: String, n: Int, itypes: Option[Seq[String]])(
-    implicit app: App, algo: Algo,
-    offlineEval: Option[OfflineEval]): Seq[(String, Double)]
-}
-
-object ItemSimAlgoOutput {
-  val config = new Config
-
-  def serendipityN(n: Int)(implicit engine: Engine) = {
-    /** Serendipity settings. */
-    val serendipity = engine.params.get("serendipity").map(_.asInstanceOf[Int])
-
-    /**
-     * Serendipity value (s) from 0-10 in engine settings.
-     * Implemented as randomly picking items from top n*(s+1) results.
-     */
-    serendipity.map { s => n * (s + 1) }.getOrElse(n)
-  }
-
-  def serendipityOutput(output: Seq[(Item, Double)],
-    n: Int)(implicit engine: Engine) = {
-    val serendipity = engine.params.get("serendipity").map(_.asInstanceOf[Int])
-    /** Serendipity output. */
-    serendipity.map { s =>
-      if (s > 0)
-        Random.shuffle(output.take(n * (s + 1)))
-      else
-        output
-    } getOrElse output
-  }
-
-  def freshnessOutput(output: Seq[(Item, Double)])(implicit app: App,
-    engine: Engine, items: Items) = {
-    val freshness = engine.params.get("freshness").map(_.asInstanceOf[Int])
-    val freshnessTimeUnit = engine.params.get("freshnessTimeUnit").map(
-      _.asInstanceOf[Long])
-    /** Freshness output. */
-    (freshness, freshnessTimeUnit) match {
-      case (Some(f), Some(ftu)) => if (f > 0) {
-        val recommendationTime = DateTime.now.millis
-        output.map { itemAndScore =>
-          val item = itemAndScore._1
-          item.starttime map { st =>
-            val timeDiff = (recommendationTime - st.millis) / 1000 / ftu
-            if (timeDiff > 0)
-              (itemAndScore._1, itemAndScore._2 * scala.math.exp(-timeDiff /
-                (11 - f)))
-            else
-              itemAndScore
-          } getOrElse itemAndScore
-        }.sortBy(t => t._2).reverse
-      } else output
-      case _ => output
-    }
-  }
-
-  private def dedupByAttribute(output: Seq[(Item, Double)],
-    attribute: String) = {
-    val seenValueSet = mutable.Set[String]()
-    output.filter { itemAndScore =>
-      if (itemAndScore._1.attributes.isEmpty) {
-        false
-      } else if (!itemAndScore._1.attributes.get.contains(attribute)) {
-        // If item doesn't have the attribute, drop the item
-        false
-      } else {
-        val attributeValue = itemAndScore._1.attributes.get(attribute)
-          .asInstanceOf[String]
-        if (seenValueSet(attributeValue)) {
-          false
-        } else {
-          seenValueSet.add(attributeValue)
-          true
-        }
-      }
-    }
-  }
-
-  def dedupOutput(output: Seq[(Item, Double)])(implicit engine: Engine) = {
-    val attribute = engine.params.get("dedupByAttribute")
-      .map(_.asInstanceOf[String])
-
-    if (!attribute.isEmpty && attribute.get != "")
-      dedupByAttribute(output, attribute.get)
-    else
-      output
-  }
-
-  def output(iid: String, n: Int, itypes: Option[Seq[String]],
-    latlng: Option[Tuple2[Double, Double]], within: Option[Double],
-    unit: Option[String])(implicit app: App, engine: Engine, algo: Algo,
-      offlineEval: Option[OfflineEval] = None): Seq[String] = {
-    val algoInfos = config.getSettingsAlgoInfos
-    implicit val items = offlineEval map { _ =>
-      config.getAppdataTrainingItems
-    } getOrElse { config.getAppdataItems }
-
-    /**
-     * Determine capability of algo to see what this engine output layer needs
-     * to handle.
-     */
-    val engineCapabilities = Seq("dedupByAttribute", "freshness", "serendipity")
-    val algoCapabilities = algoInfos.get(algo.infoid).map(_.capabilities).
-      getOrElse(Seq())
-    val handledByEngine = engineCapabilities.filterNot(
-      algoCapabilities.contains(_))
-
-    // Determine the number of items to process in the filtering stage.
-    val filterN = handledByEngine.foldLeft(n) { (n, cap) =>
-      if (cap == "serendipity") serendipityN(n) else n
-    }
-
-    // Time-dependent logic should reference to the same instant.
-    val instant = DateTime.now
-
-    /**
-     * At the moment, PredictionIO depends only on MongoDB for its model data storage.
-     * Since we are still using the legacy longitude-latitude format, the maximum number
-     * of documents that can be returned from a query with geospatial constraint is 100.
-     * A "manual join" is still feasible with this size.
-     */
-    val iidsAndScores = latlng.map { ll =>
-      val geoItems = items.getByAppidAndLatlng(app.id, ll, within, unit)
-        .map(_.id).toSet
-      // use n = 0 to return all available iids for now
-      ItemSimCFAlgoOutput.output(iid, 0, itypes).filter(t => geoItems(t._1))
-    }.getOrElse {
-      // use n = 0 to return all available iids for now
-      ItemSimCFAlgoOutput.output(iid, 0, itypes)
-    }
-    val iids = iidsAndScores map { _._1 }
-
-    /** Start and end time filtering. */
-    val itemsForTimeCheck = items.getByIds(app.id, iids)
-    // valid time and !inactive
-    val iidsWithValidMap = (itemsForTimeCheck filter { item =>
-      val validTime = (item.starttime, item.endtime) match {
-        case (Some(st), None) => instant >= st
-        case (None, Some(et)) => instant <= et
-        case (Some(st), Some(et)) => st <= instant && instant <= et
-        case _ => true
-      }
-      val inactive = item.inactive.getOrElse(false)
-      validTime && (!inactive)
-    }).map(item => (item.id, item)).toMap
-
-    val itemsAndScoresWithValid = iidsAndScores
-      .filter(t => iidsWithValidMap.contains(t._1))
-      .map(t => (iidsWithValidMap(t._1), t._2))
-
-    val finalOutput = handledByEngine.foldLeft(itemsAndScoresWithValid) {
-      (output, cap) =>
-        cap match {
-          case "dedupByAttribute" => dedupOutput(output)
-          case "freshness" => freshnessOutput(output)
-          case "serendipity" => serendipityOutput(output, n)
-        }
-    }
-
-    finalOutput.take(n).map(_._1.id)
-  }
-}
diff --git a/output/src/main/scala/io/prediction/output/itemsim/ItemSimCFAlgoBatchOutput.scala b/output/src/main/scala/io/prediction/output/itemsim/ItemSimCFAlgoBatchOutput.scala
deleted file mode 100644
index b4d8fd9..0000000
--- a/output/src/main/scala/io/prediction/output/itemsim/ItemSimCFAlgoBatchOutput.scala
+++ /dev/null
@@ -1,53 +0,0 @@
-package io.prediction.output.itemsim
-
-import io.prediction.commons.Config
-import io.prediction.commons.modeldata.{ ItemSimScore, ItemSimScores }
-import io.prediction.commons.settings.{ Algo, App, OfflineEval }
-
-import breeze.stats.{ mean, variance }
-import scala.math
-
-object ItemSimCFAlgoBatchOutput {
-  private val config = new Config
-
-  def combinedOutput(itemSimScores: ItemSimScores, iidList: Seq[String],
-    n: Int, itypes: Option[Seq[String]])(
-      implicit app: App, algo: Algo, offlineEval: Option[OfflineEval]) = {
-    val iidSet = iidList.toSet
-
-    val iidScoreList = iidList.map { iid =>
-      {
-        val itemScores = itemSimScores.getTopNIidsAndScores(iid, 0, itypes)
-        val scores = itemScores.map(_._2)
-        val meanScore = mean(scores)
-        val stdevScore = math.sqrt(variance(scores))
-
-        val itemStdScoreList = itemScores
-          // remove input items from output list
-          .filter { case (item, score) => !iidSet.contains(item) }
-          .map { case (item, score) => (item, (score - meanScore) / stdevScore) }
-        itemStdScoreList
-      }
-    }.flatten
-
-    // Sum score group by iid, then sort by score in descending order
-    iidScoreList.groupBy(_._1).mapValues(_.map(_._2).sum).toSeq.sortBy(-_._2)
-  }
-
-  // iid can be a comma-delimited list of iids. In such case, this function
-  // takes a union of all the simliar items and sorts by standardized score.
-  def output(iid: String, n: Int, itypes: Option[Seq[String]])(
-    implicit app: App, algo: Algo, offlineEval: Option[OfflineEval]): Seq[(String, Double)] = {
-    val itemSimScores = offlineEval map { _ =>
-      config.getModeldataTrainingItemSimScores
-    } getOrElse config.getModeldataItemSimScores
-
-    //itemSimScores.getTopNIidsAndScores(iid, n, itypes)
-    val iidList = iid.split(',')
-    if (iidList.length == 1) {
-      itemSimScores.getTopNIidsAndScores(iid, n, itypes)
-    } else {
-      combinedOutput(itemSimScores, iidList, n, itypes)
-    }
-  }
-}
diff --git a/output/src/main/scala/io/prediction/output/itemsim/ItemSimCFAlgoOutput.scala b/output/src/main/scala/io/prediction/output/itemsim/ItemSimCFAlgoOutput.scala
deleted file mode 100644
index a4a3e1b..0000000
--- a/output/src/main/scala/io/prediction/output/itemsim/ItemSimCFAlgoOutput.scala
+++ /dev/null
@@ -1,13 +0,0 @@
-package io.prediction.output.itemsim
-
-import io.prediction.commons.modeldata.ItemSimScore
-import io.prediction.commons.settings.{ App, Algo, OfflineEval }
-
-object ItemSimCFAlgoOutput extends ItemSimAlgoOutput {
-  override def output(iid: String, n: Int, itypes: Option[Seq[String]])(
-    implicit app: App, algo: Algo,
-    offlineEval: Option[OfflineEval]): Seq[(String, Double)] = {
-    /** Batch mode output only for now. */
-    ItemSimCFAlgoBatchOutput.output(iid, n, itypes)
-  }
-}
diff --git a/output/src/test/resources/application.conf b/output/src/test/resources/application.conf
deleted file mode 100644
index 82b936a..0000000
--- a/output/src/test/resources/application.conf
+++ /dev/null
@@ -1,15 +0,0 @@
-io.prediction.base=..
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.name=predictionio_algooutputselection_test
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.name=predictionio_algooutputselection_test
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.name=predictionio_algooutputselection_test
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.name=predictionio_algooutputselection_test
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.name=predictionio_algooutputselection_test
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.name=predictionio_algooutputselection_test
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.name=predictionio_algooutputselection_test
diff --git a/output/src/test/scala/io/prediction/output/AlgoOutputSelectorSpec.scala b/output/src/test/scala/io/prediction/output/AlgoOutputSelectorSpec.scala
deleted file mode 100644
index 2c60721..0000000
--- a/output/src/test/scala/io/prediction/output/AlgoOutputSelectorSpec.scala
+++ /dev/null
@@ -1,1757 +0,0 @@
-package io.prediction.output
-
-import io.prediction.commons.Config
-import io.prediction.commons.appdata._
-import io.prediction.commons.appdata.mongodb._
-import io.prediction.commons.modeldata._
-import io.prediction.commons.modeldata.mongodb._
-import io.prediction.commons.settings._
-import io.prediction.commons.settings.mongodb._
-
-import org.specs2._
-import org.specs2.specification.Step
-
-import com.mongodb.casbah.Imports._
-import com.github.nscala_time.time.Imports._
-
-class AlgoOutputSelectorSpec extends Specification {
-  def is = s2"""
-
-  PredictionIO AlgoOutputSelector Specification
-
-  get itemrec output from a valid engine ${itemRecOutputSelection(algoOutputSelector)}
-  get itemrec output from a valid engine with freshness ${itemRecOutputSelectionWithFreshness(algoOutputSelector)}
-  get itemrec output with geo from a valid engine ${itemRecOutputSelectionWithLatlng(algoOutputSelector)}
-  get itemrec output with time constraints from a valid engine ${itemRecOutputSelectionWithTime(algoOutputSelector)}
-  get itemrec output with inactive constraints from a valid engine ${itemRecOutputSelectionWithInactive(algoOutputSelector)}
-  get itemrec output with dedup from a valid engine ${itemRecOutputSelectionDedupByAttribute(algoOutputSelector)}
-  get itemrec output from a valid engine with no algorithm ${itemRecOutputSelectionNoAlgo(algoOutputSelector)}
-  get itemrec output from an invalid engine ${itemRecOutputSelectionBadEngine(algoOutputSelector)}
-
-  get itemsim output from a valid engine ${itemSimOutputSelection(algoOutputSelector)}
-  get itemsim output from a valid engine with freshness ${itemSimOutputSelectionWithFreshness(algoOutputSelector)}
-  get itemsim output with geo from a valid engine ${itemSimOutputSelectionWithLatlng(algoOutputSelector)}
-  get itemsim output with time constraints from a valid engine ${itemSimOutputSelectionWithTime(algoOutputSelector)}
-  get itemsim output with inactive constraints from a valid engine ${itemSimOutputSelectionWithInactive(algoOutputSelector)}
-  get itemsim output with dedup from a valid engine ${itemSimOutputSelectionDedupByAttribute(algoOutputSelector)}
-  get itemsim output from a valid engine with no algorithm ${itemSimOutputSelectionNoAlgo(algoOutputSelector)}
-  get itemsim output from an invalid engine ${itemSimOutputSelectionBadEngine(algoOutputSelector)}
-  get itemsim output from multiple iids ${itemSimOutputSelectionMultipleIids(algoOutputSelector)}
-
-  get itemrank output from a valid engine ${itemRankOutputSelection(algoOutputSelector)}
-  get itemrank output from a valid engine with freshness ${itemRankOutputSelectionWithFreshness(algoOutputSelector)}
-  get itemrank output from a valid engine with no algorithm ${itemRankOutputSelectionNoAlgo(algoOutputSelector)}
-  get itemrank output from an invalid engine ${itemRankOutputSelectionBadEngine(algoOutputSelector)}
-
-  ${Step(mongoDb.dropDatabase())}
-
-  """
-
-  //"get itemrec output from a valid engine without seen items"               ! itemRecOutputSelectionUnseenOnly(algoOutputSelector) ^
-  //"get itemrec output from a valid engine with an unsupported algorithm"    ! itemRecOutputSelectionUnsupportedAlgo(algoOutputSelector) ^
-  //"get itemsim output from a valid engine with an unsupported algorithm"    ! itemSimOutputSelectionUnsupportedAlgo(algoOutputSelector) ^
-
-  val mongoDbName = "predictionio_algooutputselection_test"
-  val mongoDb = MongoClient()(mongoDbName)
-  val mongoEngines = new MongoEngines(mongoDb)
-  val mongoAlgos = new MongoAlgos(mongoDb)
-  val mongoItems = new MongoItems(mongoDb)
-  val mongoU2IActions = new MongoU2IActions(mongoDb)
-  val mongoItemRecScores = new MongoItemRecScores(new Config, mongoDb)
-  val mongoItemSimScores = new MongoItemSimScores(new Config, mongoDb)
-  val algoOutputSelector = new AlgoOutputSelector(mongoAlgos)
-
-  val dummyApp = App(
-    id = 0,
-    userid = 0,
-    appkey = "dummy",
-    display = "dummy",
-    url = None,
-    cat = None,
-    desc = None,
-    timezone = "UTC"
-  )
-
-  val items = Seq(Item(
-    id = "item_x",
-    appid = dummyApp.id,
-    ct = DateTime.now,
-    itypes = Seq("bar"),
-    starttime = Some(DateTime.now.minusHours(2)),
-    endtime = None,
-    price = None,
-    profit = None,
-    latlng = None,
-    inactive = None,
-    //attributes = Some(Map("ca_attr1"->"a", "ca_attr2"->"b"))
-    attributes = None
-  ), Item(
-    id = "item_y",
-    appid = dummyApp.id,
-    ct = DateTime.now,
-    itypes = Seq("bar"),
-    starttime = Some(DateTime.now.minusHours(8)),
-    endtime = None,
-    price = None,
-    profit = None,
-    latlng = None,
-    inactive = None,
-    attributes = None), Item(
-    id = "item_a",
-    appid = dummyApp.id,
-    ct = DateTime.now,
-    itypes = Seq("bar"),
-    starttime = Some(DateTime.now.minusHours(5)),
-    endtime = None,
-    price = None,
-    profit = None,
-    latlng = None,
-    inactive = None,
-    attributes = None), Item(
-    id = "item_b",
-    appid = dummyApp.id,
-    ct = DateTime.now,
-    itypes = Seq("bar"),
-    starttime = Some(DateTime.now.minusHours(3)),
-    endtime = None,
-    price = None,
-    profit = None,
-    latlng = None,
-    inactive = None,
-    attributes = None), Item(
-    id = "item_c",
-    appid = dummyApp.id,
-    ct = DateTime.now,
-    itypes = Seq("bar"),
-    starttime = Some(DateTime.now.minusHours(10)),
-    endtime = None,
-    price = None,
-    profit = None,
-    latlng = None,
-    inactive = None,
-    attributes = None), Item(
-    id = "item_d",
-    appid = dummyApp.id,
-    ct = DateTime.now,
-    itypes = Seq("bar"),
-    starttime = Some(DateTime.now.minusHours(7)),
-    endtime = None,
-    price = None,
-    profit = None,
-    latlng = None,
-    inactive = None,
-    attributes = None), Item(
-    id = "item_e",
-    appid = dummyApp.id,
-    ct = DateTime.now,
-    itypes = Seq("bar"),
-    starttime = Some(DateTime.now.minusHours(1)),
-    endtime = None,
-    price = None,
-    profit = None,
-    latlng = None,
-    inactive = None,
-    attributes = None), Item(
-    id = "item_f",
-    appid = dummyApp.id,
-    ct = DateTime.now,
-    itypes = Seq("bar"),
-    starttime = Some(DateTime.now.minusHours(10)),
-    endtime = None,
-    price = None,
-    profit = None,
-    latlng = None,
-    inactive = None,
-    attributes = None), Item(
-    id = "item_g",
-    appid = dummyApp.id,
-    ct = DateTime.now,
-    itypes = Seq("bar"),
-    starttime = Some(DateTime.now.minusHours(4)),
-    endtime = None,
-    price = None,
-    profit = None,
-    latlng = None,
-    inactive = None,
-    attributes = None), Item(
-    id = "item_h",
-    appid = dummyApp.id,
-    ct = DateTime.now,
-    itypes = Seq("bar"),
-    starttime = Some(DateTime.now.minusHours(6)),
-    endtime = None,
-    price = None,
-    profit = None,
-    latlng = None,
-    inactive = None,
-    attributes = None))
-
-  items foreach { mongoItems.insert(_) }
-
-  /** ItemRec engine. */
-  def itemRecOutputSelection(algoOutputSelector: AlgoOutputSelector) = {
-    val engine = Engine(
-      id = 0,
-      appid = dummyApp.id,
-      name = "itemRecOutputSelection",
-      infoid = "itemrec",
-      itypes = Some(Seq("foo", "bar")),
-      params = Map("serendipity" -> 5, "freshness" -> 5,
-        "freshnessTimeUnit" -> 3600L))
-    val engineid = mongoEngines.insert(engine)
-
-    val algo = Algo(
-      id = 0,
-      engineid = engineid,
-      name = "itemRecOutputSelection",
-      infoid = "pdio-knnitembased",
-      command = "itemRecOutputSelection",
-      params = Map("foo" -> "bar"),
-      settings = Map("dead" -> "beef"),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed",
-      offlineevalid = None
-    )
-    val algoid = mongoAlgos.insert(algo)
-
-    val scores = Seq(ItemRecScore(
-      uid = "user1",
-      iids = Seq("item_z", "item_h", "item_d", "item_g", "item_e", "item_f", "item_x", "item_y", "item_b", "item_c", "item_a"),
-      scores = Seq(11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1),
-      itypes = Seq(Seq("unrelated"), Seq("foo"), Seq("foo"), Seq("bar"), Seq("bar"), Seq("foo"), Seq("bar"), Seq("foo"), Seq("foo"), Seq("bar"), Seq("bar")),
-      appid = dummyApp.id,
-      algoid = algoid,
-      modelset = true))
-
-    scores foreach { mongoItemRecScores.insert(_) }
-
-    val result = algoOutputSelector.itemRecSelection("user1", 10, Some(Seq("bar", "foo")), None, None, None)(dummyApp, engine.copy(id = engineid))
-    val resultBar = algoOutputSelector.itemRecSelection("user1", 10, Some(Seq("bar")), None, None, None)(dummyApp, engine.copy(id = engineid))
-
-    result must contain(
-      "item_x",
-      "item_y",
-      "item_a",
-      "item_b",
-      "item_c",
-      "item_d",
-      "item_e",
-      "item_f",
-      "item_g",
-      "item_h") and
-      (resultBar must contain(
-        "item_a",
-        "item_c",
-        "item_e",
-        "item_x",
-        "item_g"))
-
-  }
-
-  def itemRecOutputSelectionWithFreshness(algoOutputSelector: AlgoOutputSelector) = {
-    val engine = Engine(
-      id = 0,
-      appid = dummyApp.id,
-      name = "itemRecOutputSelection",
-      infoid = "itemrec",
-      itypes = Some(Seq("foo", "bar")),
-      params = Map("serendipity" -> 0, "freshness" -> 5,
-        "freshnessTimeUnit" -> 3600L))
-    val engineid = mongoEngines.insert(engine)
-
-    val algo = Algo(
-      id = 0,
-      engineid = engineid,
-      name = "itemRecOutputSelection",
-      infoid = "pdio-knnitembased",
-      command = "itemRecOutputSelection",
-      params = Map("foo" -> "bar"),
-      settings = Map("dead" -> "beef"),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed",
-      offlineevalid = None
-    )
-    val algoid = mongoAlgos.insert(algo)
-
-    val scores = Seq(ItemRecScore(
-      uid = "user1",
-      iids = Seq("item_z", "item_h", "item_d", "item_g", "item_e", "item_f", "item_x", "item_y", "item_b", "item_c", "item_a"),
-      scores = Seq(11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1),
-      itypes = Seq(Seq("unrelated"), Seq("foo"), Seq("foo"), Seq("bar"), Seq("bar"), Seq("foo"), Seq("bar"), Seq("foo"), Seq("foo"), Seq("bar"), Seq("bar")),
-      appid = dummyApp.id,
-      algoid = algoid,
-      modelset = true))
-
-    scores foreach { mongoItemRecScores.insert(_) }
-
-    val result = algoOutputSelector.itemRecSelection("user1", 10, Some(Seq("bar", "foo")), None, None, None)(dummyApp, engine.copy(id = engineid))
-    val resultBar = algoOutputSelector.itemRecSelection("user1", 10, Some(Seq("bar")), None, None, None)(dummyApp, engine.copy(id = engineid))
-
-    result must_== Seq(
-      "item_g",
-      "item_e",
-      "item_x",
-      "item_h",
-      "item_d",
-      "item_b",
-      "item_f",
-      "item_y",
-      "item_a",
-      "item_c") and
-      (resultBar must_== Seq(
-        "item_g",
-        "item_e",
-        "item_x",
-        "item_a",
-        "item_c"))
-  }
-
-  def itemRecOutputSelectionWithLatlng(algoOutputSelector: AlgoOutputSelector) = {
-    val appid = dummyApp.id
-    val engine = Engine(
-      id = 0,
-      appid = appid,
-      name = "itemRecOutputSelectionWithLatlng",
-      infoid = "itemrec",
-      itypes = Some(Seq("foo", "bar")),
-      params = Map()
-    )
-    val engineid = mongoEngines.insert(engine)
-
-    val algo = Algo(
-      id = 0,
-      engineid = engineid,
-      name = "itemRecOutputSelectionWithLatlng",
-      infoid = "pdio-knnitembased",
-      command = "itemRecOutputSelectionWithLatlng",
-      params = Map("foo" -> "bar"),
-      settings = Map("dead" -> "beef"),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed",
-      offlineevalid = None
-    )
-    val algoid = mongoAlgos.insert(algo)
-
-    val id = "itemRecOutputSelectionWithLatlng"
-
-    val dac = Item(
-      id = id + "dac",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.3197611, -122.0466141)),
-      inactive = None,
-      attributes = Some(Map("foo" -> "bar", "foo2" -> "bar2")))
-    val hsh = Item(
-      id = id + "hsh",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.3370801, -122.0493201)),
-      inactive = None,
-      attributes = None)
-    val mvh = Item(
-      id = id + "mvh",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.3154153, -122.0566829)),
-      inactive = None,
-      attributes = Some(Map("foo3" -> "bar3")))
-    val lbh = Item(
-      id = id + "lbh",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.2997029, -122.0034684)),
-      inactive = None,
-      attributes = Some(Map("foo4" -> "bar4", "foo5" -> "bar5")))
-    val allItems = Seq(dac, hsh, lbh, mvh)
-    allItems foreach { mongoItems.insert(_) }
-
-    val scores: Seq[(String, Double, Seq[String])] = Seq(
-      // (iid, score, itypes)
-      (id + "hsh", 4, Seq("foo")),
-      (id + "mvh", 3, Seq("unrelated")),
-      (id + "lbh", 2, Seq("unrelated")),
-      (id + "dac", 1, Seq("bar")))
-
-    mongoItemRecScores.insert(ItemRecScore(
-      uid = "user1",
-      iids = scores.map(_._1),
-      scores = scores.map(_._2),
-      itypes = scores.map(_._3),
-      appid = dummyApp.id,
-      algoid = algoid,
-      modelset = true
-    ))
-
-    algoOutputSelector.itemRecSelection("user1", 10, None, Some((37.3229978, -122.0321823)), Some(2.2), None)(dummyApp, engine.copy(id = engineid)) must beEqualTo(Seq(id + "hsh", id + "dac"))
-  }
-
-  def itemRecOutputSelectionWithTime(algoOutputSelector: AlgoOutputSelector) = {
-    val appid = dummyApp.id
-    val engine = Engine(
-      id = 0,
-      appid = appid,
-      name = "itemRecOutputSelectionWithTime",
-      infoid = "itemrec",
-      itypes = Some(Seq("foo", "bar")),
-      params = Map()
-    )
-    val engineid = mongoEngines.insert(engine)
-
-    val algo = Algo(
-      id = 0,
-      engineid = engineid,
-      name = "itemRecOutputSelectionWithTime",
-      infoid = "pdio-knnitembased",
-      command = "itemRecOutputSelectionWithTime",
-      params = Map("foo" -> "bar"),
-      settings = Map("dead" -> "beef"),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed",
-      offlineevalid = None
-    )
-    val algoid = mongoAlgos.insert(algo)
-
-    val id = "itemRecOutputSelectionWithTime"
-
-    val dac = Item(
-      id = id + "dac",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.3197611, -122.0466141)),
-      inactive = None,
-      attributes = Some(Map("foo" -> "bar", "foo2" -> "bar2")))
-    val hsh = Item(
-      id = id + "hsh",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.lastHour),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.3370801, -122.0493201)),
-      inactive = None,
-      attributes = None)
-    val mvh = Item(
-      id = id + "mvh",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = None,
-      endtime = Some(DateTime.nextHour),
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.3154153, -122.0566829)),
-      inactive = None,
-      attributes = Some(Map("foo3" -> "bar3")))
-    val lbh = Item(
-      id = id + "lbh",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = None,
-      endtime = Some(DateTime.lastHour),
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.2997029, -122.0034684)),
-      inactive = None,
-      attributes = Some(Map("foo4" -> "bar4", "foo5" -> "bar5")))
-    val lbh2 = Item(
-      id = id + "lbh2",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = None,
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.2997029, -122.0034684)),
-      inactive = None,
-      attributes = Some(Map("foo4" -> "bar4", "foo5" -> "bar5")))
-    val allItems = Seq(dac, hsh, lbh, lbh2, mvh)
-    allItems foreach { mongoItems.insert(_) }
-
-    val scores: Seq[(String, Double, Seq[String])] = Seq(
-      // (iid, score, itypes)
-      (id + "hsh", 5, Seq("foo")),
-      (id + "mvh", 4, Seq("foo")),
-      (id + "lbh", 3, Seq("bar")),
-      (id + "lbh2", 2, Seq("bar")),
-      (id + "dac", 1, Seq("bar")))
-
-    mongoItemRecScores.insert(ItemRecScore(
-      uid = "user1",
-      iids = scores.map(_._1),
-      scores = scores.map(_._2),
-      itypes = scores.map(_._3),
-      appid = dummyApp.id,
-      algoid = algoid,
-      modelset = true
-    ))
-
-    algoOutputSelector.itemRecSelection("user1", 10, None, Some((37.3229978, -122.0321823)), Some(10), None)(dummyApp, engine.copy(id = engineid)) must beEqualTo(Seq(id + "hsh", id + "mvh", id + "lbh2", id + "dac"))
-  }
-
-  def itemRecOutputSelectionWithInactive(algoOutputSelector: AlgoOutputSelector) = {
-    val appid = dummyApp.id
-    val engine = Engine(
-      id = 0,
-      appid = appid,
-      name = "itemRecOutputSelectionWithInactive",
-      infoid = "itemrec",
-      itypes = Some(Seq("foo", "bar")),
-      params = Map()
-    )
-    val engineid = mongoEngines.insert(engine)
-
-    val algo = Algo(
-      id = 0,
-      engineid = engineid,
-      name = "itemRecOutputSelectionWithInactive",
-      infoid = "pdio-knnitembased",
-      command = "itemRecOutputSelectionWithInactive",
-      params = Map("foo" -> "bar"),
-      settings = Map("dead" -> "beef"),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed",
-      offlineevalid = None
-    )
-    val algoid = mongoAlgos.insert(algo)
-
-    val id = "itemRecOutputSelectionWithInactive"
-
-    val dac = Item(
-      id = id + "dac",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.lastHour),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.3197611, -122.0466141)),
-      inactive = Some(true),
-      attributes = Some(Map("foo" -> "bar", "foo2" -> "bar2")))
-    val hsh = Item(
-      id = id + "hsh",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.lastHour),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.3370801, -122.0493201)),
-      inactive = None,
-      attributes = None)
-    val mvh = Item(
-      id = id + "mvh",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = None,
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.3154153, -122.0566829)),
-      inactive = Some(false),
-      attributes = Some(Map("foo3" -> "bar3")))
-    val lbh = Item(
-      id = id + "lbh",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = None,
-      endtime = Some(DateTime.nextHour),
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.2997029, -122.0034684)),
-      inactive = None,
-      attributes = Some(Map("foo4" -> "bar4", "foo5" -> "bar5")))
-    val lbh2 = Item(
-      id = id + "lbh2",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = None,
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.2997029, -122.0034684)),
-      inactive = Some(true),
-      attributes = Some(Map("foo4" -> "bar4", "foo5" -> "bar5")))
-    val allItems = Seq(dac, hsh, lbh, lbh2, mvh)
-    allItems foreach { mongoItems.insert(_) }
-
-    val scores: Seq[(String, Double, Seq[String])] = Seq(
-      // (iid, score, itypes)
-      (id + "hsh", 5, Seq("foo")),
-      (id + "mvh", 4, Seq("foo")),
-      (id + "lbh", 3, Seq("bar")),
-      (id + "lbh2", 2, Seq("bar")),
-      (id + "dac", 1, Seq("bar")))
-
-    mongoItemRecScores.insert(ItemRecScore(
-      uid = "user1",
-      iids = scores.map(_._1),
-      scores = scores.map(_._2),
-      itypes = scores.map(_._3),
-      appid = dummyApp.id,
-      algoid = algoid,
-      modelset = true
-    ))
-
-    algoOutputSelector.itemRecSelection("user1", 10, None, Some((37.3229978, -122.0321823)), Some(10), None)(dummyApp, engine.copy(id = engineid)) must beEqualTo(Seq(id + "hsh", id + "mvh", id + "lbh"))
-  }
-
-  def itemRecOutputSelectionUnseenOnly(algoOutputSelector: AlgoOutputSelector) = {
-    val engine = Engine(
-      id = 0,
-      appid = dummyApp.id,
-      name = "itemRecOutputSelection",
-      infoid = "itemrec",
-      itypes = Some(Seq("foo", "bar")),
-      params = Map("unseenonly" -> true)
-    )
-    val engineid = mongoEngines.insert(engine)
-
-    val algo = Algo(
-      id = 0,
-      engineid = engineid,
-      name = "itemRecOutputSelection",
-      infoid = "pdio-knnitembased",
-      command = "itemRecOutputSelection",
-      params = Map("foo" -> "bar"),
-      settings = Map("dead" -> "beef"),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed",
-      offlineevalid = None
-    )
-    val algoid = mongoAlgos.insert(algo)
-
-    val scores: Seq[(String, Double, Seq[String])] = Seq(
-      // (iid, score, itypes)
-      ("item_x", 5, Seq("bar")),
-      ("item_y", 4, Seq("foo")),
-      ("item_z", 3, Seq("bar")),
-      ("item_c", 2, Seq("foo", "bar")),
-      ("item_b", 1, Seq("foo")),
-      ("item_a", 0, Seq("bar")),
-      ("item_d", -1, Seq("foo", "bar"))
-    )
-
-    mongoItemRecScores.insert(ItemRecScore(
-      uid = "user1",
-      iids = scores.map(_._1),
-      scores = scores.map(_._2),
-      itypes = scores.map(_._3),
-      appid = dummyApp.id,
-      algoid = algoid,
-      modelset = true
-    ))
-
-    mongoU2IActions.insert(U2IAction(
-      appid = dummyApp.id,
-      action = mongoU2IActions.view,
-      uid = "user1",
-      iid = "item_b",
-      t = DateTime.now,
-      latlng = None,
-      v = None,
-      price = None
-    ))
-
-    algoOutputSelector.itemRecSelection("user1", 5, Some(Seq("bar", "foo")), None, None, None)(dummyApp, engine.copy(id = engineid)) must beEqualTo(Seq("item_x", "item_y", "item_z", "item_c", "item_a"))
-  }
-
-  def itemRecOutputSelectionDedupByAttribute(algoOutputSelector: AlgoOutputSelector) = {
-    val appid = dummyApp.id
-    val engine = Engine(
-      id = 0,
-      appid = appid,
-      name = "itemRecOutputSelectionDedupByAttribute",
-      infoid = "itemrec",
-      itypes = Some(Seq("foo", "bar")),
-      params = Map("dedupByAttribute" -> "foo")
-    )
-    val engineid = mongoEngines.insert(engine)
-
-    val algo = Algo(
-      id = 0,
-      engineid = engineid,
-      name = "itemRecOutputSelectionDedupByAttribute",
-      infoid = "pdio-knnitembased",
-      command = "itemRecOutputSelectionDedupByAttribute",
-      params = Map("foo" -> "bar"),
-      settings = Map("dead" -> "beef"),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed",
-      offlineevalid = None
-    )
-    val algoid = mongoAlgos.insert(algo)
-
-    val id = "itemRecOutputSelectionDedupByAttribute"
-
-    val fooA1 = Item(
-      id = id + "fooA1",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = None,
-      inactive = None,
-      attributes = Some(Map("foo" -> "a", "bar" -> "a")))
-    val fooA2 = Item(
-      id = id + "fooA2",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = None,
-      inactive = None,
-      attributes = Some(Map("foo" -> "a", "bar" -> "b")))
-    val noFoo1 = Item(
-      id = id + "noFoo1",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.3154153, -122.0566829)),
-      inactive = None,
-      attributes = Some(Map("bar" -> "c")))
-    val fooB1 = Item(
-      id = id + "fooB1",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.2997029, -122.0034684)),
-      inactive = None,
-      attributes = Some(Map("foo" -> "b")))
-    val allItems = Seq(fooA1, fooA2, noFoo1, fooB1)
-    allItems foreach { mongoItems.insert(_) }
-
-    val scores1: Seq[(String, Double, Seq[String])] = Seq(
-      // (iid, score, itypes)
-      (id + "fooA2", 4, Seq("foo")),
-      (id + "noFoo1", 3, Seq("unrelated")),
-      (id + "fooA1", 2, Seq("unrelated")),
-      (id + "fooB1", 1, Seq("bar")))
-
-    mongoItemRecScores.insert(ItemRecScore(
-      uid = "user1",
-      iids = scores1.map(_._1),
-      scores = scores1.map(_._2),
-      itypes = scores1.map(_._3),
-      appid = dummyApp.id,
-      algoid = algoid,
-      modelset = true
-    ))
-
-    val result1 = algoOutputSelector.itemRecSelection(
-      "user1", 10, None, None, None, None)(
-        dummyApp, engine.copy(id = engineid))
-
-    val scores2: Seq[(String, Double, Seq[String])] = Seq(
-      // (iid, score, itypes)
-      (id + "noFoo1", 3, Seq("unrelated")))
-
-    mongoItemRecScores.insert(ItemRecScore(
-      uid = "user2",
-      iids = scores2.map(_._1),
-      scores = scores2.map(_._2),
-      itypes = scores2.map(_._3),
-      appid = dummyApp.id,
-      algoid = algoid,
-      modelset = true
-    ))
-
-    val result2 = algoOutputSelector.itemRecSelection(
-      "user2", 10, None, None, None, None)(
-        dummyApp, engine.copy(id = engineid))
-
-    ((result1 must beEqualTo(Seq(id + "fooA2", id + "fooB1")))
-      and (result2 must beEqualTo(Seq())))
-  }
-
-  def itemRecOutputSelectionUnsupportedAlgo(algoOutputSelector: AlgoOutputSelector) = {
-    val engine = Engine(
-      id = 0,
-      appid = dummyApp.id,
-      name = "itemRecOutputSelection",
-      infoid = "itemrec",
-      itypes = Some(Seq("foo", "bar")),
-      params = Map()
-    )
-    val engineid = mongoEngines.insert(engine)
-
-    val algo = Algo(
-      id = 0,
-      engineid = engineid,
-      name = "itemRecOutputSelection",
-      infoid = "abc4",
-      command = "itemRecOutputSelection",
-      params = Map("foo" -> "bar"),
-      settings = Map("dead" -> "beef"),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed",
-      offlineevalid = None
-    )
-    val algoid = mongoAlgos.insert(algo)
-
-    algoOutputSelector.itemRecSelection("", 10, None, None, None, None)(dummyApp, engine.copy(id = engineid)) must throwA[RuntimeException]
-  }
-
-  def itemRecOutputSelectionNoAlgo(algoOutputSelector: AlgoOutputSelector) = {
-    val engine = Engine(
-      id = 0,
-      appid = dummyApp.id,
-      name = "itemRecOutputSelectionNoAlgo",
-      infoid = "itemrec",
-      itypes = Some(Seq("foo", "bar")),
-      params = Map()
-    )
-    val engineid = mongoEngines.insert(engine)
-    algoOutputSelector.itemRecSelection("", 10, None, None, None, None)(dummyApp, engine.copy(id = engineid)) must throwA[RuntimeException]
-  }
-
-  def itemRecOutputSelectionBadEngine(algoOutputSelector: AlgoOutputSelector) = {
-    val engine = Engine(
-      id = 0,
-      appid = dummyApp.id,
-      name = "itemRecOutputSelectionBadEngine",
-      infoid = "itemRecOutputSelectionBadEngine",
-      itypes = Some(Seq("foo", "bar")),
-      params = Map()
-    )
-    val engineid = mongoEngines.insert(engine)
-    algoOutputSelector.itemRecSelection("", 10, None, None, None, None)(dummyApp, engine.copy(id = engineid)) must throwA[RuntimeException]
-  }
-
-  /** ItemSim engine. */
-  def itemSimOutputSelection(algoOutputSelector: AlgoOutputSelector) = {
-    val engine = Engine(
-      id = 0,
-      appid = dummyApp.id,
-      name = "itemSimOutputSelection",
-      infoid = "itemsim",
-      itypes = Some(Seq("foo", "bar")),
-      params = Map("freshness" -> 4, "serendipity" -> 6))
-    val engineid = mongoEngines.insert(engine)
-
-    val algo = Algo(
-      id = 0,
-      engineid = engineid,
-      name = "itemSimOutputSelection",
-      infoid = "io.prediction.algorithms.scalding.itemsim.itemsimcf",
-      command = "itemSimOutputSelection",
-      params = Map("foo" -> "bar"),
-      settings = Map("dead" -> "beef"),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed",
-      offlineevalid = None
-    )
-    val algoid = mongoAlgos.insert(algo)
-
-    val scores = Seq(ItemSimScore(
-      iid = "user1",
-      simiids = Seq("item_z", "item_h", "item_d", "item_g", "item_e", "item_f", "item_x", "item_y", "item_b", "item_c", "item_a"),
-      scores = Seq(11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1),
-      itypes = Seq(Seq("unrelated"), Seq("foo"), Seq("foo"), Seq("bar"), Seq("bar"), Seq("foo"), Seq("bar"), Seq("foo"), Seq("foo"), Seq("bar"), Seq("bar")),
-      appid = dummyApp.id,
-      algoid = algoid,
-      modelset = true))
-
-    scores foreach { mongoItemSimScores.insert(_) }
-
-    val result = algoOutputSelector.itemSimSelection("user1", 10, Some(Seq("bar", "foo")), None, None, None)(dummyApp, engine.copy(id = engineid))
-    val resultBar = algoOutputSelector.itemSimSelection("user1", 10, Some(Seq("bar")), None, None, None)(dummyApp, engine.copy(id = engineid))
-
-    result must contain(
-      "item_x",
-      "item_y",
-      "item_a",
-      "item_b",
-      "item_c",
-      "item_d",
-      "item_e",
-      "item_f",
-      "item_g",
-      "item_h") and
-      (resultBar must contain(
-        "item_a",
-        "item_c",
-        "item_e",
-        "item_x",
-        "item_g"))
-  }
-
-  def itemSimOutputSelectionWithFreshness(algoOutputSelector: AlgoOutputSelector) = {
-    val engine = Engine(
-      id = 0,
-      appid = dummyApp.id,
-      name = "itemSimOutputSelection",
-      infoid = "itemsim",
-      itypes = Some(Seq("foo", "bar")),
-      params = Map("serendipity" -> 0, "freshness" -> 5,
-        "freshnessTimeUnit" -> 3600L))
-    val engineid = mongoEngines.insert(engine)
-
-    val algo = Algo(
-      id = 0,
-      engineid = engineid,
-      name = "itemSimOutputSelection",
-      infoid = "pdio-knnitembased",
-      command = "itemSimOutputSelection",
-      params = Map("foo" -> "bar"),
-      settings = Map("dead" -> "beef"),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed",
-      offlineevalid = None
-    )
-    val algoid = mongoAlgos.insert(algo)
-
-    val scores = Seq(ItemSimScore(
-      iid = "user1",
-      simiids = Seq("item_z", "item_h", "item_d", "item_g", "item_e", "item_f", "item_x", "item_y", "item_b", "item_c", "item_a"),
-      scores = Seq(11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1),
-      itypes = Seq(Seq("unrelated"), Seq("foo"), Seq("foo"), Seq("bar"), Seq("bar"), Seq("foo"), Seq("bar"), Seq("foo"), Seq("foo"), Seq("bar"), Seq("bar")),
-      appid = dummyApp.id,
-      algoid = algoid,
-      modelset = true))
-
-    scores foreach { mongoItemSimScores.insert(_) }
-
-    val result = algoOutputSelector.itemSimSelection("user1", 10, Some(Seq("bar", "foo")), None, None, None)(dummyApp, engine.copy(id = engineid))
-    val resultBar = algoOutputSelector.itemSimSelection("user1", 10, Some(Seq("bar")), None, None, None)(dummyApp, engine.copy(id = engineid))
-
-    result must_== Seq(
-      "item_g",
-      "item_e",
-      "item_x",
-      "item_h",
-      "item_d",
-      "item_b",
-      "item_f",
-      "item_y",
-      "item_a",
-      "item_c") and
-      (resultBar must_== Seq(
-        "item_g",
-        "item_e",
-        "item_x",
-        "item_a",
-        "item_c"))
-  }
-
-  def itemSimOutputSelectionWithLatlng(algoOutputSelector: AlgoOutputSelector) = {
-    val appid = dummyApp.id
-    val engine = Engine(
-      id = 0,
-      appid = appid,
-      name = "itemSimOutputSelectionWithLatlng",
-      infoid = "itemsim",
-      itypes = Some(Seq("foo", "bar")),
-      params = Map()
-    )
-    val engineid = mongoEngines.insert(engine)
-
-    val algo = Algo(
-      id = 0,
-      engineid = engineid,
-      name = "itemRecOutputSelectionWithLatlng",
-      infoid = "pdio-knnitembased",
-      command = "itemRecOutputSelectionWithLatlng",
-      params = Map("foo" -> "bar"),
-      settings = Map("dead" -> "beef"),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed",
-      offlineevalid = None
-    )
-    val algoid = mongoAlgos.insert(algo)
-
-    val id = "itemSimOutputSelectionWithLatlng"
-
-    val dac = Item(
-      id = id + "dac",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.3197611, -122.0466141)),
-      inactive = None,
-      attributes = Some(Map("foo" -> "bar", "foo2" -> "bar2")))
-    val hsh = Item(
-      id = id + "hsh",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.3370801, -122.0493201)),
-      inactive = None,
-      attributes = None)
-    val mvh = Item(
-      id = id + "mvh",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.3154153, -122.0566829)),
-      inactive = None,
-      attributes = Some(Map("foo3" -> "bar3")))
-    val lbh = Item(
-      id = id + "lbh",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.2997029, -122.0034684)),
-      inactive = None,
-      attributes = Some(Map("foo4" -> "bar4", "foo5" -> "bar5")))
-    val allItems = Seq(dac, hsh, lbh, mvh)
-    allItems foreach { mongoItems.insert(_) }
-
-    val scores: Seq[(String, Double, Seq[String])] = Seq(
-      // (iid, score, itypes)
-      (id + "hsh", 4, Seq("foo")),
-      (id + "mvh", 3, Seq("unrelated")),
-      (id + "lbh", 2, Seq("unrelated")),
-      (id + "dac", 1, Seq("bar")))
-
-    mongoItemSimScores.insert(ItemSimScore(
-      iid = "user1",
-      simiids = scores.map(_._1),
-      scores = scores.map(_._2),
-      itypes = scores.map(_._3),
-      appid = dummyApp.id,
-      algoid = algoid,
-      modelset = true
-    ))
-
-    algoOutputSelector.itemSimSelection("user1", 10, None, Some((37.3229978, -122.0321823)), Some(2.2), None)(dummyApp, engine.copy(id = engineid)) must beEqualTo(Seq(id + "hsh", id + "dac"))
-  }
-
-  def itemSimOutputSelectionWithTime(algoOutputSelector: AlgoOutputSelector) = {
-    val appid = dummyApp.id
-    val engine = Engine(
-      id = 0,
-      appid = appid,
-      name = "itemSimOutputSelectionWithTime",
-      infoid = "itemsim",
-      itypes = Some(Seq("foo", "bar")),
-      params = Map()
-    )
-    val engineid = mongoEngines.insert(engine)
-
-    val algo = Algo(
-      id = 0,
-      engineid = engineid,
-      name = "itemSimOutputSelectionWithTime",
-      infoid = "pdio-knnitembased",
-      command = "itemSimOutputSelectionWithTime",
-      params = Map("foo" -> "bar"),
-      settings = Map("dead" -> "beef"),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed",
-      offlineevalid = None
-    )
-    val algoid = mongoAlgos.insert(algo)
-
-    val id = "itemSimOutputSelectionWithTime"
-
-    val dac = Item(
-      id = id + "dac",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.3197611, -122.0466141)),
-      inactive = None,
-      attributes = Some(Map("foo" -> "bar", "foo2" -> "bar2")))
-    val hsh = Item(
-      id = id + "hsh",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.lastHour),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.3370801, -122.0493201)),
-      inactive = None,
-      attributes = None)
-    val mvh = Item(
-      id = id + "mvh",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = None,
-      endtime = Some(DateTime.nextHour),
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.3154153, -122.0566829)),
-      inactive = None,
-      attributes = Some(Map("foo3" -> "bar3")))
-    val lbh = Item(
-      id = id + "lbh",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = None,
-      endtime = Some(DateTime.lastHour),
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.2997029, -122.0034684)),
-      inactive = None,
-      attributes = Some(Map("foo4" -> "bar4", "foo5" -> "bar5")))
-    val lbh2 = Item(
-      id = id + "lbh2",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = None,
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.2997029, -122.0034684)),
-      inactive = None,
-      attributes = Some(Map("foo4" -> "bar4", "foo5" -> "bar5")))
-    val allItems = Seq(dac, hsh, lbh, lbh2, mvh)
-    allItems foreach { mongoItems.insert(_) }
-
-    val scores: Seq[(String, Double, Seq[String])] = Seq(
-      // (iid, score, itypes)
-      (id + "hsh", 5, Seq("foo")),
-      (id + "mvh", 4, Seq("foo")),
-      (id + "lbh", 3, Seq("bar")),
-      (id + "lbh2", 2, Seq("bar")),
-      (id + "dac", 1, Seq("bar")))
-
-    mongoItemSimScores.insert(ItemSimScore(
-      iid = "item1",
-      simiids = scores.map(_._1),
-      scores = scores.map(_._2),
-      itypes = scores.map(_._3),
-      appid = dummyApp.id,
-      algoid = algoid,
-      modelset = true
-    ))
-
-    algoOutputSelector.itemSimSelection("item1", 10, None, Some((37.3229978, -122.0321823)), Some(10), None)(dummyApp, engine.copy(id = engineid)) must beEqualTo(Seq(id + "hsh", id + "mvh", id + "lbh2", id + "dac"))
-  }
-
-  def itemSimOutputSelectionWithInactive(algoOutputSelector: AlgoOutputSelector) = {
-    val appid = dummyApp.id
-    val engine = Engine(
-      id = 0,
-      appid = appid,
-      name = "itemSimOutputSelectionWithInactive",
-      infoid = "itemsim",
-      itypes = Some(Seq("foo", "bar")),
-      params = Map()
-    )
-    val engineid = mongoEngines.insert(engine)
-
-    val algo = Algo(
-      id = 0,
-      engineid = engineid,
-      name = "itemSimOutputSelectionWithInactive",
-      infoid = "pdio-knnitembased",
-      command = "itemSimOutputSelectionWithInactive",
-      params = Map("foo" -> "bar"),
-      settings = Map("dead" -> "beef"),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed",
-      offlineevalid = None
-    )
-    val algoid = mongoAlgos.insert(algo)
-
-    val id = "itemSimOutputSelectionWithInactive"
-
-    val dac = Item(
-      id = id + "dac",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.3197611, -122.0466141)),
-      inactive = Some(false),
-      attributes = Some(Map("foo" -> "bar", "foo2" -> "bar2")))
-    val hsh = Item(
-      id = id + "hsh",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.lastHour),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.3370801, -122.0493201)),
-      inactive = Some(true),
-      attributes = None)
-    val mvh = Item(
-      id = id + "mvh",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = None,
-      endtime = Some(DateTime.nextHour),
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.3154153, -122.0566829)),
-      inactive = None,
-      attributes = Some(Map("foo3" -> "bar3")))
-    val lbh = Item(
-      id = id + "lbh",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = None,
-      endtime = Some(DateTime.nextHour),
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.2997029, -122.0034684)),
-      inactive = None,
-      attributes = Some(Map("foo4" -> "bar4", "foo5" -> "bar5")))
-    val lbh2 = Item(
-      id = id + "lbh2",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = None,
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.2997029, -122.0034684)),
-      inactive = Some(true),
-      attributes = Some(Map("foo4" -> "bar4", "foo5" -> "bar5")))
-    val allItems = Seq(dac, hsh, lbh, lbh2, mvh)
-    allItems foreach { mongoItems.insert(_) }
-
-    val scores: Seq[(String, Double, Seq[String])] = Seq(
-      // (iid, score, itypes)
-      (id + "hsh", 5, Seq("foo")),
-      (id + "mvh", 4, Seq("foo")),
-      (id + "lbh", 3, Seq("bar")),
-      (id + "lbh2", 2, Seq("bar")),
-      (id + "dac", 1, Seq("bar")))
-
-    mongoItemSimScores.insert(ItemSimScore(
-      iid = "item1",
-      simiids = scores.map(_._1),
-      scores = scores.map(_._2),
-      itypes = scores.map(_._3),
-      appid = dummyApp.id,
-      algoid = algoid,
-      modelset = true
-    ))
-
-    algoOutputSelector.itemSimSelection("item1", 10, None, Some((37.3229978, -122.0321823)), Some(10), None)(dummyApp, engine.copy(id = engineid)) must beEqualTo(Seq(id + "mvh", id + "lbh", id + "dac"))
-  }
-
-  def itemSimOutputSelectionDedupByAttribute(algoOutputSelector: AlgoOutputSelector) = {
-    val appid = dummyApp.id
-    val engine = Engine(
-      id = 0,
-      appid = appid,
-      name = "itemSimOutputSelectionDedupByAttribute",
-      infoid = "itemsim",
-      itypes = Some(Seq("foo", "bar")),
-      params = Map("dedupByAttribute" -> "foo")
-    )
-    val engineid = mongoEngines.insert(engine)
-
-    val algo = Algo(
-      id = 0,
-      engineid = engineid,
-      name = "itemSimOutputSelectionDedupByAttribute",
-      infoid = "pdio-knnitembased",
-      command = "itemSimOutputSelectionDedupByAttribute",
-      params = Map("foo" -> "bar"),
-      settings = Map("dead" -> "beef"),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed",
-      offlineevalid = None
-    )
-    val algoid = mongoAlgos.insert(algo)
-
-    val id = "itemSimOutputSelectionDedupByAttribute"
-
-    val fooA1 = Item(
-      id = id + "fooA1",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = None,
-      inactive = None,
-      attributes = Some(Map("foo" -> "a", "bar" -> "a")))
-    val fooA2 = Item(
-      id = id + "fooA2",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = None,
-      inactive = None,
-      attributes = Some(Map("foo" -> "a", "bar" -> "b")))
-    val noFoo1 = Item(
-      id = id + "noFoo1",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.3154153, -122.0566829)),
-      inactive = None,
-      attributes = Some(Map("bar" -> "c")))
-    val fooB1 = Item(
-      id = id + "fooB1",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("fresh", "meat"),
-      starttime = Some(DateTime.now),
-      endtime = None,
-      price = Some(49.394),
-      profit = None,
-      latlng = Some((37.2997029, -122.0034684)),
-      inactive = None,
-      attributes = Some(Map("foo" -> "b")))
-    val allItems = Seq(fooA1, fooA2, noFoo1, fooB1)
-    allItems foreach { mongoItems.insert(_) }
-
-    val scores1: Seq[(String, Double, Seq[String])] = Seq(
-      // (iid, score, itypes)
-      (id + "fooA2", 4, Seq("foo")),
-      (id + "noFoo1", 3, Seq("unrelated")),
-      (id + "fooA1", 2, Seq("unrelated")),
-      (id + "fooB1", 1, Seq("bar")))
-
-    mongoItemSimScores.insert(ItemSimScore(
-      iid = "user1",
-      simiids = scores1.map(_._1),
-      scores = scores1.map(_._2),
-      itypes = scores1.map(_._3),
-      appid = dummyApp.id,
-      algoid = algoid,
-      modelset = true
-    ))
-
-    val result1 = algoOutputSelector.itemSimSelection(
-      "user1", 10, None, None, None, None)(
-        dummyApp, engine.copy(id = engineid))
-
-    result1 must beEqualTo(Seq(id + "fooA2", id + "fooB1"))
-
-    val scores2: Seq[(String, Double, Seq[String])] = Seq(
-      // (iid, score, itypes)
-      (id + "noFoo1", 3, Seq("unrelated")))
-
-    mongoItemSimScores.insert(ItemSimScore(
-      iid = "user2",
-      simiids = scores2.map(_._1),
-      scores = scores2.map(_._2),
-      itypes = scores2.map(_._3),
-      appid = dummyApp.id,
-      algoid = algoid,
-      modelset = true
-    ))
-
-    val result2 = algoOutputSelector.itemSimSelection(
-      "user2", 10, None, None, None, None)(
-        dummyApp, engine.copy(id = engineid))
-
-    result2 must beEqualTo(Seq())
-  }
-
-  def itemSimOutputSelectionUnsupportedAlgo(algoOutputSelector: AlgoOutputSelector) = {
-    val engine = Engine(
-      id = 0,
-      appid = dummyApp.id,
-      name = "itemSimOutputSelection",
-      infoid = "itemsim",
-      itypes = Some(Seq("foo", "bar")),
-      params = Map()
-    )
-    val engineid = mongoEngines.insert(engine)
-
-    val algo = Algo(
-      id = 0,
-      engineid = engineid,
-      name = "itemSimOutputSelection",
-      infoid = "abc",
-      command = "itemSimOutputSelection",
-      params = Map("foo" -> "bar"),
-      settings = Map("dead" -> "beef"),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed",
-      offlineevalid = None
-    )
-    val algoid = mongoAlgos.insert(algo)
-
-    algoOutputSelector.itemSimSelection("", 10, None, None, None, None)(dummyApp, engine.copy(id = engineid)) must throwA[RuntimeException]
-  }
-
-  def itemSimOutputSelectionNoAlgo(algoOutputSelector: AlgoOutputSelector) = {
-    val engine = Engine(
-      id = 0,
-      appid = dummyApp.id,
-      name = "itemSimOutputSelectionNoAlgo",
-      infoid = "itemsim",
-      itypes = Some(Seq("foo", "bar")),
-      params = Map()
-    )
-    val engineid = mongoEngines.insert(engine)
-    algoOutputSelector.itemSimSelection("", 10, None, None, None, None)(dummyApp, engine.copy(id = engineid)) must throwA[RuntimeException]
-  }
-
-  def itemSimOutputSelectionBadEngine(algoOutputSelector: AlgoOutputSelector) = {
-    val engine = Engine(
-      id = 0,
-      appid = dummyApp.id,
-      name = "itemSimOutputSelectionBadEngine",
-      infoid = "itemSimOutputSelectionBadEngine",
-      itypes = Some(Seq("foo", "bar")),
-      params = Map()
-    )
-    val engineid = mongoEngines.insert(engine)
-    algoOutputSelector.itemSimSelection("", 10, None, None, None, None)(dummyApp, engine.copy(id = engineid)) must throwA[RuntimeException]
-  }
-
-  def itemSimOutputSelectionMultipleIids(algoOutputSelector: AlgoOutputSelector) = {
-    val appid = dummyApp.id
-    val engine = Engine(
-      id = 0,
-      appid = appid,
-      name = "itemSimOutputSelectionMultipleIids",
-      infoid = "itemsim",
-      itypes = None,
-      params = Map("a" -> "b")
-    )
-    val engineid = mongoEngines.insert(engine)
-
-    val algo = Algo(
-      id = 0,
-      engineid = engineid,
-      name = "itemSimOutputSelectionMultipleIids",
-      infoid = "it-does-not-matter",
-      command = "it-does-not-matter-too",
-      params = Map("foo" -> "bar"),
-      settings = Map("dead" -> "beef"),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed",
-      offlineevalid = None
-    )
-    val algoid = mongoAlgos.insert(algo)
-
-    val id = "i"
-
-    def item(index: Int) = Item(
-      id = id + index,
-      appid = appid,
-      ct = DateTime.now,
-      itypes = Seq[String](),
-      starttime = Some(DateTime.now),
-      endtime = None)
-
-    (1 to 6).foreach { i => mongoItems.insert(item(i)) }
-
-    val itemSimRawMap = Map(
-      "i1" -> Seq(("i2", 1.0), ("i3", 0.5), ("i4", 0.2)),
-      // aggregation should be unaffected by scale
-      "i2" -> Seq(("i3", 100.0), ("i5", 200.0)),
-      "i3" -> Seq(("i1", -0.5), ("i2", -0.2), ("i4", -0.4)),
-      "i4" -> Seq(("i5", 2.0), ("i6", 3.0)))
-
-    itemSimRawMap.foreach {
-      case (item, simRaw) => {
-        val itemSimScore = ItemSimScore(
-          iid = item,
-          simiids = simRaw.map(_._1),
-          scores = simRaw.map(_._2),
-          itypes = Seq.fill(simRaw.length)(Seq[String]()),
-          appid = appid,
-          algoid = algoid,
-          modelset = true
-        )
-        mongoItemSimScores.insert(itemSimScore)
-      }
-    }
-
-    val tests = List(
-      (algoOutputSelector.itemSimSelection("i1", 10, None, None, None, None)(
-        dummyApp, engine.copy(id = engineid))
-        must beEqualTo(Seq("i2", "i3", "i4"))),
-      (algoOutputSelector.itemSimSelection("i1,i4", 10, None, None, None, None)(
-        dummyApp, engine.copy(id = engineid))
-        must beEqualTo(Seq("i2", "i6", "i3", "i5"))),
-      (algoOutputSelector.itemSimSelection("i1,i2", 3, None, None, None, None)(
-        dummyApp, engine.copy(id = engineid))
-        must beEqualTo(Seq("i5", "i3", "i4"))),
-      (algoOutputSelector.itemSimSelection("i1,i2,i3,i4", 10, None, None,
-        None, None)(dummyApp, engine.copy(id = engineid))
-        must beEqualTo(Seq("i6", "i5")))
-    )
-    tests.reduce(_ and _)
-  }
-
-  /** ItemRank engine. */
-  def itemRankOutputSelection(algoOutputSelector: AlgoOutputSelector) = {
-    val engine = Engine(
-      id = 0,
-      appid = dummyApp.id,
-      name = "itemRankOutputSelection",
-      infoid = "itemrank",
-      itypes = Some(Seq("foo", "bar")),
-      params = Map())
-    val engineid = mongoEngines.insert(engine)
-
-    val algo = Algo(
-      id = 0,
-      engineid = engineid,
-      name = "itemRankOutputSelection",
-      infoid = "pio-itemrank-single-mahout-knnitembased",
-      command = "itemRankOutputSelection",
-      params = Map("foo" -> "bar"),
-      settings = Map("dead" -> "beef"),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed",
-      offlineevalid = None)
-    val algoid = mongoAlgos.insert(algo)
-
-    val scores = Seq(ItemRecScore(
-      uid = "user1",
-      iids = Seq("item_z", "item_h", "item_d", "item_g", "item_e", "item_f",
-        "item_x", "item_y", "item_b", "item_c", "item_a"),
-      scores = Seq(11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1),
-      itypes = Seq(Seq("unrelated"), Seq("foo"), Seq("foo"), Seq("bar"),
-        Seq("bar"), Seq("foo"), Seq("bar"), Seq("foo"), Seq("foo"), Seq("bar"),
-        Seq("bar")),
-      appid = dummyApp.id,
-      algoid = algoid,
-      modelset = true))
-
-    scores foreach { mongoItemRecScores.insert(_) }
-
-    val result = algoOutputSelector.itemRankSelection("user1",
-      Seq("item_e", "item_d", "item_a", "item_x", "item_h"))(dummyApp,
-        engine.copy(id = engineid))
-    val resultBar = algoOutputSelector.itemRankSelection("user1",
-      Seq("x", "y", "z"))(dummyApp, engine.copy(id = engineid))
-    val resultBaz = algoOutputSelector.itemRankSelection("user1",
-      Seq("item_e", "item_d", "item_a", "x", "y", "z"))(dummyApp,
-        engine.copy(id = engineid))
-
-    result must_== Seq("item_h", "item_d", "item_e", "item_x", "item_a") and
-      (resultBar must_== Seq("x", "y", "z")) and
-      (resultBaz must_== Seq("item_d", "item_e", "item_a", "x", "y", "z"))
-  }
-
-  def itemRankOutputSelectionWithFreshness(
-    algoOutputSelector: AlgoOutputSelector) = {
-    val engine = Engine(
-      id = 0,
-      appid = dummyApp.id,
-      name = "itemRankOutputSelection",
-      infoid = "itemrank",
-      itypes = Some(Seq("foo", "bar")),
-      params = Map("freshness" -> 5, "freshnessTimeUnit" -> 3600L))
-    val engineid = mongoEngines.insert(engine)
-
-    val algo = Algo(
-      id = 0,
-      engineid = engineid,
-      name = "itemRankOutputSelection",
-      infoid = "pio-itemrank-single-mahout-knnitembased",
-      command = "itemRankOutputSelection",
-      params = Map("foo" -> "bar"),
-      settings = Map("dead" -> "beef"),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed",
-      offlineevalid = None)
-    val algoid = mongoAlgos.insert(algo)
-
-    val scores = Seq(ItemRecScore(
-      uid = "user1",
-      iids = Seq("item_z", "item_h", "item_d", "item_g", "item_e", "item_f",
-        "item_x", "item_y", "item_b", "item_c", "item_a"),
-      scores = Seq(11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1),
-      itypes = Seq(Seq("unrelated"), Seq("foo"), Seq("foo"), Seq("bar"),
-        Seq("bar"), Seq("foo"), Seq("bar"), Seq("foo"), Seq("foo"), Seq("bar"),
-        Seq("bar")),
-      appid = dummyApp.id,
-      algoid = algoid,
-      modelset = true))
-
-    scores foreach { mongoItemRecScores.insert(_) }
-
-    val result = algoOutputSelector.itemRankSelection("user1",
-      Seq("item_e", "item_d", "item_a", "item_x", "item_h"))(dummyApp,
-        engine.copy(id = engineid))
-    val resultBar = algoOutputSelector.itemRankSelection("user1",
-      Seq("x", "y", "z"))(dummyApp, engine.copy(id = engineid))
-    val resultBaz = algoOutputSelector.itemRankSelection("user1",
-      Seq("item_e", "item_d", "item_a", "x", "y", "z"))(dummyApp,
-        engine.copy(id = engineid))
-
-    result must_== Seq("item_e", "item_x", "item_h", "item_d", "item_a") and
-      (resultBar must_== Seq("x", "y", "z")) and
-      (resultBaz must_== Seq("item_e", "item_d", "item_a", "x", "y", "z"))
-  }
-
-  def itemRankOutputSelectionUnsupportedAlgo(
-    algoOutputSelector: AlgoOutputSelector) = {
-    val engine = Engine(
-      id = 0,
-      appid = dummyApp.id,
-      name = "itemRankOutputSelection",
-      infoid = "itemrank",
-      itypes = Some(Seq("foo", "bar")),
-      params = Map()
-    )
-    val engineid = mongoEngines.insert(engine)
-
-    val algo = Algo(
-      id = 0,
-      engineid = engineid,
-      name = "itemRankOutputSelection",
-      infoid = "abc4",
-      command = "itemRankOutputSelection",
-      params = Map("foo" -> "bar"),
-      settings = Map("dead" -> "beef"),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed",
-      offlineevalid = None
-    )
-    val algoid = mongoAlgos.insert(algo)
-
-    algoOutputSelector.itemRankSelection("", Seq())(dummyApp, engine.copy(id = engineid)) must throwA[RuntimeException]
-  }
-
-  def itemRankOutputSelectionNoAlgo(algoOutputSelector: AlgoOutputSelector) = {
-    val engine = Engine(
-      id = 0,
-      appid = dummyApp.id,
-      name = "itemRankOutputSelectionNoAlgo",
-      infoid = "itemrec",
-      itypes = Some(Seq("foo", "bar")),
-      params = Map()
-    )
-    val engineid = mongoEngines.insert(engine)
-    algoOutputSelector.itemRankSelection("", Seq())(dummyApp, engine.copy(id = engineid)) must throwA[RuntimeException]
-  }
-
-  def itemRankOutputSelectionBadEngine(algoOutputSelector: AlgoOutputSelector) = {
-    val engine = Engine(
-      id = 0,
-      appid = dummyApp.id,
-      name = "itemRankOutputSelectionBadEngine",
-      infoid = "itemRankOutputSelectionBadEngine",
-      itypes = Some(Seq("foo", "bar")),
-      params = Map()
-    )
-    val engineid = mongoEngines.insert(engine)
-    algoOutputSelector.itemRankSelection("", Seq())(dummyApp, engine.copy(id = engineid)) must throwA[RuntimeException]
-  }
-}
diff --git a/process/build.sbt b/process/build.sbt
deleted file mode 100644
index cb0c93b..0000000
--- a/process/build.sbt
+++ /dev/null
@@ -1,38 +0,0 @@
-import AssemblyKeys._
-
-name := "predictionio-process-hadoop-scalding"
-
-packageOptions += Package.ManifestAttributes(java.util.jar.Attributes.Name.MAIN_CLASS -> "com.twitter.scalding.Tool")
-
-parallelExecution in Test := false
-
-resolvers ++= Seq("Concurrent Maven Repo" at "http://conjars.org/repo")
-
-assemblySettings
-
-test in assembly := {}
-
-assembleArtifact in packageScala := true
-
-excludedJars in assembly <<= (fullClasspath in assembly) map { cp =>
-  val excludes = Set(
-    "jsp-api-2.1-6.1.14.jar",
-    "jsp-2.1-6.1.14.jar",
-    "jasper-compiler-5.5.12.jar",
-    "janino-2.5.16.jar",
-    "minlog-1.2.jar",
-    "hadoop-core-1.0.4.jar")
-  cp filter { jar => excludes(jar.data.getName)}
-}
-
-// Some of these files have duplicates, let's ignore:
-mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) =>
-  {
-    case s if s.endsWith(".class") => MergeStrategy.last
-    case s if s.endsWith("project.clj") => MergeStrategy.concat
-    case s if s.endsWith(".html") => MergeStrategy.last
-    case s if s.endsWith(".properties") => MergeStrategy.last
-    case s if s.endsWith(".xml") => MergeStrategy.last
-    case x => old(x)
-  }
-}
diff --git a/process/commons/hadoop/scalding/build.sbt b/process/commons/hadoop/scalding/build.sbt
deleted file mode 100644
index 903edf6..0000000
--- a/process/commons/hadoop/scalding/build.sbt
+++ /dev/null
@@ -1,23 +0,0 @@
-name := "predictionio-process-commons-hadoop-scalding"
-
-javacOptions ++= Seq("-source", "1.6", "-target", "1.6", "-Xlint:deprecation", "-Xlint:unchecked")
-
-parallelExecution in Test := false
-
-libraryDependencies += "org.apache.hadoop" % "hadoop-core" % "1.0.4"
-
-libraryDependencies += "com.twitter" %% "scalding-core" % "0.8.6"
-
-libraryDependencies ++= Seq(
-  "joda-time" % "joda-time" % "2.2",
-  "org.joda" % "joda-convert" % "1.3.1"
-)
-
-// for compiling mongotap
-libraryDependencies ++= Seq(
-  "com.google.guava" % "guava" % "17.0",
-  "org.mongodb" %% "casbah" % "2.7.2",
-  "io.prediction" % "mongo-hadoop-core" % "1.1.0"
-)
-
-resolvers += "Concurrent Maven Repo" at "http://conjars.org/repo"
diff --git a/process/commons/hadoop/scalding/src/main/java/com/clojurewekz/cascading/mongodb/MongoDBScheme.java b/process/commons/hadoop/scalding/src/main/java/com/clojurewekz/cascading/mongodb/MongoDBScheme.java
deleted file mode 100644
index d416391..0000000
--- a/process/commons/hadoop/scalding/src/main/java/com/clojurewekz/cascading/mongodb/MongoDBScheme.java
+++ /dev/null
@@ -1,231 +0,0 @@
-package com.clojurewerkz.cascading.mongodb;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-import cascading.tuple.FieldsResolverException;
-import cascading.tuple.TupleEntry;
-import com.google.common.base.Joiner;
-import com.mongodb.MongoURI;
-import com.mongodb.hadoop.mapred.MongoOutputFormat;
-import com.mongodb.DBObject;
-import org.apache.hadoop.mapred.*;
-import org.apache.hadoop.fs.Path;
-
-import org.apache.hadoop.io.Text;
-import org.apache.hadoop.util.StringUtils;
-import org.bson.types.ObjectId;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import cascading.flow.FlowProcess;
-import cascading.scheme.Scheme;
-import cascading.scheme.SinkCall;
-import cascading.scheme.SourceCall;
-import cascading.tap.Tap;
-import cascading.tuple.Fields;
-import cascading.tuple.Tuple;
-import com.mongodb.BasicDBObject;
-import com.mongodb.hadoop.io.BSONWritable;
-import com.mongodb.hadoop.mapred.MongoInputFormat;
-import com.mongodb.hadoop.util.MongoConfigUtil;
-
-@SuppressWarnings("rawtypes")
-public class MongoDBScheme extends Scheme<JobConf, RecordReader, OutputCollector, BSONWritable[], BSONWritable[]> {
-
-  /**
-   * Field logger
-   */
-  private static final Logger logger = LoggerFactory.getLogger(MongoDbCollector.class);
-
-  private String pathUUID;
-  public String mongoUri;
-  public List<String> columnFieldNames;
-  public Map<String, String> fieldMappings;
-  public String keyColumnName;
-  public int splitSize = 64;
-
-  private String host;
-  private Integer port;
-  private String database;
-  private String collection;
-  private DBObject query;
-
-  // with default id, without query
-  public MongoDBScheme(String[] hosts, Integer[] ports, String database, String collection, List<String> columnFieldNames, Map<String, String> fieldMappings) {
-    this(hosts, ports, database, collection, "_id", columnFieldNames, fieldMappings);
-  }
-
-  // with default id and query
-  public MongoDBScheme(String[] hosts, Integer[] ports, String database, String collection, List<String> columnFieldNames, Map<String, String> fieldMappings, DBObject query) {
-    this(hosts, ports, database, collection, "_id", columnFieldNames, fieldMappings, query);
-  }
-
-  // without query
-  public MongoDBScheme(String[] hosts, Integer[] ports, String database, String collection, String keyColumnName, List<String> columnFieldNames, Map<String, String> fieldMappings) {
-	  this(hosts, ports, database, collection, keyColumnName, columnFieldNames, fieldMappings, new BasicDBObject());
-  }
-
-  public MongoDBScheme(String[] hosts, Integer[] ports, String database, String collection, String keyColumnName, List<String> columnFieldNames, Map<String, String> fieldMappings, DBObject query) {
-    String[] hostsAndPorts = new String[hosts.length];
-    for (int i = 0; i != hosts.length; i++) {
-      hostsAndPorts[i] = hosts[i] + ":" + ports[i];
-    }
-    this.mongoUri = String.format("mongodb://%s/%s.%s", Joiner.on(",").join(hostsAndPorts), database, collection);
-    this.pathUUID = UUID.randomUUID().toString();
-    this.columnFieldNames = columnFieldNames;
-    this.fieldMappings = fieldMappings;
-    this.keyColumnName = keyColumnName;
-
-    this.host = host;
-    this.port = port;
-    this.database = database;
-    this.collection = collection;
-    this.query = query;
-  }
-
-  /**
-   *
-   * @return
-   */
-  public Path getPath() {
-    return new Path(pathUUID);
-  }
-
-  /**
-   *
-   * @return
-   */
-  public String getIdentifier() {
-    return String.format("%s_%d_%s_%s", this.host, this.port, this.database, this.collection);
-  }
-
-  /**
-   *
-   * @param process
-   * @param tap
-   * @param conf
-   */
-  @Override
-  public void sourceConfInit(FlowProcess<JobConf> process, Tap<JobConf, RecordReader, OutputCollector> tap, JobConf conf) {
-    MongoConfigUtil.setInputURI( conf, this.mongoUri );
-    FileInputFormat.setInputPaths(conf, this.getIdentifier());
-    conf.setInputFormat(MongoInputFormat.class);
-
-    // TODO: MongoConfigUtil.setFields(conf, fieldsBson);
-    //if (!this.query.isEmpty())
-    MongoConfigUtil.setQuery(conf, this.query);
-    MongoConfigUtil.setSplitSize(conf, splitSize);
-    // TODO: MongoConfigUtil.setFields(conf, fields);
-  }
-
-  /**
-   *
-   * @param process
-   * @param tap
-   * @param conf
-   */
-  @Override
-  public void sinkConfInit(FlowProcess<JobConf> process, Tap<JobConf, RecordReader, OutputCollector> tap,
-                           JobConf conf) {
-    conf.setOutputFormat(MongoOutputFormat.class);
-    MongoConfigUtil.setOutputURI(conf, this.mongoUri);
-
-    //FileOutputFormat.setOutputPath(conf, getPath());
-  }
-
-  /**
-   *
-   * @param flowProcess
-   * @param sourceCall
-   */
-  @Override
-  public void sourcePrepare(FlowProcess<JobConf> flowProcess, SourceCall<BSONWritable[], RecordReader> sourceCall) {
-    sourceCall.setContext(new BSONWritable[2]);
-
-    sourceCall.getContext()[0] = (BSONWritable) sourceCall.getInput().createKey();
-    sourceCall.getContext()[1] = (BSONWritable) sourceCall.getInput().createValue();
-  }
-
-  /**
-   *
-   * @param flowProcess
-   * @param sourceCall
-   * @return
-   * @throws IOException
-   */
-  @Override
-  public boolean source(FlowProcess<JobConf> flowProcess, SourceCall<BSONWritable[], RecordReader> sourceCall) throws IOException {
-    Tuple result = new Tuple();
-
-    BSONWritable key = sourceCall.getContext()[0];
-    BSONWritable value = sourceCall.getContext()[1];
-
-    if (!sourceCall.getInput().next(key, value)) {
-      logger.info("Nothing left to read, exiting");
-      return false;
-    }
-
-    for (String columnFieldName : columnFieldNames) {
-      Object tupleEntry= value.getDoc().get(columnFieldName);
-      if (tupleEntry != null) {
-        result.add(tupleEntry);
-      } else if (columnFieldName != this.keyColumnName) {
-        result.add(null);
-      }
-    }
-
-    sourceCall.getIncomingEntry().setTuple(result);
-    return true;
-  }
-
-  /**
-   *
-   * @param flowProcess
-   * @param sinkCall
-   * @throws IOException
-   */
-  @Override
-  public void sink(FlowProcess<JobConf> flowProcess, SinkCall<BSONWritable[], OutputCollector> sinkCall) throws IOException {
-    TupleEntry tupleEntry = sinkCall.getOutgoingEntry();
-    OutputCollector outputCollector = sinkCall.getOutput();
-
-    String keyFieldName = this.fieldMappings.get(this.keyColumnName);
-    Object key;
-
-    // if fieldMappings doesn't have keyColumnName ("_id") field, then use new ObjectId() as key
-    if (keyFieldName == null) {
-	key = null;
-    } else {
-	key = new Text((String)(tupleEntry.selectTuple(new Fields(keyFieldName)).get(0)));
-    }
-    //Object key = tupleEntry.selectTuple(new Fields(this.fieldMappings.get(this.keyColumnName))).get(0);
-
-    BasicDBObject dbObject = new BasicDBObject();
-
-    for (String columnFieldName : columnFieldNames) {
-      String columnFieldMapping = fieldMappings.get(columnFieldName);
-      Object tupleEntryValue = null;
-
-      try {
-        if (columnFieldMapping != null) {
-          // columnFieldMapping is null if no corresponding field name defined in Mappings.
-          // only write the field value back to mongo if the field also defined in Mappings (ie. not null)
-          tupleEntryValue = tupleEntry.get(columnFieldMapping);
-        }
-      } catch(FieldsResolverException e) {
-        logger.error("Couldn't resolve field: {}", columnFieldName);
-      }
-
-      if(tupleEntryValue != null && columnFieldName != keyColumnName) {
-        //logger.info("Putting for output: {} {}", columnFieldName, tupleEntryValue);
-        dbObject.put(columnFieldName, tupleEntryValue);
-      }
-    }
-    //logger.info("Putting key for output: {} {}", key, dbObject);
-    outputCollector.collect(key, new BSONWritable(dbObject));
-  }
-
-}
diff --git a/process/commons/hadoop/scalding/src/main/java/com/clojurewekz/cascading/mongodb/MongoDBTap.java b/process/commons/hadoop/scalding/src/main/java/com/clojurewekz/cascading/mongodb/MongoDBTap.java
deleted file mode 100644
index fef034a..0000000
--- a/process/commons/hadoop/scalding/src/main/java/com/clojurewekz/cascading/mongodb/MongoDBTap.java
+++ /dev/null
@@ -1,161 +0,0 @@
-package com.clojurewerkz.cascading.mongodb;
-
-import java.io.IOException;
-
-import cascading.tuple.TupleEntryCollector;
-import org.apache.hadoop.mapred.FileInputFormat;
-import org.apache.hadoop.mapred.JobConf;
-import org.apache.hadoop.mapred.RecordReader;
-import org.apache.hadoop.mapred.OutputCollector;
-
-import cascading.flow.FlowProcess;
-import cascading.tap.Tap;
-import cascading.tap.hadoop.io.HadoopTupleEntrySchemeIterator;
-import cascading.tap.hadoop.io.RecordReaderIterator;
-import cascading.tuple.TupleEntryIterator;
-import cascading.tuple.TupleEntrySchemeIterator;
-
-import com.mongodb.hadoop.io.BSONWritable;
-import com.mongodb.hadoop.util.MongoConfigUtil;
-
-@SuppressWarnings({"rawtypes", "unchecked"})
-public class MongoDBTap extends Tap<JobConf, RecordReader, OutputCollector> {
-
-  public final String id = "TEMP_ID";
-
-  public MongoDBScheme scheme;
-
-  public MongoDBTap(MongoDBScheme scheme) {
-    super(scheme);
-    this.scheme = scheme;
-  }
-
-  //
-  // Reader and writer initialization
-  //
-
-  /**
-   *
-   * @param flowProcess
-   * @param reader
-   * @return
-   * @throws IOException
-   */
-  @Override
-  public TupleEntryIterator openForRead(FlowProcess<JobConf> flowProcess, RecordReader reader) throws IOException {
-    return new HadoopTupleEntrySchemeIterator(flowProcess, this , reader);
-  }
-
-  /**
-   *
-   * @param flowProcess
-   * @param outputCollector
-   * @return
-   * @throws IOException
-   */
-  @Override
-  public TupleEntryCollector openForWrite(FlowProcess<JobConf> flowProcess, OutputCollector outputCollector) throws IOException {
-    MongoDbCollector collector = new MongoDbCollector(flowProcess, this);
-    collector.prepare();
-    return collector;
-  }
-
-  //
-  // Resource manipulation
-  //
-
-  /**
-   *
-   * @param jobConf
-   * @return
-   * @throws IOException
-   */
-  @Override
-  public boolean createResource(JobConf jobConf) throws IOException {
-    // TODO
-    return true;
-  }
-
-
-  /**
-   *
-   * @param jobConf
-   * @return
-   * @throws IOException
-   */
-  @Override
-  public boolean deleteResource(JobConf jobConf) throws IOException {
-    // TODO
-    return true;
-  }
-
-  /**
-   *
-   * @param jobConf
-   * @return
-   * @throws IOException
-   */
-  @Override
-  public boolean resourceExists(JobConf jobConf) throws IOException {
-    // TODO check if column-family exists
-    return true;
-  }
-
-  //
-  // Helper methods
-  //
-
-  /**
-   *
-   * @param jobConf
-   * @return
-   * @throws IOException
-   */
-  @Override
-  public long getModifiedTime(JobConf jobConf) throws IOException {
-    // TODO could read this from tables
-    return System.currentTimeMillis();
-  }
-
-  /**
-   *
-   * @param other
-   * @return
-   */
-  @Override
-  public boolean equals(Object other) {
-    if( this == other )
-      return true;
-    if( !( other instanceof MongoDBTap ) )
-      return false;
-    if( !super.equals( other ) )
-      return false;
-
-    MongoDBTap otherTap = (MongoDBTap) other;
-    if (!otherTap.getIdentifier().equals(getIdentifier())) return false;
-
-    return true;
-  }
-
-  /**
-   *
-   * @return
-   */
-  @Override
-  public int hashCode(){
-    int result = super.hashCode();
-    result = 31 * result + getIdentifier().hashCode();
-
-    return result;
-  }
-
-  /**
-   *
-   * @return
-   */
-  @Override
-  public String getIdentifier() {
-    return id + "_" + scheme.getIdentifier();
-  }
-
-}
diff --git a/process/commons/hadoop/scalding/src/main/java/com/clojurewekz/cascading/mongodb/MongoDbCollector.java b/process/commons/hadoop/scalding/src/main/java/com/clojurewekz/cascading/mongodb/MongoDbCollector.java
deleted file mode 100644
index 057bad6..0000000
--- a/process/commons/hadoop/scalding/src/main/java/com/clojurewekz/cascading/mongodb/MongoDbCollector.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package com.clojurewerkz.cascading.mongodb;
-
-import cascading.flow.FlowProcess;
-import cascading.flow.hadoop.HadoopFlowProcess;
-import cascading.tap.Tap;
-import cascading.tap.TapException;
-import cascading.tuple.TupleEntrySchemeCollector;
-import com.mongodb.DBObject;
-import com.mongodb.hadoop.MongoOutput;
-import com.mongodb.hadoop.io.BSONWritable;
-import com.mongodb.hadoop.mapred.output.MongoRecordWriter;
-import org.apache.hadoop.mapred.*;
-import org.bson.BSONObject;
-import org.bson.types.ObjectId;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.IOException;
-
-public class MongoDbCollector extends TupleEntrySchemeCollector<JobConf, OutputCollector> implements OutputCollector {
-
-  /**
-   * Field LOG
-   */
-  private static final Logger LOG = LoggerFactory.getLogger(MongoDbCollector.class);
-
-  private final JobConf conf;
-  private RecordWriter writer;
-  private final FlowProcess<JobConf> hadoopFlowProcess;
-  private final Tap<JobConf, RecordReader, OutputCollector> tap;
-  private final Reporter reporter = Reporter.NULL;
-
-  /**
-   * Constructor TapCollector creates a new TapCollector instance.
-   *
-   * @param flowProcess
-   * @param tap         of type Tap
-   * @throws IOException when fails to initialize
-   */
-
-  public MongoDbCollector(FlowProcess<JobConf> flowProcess, Tap<JobConf, RecordReader, OutputCollector> tap) throws IOException {
-    super(flowProcess, tap.getScheme());
-    this.hadoopFlowProcess = flowProcess;
-
-    this.tap = tap;
-    this.conf = new JobConf(flowProcess.getConfigCopy());
-
-    this.setOutput(this);
-  }
-
-  /**
-   *
-   */
-  @Override
-  public void prepare() {
-    try {
-      initialize();
-    } catch (IOException e) {
-      throw new RuntimeException(e);
-    }
-
-    super.prepare();
-  }
-
-  /**
-   *
-   * @throws IOException
-   */
-  private void initialize() throws IOException {
-    tap.sinkConfInit(hadoopFlowProcess, conf);
-
-    OutputFormat outputFormat = conf.getOutputFormat();
-
-    LOG.info("Output format class is: " + outputFormat.getClass().toString());
-
-    writer = outputFormat.getRecordWriter(null, conf, tap.getIdentifier(), Reporter.NULL);
-
-    sinkCall.setOutput(this);
-  }
-
-  /**
-   *
-   */
-  @Override
-  public void close() {
-    try {
-      LOG.info("closing tap collector for: {}", tap);
-      writer.close(reporter);
-    } catch (IOException exception) {
-      LOG.warn("exception closing: {}", exception);
-      throw new TapException("exception closing JDBCTapCollector", exception);
-    } finally {
-      super.close();
-    }
-  }
-
-  /**
-   *
-   * @param writableComparable
-   * @param writable
-   * @throws IOException
-   */
-  public void collect(Object writableComparable, Object writable) throws IOException {
-    if (hadoopFlowProcess instanceof HadoopFlowProcess)
-      ((HadoopFlowProcess) hadoopFlowProcess).getReporter().progress();
-
-    ((MongoRecordWriter) writer).write(writableComparable, writable);
-  }
-}
diff --git a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/MongoSource.scala b/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/MongoSource.scala
deleted file mode 100644
index 5f219fa..0000000
--- a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/MongoSource.scala
+++ /dev/null
@@ -1,39 +0,0 @@
-package io.prediction.commons.scalding
-
-import scala.collection.JavaConversions._
-
-import com.twitter.scalding._
-
-import cascading.tap.Tap
-
-import org.apache.hadoop.mapred.JobConf
-import org.apache.hadoop.mapred.OutputCollector
-import org.apache.hadoop.mapred.RecordReader
-
-import com.clojurewerkz.cascading.mongodb.MongoDBScheme
-import com.clojurewerkz.cascading.mongodb.MongoDBTap
-import com.mongodb.casbah.Imports.MongoDBObject
-import com.mongodb.DBObject
-
-import java.util.List
-import java.util.ArrayList
-import java.util.Map
-import java.util.HashMap
-
-case class MongoSource(db: String, coll: String, cols: List[String], mappings: Map[String, String], query: DBObject = MongoDBObject(), hosts: Seq[String] = Seq("localhost"), ports: Seq[Int] = Seq(27017)) extends Source {
-
-  val mongoScheme = new MongoDBScheme(hosts.toArray, ports.toArray.map(_.asInstanceOf[Integer]), db, coll, cols, mappings, query)
-
-  // auxiliary constructor for no-query case
-  //def this(db: String, coll: String, cols: List[String], mappings: Map[String, String], hosts: Seq[String] = Seq("localhost"), ports: Seq[Int] = Seq(27017)) =
-  //  this(db, coll, cols, mappings, MongoDBObject(), hosts, ports)
-
-  protected def castMongoTap(tap: MongoDBTap): Tap[JobConf, RecordReader[_, _], OutputCollector[_, _]] = {
-    tap.asInstanceOf[Tap[JobConf, RecordReader[_, _], OutputCollector[_, _]]]
-
-  }
-
-  override def createTap(readOrWrite: AccessMode)(implicit mode: Mode): Tap[_, _, _] = {
-    castMongoTap(new MongoDBTap(mongoScheme))
-  }
-}
diff --git a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/AppData.scala b/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/AppData.scala
deleted file mode 100644
index 3ba5318..0000000
--- a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/AppData.scala
+++ /dev/null
@@ -1,79 +0,0 @@
-package io.prediction.commons.scalding.appdata
-
-import com.twitter.scalding._
-
-import cascading.flow.FlowDef
-import cascading.tuple.Tuple
-
-import io.prediction.commons.scalding.appdata.mongodb.{ MongoUsersSource, MongoItemsSource, MongoU2iActionsSource }
-import io.prediction.commons.scalding.appdata.file.{ FileUsersSource, FileItemsSource, FileU2iActionsSource }
-
-object Users {
-
-  /**
-   * dbName: used as file path in dbType=="file"
-   */
-  def apply(appId: Int, dbType: String, dbName: String, dbHost: Seq[String], dbPort: Seq[Int]): UsersSource = {
-    dbType match {
-      case "file" => {
-        new FileUsersSource(dbName, appId)
-      }
-      case "mongodb" => {
-        require(((!dbHost.isEmpty) && (!dbPort.isEmpty)), "Please specify host and port number for mongodb.")
-        new MongoUsersSource(dbName, dbHost, dbPort, appId)
-      }
-      case _ => {
-        throw new RuntimeException("Invalid Users database type: " + dbType)
-      }
-    }
-  }
-
-}
-
-object Items {
-
-  /**
-   * dbName: used as file path in dbType=="file"
-   */
-  def apply(appId: Int, itypes: Option[List[String]], dbType: String, dbName: String, dbHost: Seq[String], dbPort: Seq[Int]): ItemsSource = {
-    dbType match {
-      case "file" => {
-        new FileItemsSource(dbName, appId, itypes)
-      }
-      case "mongodb" => {
-        require(((!dbHost.isEmpty) && (!dbPort.isEmpty)), "Please specify host and port number for mongodb.")
-        new MongoItemsSource(dbName, dbHost, dbPort, appId, itypes)
-      }
-      case _ => {
-        throw new RuntimeException("Invalid Items database type: " + dbType)
-      }
-    }
-  }
-
-}
-
-object U2iActions {
-
-  /**
-   * dbName: used as file path in dbType=="file"
-   */
-  def apply(appId: Int, dbType: String, dbName: String, dbHost: Seq[String], dbPort: Seq[Int]): U2iActionsSource = {
-    dbType match {
-      case "file" => {
-        new FileU2iActionsSource(dbName, appId)
-      }
-      case "mongodb" => {
-        require(((!dbHost.isEmpty) && (!dbPort.isEmpty)), "Please specify host and port number for mongodb.")
-        /*
-        val opt = evalId.map(x => Map("evalid" -> x)).getOrElse(Map())
-        val queryData = Map("appid" -> appId) ++ opt
-        */
-        new MongoU2iActionsSource(dbName, dbHost, dbPort, appId)
-      }
-      case _ => {
-        throw new RuntimeException("Invalid U2iActions database type: " + dbType)
-      }
-    }
-  }
-
-}
diff --git a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/ItemsSource.scala b/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/ItemsSource.scala
deleted file mode 100644
index 238e9e6..0000000
--- a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/ItemsSource.scala
+++ /dev/null
@@ -1,73 +0,0 @@
-package io.prediction.commons.scalding.appdata
-
-import com.twitter.scalding._
-
-import cascading.pipe.Pipe
-import cascading.flow.FlowDef
-
-// use trait because different DB may have a bit different raw read data.
-// such as time format, etc.
-// The DB Source class should implement this trait so the algo implementers
-// can get the same type of pipe returned regardless of the actual DB type.
-
-trait ItemsSource {
-
-  import com.twitter.scalding.Dsl._ // get all the fancy implicit conversions that define the DSL
-
-  def getSource: Source
-
-  /**
-   * read data and return Pipe with field name of the Symbol parameters and expected data type
-   * iidField: Symbol of iid(String)
-   * itypesField: Symbol of itypes(List[String])
-   */
-  def readData(iidField: Symbol, itypesField: Symbol)(implicit fd: FlowDef): Pipe
-
-  /**
-   * iidField: Symbol of iid(String)
-   * itypesField: Symbol of itypes(List[String])
-   * starttimeField: Symbol of starttime(Long)
-   * endtimeField: Symbol of endtime(Option[Long])
-   */
-  def readStartEndtime(iidField: Symbol, itypesField: Symbol, starttimeField: Symbol, endtimeField: Symbol)(implicit fd: FlowDef): Pipe = {
-    throw new RuntimeException("ItemsSource readStartEndtime is not implemented.")
-  }
-
-  /**
-   * return Item Obj
-   */
-  def readObj(objField: Symbol)(implicit fd: FlowDef): Pipe = {
-    throw new RuntimeException("ItemsSource readObj is not implemented.")
-  }
-
-  /**
-   * map pipe's field data to DB table fields and write to dbSink
-   * iidField: Symbol of iid(String)
-   * itypesField: Symbol of itypes(List[String])
-   * appid: Appid Int
-   */
-  def writeData(iidField: Symbol, itypesField: Symbol, appid: Int)(p: Pipe)(implicit fd: FlowDef): Pipe
-
-  /**
-   * write Item Obj
-   */
-  def writeObj(objField: Symbol)(p: Pipe)(implicit fd: FlowDef): Pipe = {
-    throw new RuntimeException("ItemsSource writeObj is not implemented.")
-  }
-}
-
-object ItemsSource {
-  /**
-   *  define the corresponding cascading Symbol name for each DB table field.
-   *  ("table field name" -> Symbol)
-   */
-  val FIELD_SYMBOLS: Map[String, Symbol] = Map(
-    ("id" -> 'id),
-    ("appid" -> 'appid),
-    ("ct" -> 'ct),
-    ("itypes" -> 'itypes),
-    ("starttime" -> 'starttime),
-    ("endtime" -> 'endtime), // optional
-    ("inactive" -> 'inactive)) // optional
-
-}
diff --git a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/U2iActionsSource.scala b/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/U2iActionsSource.scala
deleted file mode 100644
index e5f7d39..0000000
--- a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/U2iActionsSource.scala
+++ /dev/null
@@ -1,56 +0,0 @@
-package io.prediction.commons.scalding.appdata
-
-import com.twitter.scalding._
-
-import cascading.pipe.Pipe
-import cascading.flow.FlowDef
-
-// use trait because different DB may have a bit different raw read data.
-// such as time format, etc.
-// The DB Source class should implement this trait so the algo implementers 
-// can get the same type of pipe returned regardless of the actual DB type.
-
-trait U2iActionsSource {
-
-  import com.twitter.scalding.Dsl._ // get all the fancy implicit conversions that define the DSL
-
-  def getSource: Source
-
-  /**
-   * read data and return Pipe with field name of the Symbol parameters
-   * actionField: Symbol of action(String)
-   * uidField: Symbol of uid(String)
-   * iidField: Symbol of iid(String)
-   * tField: Symbol of t(String)
-   * vField: Symbol of v(Option[String])
-   */
-  def readData(actionField: Symbol, uidField: Symbol, iidField: Symbol, tField: Symbol, vField: Symbol)(implicit fd: FlowDef): Pipe
-
-  /**
-   * map pipe's field data to DB table fields and write to dbSink.
-   * actionField: Symbol of action(String)
-   * uidField: Symbol of uid(String)
-   * iidField: Symbol of iid(String)
-   * tField: Symbol of t(String)
-   * vField: Symbol of v(Option[String])
-   * appid: App ID(Int)
-   * p: Pipe. the data pipe.
-   */
-  def writeData(actionField: Symbol, uidField: Symbol, iidField: Symbol, tField: Symbol, vField: Symbol, appid: Int)(p: Pipe)(implicit fd: FlowDef): Pipe
-
-}
-
-object U2iActionsSource {
-  /**
-   *  define the corresponding cascading Symbol name for each DB table field.
-   *  ("table field name" -> Symbol)
-   */
-  val FIELD_SYMBOLS: Map[String, Symbol] = Map(
-    ("action" -> 'action),
-    ("uid" -> 'uid),
-    ("iid" -> 'iid),
-    ("t" -> 't),
-    ("v" -> 'v),
-    ("appid" -> 'appid))
-
-}
diff --git a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/UsersSource.scala b/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/UsersSource.scala
deleted file mode 100644
index 170d675..0000000
--- a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/UsersSource.scala
+++ /dev/null
@@ -1,58 +0,0 @@
-package io.prediction.commons.scalding.appdata
-
-import com.twitter.scalding._
-
-import cascading.pipe.Pipe
-import cascading.flow.FlowDef
-
-// use trait because different DB may have a bit different raw read data.
-// such as time format, etc.
-// The DB Source class should implement this trait so the algo implementers 
-// can get the same type of pipe returned regardless of the actual DB type.
-
-trait UsersSource {
-
-  import com.twitter.scalding.Dsl._ // get all the fancy implicit conversions that define the DSL
-
-  def getSource: Source
-
-  /**
-   * read data and return Pipe with field name of the Symbol parameters and expected data type
-   * uidField: Symbol of iid(String)
-   */
-  def readData(uidField: Symbol)(implicit fd: FlowDef): Pipe
-
-  /**
-   * read User object
-   */
-  def readObj(objField: Symbol)(implicit fd: FlowDef): Pipe = {
-    throw new RuntimeException("UsersSource readObj is not implemented.")
-  }
-
-  /**
-   * map pipe's field data to DB table fields and write to dbSink
-   * uidField: Symbol of iid(String)
-   * appid: Appid Int
-   */
-  def writeData(uidField: Symbol, appid: Int)(p: Pipe)(implicit fd: FlowDef): Pipe
-
-  /**
-   * write User object
-   */
-  def writeObj(objField: Symbol)(p: Pipe)(implicit fd: FlowDef): Pipe = {
-    throw new RuntimeException("UsersSource writeObj is not implemented.")
-  }
-
-}
-
-object UsersSource {
-  /**
-   *  define the corresponding cascading Symbol name for each DB table field.
-   *  ("table field name" -> Symbol)
-   */
-  val FIELD_SYMBOLS: Map[String, Symbol] = Map(
-    ("id" -> 'id),
-    ("appid" -> 'appid),
-    ("ct" -> 'ct))
-
-}
\ No newline at end of file
diff --git a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/file/FileItemsSource.scala b/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/file/FileItemsSource.scala
deleted file mode 100644
index c10d6c0..0000000
--- a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/file/FileItemsSource.scala
+++ /dev/null
@@ -1,173 +0,0 @@
-package io.prediction.commons.scalding.appdata.file
-
-import com.twitter.scalding._
-
-import cascading.pipe.Pipe
-import cascading.flow.FlowDef
-
-import org.joda.time.DateTime
-
-//import io.prediction.commons.scalding.AppDataFile
-import io.prediction.commons.scalding.appdata.ItemsSource
-import io.prediction.commons.scalding.appdata.ItemsSource.FIELD_SYMBOLS
-import io.prediction.commons.appdata.{ Item }
-
-/**
- * File Format:
- * 0     1         2        3            4      5           6
- * <id>\t<itypes>\t<appid>\t<starttime>\t<ct>\t<endtime>\t<inactive>
- *
- * endtime is optional
- * use PIO_NONE if no value for optional field
- *
- * Example:
- * 1  t1,t2,t3  4  123456  123210  654321
- * 1  t1,t2,t3  4  123456  123210  PIO_NONE
- */
-class FileItemsSource(path: String, appId: Int, itypes: Option[List[String]]) extends Tsv(
-  p = path + "items.tsv"
-) with ItemsSource {
-
-  import com.twitter.scalding.Dsl._ // get all the fancy implicit conversions that define the DSL
-
-  override def getSource: Source = this
-
-  override def readData(iidField: Symbol, itypesField: Symbol)(implicit fd: FlowDef): Pipe = {
-    this.read
-      .mapTo((0, 1) -> (iidField, itypesField)) { fields: (String, String) =>
-        val (iid, itypes) = fields
-
-        (iid, itypes.split(",").toList)
-
-      }.then(filterItypes(itypesField, itypes) _)
-
-  }
-
-  private def filterItypes(itypesField: Symbol, queryItypes: Option[List[String]])(p: Pipe)(implicit fd: FlowDef): Pipe = {
-    val dataPipe =
-      if (queryItypes == None) p
-      else p.filter(itypesField) { x: List[String] =>
-        val orgSize = x.size
-        val diffList = x diff queryItypes.get
-        // diff return a new list WITHOUT element appearing in queryItypes.
-        // if diffList is shorter than original, it means itypes has elements in queryItypes
-        // if diffList is the same, it means itypes has no element in queryItypes.
-        // Since we want items which is one of queryItypes, we only want item has diffList smaller.
-        diffList.size < orgSize
-      }
-
-    dataPipe
-  }
-
-  override def readStartEndtime(iidField: Symbol, itypesField: Symbol, starttimeField: Symbol, endtimeField: Symbol)(implicit fd: FlowDef): Pipe = {
-    this.read
-      .mapTo((0, 1, 3, 5) -> (iidField, itypesField, starttimeField, endtimeField)) { fields: (String, String, Long, String) =>
-        val (iid, itypes, starttime, endtime) = fields
-
-        val endtimeOpt: Option[Long] = endtime match {
-          case "PIO_NONE" => None
-          case x: String => {
-            try {
-              Some(x.toLong)
-            } catch {
-              case e: Exception => {
-                assert(false, s"Failed to convert ${x} to Long. Exception: " + e)
-                Some(0)
-              }
-            }
-          }
-        }
-
-        (iid, itypes.split(",").toList, starttime, endtimeOpt)
-
-      }.then(filterItypes('itypes, itypes) _)
-  }
-
-  override def readObj(objField: Symbol)(implicit fd: FlowDef): Pipe = {
-    val items = this.read
-      .mapTo((0, 1, 2, 3, 4, 5, 6) -> (objField, 'itypes)) { fields: (String, String, Int, Long, Long, String, String) =>
-        val (id, itypes, appid, starttime, ct, endtime, inactive) = fields
-
-        val itypesList = itypes.split(",").toList
-
-        val endtimeOpt: Option[Long] = endtime match {
-          case "PIO_NONE" => None
-          case x: String => {
-            try {
-              Some(x.toLong)
-            } catch {
-              case e: Exception => {
-                assert(false, s"Failed to convert ${x} to Long. Exception: " + e)
-                Some(0)
-              }
-            }
-          }
-        }
-
-        val inactiveOpt: Option[Boolean] = inactive match {
-          case "PIO_NONE" => None
-          case x: String => {
-            try {
-              Some(x.toBoolean)
-            } catch {
-              case e: Exception => {
-                assert(false, s"Failed to convert ${x} to Boolean. Exception: " + e)
-                Some(false)
-              }
-            }
-          }
-        }
-
-        (Item(
-          id = id,
-          appid = appid,
-          ct = new DateTime(ct),
-          itypes = itypesList,
-          starttime = Some(new DateTime(starttime)),
-          endtime = endtimeOpt.map(x => new DateTime(x)),
-          price = None,
-          profit = None,
-          latlng = None,
-          inactive = inactiveOpt,
-          attributes = None
-        ), itypesList)
-
-      }
-      .then(filterItypes('itypes, itypes) _)
-      .project(objField)
-
-    items
-  }
-
-  override def writeData(iidField: Symbol, itypesField: Symbol, appid: Int)(p: Pipe)(implicit fd: FlowDef): Pipe = {
-    val writtenData = p.mapTo((iidField, itypesField) ->
-      (FIELD_SYMBOLS("id"), FIELD_SYMBOLS("itypes"), FIELD_SYMBOLS("appid"))) {
-      fields: (String, List[String]) =>
-        val (iid, itypes) = fields
-
-        (iid, itypes.mkString(","), appid)
-    }.write(this)
-
-    writtenData
-  }
-
-  override def writeObj(objField: Symbol)(p: Pipe)(implicit fd: FlowDef): Pipe = {
-    val writtenData = p.mapTo(objField ->
-      (FIELD_SYMBOLS("id"), FIELD_SYMBOLS("itypes"), FIELD_SYMBOLS("appid"),
-        FIELD_SYMBOLS("starttime"), FIELD_SYMBOLS("ct"),
-        FIELD_SYMBOLS("endtime"), FIELD_SYMBOLS("inactive"))) { obj: Item =>
-
-      val starttime: java.util.Date = obj.starttime.get.toDate()
-      val ct: java.util.Date = obj.ct.toDate()
-      val endtime: String = obj.endtime.map(_.toDate().getTime().toString)
-        .getOrElse("PIO_NONE")
-      val inactive: String = obj.inactive.map(_.toString).getOrElse("PIO_NONE")
-
-      (obj.id, obj.itypes.mkString(","), obj.appid, starttime.getTime(), ct.getTime(), endtime, inactive)
-
-    }.write(this)
-
-    writtenData
-  }
-
-}
diff --git a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/file/FileU2iActionsSource.scala b/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/file/FileU2iActionsSource.scala
deleted file mode 100644
index f326e6e..0000000
--- a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/file/FileU2iActionsSource.scala
+++ /dev/null
@@ -1,60 +0,0 @@
-package io.prediction.commons.scalding.appdata.file
-
-import com.twitter.scalding._
-
-import cascading.pipe.Pipe
-import cascading.flow.FlowDef
-
-//import io.prediction.commons.scalding.AppDataFile
-import io.prediction.commons.scalding.appdata.U2iActionsSource
-import io.prediction.commons.scalding.appdata.U2iActionsSource.{ FIELD_SYMBOLS }
-
-/**
- * File Format:
- * <action>\t<uid>\t<iid>\t<t>\t<v>
- *
- * v is optional
- * use PIO_NONE if no value for optional field
- *
- * Example:
- * rate  u2  i13  123456  4
- * view  u2  i13  234567  PIO_NONE
- */
-class FileU2iActionsSource(path: String, appId: Int) extends Tsv(
-  p = path + "u2iActions.tsv"
-) with U2iActionsSource {
-
-  import com.twitter.scalding.Dsl._ // get all the fancy implicit conversions that define the DSL
-
-  override def getSource: Source = this
-
-  override def readData(actionField: Symbol, uidField: Symbol, iidField: Symbol, tField: Symbol, vField: Symbol)(implicit fd: FlowDef): Pipe = {
-    this.read
-      .mapTo((0, 1, 2, 3, 4) -> (actionField, uidField, iidField, tField, vField)) {
-        fields: (String, String, String, String, String) =>
-          val (action, uid, iid, t, v) = fields
-
-          val vOpt: Option[String] = v match {
-            case "PIO_NONE" => None
-            case x: String => Some(x)
-          }
-
-          (action, uid, iid, t, vOpt)
-      }
-  }
-
-  override def writeData(actionField: Symbol, uidField: Symbol, iidField: Symbol, tField: Symbol, vField: Symbol, appid: Int)(p: Pipe)(implicit fd: FlowDef): Pipe = {
-    val writtenData = p.mapTo((actionField, uidField, iidField, tField, vField) ->
-      (FIELD_SYMBOLS("action"), FIELD_SYMBOLS("uid"), FIELD_SYMBOLS("iid"), FIELD_SYMBOLS("t"), FIELD_SYMBOLS("v"), FIELD_SYMBOLS("appid"))) {
-      fields: (String, String, String, String, Option[String]) =>
-        val (action, uid, iid, t, v) = fields
-
-        val vData: String = v.getOrElse("PIO_NONE")
-
-        (action, uid, iid, t, vData, appid)
-    }.write(this)
-
-    writtenData
-  }
-
-}
\ No newline at end of file
diff --git a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/file/FileUsersSource.scala b/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/file/FileUsersSource.scala
deleted file mode 100644
index ebc3d60..0000000
--- a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/file/FileUsersSource.scala
+++ /dev/null
@@ -1,81 +0,0 @@
-package io.prediction.commons.scalding.appdata.file
-
-import com.twitter.scalding._
-
-import cascading.pipe.Pipe
-import cascading.flow.FlowDef
-
-import org.joda.time.DateTime
-
-import io.prediction.commons.scalding.appdata.UsersSource
-import io.prediction.commons.scalding.appdata.UsersSource.FIELD_SYMBOLS
-import io.prediction.commons.appdata.{ User }
-
-/**
- * File Format:
- * <id>\t<appid>\t<ct>
- *
- * Example:
- * 1  2  12345
- */
-class FileUsersSource(path: String, appId: Int) extends Tsv(
-  p = path + "users.tsv"
-) with UsersSource {
-
-  import com.twitter.scalding.Dsl._ // get all the fancy implicit conversions that define the DSL
-
-  override def getSource: Source = this
-
-  override def readData(uidField: Symbol)(implicit fd: FlowDef): Pipe = {
-    val users = this.read
-      .mapTo((0) -> (uidField)) { fields: String =>
-
-        fields
-      }
-
-    users
-  }
-
-  override def readObj(objField: Symbol)(implicit fd: FlowDef): Pipe = {
-    val users = this.read
-      .mapTo((0, 1, 2) -> objField) { fields: (String, Int, Long) =>
-        val (id, appid, ct) = fields
-
-        User(
-          id = id,
-          appid = appid,
-          ct = new DateTime(ct),
-          latlng = None,
-          inactive = None,
-          attributes = None
-        )
-      }
-
-    users
-  }
-
-  override def writeData(uidField: Symbol, appid: Int)(p: Pipe)(implicit fd: FlowDef): Pipe = {
-    val writtenData = p.mapTo((uidField) ->
-      (FIELD_SYMBOLS("id"), FIELD_SYMBOLS("appid"))) {
-      fields: String =>
-        val uid = fields
-
-        (uid, appid)
-    }.write(this)
-
-    writtenData
-  }
-
-  override def writeObj(objField: Symbol)(p: Pipe)(implicit fd: FlowDef): Pipe = {
-    val writtenData = p.mapTo((objField) ->
-      (FIELD_SYMBOLS("id"), FIELD_SYMBOLS("appid"), FIELD_SYMBOLS("ct"))) { obj: User =>
-
-      val ct: java.util.Date = obj.ct.toDate()
-
-      (obj.id, obj.appid, ct.getTime())
-    }.write(this)
-
-    writtenData
-  }
-
-}
\ No newline at end of file
diff --git a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/monogodb/MongoItemsSource.scala b/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/monogodb/MongoItemsSource.scala
deleted file mode 100644
index a6c8214..0000000
--- a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/monogodb/MongoItemsSource.scala
+++ /dev/null
@@ -1,163 +0,0 @@
-package io.prediction.commons.scalding.appdata.mongodb
-
-import com.twitter.scalding._
-
-import cascading.pipe.Pipe
-import cascading.flow.FlowDef
-import cascading.tuple.Tuple
-
-import java.util.ArrayList
-import java.util.HashMap
-
-//import org.scala_tools.time.Imports._
-//import com.github.nscala_time.time.Imports._
-import org.joda.time.DateTime
-
-import com.mongodb.BasicDBList
-import com.mongodb.casbah.Imports._
-//import com.mongodb.casbah.commons.conversions.scala.RegisterJodaTimeConversionHelpers
-
-import io.prediction.commons.scalding.MongoSource
-import io.prediction.commons.scalding.appdata.ItemsSource
-import io.prediction.commons.scalding.appdata.ItemsSource.FIELD_SYMBOLS
-import io.prediction.commons.appdata.{ Item }
-
-class MongoItemsSource(db: String, hosts: Seq[String], ports: Seq[Int], appid: Int, itypes: Option[List[String]]) extends MongoSource(
-  db = db,
-  coll = "items",
-  cols = {
-    val itemsCols = new ArrayList[String]()
-
-    itemsCols.add("_id") // 0
-    itemsCols.add("itypes") // 1
-    itemsCols.add("appid") // 2
-    itemsCols.add("starttime") // 3
-    itemsCols.add("ct") // 4
-    itemsCols.add("endtime") // 5 optional
-    itemsCols.add("inactive") // 6 optional
-
-    itemsCols
-  },
-  mappings = {
-    val itemsMappings = new HashMap[String, String]()
-
-    itemsMappings.put("_id", FIELD_SYMBOLS("id").name)
-    itemsMappings.put("itypes", FIELD_SYMBOLS("itypes").name)
-    itemsMappings.put("appid", FIELD_SYMBOLS("appid").name)
-    itemsMappings.put("starttime", FIELD_SYMBOLS("starttime").name)
-    itemsMappings.put("ct", FIELD_SYMBOLS("ct").name)
-    itemsMappings.put("endtime", FIELD_SYMBOLS("endtime").name) // optional
-    itemsMappings.put("inactive", FIELD_SYMBOLS("inactive").name) // optional
-
-    itemsMappings
-  },
-  query = { // read query
-    val itemsQuery = MongoDBObject("appid" -> appid) ++ (itypes.map(x => MongoDBObject("itypes" -> MongoDBObject("$in" -> x))).getOrElse(MongoDBObject()))
-
-    itemsQuery
-  },
-  hosts = hosts, // String
-  ports = ports // Int
-) with ItemsSource {
-
-  import com.twitter.scalding.Dsl._ // get all the fancy implicit conversions that define the DSL
-
-  override def getSource: Source = this
-
-  override def readData(iidField: Symbol, itypesField: Symbol)(implicit fd: FlowDef): Pipe = {
-    val items = this.read
-      .mapTo((0, 1) -> (iidField, itypesField)) { fields: (String, BasicDBList) =>
-        // NOTE: convert itypes form BasicDBList to scala List.
-        (fields._1, fields._2.toList)
-      }
-
-    items
-  }
-
-  override def readStartEndtime(iidField: Symbol, itypesField: Symbol, starttimeField: Symbol, endtimeField: Symbol)(implicit fd: FlowDef): Pipe = {
-    val items = this.read
-      .mapTo((0, 1, 3, 5) -> (iidField, itypesField, starttimeField, endtimeField)) { fields: (String, BasicDBList, java.util.Date, java.util.Date) =>
-
-        //val dt = new DateTime(fields._3)
-        val starttime: Long = fields._3.getTime()
-        val endtimeOpt: Option[Long] = Option(fields._4).map(_.getTime()) // NOTE: become None if fields._4 is null
-
-        // NOTE: convert itypes form BasicDBList to scala List.
-        (fields._1, fields._2.toList, starttime, endtimeOpt)
-      }
-
-    items
-  }
-
-  override def readObj(objField: Symbol)(implicit fd: FlowDef): Pipe = {
-    val items = this.read
-      .mapTo((0, 1, 2, 3, 4, 5, 6) -> (objField)) {
-        fields: (String, BasicDBList, Int, java.util.Date, java.util.Date, java.util.Date, Any) =>
-          val (id, itypes, appid, starttime, ct, endtime, inactiveAny) = fields
-
-          val inactive: Option[Boolean] = inactiveAny match {
-            case null => None
-            case x: Boolean => Some(x)
-            case _ => None
-          }
-
-          Item(
-            id = id,
-            appid = appid,
-            ct = new DateTime(ct),
-            itypes = itypes.toList.map(x => x.toString),
-            starttime = Some(new DateTime(starttime)),
-            endtime = Option(endtime).map(x => new DateTime(x)),
-            price = None,
-            profit = None,
-            latlng = None,
-            inactive = inactive,
-            attributes = None
-          )
-
-      }
-    items
-  }
-
-  override def writeData(iidField: Symbol, itypesField: Symbol, appid: Int)(p: Pipe)(implicit fd: FlowDef): Pipe = {
-    val writtenData = p.mapTo((iidField, itypesField) ->
-      (FIELD_SYMBOLS("id"), FIELD_SYMBOLS("itypes"), FIELD_SYMBOLS("appid"))) {
-      fields: (String, List[String]) =>
-        val (iid, itypes) = fields
-
-        val itypesTuple = new Tuple()
-
-        for (x <- itypes) {
-          itypesTuple.add(x)
-        }
-
-        (iid, itypesTuple, appid)
-    }.write(this)
-
-    writtenData
-  }
-
-  override def writeObj(objField: Symbol)(p: Pipe)(implicit fd: FlowDef): Pipe = {
-    val writtenData = p.mapTo(objField ->
-      (FIELD_SYMBOLS("id"), FIELD_SYMBOLS("itypes"), FIELD_SYMBOLS("appid"),
-        FIELD_SYMBOLS("starttime"), FIELD_SYMBOLS("ct"),
-        FIELD_SYMBOLS("endtime"), FIELD_SYMBOLS("inactive"))) { obj: Item =>
-
-      val itypesTuple = new Tuple()
-
-      for (x <- obj.itypes) {
-        itypesTuple.add(x)
-      }
-
-      val starttime: java.util.Date = obj.starttime.get.toDate()
-      val ct: java.util.Date = obj.ct.toDate()
-      val endtime: java.util.Date = obj.endtime.map(_.toDate()).getOrElse(null)
-      val inactive: Any = obj.inactive.getOrElse(null)
-
-      (obj.id, itypesTuple, obj.appid, starttime, ct, endtime, inactive)
-    }.write(this)
-
-    writtenData
-  }
-
-}
diff --git a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/monogodb/MongoU2iActionsSource.scala b/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/monogodb/MongoU2iActionsSource.scala
deleted file mode 100644
index 7ff3d81..0000000
--- a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/monogodb/MongoU2iActionsSource.scala
+++ /dev/null
@@ -1,115 +0,0 @@
-package io.prediction.commons.scalding.appdata.mongodb
-
-import com.twitter.scalding._
-
-import cascading.pipe.Pipe
-import cascading.flow.FlowDef
-
-import java.util.ArrayList
-import java.util.HashMap
-
-//import org.scala_tools.time.Imports._
-//import com.github.nscala_time.time.Imports._
-import org.joda.time.DateTime
-
-import com.mongodb.BasicDBList
-import com.mongodb.casbah.Imports._
-//import com.mongodb.casbah.commons.conversions.scala.RegisterJodaTimeConversionHelpers
-
-import io.prediction.commons.scalding.MongoSource
-import io.prediction.commons.scalding.appdata.U2iActionsSource
-import io.prediction.commons.scalding.appdata.U2iActionsSource.FIELD_SYMBOLS
-
-class MongoU2iActionsSource(db: String, hosts: Seq[String], ports: Seq[Int], appId: Int) extends MongoSource(
-  db = db,
-  coll = "u2iActions",
-  cols = {
-    val u2iCols = new ArrayList[String]()
-    u2iCols.add("action") // 0
-    u2iCols.add("uid") // 1
-    u2iCols.add("iid") // 2
-    u2iCols.add("t") // 3
-    u2iCols.add("v") // 4 optional
-    u2iCols.add("appid")
-
-    u2iCols
-  },
-  mappings = {
-    val u2iMappings = new HashMap[String, String]()
-
-    u2iMappings.put("action", FIELD_SYMBOLS("action").name)
-    u2iMappings.put("uid", FIELD_SYMBOLS("uid").name)
-    u2iMappings.put("iid", FIELD_SYMBOLS("iid").name)
-    u2iMappings.put("t", FIELD_SYMBOLS("t").name)
-    u2iMappings.put("v", FIELD_SYMBOLS("v").name)
-    u2iMappings.put("appid", FIELD_SYMBOLS("appid").name)
-
-    u2iMappings
-  },
-  query = { // read query
-    /*
-      val builder = MongoDBObject.newBuilder
-
-      queryData foreach {
-        case (field, value) =>
-          builder += field -> value
-      }
-
-      builder.result
-      */
-
-    val u2iQuery = MongoDBObject("appid" -> appId)
-    //++
-    //  (evalId.map(x => MongoDBObject("evalid" -> x)).getOrElse(MongoDBObject()))
-
-    u2iQuery
-  },
-  hosts = hosts, // String
-  ports = ports // Int
-) with U2iActionsSource {
-
-  import com.twitter.scalding.Dsl._ // get all the fancy implicit conversions that define the DSL
-
-  //RegisterJodaTimeConversionHelpers()
-
-  override def getSource: Source = this
-
-  /**
-   * NOTE:
-   * for optional field vField, due to the current limitation/issue of mongo-hadoop/cascading-mongo Tap,
-   * the value will be the same as previous read record if this record has this field missing while
-   * None/Null should be expected.
-   * Since the meaning of v field depends on action field while action field is a required field,
-   * can still work around this issue because can decode meaning of v field based on action field.
-   */
-  override def readData(actionField: Symbol, uidField: Symbol, iidField: Symbol, tField: Symbol, vField: Symbol)(implicit fd: FlowDef): Pipe = {
-    val u2iactions = this.read
-      .mapTo((0, 1, 2, 3, 4) -> (actionField, uidField, iidField, tField, vField)) {
-        fields: (String, String, String, java.util.Date, String) =>
-          val (action, uid, iid, t, v) = fields
-
-          //val dt = new DateTime(t)
-          val vOpt: Option[String] = Option(v)
-
-          (action, uid, iid, t.getTime().toString, vOpt)
-      }
-
-    u2iactions
-  }
-
-  override def writeData(actionField: Symbol, uidField: Symbol, iidField: Symbol, tField: Symbol, vField: Symbol, appid: Int)(p: Pipe)(implicit fd: FlowDef): Pipe = {
-    val dbData = p.mapTo((actionField, uidField, iidField, tField, vField) ->
-      (FIELD_SYMBOLS("action"), FIELD_SYMBOLS("uid"), FIELD_SYMBOLS("iid"), FIELD_SYMBOLS("t"), FIELD_SYMBOLS("v"), FIELD_SYMBOLS("appid"))) {
-      fields: (String, String, String, String, Option[String]) =>
-        val (action, uid, iid, t, v) = fields
-
-        // u2iAction v field type is Int
-        val vData: Any = v.map(_.toInt).getOrElse(null) // use null if no such field for this record
-
-        (action, uid, iid, new java.util.Date(t.toLong), vData, appid)
-    }.write(this)
-
-    dbData
-  }
-
-}
diff --git a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/monogodb/MongoUsersSource.scala b/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/monogodb/MongoUsersSource.scala
deleted file mode 100644
index dd6da21..0000000
--- a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/monogodb/MongoUsersSource.scala
+++ /dev/null
@@ -1,113 +0,0 @@
-package io.prediction.commons.scalding.appdata.mongodb
-
-import com.twitter.scalding._
-
-import cascading.pipe.Pipe
-import cascading.flow.FlowDef
-import cascading.tuple.Tuple
-
-import java.util.ArrayList
-import java.util.HashMap
-
-//import org.scala_tools.time.Imports._
-//import com.github.nscala_time.time.Imports._
-import org.joda.time.DateTime
-
-import com.mongodb.BasicDBList
-import com.mongodb.casbah.Imports._
-//import com.mongodb.casbah.commons.conversions.scala.RegisterJodaTimeConversionHelpers
-
-import io.prediction.commons.scalding.MongoSource
-import io.prediction.commons.scalding.appdata.UsersSource
-import io.prediction.commons.scalding.appdata.UsersSource.FIELD_SYMBOLS
-import io.prediction.commons.appdata.{ User }
-
-class MongoUsersSource(db: String, hosts: Seq[String], ports: Seq[Int], appid: Int) extends MongoSource(
-  db = db,
-  coll = "users",
-  cols = {
-    val usersCols = new ArrayList[String]()
-
-    usersCols.add("_id") // 0
-    usersCols.add("appid") // 1
-    usersCols.add("ct") // 2
-
-    usersCols
-  },
-  mappings = {
-    val usersMappings = new HashMap[String, String]()
-
-    usersMappings.put("_id", FIELD_SYMBOLS("id").name)
-    usersMappings.put("appid", FIELD_SYMBOLS("appid").name)
-    usersMappings.put("ct", FIELD_SYMBOLS("ct").name)
-
-    usersMappings
-  },
-  query = { // read query
-    val usersQuery = MongoDBObject("appid" -> appid)
-
-    usersQuery
-  },
-  hosts = hosts, // String
-  ports = ports // Int
-) with UsersSource {
-
-  import com.twitter.scalding.Dsl._ // get all the fancy implicit conversions that define the DSL
-
-  //RegisterJodaTimeConversionHelpers()
-
-  override def getSource: Source = this
-
-  override def readData(uidField: Symbol)(implicit fd: FlowDef): Pipe = {
-    val users = this.read
-      .mapTo((0) -> (uidField)) { fields: String =>
-
-        fields
-      }
-
-    users
-  }
-
-  override def readObj(objField: Symbol)(implicit fd: FlowDef): Pipe = {
-    val users = this.read
-      .mapTo((0, 1, 2) -> objField) { fields: (String, Int, java.util.Date) =>
-        val (id, appid, ct) = fields
-
-        User(
-          id = id,
-          appid = appid,
-          ct = new DateTime(ct),
-          latlng = None,
-          inactive = None,
-          attributes = None
-        )
-      }
-
-    users
-  }
-
-  override def writeData(uidField: Symbol, appid: Int)(p: Pipe)(implicit fd: FlowDef): Pipe = {
-    val writtenData = p.mapTo((uidField) ->
-      (FIELD_SYMBOLS("id"), FIELD_SYMBOLS("appid"))) {
-      fields: String =>
-        val uid = fields
-
-        (uid, appid)
-    }.write(this)
-
-    writtenData
-  }
-
-  override def writeObj(objField: Symbol)(p: Pipe)(implicit fd: FlowDef): Pipe = {
-    val writtenData = p.mapTo((objField) ->
-      (FIELD_SYMBOLS("id"), FIELD_SYMBOLS("appid"), FIELD_SYMBOLS("ct"))) { obj: User =>
-
-      val ct: java.util.Date = obj.ct.toDate()
-
-      (obj.id, obj.appid, ct)
-    }.write(this)
-
-    writtenData
-  }
-
-}
diff --git a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/monogodb/examples/ReadWrite.scala b/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/monogodb/examples/ReadWrite.scala
deleted file mode 100644
index 4423f23..0000000
--- a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/monogodb/examples/ReadWrite.scala
+++ /dev/null
@@ -1,84 +0,0 @@
-package io.prediction.commons.scalding.appdata.mongodb.examples
-
-import com.twitter.scalding._
-
-import io.prediction.commons.scalding.appdata.mongodb.{ MongoUsersSource, MongoItemsSource, MongoU2iActionsSource }
-import io.prediction.commons.appdata.{ Item, User }
-
-//TODO: clean up this example. see if there is better way to test MongoSource?
-class ReadWrite(args: Args) extends Job(args) {
-
-  val read_dbNameArg = args("read_dbName")
-  val read_dbHostArg = args.list("read_dbHost")
-  val read_dbPortArg = args.list("read_dbPort").map(_.toInt)
-
-  val read_appidArg = args("read_appid").toInt
-
-  val write_dbNameArg = args("write_dbName")
-  val write_dbHostArg = args.list("write_dbHost")
-  val write_dbPortArg = args.list("write_dbPort").map(_.toInt)
-
-  val write_appidArg = args("write_appid").toInt
-
-  val preItypesArg = args.list("itypes")
-  val itypesArg: Option[List[String]] = if (preItypesArg.mkString(",").length == 0) None else Option(preItypesArg)
-
-  val hdfsDir = args("hdfsDir")
-  /**
-   * test MongoUsersSource
-   * read from DB and write to Tsv
-   */
-  val usersSource = new MongoUsersSource(read_dbNameArg, read_dbHostArg, read_dbPortArg, read_appidArg)
-
-  val users = usersSource.readData('uid)
-    .write(Tsv(hdfsDir + "users.tsv"))
-
-  val usersObj = usersSource.readObj('user)
-    .write(Tsv(hdfsDir + "usersObj.tsv"))
-
-  val testUsersObj = new MongoUsersSource(write_dbNameArg + "_obj", write_dbHostArg, write_dbPortArg, write_appidArg)
-
-  usersObj.mapTo('user -> 'user) { obj: User =>
-    obj.copy(appid = write_appidArg)
-  }.then(testUsersObj.writeObj('user) _)
-
-  val testUsers = new MongoUsersSource(write_dbNameArg, write_dbHostArg, write_dbPortArg, write_appidArg)
-  users.then(testUsers.writeData('uid, write_appidArg) _)
-
-  /**
-   * test MongoItemsSource
-   * read from DB and write to Tsv
-   */
-  val itemsSource = new MongoItemsSource(read_dbNameArg, read_dbHostArg, read_dbPortArg, read_appidArg, itypesArg)
-
-  val items = itemsSource.readData('iid, 'itypes)
-    .write(Tsv(hdfsDir + "items.tsv"))
-
-  val itemsStarttime = itemsSource.readStartEndtime('iid, 'itypes, 'starttime, 'endtime)
-    .write(Tsv(hdfsDir + "itemsStarttime.tsv"))
-
-  val itemsObj = itemsSource.readObj('item)
-    .write(Tsv(hdfsDir + "itemsObj.tsv"))
-
-  val testItemsObj = new MongoItemsSource(write_dbNameArg + "_obj", write_dbHostArg, write_dbPortArg, write_appidArg, itypesArg)
-
-  itemsObj.mapTo('item -> 'item) { obj: Item =>
-    obj.copy(appid = write_appidArg)
-  }.then(testItemsObj.writeObj('item) _)
-
-  val testItems = new MongoItemsSource(write_dbNameArg, write_dbHostArg, write_dbPortArg, write_appidArg, itypesArg)
-  items.then(testItems.writeData('iid, 'itypes, write_appidArg) _)
-
-  /**
-   * test MongoU2iActionsSource
-   * read from DB and write to Tsv
-   */
-  val u2iSource = new MongoU2iActionsSource(read_dbNameArg, read_dbHostArg, read_dbPortArg, read_appidArg)
-
-  val u2i = u2iSource.readData('action, 'uid, 'iid, 't, 'v)
-  u2i.write(Tsv(hdfsDir + "u2iData.tsv"))
-
-  val testU2i = new MongoU2iActionsSource(write_dbNameArg, write_dbHostArg, write_dbPortArg, write_appidArg)
-  u2i.then(testU2i.writeData('action, 'uid, 'iid, 't, 'v, write_appidArg) _)
-
-}
diff --git a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/monogodb/examples/TestSchemaless.scala b/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/monogodb/examples/TestSchemaless.scala
deleted file mode 100644
index 0db4a0c..0000000
--- a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/appdata/monogodb/examples/TestSchemaless.scala
+++ /dev/null
@@ -1,46 +0,0 @@
-package io.prediction.commons.scalding.appdata.mongodb.examples
-
-import com.twitter.scalding._
-
-import io.prediction.commons.scalding.appdata.mongodb.{ MongoUsersSource, MongoItemsSource, MongoU2iActionsSource }
-import io.prediction.commons.appdata.{ Item, User }
-
-class TestSchemaless(args: Args) extends Job(args) {
-
-  val read_dbNameArg = args("read_dbName")
-  val read_dbHostArg = args.list("read_dbHost")
-  val read_dbPortArg = args.list("read_dbPort").map(_.toInt)
-
-  val read_appidArg = args("read_appid").toInt
-
-  val preItypesArg = args.list("itypes")
-  val itypesArg: Option[List[String]] = if (preItypesArg.mkString(",").length == 0) None else Option(preItypesArg)
-
-  val itemsSource = new MongoItemsSource(read_dbNameArg, read_dbHostArg, read_dbPortArg, read_appidArg, itypesArg)
-
-  val itemsStarttime = itemsSource.readStartEndtime('iid, 'itypes, 'starttime, 'endtime)
-    .mapTo(('iid, 'itypes, 'starttime, 'endtime) -> ('iid, 'itypes, 'starttime, 'endtime)) {
-      fields: (String, List[String], Long, Option[Long]) =>
-        (fields._1, fields._2.mkString(","), fields._3, fields._4.getOrElse("PIO_NONE"))
-    }
-    .write(Tsv("itemsStarttime.tsv"))
-
-}
-
-class TestSchemaless2(args: Args) extends Job(args) {
-
-  Tsv("itemsStarttime.tsv").read
-    .mapTo((0, 1, 2, 3) -> ('id, 'itypes, 'starttime, 'endtime)) {
-      fields: (String, String, Long, String) =>
-        val endtime: Option[Long] = fields._4 match {
-          case "PIO_NONE" => None
-          case x: String => Some(x.toLong)
-        }
-
-        (fields._1, fields._2, fields._3, endtime)
-    }
-    .write(Tsv("itemsStarttime2.tsv"))
-    .filter('endtime) { x: Option[Long] => x != None }
-    .write(Tsv("itemsStarttime3.tsv"))
-
-}
diff --git a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/modeldata/ItemRecScoresSource.scala b/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/modeldata/ItemRecScoresSource.scala
deleted file mode 100644
index 6400601..0000000
--- a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/modeldata/ItemRecScoresSource.scala
+++ /dev/null
@@ -1,46 +0,0 @@
-package io.prediction.commons.scalding.modeldata
-
-import com.twitter.scalding._
-
-import cascading.pipe.Pipe
-import cascading.flow.FlowDef
-
-/**
- * ItemRecScoresSource
- */
-trait ItemRecScoresSource {
-
-  import com.twitter.scalding.Dsl._ // get all the fancy implicit conversions that define the DSL
-
-  /**
-   * return the Source object
-   */
-  def getSource: Source
-
-  /**
-   * map pipe's field data to DB table fields and write to dbSink.
-   * uidField: Symbol of uid(String).
-   * iidsField: Symbol of List(iid, score, itypes). List[(String, Double, List[String])]
-   * algoid: Int. algo ID. TODO: remove
-   * modelset: Boolean. model set number(false means set 0, true means set 1). TODO: remove
-   * p: Pipe. the data pipe.
-   */
-  def writeData(uidField: Symbol, iidsField: Symbol, algoid: Int, modelSet: Boolean)(p: Pipe)(implicit fd: FlowDef): Pipe
-
-}
-
-object ItemRecScoresSource {
-
-  /**
-   *  define the corresponding cascading Symbol name for each DB table field.
-   *  ("table field name" -> Symbol)
-   */
-  val FIELD_SYMBOLS: Map[String, Symbol] = Map(
-    ("uid" -> 'uid),
-    ("iids" -> 'iids),
-    ("scores" -> 'scores),
-    ("itypes" -> 'itypes),
-    ("algoid" -> 'algoid),
-    ("modelset" -> 'modelset))
-
-}
diff --git a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/modeldata/ItemSimScoresSource.scala b/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/modeldata/ItemSimScoresSource.scala
deleted file mode 100644
index a234a19..0000000
--- a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/modeldata/ItemSimScoresSource.scala
+++ /dev/null
@@ -1,48 +0,0 @@
-package io.prediction.commons.scalding.modeldata
-
-import com.twitter.scalding._
-
-import cascading.pipe.Pipe
-import cascading.flow.FlowDef
-
-/**
- * ItemSimScoresSource
- */
-trait ItemSimScoresSource {
-
-  import com.twitter.scalding.Dsl._ // get all the fancy implicit conversions that define the DSL
-
-  /**
-   * return the Source object
-   */
-  def getSource: Source
-
-  // TODO: readData
-
-  /**
-   * map pipe's field data to DB table fields and write to dbSink.
-   * iidField: Symbol of iid(String)
-   * simiidsField: Symbol of List(simiid, score, simitypes). List[(String, Double, List[String])]
-   * algoid: Int. algo ID. TODO: remove
-   * modelSet: Boolean. model set number(false means set 0, true means set 1). TODO: remove
-   * p: Pipe. the data pipe.
-   */
-  def writeData(iidField: Symbol, simiidsField: Symbol, algoid: Int, modelSet: Boolean)(p: Pipe)(implicit fd: FlowDef): Pipe
-
-}
-
-object ItemSimScoresSource {
-
-  /**
-   *  define the corresponding cascading Symbol name for each DB table field.
-   *  ("table field name" -> Symbol)
-   */
-  val FIELD_SYMBOLS: Map[String, Symbol] = Map(
-    ("iid" -> 'uid),
-    ("simiids" -> 'simiid),
-    ("scores" -> 'score),
-    ("simitypes" -> 'simitypes),
-    ("algoid" -> 'algoid),
-    ("modelset" -> 'modelset))
-
-}
diff --git a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/modeldata/ModelData.scala b/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/modeldata/ModelData.scala
deleted file mode 100644
index 65b56fe..0000000
--- a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/modeldata/ModelData.scala
+++ /dev/null
@@ -1,47 +0,0 @@
-package io.prediction.commons.scalding.modeldata
-
-import io.prediction.commons.scalding.modeldata.mongodb.{ MongoItemRecScoresSource, MongoItemSimScoresSource }
-import io.prediction.commons.scalding.modeldata.file.{ FileItemRecScoresSource, FileItemSimScoresSource }
-
-object ItemSimScores {
-
-  /**
-   * dbName: used as file path in dbType=="file"
-   */
-  def apply(dbType: String, dbName: String, dbHost: Seq[String], dbPort: Seq[Int], algoid: Int, modelset: Boolean): ItemSimScoresSource = {
-    dbType match {
-      case "file" => {
-        new FileItemSimScoresSource(dbName)
-      }
-      case "mongodb" => {
-        require(((!dbHost.isEmpty) && (!dbPort.isEmpty)), "Please specify host and port number for mongodb.")
-        new MongoItemSimScoresSource(dbName, dbHost, dbPort, algoid, modelset)
-      }
-      case _ => {
-        throw new RuntimeException("Invalid ItemSimScores database type: " + dbType)
-      }
-    }
-  }
-}
-
-object ItemRecScores {
-
-  /**
-   * dbName: used as file path in dbType=="file"
-   */
-  def apply(dbType: String, dbName: String, dbHost: Seq[String], dbPort: Seq[Int], algoid: Int, modelset: Boolean): ItemRecScoresSource = {
-    dbType match {
-      case "file" => {
-        new FileItemRecScoresSource(dbName)
-      }
-      case "mongodb" => {
-        require(((!dbHost.isEmpty) && (!dbPort.isEmpty)), "Please specify host and port number for mongodb.")
-        new MongoItemRecScoresSource(dbName, dbHost, dbPort, algoid, modelset)
-      }
-      case _ => {
-        throw new RuntimeException("Invalid ItemRecScores database type: " + dbType)
-      }
-    }
-  }
-
-}
diff --git a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/modeldata/file/FileItemRecScoresSource.scala b/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/modeldata/file/FileItemRecScoresSource.scala
deleted file mode 100644
index fa2d944..0000000
--- a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/modeldata/file/FileItemRecScoresSource.scala
+++ /dev/null
@@ -1,38 +0,0 @@
-package io.prediction.commons.scalding.modeldata.file
-
-import com.twitter.scalding._
-
-import cascading.pipe.Pipe
-import cascading.flow.FlowDef
-
-//import io.prediction.commons.scalding.ModelDataFile
-import io.prediction.commons.scalding.modeldata.ItemRecScoresSource
-import io.prediction.commons.scalding.modeldata.ItemRecScoresSource.FIELD_SYMBOLS
-
-class FileItemRecScoresSource(path: String) extends Tsv(
-  p = path + "itemRecScores.tsv" //ModelDataFile(appId, engineId, algoId, evalId, "itemRecScores.tsv")
-) with ItemRecScoresSource {
-
-  import com.twitter.scalding.Dsl._ // get all the fancy implicit conversions that define the DSL
-
-  override def getSource = this
-
-  override def writeData(uidField: Symbol, iidsField: Symbol, algoid: Int, modelSet: Boolean)(p: Pipe)(implicit fd: FlowDef): Pipe = {
-    val dataPipe = p.mapTo((uidField, iidsField) ->
-      (FIELD_SYMBOLS("uid"), FIELD_SYMBOLS("iids"), FIELD_SYMBOLS("scores"), FIELD_SYMBOLS("itypes"), FIELD_SYMBOLS("algoid"), FIELD_SYMBOLS("modelset"))) {
-      fields: (String, List[(String, Double, List[String])]) =>
-        val (uid, iidsList) = fields
-
-        // convert list to comma-separated String
-        val iids = iidsList.map(_._1).mkString(",")
-        val scores = iidsList.map(_._2).mkString(",")
-        val itypes = iidsList.map(_._3).map(x => "[" + x.mkString(",") + "]").mkString(",")
-
-        (uid, iids, scores, itypes, algoid, modelSet)
-
-    }.write(this)
-
-    dataPipe
-  }
-
-}
\ No newline at end of file
diff --git a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/modeldata/file/FileItemSimScoresSource.scala b/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/modeldata/file/FileItemSimScoresSource.scala
deleted file mode 100644
index c4eca3c..0000000
--- a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/modeldata/file/FileItemSimScoresSource.scala
+++ /dev/null
@@ -1,37 +0,0 @@
-package io.prediction.commons.scalding.modeldata.file
-
-import com.twitter.scalding._
-
-import cascading.pipe.Pipe
-import cascading.flow.FlowDef
-
-//import io.prediction.commons.scalding.ModelDataFile
-import io.prediction.commons.scalding.modeldata.ItemSimScoresSource
-import io.prediction.commons.scalding.modeldata.ItemSimScoresSource.FIELD_SYMBOLS
-
-class FileItemSimScoresSource(path: String) extends Tsv(
-  p = path + "itemSimScores.tsv" //ModelDataFile(appId, engineId, algoId, evalId, "itemSimScores.tsv")
-) with ItemSimScoresSource {
-
-  import com.twitter.scalding.Dsl._ // get all the fancy implicit conversions that define the DSL
-
-  override def getSource = this
-
-  override def writeData(iidField: Symbol, simiidsField: Symbol, algoid: Int, modelSet: Boolean)(p: Pipe)(implicit fd: FlowDef): Pipe = {
-    val dataPipe = p.mapTo((iidField, simiidsField) ->
-      (FIELD_SYMBOLS("iid"), FIELD_SYMBOLS("simiids"), FIELD_SYMBOLS("scores"), FIELD_SYMBOLS("simitypes"), FIELD_SYMBOLS("algoid"), FIELD_SYMBOLS("modelset"))) {
-      fields: (String, List[(String, Double, List[String])]) =>
-        val (iid, simiidsList) = fields
-
-        // convert list to comma-separated string
-        val simiids = simiidsList.map(_._1).mkString(",")
-        val scores = simiidsList.map(_._2).mkString(",")
-        val simitypes = simiidsList.map(_._3).map(x => "[" + x.mkString(",") + "]").mkString(",")
-
-        (iid, simiids, scores, simitypes, algoid, modelSet)
-    }.write(this)
-
-    dataPipe
-  }
-
-}
diff --git a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/modeldata/mongodb/MongoItemRecScoresSource.scala b/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/modeldata/mongodb/MongoItemRecScoresSource.scala
deleted file mode 100644
index 1b4b136..0000000
--- a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/modeldata/mongodb/MongoItemRecScoresSource.scala
+++ /dev/null
@@ -1,81 +0,0 @@
-package io.prediction.commons.scalding.modeldata.mongodb
-
-import com.twitter.scalding._
-
-import cascading.pipe.Pipe
-import cascading.flow.FlowDef
-import cascading.tuple.Tuple
-
-import java.util.ArrayList
-import java.util.HashMap
-
-import com.mongodb.casbah.Imports._
-
-import io.prediction.commons.scalding.MongoSource
-import io.prediction.commons.scalding.modeldata.ItemRecScoresSource
-import io.prediction.commons.scalding.modeldata.ItemRecScoresSource.FIELD_SYMBOLS
-
-class MongoItemRecScoresSource(db: String, hosts: Seq[String], ports: Seq[Int], algoid: Int, modelset: Boolean) extends MongoSource(
-  db = db,
-  coll = s"algo_${algoid}_${modelset}",
-  cols = {
-    val itemRecScoreCols = new ArrayList[String]()
-    itemRecScoreCols.add("uid")
-    itemRecScoreCols.add("iids")
-    itemRecScoreCols.add("scores")
-    itemRecScoreCols.add("itypes")
-    itemRecScoreCols.add("algoid")
-    itemRecScoreCols.add("modelset")
-
-    itemRecScoreCols
-  },
-  mappings = {
-    val itemRecScoreMappings = new HashMap[String, String]()
-    itemRecScoreMappings.put("uid", FIELD_SYMBOLS("uid").name)
-    itemRecScoreMappings.put("iids", FIELD_SYMBOLS("iids").name)
-    itemRecScoreMappings.put("scores", FIELD_SYMBOLS("scores").name)
-    itemRecScoreMappings.put("itypes", FIELD_SYMBOLS("itypes").name)
-    itemRecScoreMappings.put("algoid", FIELD_SYMBOLS("algoid").name)
-    itemRecScoreMappings.put("modelset", FIELD_SYMBOLS("modelset").name)
-
-    itemRecScoreMappings
-  },
-  query = MongoDBObject(), // don't support read query
-  hosts = hosts, // String
-  ports = ports // Int
-) with ItemRecScoresSource {
-
-  import com.twitter.scalding.Dsl._
-
-  override def getSource: Source = this
-
-  override def writeData(uidField: Symbol, iidsField: Symbol, algoid: Int, modelSet: Boolean)(p: Pipe)(implicit fd: FlowDef): Pipe = {
-    val dbData = p.mapTo((uidField, iidsField) ->
-      (FIELD_SYMBOLS("uid"), FIELD_SYMBOLS("iids"), FIELD_SYMBOLS("scores"), FIELD_SYMBOLS("itypes"), FIELD_SYMBOLS("algoid"), FIELD_SYMBOLS("modelset"))) {
-      fields: (String, List[(String, Double, List[String])]) =>
-        val (uid, iidsList) = fields
-
-        // NOTE: convert itypes List to Cascading Tuple which will become array in Mongo.
-        // can't use List directly because it doesn't implement Comparable interface
-        val iidsTuple = new Tuple()
-        val scoresTuple = new Tuple()
-        val itypesTuple = new Tuple()
-
-        for (x <- iidsList) {
-          iidsTuple.add(x._1)
-          scoresTuple.add(x._2)
-          val itypesOfOneItem = new Tuple()
-          for (y <- x._3) {
-            itypesOfOneItem.add(y)
-          }
-          itypesTuple.add(itypesOfOneItem)
-        }
-
-        (uid, iidsTuple, scoresTuple, itypesTuple, algoid, modelSet)
-
-    }.write(this)
-
-    dbData
-  }
-
-}
diff --git a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/modeldata/mongodb/MongoItemSimScoresSource.scala b/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/modeldata/mongodb/MongoItemSimScoresSource.scala
deleted file mode 100644
index adb5008..0000000
--- a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/modeldata/mongodb/MongoItemSimScoresSource.scala
+++ /dev/null
@@ -1,84 +0,0 @@
-package io.prediction.commons.scalding.modeldata.mongodb
-
-import com.twitter.scalding._
-
-import cascading.pipe.Pipe
-import cascading.flow.FlowDef
-import cascading.tuple.Tuple
-
-import java.util.ArrayList
-import java.util.HashMap
-
-import com.mongodb.BasicDBList
-import com.mongodb.casbah.Imports.MongoDBObject
-
-import io.prediction.commons.scalding.MongoSource
-import io.prediction.commons.scalding.modeldata.ItemSimScoresSource
-import io.prediction.commons.scalding.modeldata.ItemSimScoresSource.FIELD_SYMBOLS
-
-class MongoItemSimScoresSource(db: String, hosts: Seq[String], ports: Seq[Int], algoid: Int, modelset: Boolean) extends MongoSource(
-  db = db,
-  coll = s"algo_${algoid}_${modelset}",
-  cols = {
-    val itemSimScoreCols = new ArrayList[String]()
-
-    itemSimScoreCols.add("iid")
-    itemSimScoreCols.add("simiids") // iid of similiar item
-    itemSimScoreCols.add("scores")
-    itemSimScoreCols.add("simitypes") // itypes of simiid
-    itemSimScoreCols.add("algoid")
-    itemSimScoreCols.add("modelset")
-
-    itemSimScoreCols
-  },
-  mappings = {
-    val itemSimScoreMappings = new HashMap[String, String]()
-
-    itemSimScoreMappings.put("iid", FIELD_SYMBOLS("iid").name)
-    itemSimScoreMappings.put("simiids", FIELD_SYMBOLS("simiids").name)
-    itemSimScoreMappings.put("scores", FIELD_SYMBOLS("scores").name)
-    itemSimScoreMappings.put("simitypes", FIELD_SYMBOLS("simitypes").name)
-    itemSimScoreMappings.put("algoid", FIELD_SYMBOLS("algoid").name)
-    itemSimScoreMappings.put("modelset", FIELD_SYMBOLS("modelset").name)
-
-    itemSimScoreMappings
-  },
-  query = MongoDBObject(), // don't support read query
-  hosts = hosts, // String
-  ports = ports // Int
-) with ItemSimScoresSource {
-
-  import com.twitter.scalding.Dsl._
-
-  override def getSource: Source = this
-
-  override def writeData(iidField: Symbol, simiidsField: Symbol, algoid: Int, modelSet: Boolean)(p: Pipe)(implicit fd: FlowDef): Pipe = {
-    val dbData = p.mapTo((iidField, simiidsField) ->
-      (FIELD_SYMBOLS("iid"), FIELD_SYMBOLS("simiids"), FIELD_SYMBOLS("scores"), FIELD_SYMBOLS("simitypes"), FIELD_SYMBOLS("algoid"), FIELD_SYMBOLS("modelset"))) {
-      fields: (String, List[(String, Double, List[String])]) =>
-        val (iid, simiidsList) = fields
-
-        // NOTE: convert itypes List to Cascading Tuple which will become array in Mongo.
-        // can't use List directly because it doesn't implement Comparable interface
-        val simiidsTuple = new Tuple()
-        val scoresTuple = new Tuple()
-        val simitypesTuple = new Tuple()
-
-        for (x <- simiidsList) {
-          simiidsTuple.add(x._1)
-          scoresTuple.add(x._2)
-          val itypesOfOneItem = new Tuple()
-          for (y <- x._3) {
-            itypesOfOneItem.add(y)
-          }
-          simitypesTuple.add(itypesOfOneItem)
-        }
-
-        (iid, simiidsTuple, scoresTuple, simitypesTuple, algoid, modelSet)
-
-    }.write(this)
-
-    dbData
-  }
-
-}
diff --git a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/modeldata/mongodb/examples/ReadWrite.scala b/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/modeldata/mongodb/examples/ReadWrite.scala
deleted file mode 100644
index 6b7d5b4..0000000
--- a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/modeldata/mongodb/examples/ReadWrite.scala
+++ /dev/null
@@ -1,40 +0,0 @@
-package io.prediction.commons.scalding.modeldata.mongodb.examples
-
-import com.twitter.scalding._
-
-import io.prediction.commons.scalding.modeldata.mongodb.{ MongoItemRecScoresSource, MongoItemSimScoresSource }
-
-//TODO: clean up this example. see if there is better way to test MongoSource?
-class ReadWrite(args: Args) extends Job(args) {
-
-  /**
-   * test MongoItemSimScoresSource
-   * read from Tsv and write to DB
-   */
-  val itemSimSink = new MongoItemSimScoresSource("test", Seq("localhost"), Seq(27017), 2, true)
-
-  Tsv("itemSimScores.tsv").read
-    .mapTo((0, 1, 2, 3) -> ('iid, 'simiid, 'score, 'simitypes)) { fields: (String, String, Double, String) =>
-      val (iid, simiid, score, simitypes) = fields
-
-      (iid, simiid, score, simitypes.split(",").toList)
-    }
-    .groupBy('iid) { _.sortBy('score).reverse.toList[(String, Double, List[String])](('simiid, 'score, 'simitypes) -> 'simiidsList) }
-    .then(itemSimSink.writeData('iid, 'simiidsList, 12, false) _)
-
-  /**
-   * test MongoItemRecScoresSource
-   * read from Tsv and write to DB
-   */
-  val itemRecSink = new MongoItemRecScoresSource("test", Seq("localhost"), Seq(27017), 1, true)
-
-  Tsv("itemRecScores.tsv").read
-    .mapTo((0, 1, 2, 3) -> ('uid, 'iid, 'score, 'itypes)) { fields: (String, String, Double, String) =>
-      val (uid, iid, score, itypes) = fields
-
-      (uid, iid, score, itypes.split(",").toList)
-    }
-    .groupBy('uid) { _.sortBy('score).reverse.toList[(String, Double, List[String])](('iid, 'score, 'itypes) -> 'iidsList) }
-    .then(itemRecSink.writeData('uid, 'iidsList, 3, true) _)
-
-}
diff --git a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/settings/OfflineEvalResultsSource.scala b/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/settings/OfflineEvalResultsSource.scala
deleted file mode 100644
index f672f30..0000000
--- a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/settings/OfflineEvalResultsSource.scala
+++ /dev/null
@@ -1,32 +0,0 @@
-package io.prediction.commons.scalding.settings
-
-import com.twitter.scalding._
-
-import cascading.pipe.Pipe
-import cascading.flow.FlowDef
-
-/**
- * OfflineEvalResultsSource
- */
-trait OfflineEvalResultsSource {
-
-  import com.twitter.scalding.Dsl._ // get all the fancy implicit conversions that define the DSL
-
-  def getSource: Source
-
-  def writeData(evalidField: Symbol, metricidField: Symbol, algoidField: Symbol, scoreField: Symbol, iterationField: Symbol, splitsetField: Symbol)(p: Pipe)(implicit fd: FlowDef): Pipe
-
-}
-
-object OfflineEvalResultsSource {
-
-  val FIELD_SYMBOLS: Map[String, Symbol] = Map(
-    ("id" -> 'id),
-    ("evalid" -> 'evalid),
-    ("metricid" -> 'metricid),
-    ("algoid" -> 'algoid),
-    ("score" -> 'score),
-    ("iteration" -> 'iteration),
-    ("splitset" -> 'splitset))
-
-}
\ No newline at end of file
diff --git a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/settings/Settings.scala b/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/settings/Settings.scala
deleted file mode 100644
index 0ca003d..0000000
--- a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/settings/Settings.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package io.prediction.commons.scalding.settings
-
-import io.prediction.commons.scalding.settings.file.FileOfflineEvalResultsSource
-import io.prediction.commons.scalding.settings.mongodb.MongoOfflineEvalResultsSource
-
-object OfflineEvalResults {
-
-  def apply(dbType: String, dbName: String, dbHost: Seq[String], dbPort: Seq[Int]): OfflineEvalResultsSource = {
-    dbType match {
-      case "file" => {
-        new FileOfflineEvalResultsSource(dbName)
-      }
-      case "mongodb" => {
-        require(((!dbHost.isEmpty) && (!dbPort.isEmpty)), "Please specify host and port number for mongodb.")
-        new MongoOfflineEvalResultsSource(dbName, dbHost, dbPort)
-      }
-      case _ => {
-        throw new RuntimeException("Invalid OfflineEvalResults database type: " + dbType)
-      }
-    }
-  }
-}
diff --git a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/settings/file/FileOfflineEvalResultsSource.scala b/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/settings/file/FileOfflineEvalResultsSource.scala
deleted file mode 100644
index 86d05d5..0000000
--- a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/settings/file/FileOfflineEvalResultsSource.scala
+++ /dev/null
@@ -1,32 +0,0 @@
-package io.prediction.commons.scalding.settings.file
-
-import com.twitter.scalding._
-
-import cascading.pipe.Pipe
-import cascading.flow.FlowDef
-
-//import io.prediction.commons.scalding.OfflineEvalDataFile
-import io.prediction.commons.scalding.settings.OfflineEvalResultsSource
-
-/**
- * File Format:
- * <eval id>\t<metric id>\t<algo id>\t<score>\t<iteration>
- *
- * Example:
- * 8  4  5  0.123456  3
- */
-class FileOfflineEvalResultsSource(path: String) extends Tsv(
-  p = path + "/offlineEvalResults.tsv" //OfflineEvalDataFile(appId, engineId, evalId, metricId, algoId, name="offlineEvalResults.tsv")
-) with OfflineEvalResultsSource {
-
-  import com.twitter.scalding.Dsl._ // get all the fancy implicit conversions that define the DSL
-
-  override def getSource: Source = this
-
-  override def writeData(evalidField: Symbol, metricidField: Symbol, algoidField: Symbol, scoreField: Symbol, iterationField: Symbol, splitsetField: Symbol)(p: Pipe)(implicit fd: FlowDef): Pipe = {
-    val dataPipe = p.project(evalidField, metricidField, algoidField, scoreField, iterationField, splitsetField)
-      .write(this)
-
-    dataPipe
-  }
-}
\ No newline at end of file
diff --git a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/settings/mongodb/MongoOfflineEvalResultsSource.scala b/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/settings/mongodb/MongoOfflineEvalResultsSource.scala
deleted file mode 100644
index b2a6e76..0000000
--- a/process/commons/hadoop/scalding/src/main/scala/io/prediction/commons/scalding/settings/mongodb/MongoOfflineEvalResultsSource.scala
+++ /dev/null
@@ -1,67 +0,0 @@
-package io.prediction.commons.scalding.settings.mongodb
-
-import com.twitter.scalding._
-
-import cascading.pipe.Pipe
-import cascading.flow.FlowDef
-
-import java.util.ArrayList
-import java.util.HashMap
-
-import com.mongodb.casbah.Imports.MongoDBObject
-
-import io.prediction.commons.scalding.MongoSource
-import io.prediction.commons.scalding.settings.OfflineEvalResultsSource
-import io.prediction.commons.scalding.settings.OfflineEvalResultsSource.FIELD_SYMBOLS
-
-class MongoOfflineEvalResultsSource(db: String, hosts: Seq[String], ports: Seq[Int]) extends MongoSource(
-  db = db,
-  coll = "offlineEvalResults",
-  cols = {
-    val offlineEvalResultsCols = new ArrayList[String]()
-    offlineEvalResultsCols.add("_id")
-    offlineEvalResultsCols.add("evalid")
-    offlineEvalResultsCols.add("metricid")
-    offlineEvalResultsCols.add("algoid")
-    offlineEvalResultsCols.add("score")
-    offlineEvalResultsCols.add("iteration")
-    offlineEvalResultsCols.add("splitset")
-
-    offlineEvalResultsCols
-  },
-  mappings = {
-    val offlineEvalResultsMappings = new HashMap[String, String]()
-    offlineEvalResultsMappings.put("_id", FIELD_SYMBOLS("id").name)
-    offlineEvalResultsMappings.put("evalid", FIELD_SYMBOLS("evalid").name)
-    offlineEvalResultsMappings.put("metricid", FIELD_SYMBOLS("metricid").name)
-    offlineEvalResultsMappings.put("algoid", FIELD_SYMBOLS("algoid").name)
-    offlineEvalResultsMappings.put("score", FIELD_SYMBOLS("score").name)
-    offlineEvalResultsMappings.put("iteration", FIELD_SYMBOLS("iteration").name)
-    offlineEvalResultsMappings.put("splitset", FIELD_SYMBOLS("splitset").name)
-
-    offlineEvalResultsMappings
-  },
-  query = MongoDBObject(), // don't support read query
-  hosts = hosts,
-  ports = ports
-) with OfflineEvalResultsSource {
-
-  import com.twitter.scalding.Dsl._ // get all the fancy implicit conversions that define the DSL
-
-  override def getSource: Source = this
-
-  override def writeData(evalidField: Symbol, metricidField: Symbol, algoidField: Symbol, scoreField: Symbol, iterationField: Symbol, splitsetField: Symbol)(p: Pipe)(implicit fd: FlowDef): Pipe = {
-    val dataPipe = p.mapTo((evalidField, metricidField, algoidField, scoreField, iterationField, splitsetField) ->
-      (FIELD_SYMBOLS("id"), FIELD_SYMBOLS("evalid"), FIELD_SYMBOLS("metricid"), FIELD_SYMBOLS("algoid"), FIELD_SYMBOLS("score"), FIELD_SYMBOLS("iteration"), FIELD_SYMBOLS("splitset"))) {
-      fields: (Int, Int, Int, Double, Int, String) =>
-        val (evalid, metricid, algoid, score, iteration, splitset) = fields
-
-        val id = evalid + "_" + metricid + "_" + algoid + "_" + iteration + "_" + splitset
-
-        (id, evalid, metricid, algoid, score, iteration, splitset)
-    }.write(this)
-
-    dataPipe
-  }
-
-}
diff --git a/process/commons/hadoop/scalding/src/test/scala/io/prediction/commons/scalding/appdata/file/FileItemsSourceTest.scala b/process/commons/hadoop/scalding/src/test/scala/io/prediction/commons/scalding/appdata/file/FileItemsSourceTest.scala
deleted file mode 100644
index 70a713e..0000000
--- a/process/commons/hadoop/scalding/src/test/scala/io/prediction/commons/scalding/appdata/file/FileItemsSourceTest.scala
+++ /dev/null
@@ -1,129 +0,0 @@
-package io.prediction.commons.scalding.appdata.file
-
-import org.specs2.mutable._
-
-import com.twitter.scalding._
-
-class ReadItypesTestJob(args: Args) extends Job(args) {
-
-  val appidArg: Int = args("appid").toInt
-  val writeAppidArg: Int = args("writeAppid").toInt
-
-  val preItypesArg = args.list("itypes")
-  // use itypesArg.mkString(",").size instead of itypesArg.size
-  // to work aroud empty List("") corner case.
-  val itypesArg: Option[List[String]] = if (preItypesArg.mkString(",").length == 0) None else Option(preItypesArg)
-
-  System.err.println(itypesArg)
-
-  val src = new FileItemsSource("testpath", appidArg, itypesArg)
-
-  src.readData('iid, 'itypes)
-    .mapTo(('iid, 'itypes) -> ('iid, 'itypes)) { fields: (String, List[String]) =>
-      val (iid, itypes) = fields
-
-      // during read, itypes are converted from t1,t2,t3 to List[String] = List(t1,t2,t3)
-      // convert the List back to string with ',' as separator
-      (iid, itypes.mkString(","))
-    }.write(Tsv("output"))
-
-  src.readStartEndtime('iid, 'itypes, 'starttime, 'endtime)
-    .mapTo(('iid, 'itypes, 'starttime, 'endtime) -> ('iid, 'itypes, 'starttime, 'endtime)) { fields: (String, List[String], Long, Option[Long]) =>
-      val (iid, itypes, starttime, endtime) = fields
-
-      // during read, itypes are converted from t1,t2,t3 to List[String] = List(t1,t2,t3)
-      // convert the List back to string with ',' as separator
-      (iid, itypes.mkString(","), starttime.toString, endtime.map(_.toString).getOrElse("PIO_NONE"))
-    }.write(Tsv("outputStartEndtime"))
-
-  val writeDataSink = new FileItemsSource("writeDataTestpath", appidArg, None)
-
-  src.readData('iid, 'itypes)
-    .then(writeDataSink.writeData('iid, 'itypes, writeAppidArg) _)
-
-  val writeObjSink = new FileItemsSource("writeObjTestpath", appidArg, None)
-
-  src.readObj('item)
-    .then(writeObjSink.writeObj('item) _)
-}
-
-class FileItemsSourceTest extends Specification with TupleConversions {
-
-  val test1Input = List(
-    ("i0", "t1,t2,t3", "appid", "2293300", "1266673", "666554320", "PIO_NONE"),
-    ("i1", "t2,t3", "appid", "14526361", "12345135", "PIO_NONE", "false"),
-    ("i2", "t4", "appid", "14526361", "23423424", "PIO_NONE", "true"),
-    ("i3", "t3,t4", "appid", "1231415", "378462511", "666554323", "PIO_NONE"))
-
-  val test1output_all = test1Input
-
-  val test1output_t4 = List(
-    ("i2", "t4", "appid", "14526361", "23423424", "PIO_NONE", "true"),
-    ("i3", "t3,t4", "appid", "1231415", "378462511", "666554323", "PIO_NONE"))
-
-  val test1output_t2t3 = List(
-    ("i0", "t1,t2,t3", "appid", "2293300", "1266673", "666554320", "PIO_NONE"),
-    ("i1", "t2,t3", "appid", "14526361", "12345135", "PIO_NONE", "false"),
-    ("i3", "t3,t4", "appid", "1231415", "378462511", "666554323", "PIO_NONE"))
-
-  val test1output_none = List()
-
-  def testWithItypes(appid: Int, writeAppid: Int, itypes: List[String],
-    inputItems: List[(String, String, String, String, String, String, String)],
-    outputItems: List[(String, String, String, String, String, String, String)]) = {
-
-    val inputSource = inputItems map { case (id, itypes, tempAppid, starttime, ct, endtime, inactive) => (id, itypes, appid.toString, starttime, ct, endtime, inactive) }
-    val outputExpected = outputItems map { case (id, itypes, tempAppid, starttime, ct, endtime, inactive) => (id, itypes) }
-    val outputStartEndtimeExpected = outputItems map { case (id, itypes, tempAppid, starttime, ct, endtime, inactive) => (id, itypes, starttime, endtime) }
-    val writeDataExpected = outputItems map { case (id, itypes, tempAppid, starttime, ct, endtime, inactive) => (id, itypes, writeAppid.toString) }
-    val writeObjExpected = outputItems map { case (id, itypes, tempAppid, starttime, ct, endtime, inactive) => (id, itypes, appid.toString, starttime, ct, endtime, inactive) }
-
-    JobTest("io.prediction.commons.scalding.appdata.file.ReadItypesTestJob")
-      .arg("appid", appid.toString)
-      .arg("writeAppid", writeAppid.toString)
-      .arg("itypes", itypes)
-      .source(new FileItemsSource("testpath", appid, Some(itypes)), inputSource)
-      .sink[(String, String)](Tsv("output")) { outputBuffer =>
-        "correctly read iid and itypes" in {
-          outputBuffer must containTheSameElementsAs(outputExpected)
-        }
-      }
-      .sink[(String, String, String, String)](Tsv("outputStartEndtime")) { outputBuffer =>
-        "correctly read starttime" in {
-          outputBuffer must containTheSameElementsAs(outputStartEndtimeExpected)
-        }
-      }
-      .sink[(String, String, String)]((new FileItemsSource("writeDataTestpath", appid, None)).getSource) { outputBuffer =>
-        "sink with writeData using different appid" in {
-          outputBuffer must containTheSameElementsAs(writeDataExpected)
-        }
-      }
-      .sink[(String, String, String, String, String, String, String)]((new FileItemsSource("writeObjTestpath", appid, None)).getSource) { outputBuffer =>
-        "sink with writeObj" in {
-          outputBuffer must containTheSameElementsAs(writeObjExpected)
-        }
-      }
-      .run.finish
-  }
-
-  "FileItemsSource without itypes" should {
-    testWithItypes(1, 3, List(""), test1Input, test1output_all)
-  }
-
-  "FileItemsSource with one itype" should {
-    testWithItypes(1, 5, List("t4"), test1Input, test1output_t4)
-  }
-
-  "FileItemsSource with some itypes" should {
-    testWithItypes(3, 6, List("t2", "t3"), test1Input, test1output_t2t3)
-  }
-
-  "FileItemsSource with all itypes" should {
-    testWithItypes(3, 7, List("t2", "t3", "t1", "t4"), test1Input, test1output_all)
-  }
-
-  "FileItemsSource without any matching itypes" should {
-    testWithItypes(3, 10, List("t99"), test1Input, test1output_none)
-  }
-
-}
diff --git a/process/commons/hadoop/scalding/src/test/scala/io/prediction/commons/scalding/appdata/file/FileU2iActionsSourceTest.scala b/process/commons/hadoop/scalding/src/test/scala/io/prediction/commons/scalding/appdata/file/FileU2iActionsSourceTest.scala
deleted file mode 100644
index 76b5742..0000000
--- a/process/commons/hadoop/scalding/src/test/scala/io/prediction/commons/scalding/appdata/file/FileU2iActionsSourceTest.scala
+++ /dev/null
@@ -1,69 +0,0 @@
-package io.prediction.commons.scalding.appdata.file
-
-import org.specs2.mutable._
-
-import com.twitter.scalding._
-
-//import io.prediction.commons.scalding.AppDataFile
-
-class ReadU2iActionsTestJob(args: Args) extends Job(args) {
-
-  val appidArg: Int = args("appid").toInt
-
-  val src = new FileU2iActionsSource("testpath", appidArg)
-
-  src.readData('action, 'uid, 'iid, 't, 'v)
-    .mapTo(('action, 'uid, 'iid, 't, 'v) -> ('action, 'uid, 'iid, 't, 'v)) {
-      fields: (String, String, String, String, Option[String]) =>
-        val (action, uid, iid, t, v) = fields
-
-        (action, uid, iid, t, v.getOrElse("PIO_NONE"))
-    }
-    .write(Tsv("output"))
-
-}
-
-class WriteU2iActionsTestJob(args: Args) extends Job(args) {
-
-  val appidArg: Int = args("appid").toInt
-
-  val src = new FileU2iActionsSource("testpath", appidArg)
-  val sink = new FileU2iActionsSource("testpathwr", appidArg)
-
-  src.readData('action, 'uid, 'iid, 't, 'v)
-    .then(sink.writeData('action, 'uid, 'iid, 't, 'v, appidArg) _)
-
-}
-
-class FileU2iActionsSourceTest extends Specification with TupleConversions {
-  // action: String// 0
-  // uid: String // 1
-  // iid: String // 2
-  // t: String // 3
-  // v: String // 4
-
-  val test1Input = List(("rate", "uid3", "iid5", "12345", "5"), ("view", "uid2", "iid6", "12346", "PIO_NONE"))
-  val appid = 1
-
-  "ReadU2iActionsTest" should {
-    JobTest("io.prediction.commons.scalding.appdata.file.ReadU2iActionsTestJob")
-      .arg("appid", appid.toString)
-      .source(new FileU2iActionsSource("testpath", appid), test1Input)
-      .sink[(String, String, String, String, String)](Tsv("output")) { outputBuffer =>
-        "correctly read from a file" in {
-          outputBuffer must containTheSameElementsAs(test1Input)
-        }
-      }.run.finish
-  }
-
-  "WriteU2iActionsTest" should {
-    JobTest("io.prediction.commons.scalding.appdata.file.WriteU2iActionsTestJob")
-      .arg("appid", appid.toString)
-      .source(new FileU2iActionsSource("testpath", appid), test1Input)
-      .sink[(String, String, String, String, String)]((new FileU2iActionsSource("testpathwr", appid)).getSource) { outputBuffer =>
-        "correctly read from a file" in {
-          outputBuffer must containTheSameElementsAs(test1Input)
-        }
-      }.run.finish
-  }
-}
\ No newline at end of file
diff --git a/process/commons/hadoop/scalding/src/test/scala/io/prediction/commons/scalding/appdata/file/FileUsersSourceTest.scala b/process/commons/hadoop/scalding/src/test/scala/io/prediction/commons/scalding/appdata/file/FileUsersSourceTest.scala
deleted file mode 100644
index e0bb296..0000000
--- a/process/commons/hadoop/scalding/src/test/scala/io/prediction/commons/scalding/appdata/file/FileUsersSourceTest.scala
+++ /dev/null
@@ -1,69 +0,0 @@
-package io.prediction.commons.scalding.appdata.file
-
-import org.specs2.mutable._
-
-import com.twitter.scalding._
-
-class ReadUsersTest(args: Args) extends Job(args) {
-  val appidArg: Int = args("appid").toInt
-  val writeAppidArg: Int = args("writeAppid").toInt
-
-  val src = new FileUsersSource("testpath", appidArg)
-
-  src.readData('uid)
-    .write(Tsv("output"))
-
-  val writeDataSink = new FileUsersSource("writeDataTestpath", appidArg)
-
-  src.readData('uid)
-    .then(writeDataSink.writeData('uid, writeAppidArg) _)
-
-  val writeObjSink = new FileUsersSource("writeObjTestpath", appidArg)
-  src.readObj('user)
-    .then(writeObjSink.writeObj('user) _)
-
-}
-
-class FileUsersSourceTest extends Specification with TupleConversions {
-
-  def test(users: List[(String, String, String)]) = { //, expected: List[String]) = {
-
-    val appid = 4
-    val writeAppid = 3
-
-    val expected = users map { case (id, appid, t) => id }
-    val writeDataExpected = users map { case (id, appid, t) => (id, writeAppid.toString) }
-    val writeObjExpected = users
-
-    JobTest("io.prediction.commons.scalding.appdata.file.ReadUsersTest")
-      .arg("appid", appid.toString)
-      .arg("writeAppid", writeAppid.toString)
-      .source(new FileUsersSource("testpath", appid.toInt), users)
-      .sink[(String)](Tsv("output")) { outputBuffer =>
-        "correctly read from a file" in {
-          outputBuffer must containTheSameElementsAs(expected)
-        }
-      }
-      .sink[(String, String)]((new FileUsersSource("writeDataTestpath", appid)).getSource) { outputBuffer =>
-        "sink with writeData using different appid" in {
-          outputBuffer must containTheSameElementsAs(writeDataExpected)
-        }
-
-      }
-      .sink[(String, String, String)]((new FileUsersSource("writeObjTestpath", appid)).getSource) { outputBuffer =>
-        "sink with writeObj" in {
-          outputBuffer must containTheSameElementsAs(writeObjExpected)
-        }
-      }
-      .run
-      .finish
-  }
-
-  "FileUsersSourceTest" should {
-    val testUsers = List(("u0", "4", "123456"), ("u1", "4", "23456"), ("u2", "4", "455677"), ("u3", "4", "876563111"))
-
-    test(testUsers)
-
-  }
-
-}
\ No newline at end of file
diff --git a/process/commons/hadoop/scalding/src/test/scala/io/prediction/commons/scalding/modeldata/file/FileItemRecScoresSourcsTest.scala b/process/commons/hadoop/scalding/src/test/scala/io/prediction/commons/scalding/modeldata/file/FileItemRecScoresSourcsTest.scala
deleted file mode 100644
index 99a6816..0000000
--- a/process/commons/hadoop/scalding/src/test/scala/io/prediction/commons/scalding/modeldata/file/FileItemRecScoresSourcsTest.scala
+++ /dev/null
@@ -1,56 +0,0 @@
-package io.prediction.commons.scalding.modeldata.file
-
-import org.specs2.mutable._
-
-import com.twitter.scalding._
-
-class FileItemRecScoresSourceWriteTestJob(args: Args) extends Job(args) {
-
-  val appidArg = args("appid").toInt
-  val engineidArg = args("engineid").toInt
-  val algoidArg = args("algoid").toInt
-  val evalidArg = args.optional("evalid") map (x => x.toInt)
-  val modelSetArg = args("modelSet").toBoolean
-
-  val itemRecSink = new FileItemRecScoresSource("testpath")
-
-  Tsv("FileItemRecScoresSourceTestInput").read
-    .mapTo((0, 1, 2, 3) -> ('uid, 'iid, 'score, 'itypes)) { fields: (String, String, Double, String) =>
-      val (uid, iid, score, itypes) = fields
-
-      (uid, iid, score, itypes.split(",").toList)
-    }
-    .groupBy('uid) { _.sortBy('score).reverse.toList[(String, Double, List[String])](('iid, 'score, 'itypes) -> 'iidsList) }
-    .then(itemRecSink.writeData('uid, 'iidsList, algoidArg, modelSetArg) _)
-
-}
-
-class FileItemRecScoresSourceTest extends Specification with TupleConversions {
-
-  "FileItemRecScoresSourceWriteTestJob" should {
-    val appid = 4
-    val engineid = 3
-    val algoid = 18
-    val evalid: Option[Int] = None
-    val modelSet: Boolean = false
-
-    val test1Input = List(("u0", "i1", "0.7", "t1,t2,t3"), ("u0", "i2", "0.44", "t1"), ("u1", "i2", "0.1", "t4"))
-    val test1Output = List(("u0", "i1,i2", "0.7,0.44", "[t1,t2,t3],[t1]", algoid, modelSet), ("u1", "i2", "0.1", "[t4]", algoid, modelSet))
-
-    JobTest("io.prediction.commons.scalding.modeldata.file.FileItemRecScoresSourceWriteTestJob")
-      .arg("appid", appid.toString)
-      .arg("engineid", engineid.toString)
-      .arg("algoid", algoid.toString)
-      .arg("modelSet", modelSet.toString)
-      .source(Tsv("FileItemRecScoresSourceTestInput"), test1Input)
-      .sink[(String, String, String, String, Int, Boolean)](new FileItemRecScoresSource("testpath")) { outputBuffer =>
-        "correctly write to FileItemRecScoresSource" in {
-          outputBuffer.toList must containTheSameElementsAs(test1Output)
-        }
-
-      }
-      .run
-      .finish
-  }
-
-}
diff --git a/process/commons/hadoop/scalding/src/test/scala/io/prediction/commons/scalding/modeldata/file/FileItemSimScoresSourceTest.scala b/process/commons/hadoop/scalding/src/test/scala/io/prediction/commons/scalding/modeldata/file/FileItemSimScoresSourceTest.scala
deleted file mode 100644
index 17cefcb..0000000
--- a/process/commons/hadoop/scalding/src/test/scala/io/prediction/commons/scalding/modeldata/file/FileItemSimScoresSourceTest.scala
+++ /dev/null
@@ -1,56 +0,0 @@
-package io.prediction.commons.scalding.modeldata.file
-
-import org.specs2.mutable._
-
-import com.twitter.scalding._
-
-class FileItemSimScoresSourceTestJob(args: Args) extends Job(args) {
-
-  val appidArg = args("appid").toInt
-  val engineidArg = args("engineid").toInt
-  val algoidArg = args("algoid").toInt
-  val evalidArg = args.optional("evalid") map (x => x.toInt)
-  val modelSetArg = args("modelSet").toBoolean
-
-  val itemSimSink = new FileItemSimScoresSource("testpath")
-
-  Tsv("FileItemSimScoresSourceTestInput").read
-    .mapTo((0, 1, 2, 3) -> ('iid, 'simiid, 'score, 'simitypes)) { fields: (String, String, Double, String) =>
-      val (iid, simiid, score, simitypes) = fields
-
-      (iid, simiid, score, simitypes.split(",").toList)
-    }
-    .groupBy('iid) { _.sortBy('score).reverse.toList[(String, Double, List[String])](('simiid, 'score, 'simitypes) -> 'simiidsList) }
-    .then(itemSimSink.writeData('iid, 'simiidsList, algoidArg, modelSetArg) _)
-
-}
-
-class FileItemSimScoresSourceTest extends Specification with TupleConversions {
-
-  "FileItemSimScoresSourceTestJob" should {
-    val appid = 4
-    val engineid = 3
-    val algoid = 18
-    val evalid: Option[Int] = None
-    val modelSet: Boolean = true
-
-    val test1Input = List(("i0", "i1", "0.7", "t1,t2,t3"), ("i0", "i2", "0.44", "t1"), ("i1", "i2", "0.1", "t4"))
-    val test1Output = List(("i0", "i1,i2", "0.7,0.44", "[t1,t2,t3],[t1]", algoid, modelSet), ("i1", "i2", "0.1", "[t4]", algoid, modelSet))
-
-    JobTest("io.prediction.commons.scalding.modeldata.file.FileItemSimScoresSourceTestJob")
-      .arg("appid", appid.toString)
-      .arg("engineid", engineid.toString)
-      .arg("algoid", algoid.toString)
-      .arg("modelSet", modelSet.toString)
-      .source(Tsv("FileItemSimScoresSourceTestInput"), test1Input)
-      .sink[(String, String, String, String, Int, Boolean)](new FileItemSimScoresSource("testpath")) { outputBuffer =>
-        "correctly write to FileItemSimScoresSource" in {
-          outputBuffer.toList must containTheSameElementsAs(test1Output)
-        }
-      }
-      .run
-      .finish
-  }
-
-}
-
diff --git a/process/commons/hadoop/scalding/src/test/scala/io/prediction/commons/scalding/settings/FileOfflineEvalResultsSourceTest.scala b/process/commons/hadoop/scalding/src/test/scala/io/prediction/commons/scalding/settings/FileOfflineEvalResultsSourceTest.scala
deleted file mode 100644
index 3feee77..0000000
--- a/process/commons/hadoop/scalding/src/test/scala/io/prediction/commons/scalding/settings/FileOfflineEvalResultsSourceTest.scala
+++ /dev/null
@@ -1,45 +0,0 @@
-package io.prediction.commons.scalding.settings.file
-
-import org.specs2.mutable._
-
-import com.twitter.scalding._
-
-class FileOfflineEvalResultsSourceWriteTestJob(args: Args) extends Job(args) {
-
-  val resultsSink = new FileOfflineEvalResultsSource("testpath")
-
-  Tsv("FileOfflineEvalResultsSourceTestInput").read
-    .mapTo((0, 1, 2, 3, 4, 5) -> ('evalid, 'metricid, 'algoid, 'score, 'iteration, 'splitset)) {
-      fields: (Int, Int, Int, Double, Int, String) =>
-
-        fields
-    }
-    .then(resultsSink.writeData('evalid, 'metricid, 'algoid, 'score, 'iteration, 'splitset))
-
-}
-
-class FileOfflineEvalResultsSourceTest extends Specification with TupleConversions {
-
-  type resultTuples = (Int, Int, Int, Double, Int, String)
-
-  def test(testInput: List[resultTuples]) = {
-
-    JobTest("io.prediction.commons.scalding.settings.file.FileOfflineEvalResultsSourceWriteTestJob")
-      .source(Tsv("FileOfflineEvalResultsSourceTestInput"), testInput)
-      .sink[resultTuples](new FileOfflineEvalResultsSource("testpath")) { outputBuffer =>
-        "correctly write to FileOfflineEvalResultsSource" in {
-          outputBuffer.toList must containTheSameElementsAs(testInput)
-        }
-      }
-      .run
-      .finish
-  }
-
-  "FileOfflineEvalResultsSourceWriteTestJob" should {
-    val test1Input = List((6, 2, 3, 0.123, 5, "test"))
-    test(test1Input)
-
-    val test2Input = List((11, 2, 5, 0.444, 6, "validation"))
-    test(test2Input)
-  }
-}
\ No newline at end of file
diff --git a/process/engines/commons/algorithms/scala/random/build.sbt b/process/engines/commons/algorithms/scala/random/build.sbt
deleted file mode 100644
index 2d569eb..0000000
--- a/process/engines/commons/algorithms/scala/random/build.sbt
+++ /dev/null
@@ -1,21 +0,0 @@
-import xerial.sbt.Pack._
-
-name := "predictionio-process-commons-algorithms-scala-random"
-
-libraryDependencies ++= Seq(
-  "ch.qos.logback" % "logback-classic" % "1.1.1",
-  "ch.qos.logback" % "logback-core" % "1.1.1",
-  "com.github.scopt" %% "scopt" % "3.2.0",
-  "org.clapper" %% "grizzled-slf4j" % "1.0.1")
-
-packSettings
-
-packJarNameConvention := "full"
-
-packExpandedClasspath := true
-
-packGenerateWindowsBatFile := false
-
-packMain := Map("random" -> "io.prediction.algorithms.commons.random.Random")
-
-packJvmOpts := Map("random" -> Common.packCommonJvmOpts)
diff --git a/process/engines/commons/algorithms/scala/random/src/main/resources/application.conf b/process/engines/commons/algorithms/scala/random/src/main/resources/application.conf
deleted file mode 100644
index c85803b..0000000
--- a/process/engines/commons/algorithms/scala/random/src/main/resources/application.conf
+++ /dev/null
@@ -1,30 +0,0 @@
-# Used by PredictionIO Commons
-io.prediction.base=.
-
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.host=localhost
-io.prediction.commons.appdata.db.port=27017
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.host=localhost
-io.prediction.commons.appdata.test.db.port=27017
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.host=localhost
-io.prediction.commons.appdata.training.db.port=27017
-
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.host=localhost
-io.prediction.commons.appdata.validation.db.port=27017
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.host=localhost
-io.prediction.commons.modeldata.db.port=27017
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.host=localhost
-io.prediction.commons.modeldata.training.db.port=27017
-
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.host=localhost
-io.prediction.commons.settings.db.port=27017
diff --git a/process/engines/commons/algorithms/scala/random/src/main/resources/logback.xml b/process/engines/commons/algorithms/scala/random/src/main/resources/logback.xml
deleted file mode 100644
index f8dd5fb..0000000
--- a/process/engines/commons/algorithms/scala/random/src/main/resources/logback.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<configuration>
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <encoder>
-      <pattern>%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>
-    </encoder>
-  </appender>
-  <root level="info">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
diff --git a/process/engines/commons/algorithms/scala/random/src/main/scala/Random.scala b/process/engines/commons/algorithms/scala/random/src/main/scala/Random.scala
deleted file mode 100644
index 773c65d..0000000
--- a/process/engines/commons/algorithms/scala/random/src/main/scala/Random.scala
+++ /dev/null
@@ -1,107 +0,0 @@
-package io.prediction.algorithms.commons.random
-
-import io.prediction.commons.Config
-import io.prediction.commons.modeldata.{ ItemRecScore, ItemSimScore }
-
-import com.github.nscala_time.time.Imports._
-import grizzled.slf4j.Logger
-
-case class RandomConfig(
-  appid: Int = 0,
-  engineid: Int = 0,
-  algoid: Int = 0,
-  evalid: Option[Int] = None,
-  itypes: Option[Seq[String]] = None,
-  numPredictions: Int = 0,
-  modelSet: Boolean = false,
-  recommendationTime: DateTime = DateTime.now)
-
-object Random {
-  def main(args: Array[String]): Unit = {
-    implicit val dateTimeRead: scopt.Read[DateTime] = scopt.Read.reads(x => new DateTime(x.toLong))
-    val commonsConfig = new Config()
-    val engines = commonsConfig.getSettingsEngines
-    val parser = new scopt.OptionParser[RandomConfig]("random") {
-      head("random")
-      opt[Int]("appid") required () action { (x, c) =>
-        c.copy(appid = x)
-      } text ("the App ID that is the parent of the specified Algo ID")
-      opt[Int]("engineid") required () action { (x, c) =>
-        c.copy(engineid = x)
-      } validate { x =>
-        engines.get(x) map { _ => success } getOrElse failure(s"the Engine ID does not correspond to a valid Engine")
-      } text ("the Engine ID that is the parent of the specified Algo ID")
-      opt[Int]("algoid") required () action { (x, c) =>
-        c.copy(algoid = x)
-      } text ("the Algo ID of this run")
-      opt[Int]("evalid") action { (x, c) =>
-        c.copy(evalid = Some(x))
-      } text ("the OfflineEval ID of this run, if any")
-      opt[String]("itypes") action { (x, c) =>
-        c.copy(itypes = Some(x.split(',')))
-      } text ("restrict use of certain itypes (comma-separated, e.g. --itypes type1,type2)")
-      opt[Int]("numPredictions") required () action { (x, c) =>
-        c.copy(numPredictions = x)
-      } text ("the number of predictions to generate")
-      opt[Boolean]("modelSet") required () action { (x, c) =>
-        c.copy(modelSet = x)
-      } text ("the model set to write to after training is finished")
-      opt[DateTime]("recommendationTime") required () action { (x, c) =>
-        c.copy(recommendationTime = x)
-      } text ("the time instant of this training (UTC UNIX timestamp in milliseconds)")
-    }
-
-    parser.parse(args, RandomConfig()) map { config =>
-      val logger = Logger(Random.getClass)
-      val appid = config.evalid.getOrElse(config.appid)
-      val items = config.evalid map { _ => commonsConfig.getAppdataTrainingItems } getOrElse commonsConfig.getAppdataItems
-      val itypes = config.itypes map { _.toSet } getOrElse Set()
-      val validItems = items.getByAppid(appid).toSeq filter { item =>
-        val typeValidity = config.itypes map { t => (t.toSet & item.itypes.toSet).size > 0 } getOrElse true
-        val timeValidity = (item.starttime, item.endtime) match {
-          case (Some(st), None) => config.recommendationTime >= st
-          case (None, Some(et)) => config.recommendationTime <= et
-          case (Some(st), Some(et)) => st <= config.recommendationTime && config.recommendationTime <= et
-          case _ => true
-        }
-        val inactive = item.inactive.getOrElse(false)
-
-        typeValidity && timeValidity && (!inactive)
-      }
-      logger.info(s"# valid items: ${validItems.size}")
-      val randomScores = Seq.range(1, config.numPredictions + 1).reverse map { _.toDouble }
-      engines.get(config.engineid).get.infoid match {
-        case "itemrec" => {
-          val itemRecScores = config.evalid map { _ => commonsConfig.getModeldataTrainingItemRecScores } getOrElse commonsConfig.getModeldataItemRecScores
-          val users = config.evalid map { _ => commonsConfig.getAppdataTrainingUsers } getOrElse commonsConfig.getAppdataUsers
-          users.getByAppid(appid) foreach { user =>
-            val randomItems = scala.util.Random.shuffle(validItems).take(config.numPredictions)
-            itemRecScores.insert(ItemRecScore(
-              uid = user.id,
-              iids = randomItems map { _.id },
-              scores = randomScores,
-              itypes = randomItems map { _.itypes },
-              appid = appid,
-              algoid = config.algoid,
-              modelset = config.modelSet))
-          }
-        }
-        case "itemsim" => {
-          val itemSimScores = config.evalid map { _ => commonsConfig.getModeldataTrainingItemSimScores } getOrElse commonsConfig.getModeldataItemSimScores
-          items.getByAppid(appid) foreach { item =>
-            val randomItems = scala.util.Random.shuffle(validItems).take(config.numPredictions)
-            itemSimScores.insert(ItemSimScore(
-              iid = item.id,
-              simiids = randomItems map { _.id },
-              scores = randomScores,
-              itypes = randomItems map { _.itypes },
-              appid = appid,
-              algoid = config.algoid,
-              modelset = config.modelSet))
-          }
-        }
-      }
-      logger.info("Run finished")
-    }
-  }
-}
diff --git a/process/engines/commons/evaluations/hadoop/scalding/build.sbt b/process/engines/commons/evaluations/hadoop/scalding/build.sbt
deleted file mode 100644
index 07b8e78..0000000
--- a/process/engines/commons/evaluations/hadoop/scalding/build.sbt
+++ /dev/null
@@ -1,38 +0,0 @@
-import AssemblyKeys._
-
-name := "predictionio-process-commons-evaluations-hadoop-scalding"
-
-packageOptions += Package.ManifestAttributes(java.util.jar.Attributes.Name.MAIN_CLASS -> "com.twitter.scalding.Tool")
-
-parallelExecution in Test := false
-
-resolvers ++= Seq("Concurrent Maven Repo" at "http://conjars.org/repo")
-
-assemblySettings
-
-test in assembly := {}
-
-assembleArtifact in packageScala := true
-
-excludedJars in assembly <<= (fullClasspath in assembly) map { cp =>
-  val excludes = Set(
-    "jsp-api-2.1-6.1.14.jar",
-    "jsp-2.1-6.1.14.jar",
-    "jasper-compiler-5.5.12.jar",
-    "janino-2.5.16.jar",
-    "minlog-1.2.jar",
-    "hadoop-core-1.0.4.jar")
-  cp filter { jar => excludes(jar.data.getName)}
-}
-
-// Some of these files have duplicates, let's ignore:
-mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) =>
-  {
-    case s if s.endsWith(".class") => MergeStrategy.last
-    case s if s.endsWith("project.clj") => MergeStrategy.concat
-    case s if s.endsWith(".html") => MergeStrategy.last
-    case s if s.endsWith(".properties") => MergeStrategy.last
-    case s if s.endsWith(".xml") => MergeStrategy.last
-    case x => old(x)
-  }
-}
diff --git a/process/engines/commons/evaluations/hadoop/scalding/u2itrainingtestsplit/src/main/scala/io/prediction/evaluations/scalding/commons/u2itrainingtestsplit/U2ITrainingTestSplit.scala b/process/engines/commons/evaluations/hadoop/scalding/u2itrainingtestsplit/src/main/scala/io/prediction/evaluations/scalding/commons/u2itrainingtestsplit/U2ITrainingTestSplit.scala
deleted file mode 100644
index 49b2933..0000000
--- a/process/engines/commons/evaluations/hadoop/scalding/u2itrainingtestsplit/src/main/scala/io/prediction/evaluations/scalding/commons/u2itrainingtestsplit/U2ITrainingTestSplit.scala
+++ /dev/null
@@ -1,161 +0,0 @@
-package io.prediction.evaluations.scalding.commons.u2itrainingtestsplit
-
-import com.twitter.scalding._
-
-import io.prediction.commons.scalding.appdata.{ Users, Items, U2iActions }
-
-import io.prediction.commons.appdata.{ User, Item }
-
-/**
- * Source:
- *   appdata.items
- *   appdata.u2iActions
- *
- * Sink:
- *   training_appdata.u2iActions
- *   test_appdata.u2iAcions
- *
- * Description:
- *   Split the appata u2iActions into Training and Test set
- *
- * Args:
- * --dbType: <string> appdata DB type
- * --dbName: <string>
- * --dbHost: <string>. optional. (eg. "127.0.0.1")
- * --dbPort: <int>. optional. (eg. 27017)
- *
- * --training_dbType: <string> training_appadta DB type
- * --training_dbName: <string>
- * --training_dbHost: <string>. optional
- * --training_dbPort: <int>. optional
- *
- * --test_dbType: <string> test_appdata DB type
- * --test_dbName: <string>
- * --test_dbHost: <string>. optional
- * --test_dbPort: <int>. optional
- *
- * --appid: <int>
- * --engineid: <int>
- * --evalid: <int>
- * --itypes: <string separated by white space>. eg "--itypes type1 type2". If no --itypes specified, then ALL itypes will be used.
- *
- * --trainingsize: <int> (1 - 10)
- * --testsize: <int> (1 - 10)
- *
- * Example:
- * scald.rb --hdfs-local io.prediction.evaluations.scalding.commons.u2itrainingtestsplit.U2ITrainingTestSplit --dbType mongodb --dbName appdata --dbHost 127.0.0.1 --dbPort 27017 --appid 34 --engineid 3 --evalid 15 --itypes t2 --trainingsize 8 --testsize 2  --training_dbType mongodb --training_dbName training_appdata --training_dbHost 127.0.0.1 --training_dbPort 27017 --test_dbType mongodb --test_dbName test_appdata --test_dbHost 127.0.0.1 --test_dbPort 27017
- *
- */
-class U2ITrainingTestSplit(args: Args) extends Job(args) {
-
-  /**
-   * parse arguments
-   */
-  val dbTypeArg = args("dbType")
-  val dbNameArg = args("dbName")
-  val dbHostArg = args.list("dbHost")
-  val dbPortArg = args.list("dbPort") map (x => x.toInt)
-
-  val training_dbTypeArg = args("training_dbType")
-  val training_dbNameArg = args("training_dbName")
-  val training_dbHostArg = args.list("training_dbHost")
-  val training_dbPortArg = args.list("training_dbPort") map (x => x.toInt)
-
-  val test_dbTypeArg = args("test_dbType")
-  val test_dbNameArg = args("test_dbName")
-  val test_dbHostArg = args.list("test_dbHost")
-  val test_dbPortArg = args.list("test_dbPort") map (x => x.toInt)
-
-  val appidArg = args("appid").toInt
-  val engineidArg = args("engineid").toInt
-  val evalidArg = args("evalid").toInt
-
-  val preItypesArg = args.list("itypes")
-  val itypesArg: Option[List[String]] = if (preItypesArg.mkString(",").length == 0) None else Option(preItypesArg)
-
-  val trainingsizeArg = args("trainingsize").toInt
-  val testsizeArg = args("testsize").toInt
-
-  val totalSize = trainingsizeArg + testsizeArg
-  require((totalSize <= 10), "The total of trainingsize and testsize must be <= 10")
-
-  /**
-   * source
-   */
-  // get appdata
-  val users = Users(appId = appidArg,
-    dbType = dbTypeArg, dbName = dbNameArg, dbHost = dbHostArg, dbPort = dbPortArg).readObj('user)
-
-  val items = Items(appId = appidArg, itypes = itypesArg,
-    dbType = dbTypeArg, dbName = dbNameArg, dbHost = dbHostArg, dbPort = dbPortArg).readObj('item)
-
-  val u2i = U2iActions(appId = appidArg,
-    dbType = dbTypeArg, dbName = dbNameArg, dbHost = dbHostArg, dbPort = dbPortArg).readData('action, 'uid, 'iid, 't, 'v)
-
-  /**
-   * sink
-   */
-  // sink to training_appdata
-  // NOTE: appid is replaced by evalid for training and test set appdata
-
-  val trainingUsersSink = Users(appId = evalidArg,
-    dbType = training_dbTypeArg, dbName = training_dbNameArg, dbHost = training_dbHostArg, dbPort = training_dbPortArg)
-
-  val trainingItemsSink = Items(appId = evalidArg, itypes = None,
-    dbType = training_dbTypeArg, dbName = training_dbNameArg, dbHost = training_dbHostArg, dbPort = training_dbPortArg)
-
-  val trainingU2iSink = U2iActions(appId = evalidArg,
-    dbType = training_dbTypeArg, dbName = training_dbNameArg, dbHost = training_dbHostArg, dbPort = training_dbPortArg)
-
-  // sink to test_appadta
-  val testU2iSink = U2iActions(appId = evalidArg,
-    dbType = test_dbTypeArg, dbName = test_dbNameArg, dbHost = test_dbHostArg, dbPort = test_dbPortArg)
-
-  /**
-   * computation
-   */
-
-  val oldPrefix: String = appidArg + "_"
-  val newPrefix: String = evalidArg + "_"
-
-  def replace_prefix(org: String): String = newPrefix + org.stripPrefix(oldPrefix)
-
-  val itemsIidx = items.mapTo('item -> 'iidx) { obj: Item => obj.id }
-
-  val selectedU2i = u2i.joinWithSmaller('iid -> 'iidx, itemsIidx) // only select actions of these items
-    .map(('uid, 'iid) -> ('randValue, 'newUid, 'newIid)) { fields: (String, String) =>
-
-      // NOTE: replace appid prefix by evalid
-      val (uid, iid) = fields
-      val newUid = replace_prefix(uid)
-      val newIid = replace_prefix(iid)
-
-      // scala.math.random is evenly distributed
-      val r = (scala.math.random * 10).toInt
-
-      (r, newUid, newIid)
-    }
-
-  selectedU2i.filter('randValue) { r: Int => (r < testsizeArg) }
-    .then(testU2iSink.writeData('action, 'newUid, 'newIid, 't, 'v, evalidArg) _) // NOTE: appid is repalced by evalid
-
-  selectedU2i.filter('randValue) { r: Int => ((r >= testsizeArg) && (r < totalSize)) }
-    .then(trainingU2iSink.writeData('action, 'newUid, 'newIid, 't, 'v, evalidArg) _) // NOTE: appid is repalced by evalid
-
-  items.mapTo('item -> 'item) { obj: Item =>
-    val iid = obj.id
-    obj.copy(
-      id = replace_prefix(iid),
-      appid = evalidArg // NOTE: appid is repalced by evalid
-    )
-  }.then(trainingItemsSink.writeObj('item) _)
-
-  users.mapTo('user -> 'user) { obj: User =>
-    val uid = obj.id
-    obj.copy(
-      id = replace_prefix(uid),
-      appid = evalidArg // NOTE: appid is repalced by evalid
-    )
-  }.then(trainingUsersSink.writeObj('user) _)
-
-}
diff --git a/process/engines/commons/evaluations/hadoop/scalding/u2itrainingtestsplit/src/main/scala/io/prediction/evaluations/scalding/commons/u2itrainingtestsplit/U2ITrainingTestSplitCommon.scala b/process/engines/commons/evaluations/hadoop/scalding/u2itrainingtestsplit/src/main/scala/io/prediction/evaluations/scalding/commons/u2itrainingtestsplit/U2ITrainingTestSplitCommon.scala
deleted file mode 100644
index 6155c04..0000000
--- a/process/engines/commons/evaluations/hadoop/scalding/u2itrainingtestsplit/src/main/scala/io/prediction/evaluations/scalding/commons/u2itrainingtestsplit/U2ITrainingTestSplitCommon.scala
+++ /dev/null
@@ -1,100 +0,0 @@
-package io.prediction.evaluations.scalding.commons.u2itrainingtestsplit
-
-import com.twitter.scalding._
-
-import io.prediction.commons.scalding.appdata.{ Users, Items, U2iActions }
-import io.prediction.commons.filepath.U2ITrainingTestSplitFile
-import io.prediction.commons.appdata.{ User, Item }
-
-/**
- * Description:
- *   TrainingtestsplitCommon
- *
- * Args:
- * --dbType: <string> appdata DB type
- * --dbName: <string>
- * --dbHost: <string>. optional. (eg. "127.0.0.1")
- * --dbPort: <int>. optional. (eg. 27017)
- *
- * --training_dbType: <string> training_appadta DB type
- * --training_dbName: <string>
- * --training_dbHost: <string>. optional
- * --training_dbPort: <int>. optional
- *
- * --validation_dbType: <string> validation_appdata DB type
- * --validation_dbName: <string>
- * --validation_dbHost: <string>. optional
- * --validation_dbPort: <int>. optional
- *
- * --test_dbType: <string> test_appdata DB type
- * --test_dbName: <string>
- * --test_dbHost: <string>. optional
- * --test_dbPort: <int>. optional
- *
- * --hdfsRoot: <string>. Root directory of the HDFS
- *
- * --appid: <int>
- * --engineid: <int>
- * --evalid: <int>
- *
- * --itypes: <string separated by white space>. eg "--itypes type1 type2". If no --itypes specified, then ALL itypes will be used.
- *
- * --trainingPercent: <double> (0.01 to 1). training set percentage
- * --validationPercent: <dboule> (0 to 1). validation set percentage
- * --testPercent: <double> (0.01 to 1). test set percentage
- *
- * --timeorder: <boolean>. Require total percentage < 1
- */
-abstract class U2ITrainingTestSplitCommon(args: Args) extends Job(args) {
-
-  /**
-   * parse arguments
-   */
-  val dbTypeArg = args("dbType")
-  val dbNameArg = args("dbName")
-  val dbHostArg = args.list("dbHost")
-  val dbPortArg = args.list("dbPort") map (x => x.toInt)
-
-  val training_dbTypeArg = args("training_dbType")
-  val training_dbNameArg = args("training_dbName")
-  val training_dbHostArg = args.list("training_dbHost")
-  val training_dbPortArg = args.list("training_dbPort") map (x => x.toInt)
-
-  val validation_dbTypeArg = args("validation_dbType")
-  val validation_dbNameArg = args("validation_dbName")
-  val validation_dbHostArg = args.list("validation_dbHost")
-  val validation_dbPortArg = args.list("validation_dbPort") map (x => x.toInt)
-
-  val test_dbTypeArg = args("test_dbType")
-  val test_dbNameArg = args("test_dbName")
-  val test_dbHostArg = args.list("test_dbHost")
-  val test_dbPortArg = args.list("test_dbPort") map (x => x.toInt)
-
-  val hdfsRootArg = args("hdfsRoot")
-
-  val appidArg = args("appid").toInt
-  val engineidArg = args("engineid").toInt
-  val evalidArg = args("evalid").toInt
-
-  val preItypesArg = args.list("itypes")
-  val itypesArg: Option[List[String]] = if (preItypesArg.mkString(",").length == 0) None else Option(preItypesArg)
-
-  val trainingPercentArg = args("trainingPercent").toDouble
-  val validationPercentArg = args("validationPercent").toDouble
-  val testPercentArg = args("testPercent").toDouble
-
-  val timeorderArg = args("timeorder").toBoolean
-
-  val evaluationPercent = trainingPercentArg + validationPercentArg + testPercentArg
-
-  require(((trainingPercentArg >= 0.01) && (trainingPercentArg <= 1)), "trainingPercent must be >= 0.01 and <= 1.")
-  require(((validationPercentArg >= 0) && (validationPercentArg <= 1)), "validationPercent must be >= 0 and <= 1.")
-  require(((testPercentArg >= 0.01) && (testPercentArg <= 1)), "testPercent must be >= 0.01 and <= 1.")
-
-  // check valid size
-  if (timeorderArg)
-    require((evaluationPercent < 1), "The total of training/validation/test must be < 1 if timeorder is true.")
-  else
-    require((evaluationPercent <= 1), "The total of training/validation/test must be <= 1.")
-
-}
diff --git a/process/engines/commons/evaluations/hadoop/scalding/u2itrainingtestsplit/src/main/scala/io/prediction/evaluations/scalding/commons/u2itrainingtestsplit/U2ITrainingTestSplitTime.scala b/process/engines/commons/evaluations/hadoop/scalding/u2itrainingtestsplit/src/main/scala/io/prediction/evaluations/scalding/commons/u2itrainingtestsplit/U2ITrainingTestSplitTime.scala
deleted file mode 100644
index 4e321df..0000000
--- a/process/engines/commons/evaluations/hadoop/scalding/u2itrainingtestsplit/src/main/scala/io/prediction/evaluations/scalding/commons/u2itrainingtestsplit/U2ITrainingTestSplitTime.scala
+++ /dev/null
@@ -1,91 +0,0 @@
-package io.prediction.evaluations.scalding.commons.u2itrainingtestsplit
-
-import com.twitter.scalding._
-
-import io.prediction.commons.scalding.appdata.{ Users, Items, U2iActions }
-import io.prediction.commons.filepath.U2ITrainingTestSplitFile
-import io.prediction.commons.appdata.{ User, Item }
-
-/**
- * Description:
- *   Split u2i into training, validation and test set
- *
- * Args:
- * same as TrainingtestsplitCommon, plus additional args:
- * --totalCount <int> total u2i actions count
- */
-class U2ITrainingTestSplitTime(args: Args) extends U2ITrainingTestSplitCommon(args) {
-
-  val totalCountArg = args("totalCount").toInt // total u2i count
-
-  // evaluationPercent is sum of trainingPercentArg + validationPercentArg + testPercentArg
-  val evaluationCount: Int = (scala.math.floor(evaluationPercent * totalCountArg)).toInt
-
-  val trainingCount: Int = (scala.math.floor(trainingPercentArg * totalCountArg)).toInt
-  val validationCount: Int = (scala.math.floor(validationPercentArg * totalCountArg)).toInt
-
-  val trainingValidationCount: Int = trainingCount + validationCount
-  val testCount = evaluationCount - trainingValidationCount
-
-  require((trainingCount >= 1), "Not enough data for training set. trainingCount = " + trainingCount)
-  if (validationPercentArg != 0) {
-    require((validationCount >= 1), "Not enough data for validation set. validationCount = " + validationCount)
-  }
-  require((testCount >= 1), "Not enough data for test set. testCount = " + testCount)
-
-  /**
-   * source
-   */
-
-  // data generated at prep stage
-  val u2iSource = U2iActions(appId = evalidArg,
-    dbType = "file", dbName = U2ITrainingTestSplitFile(hdfsRootArg, appidArg, engineidArg, evalidArg, ""), dbHost = Seq(), dbPort = Seq())
-
-  /**
-   * sink
-   */
-
-  val trainingU2iSink = U2iActions(appId = evalidArg,
-    dbType = training_dbTypeArg, dbName = training_dbNameArg, dbHost = training_dbHostArg, dbPort = training_dbPortArg)
-
-  val validationU2iSink = U2iActions(appId = evalidArg,
-    dbType = validation_dbTypeArg, dbName = validation_dbNameArg, dbHost = validation_dbHostArg, dbPort = validation_dbPortArg)
-
-  // sink to test_appadta
-  val testU2iSink = U2iActions(appId = evalidArg,
-    dbType = test_dbTypeArg, dbName = test_dbNameArg, dbHost = test_dbHostArg, dbPort = test_dbPortArg)
-
-  /**
-   * computation
-   */
-
-  val randomU2i = if (timeorderArg) {
-
-    // shuffle, take and then sort
-    u2iSource.readData('action, 'uid, 'iid, 't, 'v)
-      .shuffle(11)
-      .groupAll(_.take(evaluationCount))
-      .groupAll(_.sortBy('t)) // NOTE: small to largest (oldest first, so training set should be taken first)
-
-  } else {
-
-    // shuffle and then take
-    u2iSource.readData('action, 'uid, 'iid, 't, 'v)
-      .shuffle(11)
-      .groupAll(_.take(evaluationCount))
-
-  }
-
-  // split
-  val trainingOrValidation = randomU2i.groupAll(_.take(trainingValidationCount))
-
-  trainingOrValidation.groupAll(_.take(trainingCount))
-    .then(trainingU2iSink.writeData('action, 'uid, 'iid, 't, 'v, evalidArg) _) // NOTE: appid is replaced by evalid
-
-  trainingOrValidation.groupAll(_.drop(trainingCount))
-    .then(validationU2iSink.writeData('action, 'uid, 'iid, 't, 'v, evalidArg) _) // NOTE: appid is replaced by evalid
-
-  randomU2i.groupAll(_.drop(trainingValidationCount))
-    .then(testU2iSink.writeData('action, 'uid, 'iid, 't, 'v, evalidArg) _) // NOTE: appid is replaced by evalid
-
-}
diff --git a/process/engines/commons/evaluations/hadoop/scalding/u2itrainingtestsplit/src/main/scala/io/prediction/evaluations/scalding/commons/u2itrainingtestsplit/U2ITrainingTestSplitTimePrep.scala b/process/engines/commons/evaluations/hadoop/scalding/u2itrainingtestsplit/src/main/scala/io/prediction/evaluations/scalding/commons/u2itrainingtestsplit/U2ITrainingTestSplitTimePrep.scala
deleted file mode 100644
index 4abbb67..0000000
--- a/process/engines/commons/evaluations/hadoop/scalding/u2itrainingtestsplit/src/main/scala/io/prediction/evaluations/scalding/commons/u2itrainingtestsplit/U2ITrainingTestSplitTimePrep.scala
+++ /dev/null
@@ -1,103 +0,0 @@
-package io.prediction.evaluations.scalding.commons.u2itrainingtestsplit
-
-import com.twitter.scalding._
-
-import io.prediction.commons.scalding.appdata.{ Users, Items, U2iActions }
-import io.prediction.commons.filepath.U2ITrainingTestSplitFile
-import io.prediction.commons.appdata.{ User, Item }
-
-/**
- * Description:
- *   Write user/items to db. Read u2iActions and filter with itypes and write to hdfs.
- *   Count number of u2i Actions.
- *   note: appid is replaced by evalid.
- *
- * Args:
- * same as U2ITrainingTestSplitCommon
- */
-class U2ITrainingTestSplitTimePrep(args: Args) extends U2ITrainingTestSplitCommon(args) {
-
-  /**
-   * source
-   */
-  // get appdata
-  val usersSource = Users(appId = appidArg,
-    dbType = dbTypeArg, dbName = dbNameArg, dbHost = dbHostArg, dbPort = dbPortArg)
-
-  val itemsSource = Items(appId = appidArg, itypes = itypesArg,
-    dbType = dbTypeArg, dbName = dbNameArg, dbHost = dbHostArg, dbPort = dbPortArg)
-
-  val u2iSource = U2iActions(appId = appidArg,
-    dbType = dbTypeArg, dbName = dbNameArg, dbHost = dbHostArg, dbPort = dbPortArg)
-
-  /**
-   * sink
-   */
-  val trainingUsersSink = Users(appId = evalidArg,
-    dbType = training_dbTypeArg, dbName = training_dbNameArg, dbHost = training_dbHostArg, dbPort = training_dbPortArg)
-
-  val trainingItemsSink = Items(appId = evalidArg, itypes = None,
-    dbType = training_dbTypeArg, dbName = training_dbNameArg, dbHost = training_dbHostArg, dbPort = training_dbPortArg)
-
-  // NOTE: sink to temporary hdfs first
-  val u2iSink = U2iActions(appId = evalidArg,
-    dbType = "file", dbName = U2ITrainingTestSplitFile(hdfsRootArg, appidArg, engineidArg, evalidArg, ""), dbHost = Seq(), dbPort = Seq())
-
-  val countSink = Tsv(U2ITrainingTestSplitFile(hdfsRootArg, appidArg, engineidArg, evalidArg, "u2iCount.tsv"))
-
-  /**
-   * computation
-   */
-
-  val oldPrefix: String = appidArg + "_"
-  val newPrefix: String = evalidArg + "_"
-
-  def replacePrefix(org: String): String = newPrefix + org.stripPrefix(oldPrefix)
-
-  val items = itemsSource.readObj('item)
-
-  // write items
-  items.mapTo('item -> 'item) { obj: Item =>
-    val iid = obj.id
-    obj.copy(
-      id = replacePrefix(iid),
-      appid = evalidArg // NOTE: appid is replaced by evalid
-    )
-  }.then(trainingItemsSink.writeObj('item) _)
-
-  // write users
-  usersSource.readObj('user).mapTo('user -> 'user) { obj: User =>
-    val uid = obj.id
-    obj.copy(
-      id = replacePrefix(uid),
-      appid = evalidArg // NOTE: appid is replaced by evalid
-    )
-  }.then(trainingUsersSink.writeObj('user) _)
-
-  // filter and write u2i
-  val itemsIidx = items.mapTo('item -> 'iidx) { obj: Item => obj.id }
-
-  val selectedU2i = u2iSource.readData('action, 'uid, 'iid, 't, 'v)
-    .joinWithSmaller('iid -> 'iidx, itemsIidx) // only select actions of these items
-    .map(('uid, 'iid, 'action, 'v) -> ('newUid, 'newIid, 'newV)) { fields: (String, String, String, Option[String]) =>
-
-      // NOTE: replace appid prefix by evalid
-      val (uid, iid, action, v) = fields
-      val newUid = replacePrefix(uid)
-      val newIid = replacePrefix(iid)
-
-      /* TODO remove
-      // NOTE: add default value 0 for non-rate acitons to work around the optional v field issue
-      //       (cascading-mongo tap can't take optional field yet).
-      val newV = if (v == "") "0" else v */
-
-      (newUid, newIid, v)
-    }
-
-  selectedU2i.then(u2iSink.writeData('action, 'newUid, 'newIid, 't, 'newV, evalidArg) _) // NOTE: appid is replaced by evalid
-
-  // count number of u2i
-  selectedU2i.groupAll(_.size('count))
-    .write(countSink)
-
-}
diff --git a/process/engines/commons/evaluations/hadoop/scalding/u2itrainingtestsplit/src/test/scala/io/prediction/evaluations/scalding/commons/u2itrainingtestsplit/U2ITrainingTestSplitTimeTest.scala b/process/engines/commons/evaluations/hadoop/scalding/u2itrainingtestsplit/src/test/scala/io/prediction/evaluations/scalding/commons/u2itrainingtestsplit/U2ITrainingTestSplitTimeTest.scala
deleted file mode 100644
index 3d8d2b7..0000000
--- a/process/engines/commons/evaluations/hadoop/scalding/u2itrainingtestsplit/src/test/scala/io/prediction/evaluations/scalding/commons/u2itrainingtestsplit/U2ITrainingTestSplitTimeTest.scala
+++ /dev/null
@@ -1,343 +0,0 @@
-package io.prediction.evaluations.scalding.commons.u2itrainingtestsplit
-
-import org.specs2.mutable._
-
-import com.twitter.scalding._
-
-import io.prediction.commons.scalding.appdata.{ Users, Items, U2iActions }
-import io.prediction.commons.filepath.U2ITrainingTestSplitFile
-import io.prediction.commons.appdata.{ User, Item }
-
-class U2ITrainingTestSplitTimeTest extends Specification with TupleConversions {
-
-  def test(itypes: List[String], trainingPercent: Double, validationPercent: Double, testPercent: Double, timeorder: Boolean,
-    appid: Int, evalid: Int,
-    items: List[(String, String, String, String, String, String, String)],
-    users: List[(String, String, String)],
-    u2iActions: List[(String, String, String, String, String)],
-    selectedItems: List[(String, String, String, String, String, String, String)],
-    selectedUsers: List[(String, String, String)],
-    selectedU2iActions: List[(String, String, String, String, String)]) = {
-
-    val dbType = "file"
-    val dbName = "testpath/"
-    val dbHost = Seq()
-    val dbPort = Seq()
-
-    val training_dbType = "file"
-    val training_dbName = "trainingsetpath/"
-    val training_dbHost = Seq()
-    val training_dbPort = Seq()
-
-    val validation_dbType = "file"
-    val validation_dbName = "validationpath/"
-    val validation_dbHost = Seq()
-    val validation_dbPort = Seq()
-
-    val test_dbType = "file"
-    val test_dbName = "testsetpath/"
-    val test_dbHost = Seq()
-    val test_dbPort = Seq()
-
-    val hdfsRoot = "testroot/"
-
-    val engineid = 4
-
-    val originalCount = selectedU2iActions.size
-
-    val totalPercent = (trainingPercent + validationPercent + testPercent)
-    val evalCount: Int = scala.math.floor(totalPercent * originalCount).toInt
-    val trainingCount: Int = scala.math.floor((trainingPercent * originalCount)).toInt
-    val validationCount: Int = scala.math.floor((validationPercent * originalCount)).toInt
-    val testCount: Int = evalCount - trainingCount - validationCount
-    /*
-    println("originalCount=" + originalCount)
-    println("evalCount="+ evalCount )
-    println("trainingCount="+ trainingCount)
-    println("validationCount="+ validationCount)
-    println("testCount="+testCount)
-    */
-
-    JobTest("io.prediction.evaluations.scalding.commons.u2itrainingtestsplit.U2ITrainingTestSplitTimePrep")
-      .arg("dbType", dbType)
-      .arg("dbName", dbName)
-      .arg("training_dbType", training_dbType)
-      .arg("training_dbName", training_dbName)
-      .arg("validation_dbType", validation_dbType)
-      .arg("validation_dbName", validation_dbName)
-      .arg("test_dbType", test_dbType)
-      .arg("test_dbName", test_dbName)
-      .arg("hdfsRoot", hdfsRoot)
-      .arg("appid", appid.toString)
-      .arg("engineid", engineid.toString)
-      .arg("evalid", evalid.toString)
-      .arg("trainingPercent", trainingPercent.toString)
-      .arg("validationPercent", validationPercent.toString)
-      .arg("testPercent", testPercent.toString)
-      .arg("timeorder", timeorder.toString)
-      .source(Users(appId = appid, dbType = dbType, dbName = dbName, dbHost = dbHost, dbPort = dbPort).getSource, users)
-      .source(Items(appId = appid, itypes = Some(itypes), dbType = dbType, dbName = dbName, dbHost = dbHost, dbPort = dbPort).getSource, items)
-      .source(U2iActions(appId = appid, dbType = dbType, dbName = dbName, dbHost = dbHost, dbPort = dbPort).getSource, u2iActions)
-      .sink[(String, String, String)](Users(appId = evalid, dbType = training_dbType, dbName = training_dbName, dbHost = training_dbHost, dbPort = training_dbPort).getSource) { outputBuffer =>
-        "correctly write trainingUsers" in {
-          outputBuffer must containTheSameElementsAs(selectedUsers)
-        }
-      }
-      .sink[(String, String, String, String, String, String, String)](Items(appId = evalid, itypes = None, dbType = training_dbType, dbName = training_dbName, dbHost = training_dbHost, dbPort = training_dbPort).getSource) { outputBuffer =>
-        "correctly write trainingItems" in {
-          outputBuffer must containTheSameElementsAs(selectedItems)
-        }
-      }
-      .sink[(String, String, String, String, String)](U2iActions(appId = evalid,
-        dbType = "file", dbName = U2ITrainingTestSplitFile(hdfsRoot, appid, engineid, evalid, ""), dbHost = Seq(), dbPort = Seq()).getSource) { outputBuffer =>
-        "correctly write u2iActions" in {
-          outputBuffer must containTheSameElementsAs(selectedU2iActions)
-        }
-      }
-      .sink[(Int)](Tsv(U2ITrainingTestSplitFile(hdfsRoot, appid, engineid, evalid, "u2iCount.tsv"))) { outputBuffer =>
-        "correctly write u2iActions count" in {
-          outputBuffer must containTheSameElementsAs(List(originalCount))
-        }
-      }
-      .run
-      .finish
-
-    def splitTest() = {
-
-      val results = new scala.collection.mutable.HashMap[String, List[(String, String, String, String, String)]] with scala.collection.mutable.SynchronizedMap[String, List[(String, String, String, String, String)]]
-
-      JobTest("io.prediction.evaluations.scalding.commons.u2itrainingtestsplit.U2ITrainingTestSplitTime")
-        .arg("dbType", dbType)
-        .arg("dbName", dbName)
-        .arg("training_dbType", training_dbType)
-        .arg("training_dbName", training_dbName)
-        .arg("validation_dbType", validation_dbType)
-        .arg("validation_dbName", validation_dbName)
-        .arg("test_dbType", test_dbType)
-        .arg("test_dbName", test_dbName)
-        .arg("hdfsRoot", hdfsRoot)
-        .arg("appid", appid.toString)
-        .arg("engineid", engineid.toString)
-        .arg("evalid", evalid.toString)
-        .arg("trainingPercent", trainingPercent.toString)
-        .arg("validationPercent", validationPercent.toString)
-        .arg("testPercent", testPercent.toString)
-        .arg("timeorder", timeorder.toString)
-        .arg("totalCount", originalCount.toString)
-        .source(U2iActions(appId = evalid,
-          dbType = "file", dbName = U2ITrainingTestSplitFile(hdfsRoot, appid, engineid, evalid, ""), dbHost = Seq(), dbPort = Seq()).getSource, selectedU2iActions)
-        .sink[(String, String, String, String, String)](U2iActions(appId = evalid,
-          dbType = training_dbType, dbName = training_dbName, dbHost = training_dbHost, dbPort = training_dbPort).getSource) { outputBuffer =>
-          "generate training set" in {
-            val output = outputBuffer.toList
-            results += ("training" -> output) // remember the output for later checking purpose
-
-            // note: since the selection is random, can't know the expected selection beforehand.
-            // so just check if the original data contain the selected data and the size is correct.
-            // Randomness and time order is checked in later stages.
-            selectedU2iActions must containAllOf(output) and
-              (output.size must be_==(trainingCount))
-          }
-        }
-        .sink[(String, String, String, String, String)](U2iActions(appId = evalid,
-          dbType = validation_dbType, dbName = validation_dbName, dbHost = validation_dbHost, dbPort = validation_dbPort).getSource) { outputBuffer =>
-          "generate validation set" in {
-            val output = outputBuffer.toList
-            results += ("validation" -> output)
-            selectedU2iActions must containAllOf(output) and
-              (output.size must be_==(validationCount))
-          }
-        }
-        .sink[(String, String, String, String, String)](U2iActions(appId = evalid,
-          dbType = test_dbType, dbName = test_dbName, dbHost = test_dbHost, dbPort = test_dbPort).getSource) { outputBuffer =>
-          "generate test set" in {
-            val output = outputBuffer.toList
-            results += ("test" -> output)
-            selectedU2iActions must containAllOf(output) and
-              (output.size must be_==(testCount))
-          }
-        }
-        .run
-        .finish
-
-      "all sets are mutually exclusive" in {
-        // make sure all 3 sinks are flushed
-        while (results.keys.size < 3) Thread.sleep(1000)
-        (results("training") must not(containAnyOf(results("validation")))) and
-          (results("training") must not(containAnyOf(results("test")))) and
-          (results("validation") must not(containAnyOf(results("test"))))
-      }
-
-      def getTimeOnly(dataSet: List[(String, String, String, String, String)]): List[Long] = {
-        dataSet map { case (action, uid, iid, t, v) => t.toLong }
-      }
-
-      if (timeorder) {
-        // check time order
-        if (validationPercent != 0) {
-          "validation set must be newer than training set" in {
-            while (results.keys.size < 3) Thread.sleep(1000)
-            getTimeOnly(results("validation")).min must be_>=(getTimeOnly(results("training")).max)
-          }
-          "test set must be newer than validation set" in {
-            while (results.keys.size < 3) Thread.sleep(1000)
-            getTimeOnly(results("test")).min must be_>=(getTimeOnly(results("validation")).max)
-          }
-        }
-
-        "test set must be newer than training set" in {
-          while (results.keys.size < 3) Thread.sleep(1000)
-          getTimeOnly(results("test")).min must be_>=(getTimeOnly(results("training")).max)
-        }
-      }
-
-      results
-    }
-
-    val firstSplit = splitTest()
-    val secondSplit = splitTest()
-
-    // simple check for randomness
-    if (timeorder) {
-      "at least one set of two split is different" in {
-        // for timeorder=true case, some sets may still be the same even resplit 2nd time
-        // because the original data is small, we select most of them (say > 90%) and
-        // split according to time order. The chance of ending up same data in the set is high.
-        // so here just do simple check: as long as 1 set is different, consider OK.
-        // (it's possible to check all difference if the test input data is large enough and selected percentage is relative small.)
-        (firstSplit("training") must not(containTheSameElementsAs(secondSplit("training")))) or
-          (firstSplit("validation") must not(containTheSameElementsAs(secondSplit("validation")))) or
-          (firstSplit("test") must not(containTheSameElementsAs(secondSplit("test"))))
-      }
-    } else {
-      "all sets of two splits are different" in {
-        if (validationPercent == 0) {
-          // don't check validation set since it is empty
-          (firstSplit("training") must not(containTheSameElementsAs(secondSplit("training")))) and
-            (firstSplit("test") must not(containTheSameElementsAs(secondSplit("test"))))
-        } else {
-          (firstSplit("training") must not(containTheSameElementsAs(secondSplit("training")))) and
-            (firstSplit("validation") must not(containTheSameElementsAs(secondSplit("validation")))) and
-            (firstSplit("test") must not(containTheSameElementsAs(secondSplit("test"))))
-        }
-      }
-    }
-
-  }
-
-  val appid = 2
-  val evalid = 101
-  val users = List(
-    (appid + "_u0", appid.toString, "123456"),
-    (appid + "_u1", appid.toString, "23456"),
-    (appid + "_u2", appid.toString, "455677"),
-    (appid + "_u3", appid.toString, "876563111"))
-
-  val items = List(
-    (appid + "_i0", "t1,t2,t3", appid.toString, "2293300", "1266673",
-      "978462511", "PIO_NONE"),
-    (appid + "_i1", "t2,t3", appid.toString, "14526361", "12345135",
-      "978462512", "true"),
-    (appid + "_i2", "t4", appid.toString, "14526361", "23423424",
-      "978462513", "false"),
-    (appid + "_i3", "t3,t4", appid.toString, "1231415", "378462511",
-      "978462514", "PIO_NONE"))
-
-  val u2iActions = List(
-    ("4", appid + "_u0", appid + "_i1", "1234500", "5"),
-    ("3", appid + "_u3", appid + "_i0", "1234505", "1"),
-    ("4", appid + "_u1", appid + "_i3", "1234501", "3"),
-    ("4", appid + "_u1", appid + "_i2", "1234506", "4"),
-    ("2", appid + "_u1", appid + "_i0", "1234507", "5"),
-    ("3", appid + "_u2", appid + "_i3", "1234502", "2"),
-    ("4", appid + "_u0", appid + "_i2", "1234508", "3"),
-    ("4", appid + "_u2", appid + "_i0", "1234509", "1"),
-    ("4", appid + "_u0", appid + "_i1", "1234503", "2"),
-    ("4", appid + "_u3", appid + "_i3", "1234504", "3"),
-    ("4", appid + "_u3", appid + "_i3", "1234503", "3"),
-    ("4", appid + "_u2", appid + "_i3", "1234504", "3"),
-    ("4", appid + "_u1", appid + "_i3", "1234505", "3"),
-    ("4", appid + "_u0", appid + "_i3", "1234509", "3"),
-    ("view", appid + "_u0", appid + "_i0", "1234509", "PIO_NONE"), // test missing v field case (non-rate action)
-    ("like", appid + "_u1", appid + "_i2", "1234509", "PIO_NONE")) // test missing v field case (non-rate action)
-
-  val selectedUsers = List(
-    (evalid + "_u0", evalid.toString, "123456"),
-    (evalid + "_u1", evalid.toString, "23456"),
-    (evalid + "_u2", evalid.toString, "455677"),
-    (evalid + "_u3", evalid.toString, "876563111"))
-
-  val selectedItemsAll = List(
-    (evalid + "_i0", "t1,t2,t3", evalid.toString, "2293300", "1266673",
-      "978462511", "PIO_NONE"),
-    (evalid + "_i1", "t2,t3", evalid.toString, "14526361", "12345135",
-      "978462512", "true"),
-    (evalid + "_i2", "t4", evalid.toString, "14526361", "23423424",
-      "978462513", "false"),
-    (evalid + "_i3", "t3,t4", evalid.toString, "1231415", "378462511",
-      "978462514", "PIO_NONE"))
-
-  val selectedU2iActions = List(
-    ("4", evalid + "_u0", evalid + "_i1", "1234500", "5"),
-    ("3", evalid + "_u3", evalid + "_i0", "1234505", "1"),
-    ("4", evalid + "_u1", evalid + "_i3", "1234501", "3"),
-    ("4", evalid + "_u1", evalid + "_i2", "1234506", "4"),
-    ("2", evalid + "_u1", evalid + "_i0", "1234507", "5"),
-    ("3", evalid + "_u2", evalid + "_i3", "1234502", "2"),
-    ("4", evalid + "_u0", evalid + "_i2", "1234508", "3"),
-    ("4", evalid + "_u2", evalid + "_i0", "1234509", "1"),
-    ("4", evalid + "_u0", evalid + "_i1", "1234503", "2"),
-    ("4", evalid + "_u3", evalid + "_i3", "1234504", "3"),
-    ("4", evalid + "_u3", evalid + "_i3", "1234503", "3"),
-    ("4", evalid + "_u2", evalid + "_i3", "1234504", "3"),
-    ("4", evalid + "_u1", evalid + "_i3", "1234505", "3"),
-    ("4", evalid + "_u0", evalid + "_i3", "1234509", "3"),
-    ("view", evalid + "_u0", evalid + "_i0", "1234509", "PIO_NONE"),
-    ("like", evalid + "_u1", evalid + "_i2", "1234509", "PIO_NONE"))
-
-  "U2ITrainingTestSplitTimeTest with timeorder=true" should {
-    test(List(""), 0.4, 0.3, 0.2, true, appid, evalid,
-      items,
-      users,
-      u2iActions,
-      selectedItemsAll,
-      selectedUsers,
-      selectedU2iActions
-    )
-
-  }
-
-  "U2ITrainingTestSplitTimeTest with timeorder=false" should {
-    test(List(""), 0.3, 0.2, 0.3, false, appid, evalid,
-      items,
-      users,
-      u2iActions,
-      selectedItemsAll,
-      selectedUsers,
-      selectedU2iActions
-    )
-  }
-
-  "U2ITrainingTestSplitTimeTest with timeorder=true and validation=0" should {
-    test(List(""), 0.6, 0, 0.1, true, appid, evalid,
-      items,
-      users,
-      u2iActions,
-      selectedItemsAll,
-      selectedUsers,
-      selectedU2iActions
-    )
-  }
-
-  "U2ITrainingTestSplitTimeTest with timeorder=false and validation=0" should {
-    test(List(""), 0.6, 0, 0.4, false, appid, evalid,
-      items,
-      users,
-      u2iActions,
-      selectedItemsAll,
-      selectedUsers,
-      selectedU2iActions
-    )
-  }
-
-}
diff --git a/process/engines/commons/evaluations/scala/map/build.sbt b/process/engines/commons/evaluations/scala/map/build.sbt
deleted file mode 100644
index 45d1746..0000000
--- a/process/engines/commons/evaluations/scala/map/build.sbt
+++ /dev/null
@@ -1,22 +0,0 @@
-import xerial.sbt.Pack._
-
-name := "predictionio-process-commons-metrics-scala-map"
-
-libraryDependencies ++= Seq(
-  "ch.qos.logback" % "logback-classic" % "1.1.1",
-  "ch.qos.logback" % "logback-core" % "1.1.1",
-  "com.github.scopt" %% "scopt" % "3.2.0",
-  "org.clapper" %% "grizzled-slf4j" % "1.0.1",
-  "org.specs2" %% "specs2" % "2.3.10" % "test")
-
-packSettings
-
-packJarNameConvention := "full"
-
-packExpandedClasspath := true
-
-packGenerateWindowsBatFile := false
-
-packMain := Map("mapatk" -> "io.prediction.metrics.commons.map.MAPAtK")
-
-packJvmOpts := Map("mapatk" -> Common.packCommonJvmOpts)
diff --git a/process/engines/commons/evaluations/scala/map/src/main/resources/application.conf b/process/engines/commons/evaluations/scala/map/src/main/resources/application.conf
deleted file mode 100644
index c85803b..0000000
--- a/process/engines/commons/evaluations/scala/map/src/main/resources/application.conf
+++ /dev/null
@@ -1,30 +0,0 @@
-# Used by PredictionIO Commons
-io.prediction.base=.
-
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.host=localhost
-io.prediction.commons.appdata.db.port=27017
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.host=localhost
-io.prediction.commons.appdata.test.db.port=27017
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.host=localhost
-io.prediction.commons.appdata.training.db.port=27017
-
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.host=localhost
-io.prediction.commons.appdata.validation.db.port=27017
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.host=localhost
-io.prediction.commons.modeldata.db.port=27017
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.host=localhost
-io.prediction.commons.modeldata.training.db.port=27017
-
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.host=localhost
-io.prediction.commons.settings.db.port=27017
diff --git a/process/engines/commons/evaluations/scala/map/src/main/resources/logback.xml b/process/engines/commons/evaluations/scala/map/src/main/resources/logback.xml
deleted file mode 100644
index f8dd5fb..0000000
--- a/process/engines/commons/evaluations/scala/map/src/main/resources/logback.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<configuration>
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <encoder>
-      <pattern>%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>
-    </encoder>
-  </appender>
-  <root level="info">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
diff --git a/process/engines/commons/evaluations/scala/map/src/main/scala/MAPAtK.scala b/process/engines/commons/evaluations/scala/map/src/main/scala/MAPAtK.scala
deleted file mode 100644
index 8b653d8..0000000
--- a/process/engines/commons/evaluations/scala/map/src/main/scala/MAPAtK.scala
+++ /dev/null
@@ -1,253 +0,0 @@
-package io.prediction.metrics.commons.map
-
-import io.prediction.commons.Config
-import io.prediction.commons.settings.OfflineEvalResult
-import io.prediction.commons.filepath.OfflineMetricFile
-
-import scala.io.Source
-import java.io.File
-import java.io.FileWriter
-import java.io.BufferedWriter
-
-import grizzled.slf4j.Logger
-
-case class MAPAtKConfig(
-  appid: Int = 0,
-  engineid: Int = 0,
-  evalid: Int = 0,
-  metricid: Int = 0,
-  algoid: Int = 0,
-  iteration: Int = 0,
-  splitset: String = "",
-  k: Int = 0,
-  goal: String = "",
-  debug: Boolean = false)
-
-/**
- * Mean Average Precision at K for Single Machine
- *
- * TODO: Eliminate use of Config object. Let scheduler handles it all.
- */
-object MAPAtK {
-  def main(args: Array[String]) {
-    val commonsConfig = new Config()
-    val engines = commonsConfig.getSettingsEngines
-    val parser = new scopt.OptionParser[MAPAtKConfig]("mapatk") {
-      head("mapatk")
-      opt[Int]("appid") required () action { (x, c) =>
-        c.copy(appid = x)
-      } text ("the App ID that this metric will be applied to")
-      opt[Int]("engineid") required () action { (x, c) =>
-        c.copy(engineid = x)
-      } validate { x =>
-        engines.get(x) map { _ => success } getOrElse failure(s"the Engine ID does not correspond to a valid Engine")
-      } text ("the Engine ID that this metric will be applied to")
-      opt[Int]("evalid") required () action { (x, c) =>
-        c.copy(evalid = x)
-      } text ("the OfflineEval ID that this metric will be applied to")
-      opt[Int]("metricid") required () action { (x, c) =>
-        c.copy(metricid = x)
-      } text ("the OfflineEvalMetric ID that this metric will be applied to")
-      opt[Int]("algoid") required () action { (x, c) =>
-        c.copy(algoid = x)
-      } text ("the Algo ID that this metric will be applied to")
-      opt[Int]("iteration") required () action { (x, c) =>
-        c.copy(iteration = x)
-      } text ("the iteration number (starts from 1 for the 1st iteration and then increment for later iterations)")
-      opt[String]("splitset") required () action { (x, c) =>
-        c.copy(splitset = x)
-      } validate { x =>
-        if (x == "validation" || x == "test") success else failure("--splitset must be either 'validation' or 'test'")
-      } text ("the split set (validation or test) that this metric will be run against")
-      opt[Int]("k") required () action { (x, c) =>
-        c.copy(k = x)
-      } text ("the k parameter for MAP@k")
-      opt[String]("goal") required () action { (x, c) =>
-        c.copy(goal = x)
-      } validate { x =>
-        x match {
-          case "view" | "conversion" | "like" | "rate3" | "rate4" | "rate5" => success
-          case _ => failure("invalid goal specified")
-        }
-      } text ("actions to be treated as relevant (valid values: view, conversion, like, rate3, rate4, rate5)")
-      opt[Unit]("debug") hidden () action { (x, c) =>
-        c.copy(debug = true)
-      } text ("debug mode")
-    }
-
-    parser.parse(args, MAPAtKConfig()) map { config =>
-      val logger = Logger(MAPAtK.getClass)
-      val u2iDb = if (config.splitset == "validation") commonsConfig.getAppdataValidationU2IActions else commonsConfig.getAppdataTestU2IActions
-      val resultsDb = commonsConfig.getSettingsOfflineEvalResults
-      val engine = engines.get(config.engineid).get
-
-      // Collect relevant items for all users and items
-      logger.info("Collecting relevance data...")
-      val u2i = u2iDb.getAllByAppid(config.evalid).toSeq filter { u2iAction =>
-        config.goal match {
-          case "view" | "conversion" | "like" => u2iAction.action == config.goal
-          case "rate3" => try { u2iAction.action == "rate" && u2iAction.v.get >= 3 } catch {
-            case e: Exception =>
-              logger.error(s"${u2iAction.uid}-${u2iAction.iid}: ${u2iAction.v} (${e.getMessage()})")
-              false
-          }
-          case "rate4" => try { u2iAction.action == "rate" && u2iAction.v.get >= 4 } catch {
-            case e: Exception =>
-              logger.error(s"${u2iAction.uid}-${u2iAction.iid}: ${u2iAction.v} (${e.getMessage()})")
-              false
-          }
-          case "rate5" => try { u2iAction.action == "rate" && u2iAction.v.get == 5 } catch {
-            case e: Exception =>
-              logger.error(s"${u2iAction.uid}-${u2iAction.iid}: ${u2iAction.v} (${e.getMessage()})")
-              false
-          }
-        }
-      }
-
-      val relevantItems = u2i.groupBy(_.uid).mapValues(_.map(_.iid).toSet)
-      val relevantUsers = if (engine.infoid == "itemsim") u2i.groupBy(_.iid).mapValues(_.map(_.uid).toSet) else Map[String, Set[String]]()
-
-      val relevantItemsPath = OfflineMetricFile(
-        commonsConfig.settingsLocalTempRoot,
-        config.appid,
-        config.engineid,
-        config.evalid,
-        config.metricid,
-        config.algoid,
-        "relevantItems.tsv")
-      val relevantItemsWriter = new BufferedWriter(new FileWriter(new File(relevantItemsPath)))
-      relevantItems.foreach {
-        case (uid, iids) =>
-          val iidsString = iids.mkString(",")
-          relevantItemsWriter.write(s"${uid}\t${iidsString}\n")
-      }
-      relevantItemsWriter.close()
-
-      logger.info(s"# users: ${relevantItems.size}")
-      if (engine.infoid == "itemsim") logger.info(s"# items: ${relevantUsers.size}")
-
-      // Read top-k list for every user
-      val topKFilePath = OfflineMetricFile(
-        commonsConfig.settingsLocalTempRoot,
-        config.appid,
-        config.engineid,
-        config.evalid,
-        config.metricid,
-        config.algoid,
-        "topKItems.tsv")
-      logger.info(s"Reading top-K list from: $topKFilePath")
-      val prefixSize = config.evalid.toString.length + 1
-
-      val topKItems: Map[String, Seq[String]] = engine.infoid match {
-        case "itemrec" => {
-          Source.fromFile(topKFilePath).getLines().toSeq.map(
-            _.split("\t")).groupBy(
-              _.apply(0)) map { t =>
-                (t._1.drop(prefixSize) -> t._2.apply(0).apply(1).split(",").toSeq.map(_.drop(prefixSize)))
-              }
-        }
-        case "itemsim" => {
-          /**
-           * topKItems.tsv for ItemSim
-           *     iid     simiid  score
-           *     i0      i1      3.2
-           *     i0      i4      2.5
-           *     i0      i5      1.4
-           *
-           * 1. Read all lines into a Seq[String].
-           * 2. Split by \t into Seq[Array[String]].
-           * 3. Group by first element (iid) into Map[String, Seq[Array[String]]].
-           * 4. Sort and filter Seq[Array[String]] to become Map[String, Seq[String]].
-           */
-          Source.fromFile(topKFilePath).getLines().toSeq.map(
-            _.split("\t")).groupBy(
-              _.apply(0)) map { t =>
-                (t._1.drop(prefixSize) -> t._2.sortBy(_.apply(2)).reverse.map(_.apply(1).drop(prefixSize)))
-              }
-        }
-      }
-
-      logger.info(s"Running MAP@${config.k} for ${engine.infoid} engine")
-      val mapAtK: Double = engine.infoid match {
-        case "itemrec" => {
-          val apAtK = topKItems map { t =>
-            val score = relevantItems.get(t._1) map { ri =>
-              averagePrecisionAtK(config.k, t._2, ri)
-            } getOrElse 0.0
-            (t._1, score)
-          }
-          val apAtKPath = OfflineMetricFile(
-            commonsConfig.settingsLocalTempRoot,
-            config.appid,
-            config.engineid,
-            config.evalid,
-            config.metricid,
-            config.algoid,
-            "apAtK.tsv")
-          val apAtKWriter = new BufferedWriter(new FileWriter(new File(apAtKPath)))
-          apAtK.foreach {
-            case (uid, score) =>
-              apAtKWriter.write(s"${uid}\t${score}\n")
-          }
-          apAtKWriter.close()
-
-          apAtK.map(_._2).sum / scala.math.min(topKItems.size, relevantItems.size)
-        }
-        case "itemsim" => {
-          val iapAtK = topKItems map { t =>
-            relevantUsers.get(t._1) map { ru =>
-              val apAtK = ru map { uid =>
-                relevantItems.get(uid) map { ri =>
-                  averagePrecisionAtK(config.k, t._2, ri)
-                } getOrElse 0.0
-              }
-              apAtK.sum / scala.math.min(ru.size, relevantItems.size)
-            } getOrElse 0.0
-          }
-          iapAtK.sum / scala.math.min(topKItems.size, relevantUsers.size)
-        }
-        case _ => 0.0
-      }
-
-      logger.info(s"MAP@${config.k} = $mapAtK. Saving results...")
-
-      resultsDb.save(OfflineEvalResult(
-        evalid = config.evalid,
-        metricid = config.metricid,
-        algoid = config.algoid,
-        score = mapAtK,
-        iteration = config.iteration,
-        splitset = config.splitset))
-
-      logger.info(s"MAP@${config.k} has run to completion")
-    }
-  }
-
-  /**
-   * Calculate the mean average precision @ k
-   *
-   * ap@k = sum(P(i)/min(m, k)) wher i=1 to k
-   * k is number of prediction to be retrieved.
-   * P(i) is the precision at position i of the top-K list
-   *    if the item at position i is relevant, then P(i) = (the number of releavent items up to that position in the top-k list / position)
-   *    if the item at position i is not relevant, then P(i)=0
-   * m is the number of relevant items for this user.
-   *
-   * @return the average precision at k
-   */
-  def averagePrecisionAtK(k: Int, predictedItems: Seq[String], relevantItems: Set[String]): Double = {
-    // supposedly the predictedItems.size should match k
-    // NOTE: what if predictedItems is less than k? use the avaiable items as k.
-    val n = scala.math.min(predictedItems.size, k)
-
-    // find if each element in the predictedItems is one of the relevant items
-    // if so, map to 1. else map to 0
-    // (0, 1, 0, 1, 1, 0, 0)
-    val relevantBinary: Seq[Int] = predictedItems.take(n).map { x => if (relevantItems(x)) 1 else 0 }
-    val pAtKNom = relevantBinary.scanLeft(0)(_ + _).drop(1).zip(relevantBinary).map(t => if (t._2 != 0) t._1 else 0).map(_.toDouble)
-    val pAtKDenom = 1 to relevantBinary.size
-    val pAtK = pAtKNom zip pAtKDenom map { t => t._1 / t._2 }
-    val apAtKDenom = scala.math.min(n, relevantItems.size)
-    if (apAtKDenom == 0) 0 else pAtK.sum / apAtKDenom
-  }
-}
diff --git a/process/engines/commons/evaluations/scala/map/src/test/resources/application.conf b/process/engines/commons/evaluations/scala/map/src/test/resources/application.conf
deleted file mode 100644
index 5744f1d..0000000
--- a/process/engines/commons/evaluations/scala/map/src/test/resources/application.conf
+++ /dev/null
@@ -1,22 +0,0 @@
-io.prediction.base=..
-
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.name=predictionio_mapatk_test
-
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.name=predictionio_appdata_mapatk_test
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.name=predictionio_training_appdata_mapatk_test
-
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.name=predictionio_validation_appdata_mapatk_test
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.name=predictionio_test_appdata_mapatk_test
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.name=predictionio_modeldata_mapatk_test
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.name=predictionio_training_modeldata_mapatk_test
diff --git a/process/engines/commons/evaluations/scala/map/src/test/scala/MAPAtKSpec.scala b/process/engines/commons/evaluations/scala/map/src/test/scala/MAPAtKSpec.scala
deleted file mode 100644
index e6c2994..0000000
--- a/process/engines/commons/evaluations/scala/map/src/test/scala/MAPAtKSpec.scala
+++ /dev/null
@@ -1,55 +0,0 @@
-package io.prediction.metrics.commons.map
-
-import com.mongodb.casbah.Imports._
-import org.specs2._
-import org.specs2.specification.Step
-
-class MAPAtKSpec extends Specification {
-  def is = s2"""
-
-  MAP@k Specification
-
-  Computing AP@k should be correct
-    Test 1 $apatk1
-    Test 2 $apatk2
-    Test 3 $apatk3
-    Test 4 $apatk4
-
-  At the end of test it should
-    clean up test database cleanup
-  """
-
-  def apatk1 =
-    MAPAtK.averagePrecisionAtK(
-      5,
-      Seq("foo", "bar", "abc", "def", "ghi"),
-      Set("bar", "def")) must_== 0.5
-
-  def apatk2 =
-    MAPAtK.averagePrecisionAtK(
-      10,
-      Seq("foo", "bar", "abc", "def", "ghi"),
-      Set("bar", "def")) must_== 0.5
-
-  def apatk3 =
-    MAPAtK.averagePrecisionAtK(
-      10,
-      Seq("a", "b", "c", "d", "e", "f", "g", "h"),
-      Set("a", "e", "c")) must_== 0.7555555555555555
-
-  def apatk4 =
-    MAPAtK.averagePrecisionAtK(
-      4,
-      Seq("a", "b", "c", "d", "e", "f", "g", "h"),
-      Set("a", "e", "c")) must_== 0.5555555555555555
-
-  def cleanup = {
-    Step(MongoConnection()("predictionio_mapatk_test").dropDatabase())
-    Step(MongoConnection()("predictionio_appdata_mapatk_test").dropDatabase())
-    Step(MongoConnection()("predictionio_modeldata_mapatk_test").dropDatabase())
-    Step(MongoConnection()("predictionio_training_appdata_mapatk_test").dropDatabase())
-    Step(MongoConnection()("predictionio_validation_appdata_mapatk_test").dropDatabase())
-    Step(MongoConnection()("predictionio_test_appdata_mapatk_test").dropDatabase())
-    Step(MongoConnection()("predictionio_training_modeldata_mapatk_test").dropDatabase())
-  }
-}
diff --git a/process/engines/commons/evaluations/scala/paramgen/build.sbt b/process/engines/commons/evaluations/scala/paramgen/build.sbt
deleted file mode 100644
index bc5f8a1..0000000
--- a/process/engines/commons/evaluations/scala/paramgen/build.sbt
+++ /dev/null
@@ -1,21 +0,0 @@
-import xerial.sbt.Pack._
-
-name := "predictionio-process-commons-evaluations-paramgen"
-
-libraryDependencies ++= Seq(
-  "ch.qos.logback" % "logback-classic" % "1.1.1",
-  "ch.qos.logback" % "logback-core" % "1.1.1",
-  "com.github.scopt" %% "scopt" % "3.2.0",
-  "org.clapper" %% "grizzled-slf4j" % "1.0.1")
-
-packSettings
-
-packJarNameConvention := "full"
-
-packExpandedClasspath := true
-
-packGenerateWindowsBatFile := false
-
-packMain := Map("paramgen" -> "io.prediction.evaluations.commons.paramgen.ParamGen")
-
-packJvmOpts := Map("paramgen" -> Common.packCommonJvmOpts)
diff --git a/process/engines/commons/evaluations/scala/paramgen/src/main/resources/application.conf b/process/engines/commons/evaluations/scala/paramgen/src/main/resources/application.conf
deleted file mode 100644
index c85803b..0000000
--- a/process/engines/commons/evaluations/scala/paramgen/src/main/resources/application.conf
+++ /dev/null
@@ -1,30 +0,0 @@
-# Used by PredictionIO Commons
-io.prediction.base=.
-
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.host=localhost
-io.prediction.commons.appdata.db.port=27017
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.host=localhost
-io.prediction.commons.appdata.test.db.port=27017
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.host=localhost
-io.prediction.commons.appdata.training.db.port=27017
-
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.host=localhost
-io.prediction.commons.appdata.validation.db.port=27017
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.host=localhost
-io.prediction.commons.modeldata.db.port=27017
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.host=localhost
-io.prediction.commons.modeldata.training.db.port=27017
-
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.host=localhost
-io.prediction.commons.settings.db.port=27017
diff --git a/process/engines/commons/evaluations/scala/paramgen/src/main/resources/logback.xml b/process/engines/commons/evaluations/scala/paramgen/src/main/resources/logback.xml
deleted file mode 100644
index f8dd5fb..0000000
--- a/process/engines/commons/evaluations/scala/paramgen/src/main/resources/logback.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<configuration>
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <encoder>
-      <pattern>%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>
-    </encoder>
-  </appender>
-  <root level="info">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
diff --git a/process/engines/commons/evaluations/scala/paramgen/src/main/scala/ParamGen.scala b/process/engines/commons/evaluations/scala/paramgen/src/main/scala/ParamGen.scala
deleted file mode 100644
index 8f46bcf..0000000
--- a/process/engines/commons/evaluations/scala/paramgen/src/main/scala/ParamGen.scala
+++ /dev/null
@@ -1,77 +0,0 @@
-package io.prediction.evaluations.commons.paramgen
-
-import io.prediction.commons._
-
-import grizzled.slf4j.Logger
-
-case class ParamGenConfig(
-  evalids: Seq[Int] = Seq(),
-  algoid: Int = 0,
-  loop: Int = 0,
-  paramsets: Int = 0)
-
-object ParamGen {
-  def main(args: Array[String]) {
-    val commonsConfig = new Config()
-    val algos = commonsConfig.getSettingsAlgos
-    val parser = new scopt.OptionParser[ParamGenConfig]("paramgen") {
-      head("paramgen")
-      opt[String]("evalids") required () action { (x, c) =>
-        c.copy(evalids = x.split(',').map(_.toInt))
-      } text ("comma-separated list of OfflineEval IDs that the parameter generator should consider")
-      opt[Int]("algoid") required () action { (x, c) =>
-        c.copy(algoid = x)
-      } validate { x =>
-        algos.get(x) map { _ => success } getOrElse failure(s"the Algo ID does not correspond to a valid Algo")
-      } text ("the Algo ID of the tune subject")
-      opt[Int]("loop") required () action { (x, c) =>
-        c.copy(loop = x)
-      } text ("the current loop number of this set of parameter")
-      opt[Int]("paramsets") required () action { (x, c) =>
-        c.copy(paramsets = x)
-      } text ("the number of parameter sets of this tuning")
-    }
-
-    parser.parse(args, ParamGenConfig()) map { config =>
-      val logger = Logger(ParamGen.getClass)
-
-      val evalids = config.evalids
-      val algoid = config.algoid
-      val loop = config.loop
-      val paramsets = config.paramsets
-      val algo = algos.get(algoid).get
-
-      /** Figure out what parameters can be tuned */
-      val paramsToTune = algo.params.keySet filter { k =>
-        algo.params.keySet.exists(e => s"${k}Min" == e) &&
-          algo.params.keySet.exists(e => s"${k}Max" == e)
-      }
-
-      for (i <- 1 to paramsets) {
-        /** Pick a random value between intervals */
-        val paramsValues = paramsToTune map { p =>
-          val minValue = algo.params(s"${p}Min")
-          val maxValue = algo.params(s"${p}Max")
-          algo.params(s"${p}Min") match {
-            case n: Int =>
-              val diff = maxValue.asInstanceOf[Int] - minValue.asInstanceOf[Int]
-              if (diff == 0)
-                p -> minValue.asInstanceOf[Int]
-              else
-                p -> (minValue.asInstanceOf[Int] + scala.util.Random.nextInt(diff))
-            case n: Double => p -> (minValue.asInstanceOf[Double] + scala.util.Random.nextDouble() * (maxValue.asInstanceOf[Double] - minValue.asInstanceOf[Double]))
-          }
-        }
-        evalids foreach { evalid =>
-          val algoToTune = algo.copy(
-            offlineevalid = Some(evalid.toInt),
-            loop = Some(loop),
-            params = algo.params ++ paramsValues.toMap,
-            paramset = Some(i),
-            status = "simeval")
-          algos.insert(algoToTune)
-        }
-      }
-    }
-  }
-}
diff --git a/process/engines/commons/evaluations/scala/topkitems/build.sbt b/process/engines/commons/evaluations/scala/topkitems/build.sbt
deleted file mode 100644
index b4690ae..0000000
--- a/process/engines/commons/evaluations/scala/topkitems/build.sbt
+++ /dev/null
@@ -1,21 +0,0 @@
-import xerial.sbt.Pack._
-
-name := "predictionio-process-commons-evaluations-topkitems"
-
-libraryDependencies ++= Seq(
-  "ch.qos.logback" % "logback-classic" % "1.1.1",
-  "ch.qos.logback" % "logback-core" % "1.1.1",
-  "com.github.scopt" %% "scopt" % "3.2.0",
-  "org.clapper" %% "grizzled-slf4j" % "1.0.1")
-
-packSettings
-
-packJarNameConvention := "full"
-
-packExpandedClasspath := true
-
-packGenerateWindowsBatFile := false
-
-packMain := Map("topk" -> "io.prediction.evaluations.commons.topkitems.TopKItems")
-
-packJvmOpts := Map("topk" -> Common.packCommonJvmOpts)
diff --git a/process/engines/commons/evaluations/scala/topkitems/src/main/resources/application.conf b/process/engines/commons/evaluations/scala/topkitems/src/main/resources/application.conf
deleted file mode 100644
index c85803b..0000000
--- a/process/engines/commons/evaluations/scala/topkitems/src/main/resources/application.conf
+++ /dev/null
@@ -1,30 +0,0 @@
-# Used by PredictionIO Commons
-io.prediction.base=.
-
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.host=localhost
-io.prediction.commons.appdata.db.port=27017
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.host=localhost
-io.prediction.commons.appdata.test.db.port=27017
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.host=localhost
-io.prediction.commons.appdata.training.db.port=27017
-
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.host=localhost
-io.prediction.commons.appdata.validation.db.port=27017
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.host=localhost
-io.prediction.commons.modeldata.db.port=27017
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.host=localhost
-io.prediction.commons.modeldata.training.db.port=27017
-
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.host=localhost
-io.prediction.commons.settings.db.port=27017
diff --git a/process/engines/commons/evaluations/scala/topkitems/src/main/resources/logback.xml b/process/engines/commons/evaluations/scala/topkitems/src/main/resources/logback.xml
deleted file mode 100644
index f8dd5fb..0000000
--- a/process/engines/commons/evaluations/scala/topkitems/src/main/resources/logback.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<configuration>
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <encoder>
-      <pattern>%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>
-    </encoder>
-  </appender>
-  <root level="info">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
diff --git a/process/engines/commons/evaluations/scala/topkitems/src/main/scala/TopKItems.scala b/process/engines/commons/evaluations/scala/topkitems/src/main/scala/TopKItems.scala
deleted file mode 100644
index d93a28f..0000000
--- a/process/engines/commons/evaluations/scala/topkitems/src/main/scala/TopKItems.scala
+++ /dev/null
@@ -1,135 +0,0 @@
-package io.prediction.evaluations.commons.topkitems
-
-import io.prediction.commons._
-import io.prediction.commons.filepath.OfflineMetricFile
-import io.prediction.output.itemrec.ItemRecAlgoOutput
-import io.prediction.output.itemsim.ItemSimAlgoOutput
-
-import grizzled.slf4j.Logger
-import java.io.{ File, PrintWriter }
-import scala.sys.process._
-
-case class TopKItemsConfig(
-  enginetype: String = "",
-  evalid: Int = 0,
-  metricid: Int = 0,
-  algoid: Int = 0,
-  hdfsroot: String = "",
-  k: Int = 0,
-  local: Boolean = false)
-
-object TopKItems {
-  def main(args: Array[String]) {
-    val parser = new scopt.OptionParser[TopKItemsConfig]("topk") {
-      head("topk")
-      opt[String]("enginetype") required () action { (x, c) =>
-        c.copy(enginetype = x)
-      } validate { x =>
-        x match {
-          case "itemrec" | "itemsim" => success
-          case _ => failure("--enginetype must be either itemrec or itemsim")
-        }
-      } text ("engine type (supported: itemrec, itemsim)")
-      opt[Int]("evalid") required () action { (x, c) =>
-        c.copy(evalid = x)
-      } text ("the OfflineEval ID that this metric will be applied to")
-      opt[Int]("metricid") required () action { (x, c) =>
-        c.copy(metricid = x)
-      } text ("the OfflineEvalMetric ID that this metric will be applied to")
-      opt[Int]("algoid") required () action { (x, c) =>
-        c.copy(algoid = x)
-      } text ("the Algo ID that this metric will be applied to")
-      opt[String]("hdfsroot") required () action { (x, c) =>
-        c.copy(hdfsroot = x)
-      } text ("the HDFS root directory location where temporary files will be stored")
-      opt[Int]("k") required () action { (x, c) =>
-        c.copy(k = x)
-      } text ("the k parameter for MAP@k")
-      opt[Unit]("local") action { (_, c) =>
-        c.copy(local = true)
-      } text ("run in local mode, i.e. do not copy the end result to HDFS")
-    }
-
-    parser.parse(args, TopKItemsConfig()) map { config =>
-      val logger = Logger(TopKItems.getClass)
-      val evalid = config.evalid
-      val algoid = config.algoid
-      val metricid = config.metricid
-      val hdfsRoot = config.hdfsroot
-      val k = config.k
-      val commonsConfig = new Config
-
-      /** Try search path if hadoop home is not set. */
-      val hadoopCommand = commonsConfig.settingsHadoopHome map { h => h + "/bin/hadoop" } getOrElse { "hadoop" }
-
-      val apps = commonsConfig.getSettingsApps
-      val engines = commonsConfig.getSettingsEngines
-      val algos = commonsConfig.getSettingsAlgos
-      val offlineEvals = commonsConfig.getSettingsOfflineEvals
-
-      val algo = algos.get(algoid).get
-      val offlineEval = offlineEvals.get(evalid).get
-      val engine = engines.get(offlineEval.engineid).get
-      val app = apps.get(engine.appid).get.copy(id = evalid)
-
-      val tmpFilePath = OfflineMetricFile(commonsConfig.settingsLocalTempRoot, engine.appid, engine.id, evalid, metricid, algoid, "topKItems.tsv")
-      val tmpFile = new File(tmpFilePath)
-      tmpFile.getParentFile().mkdirs()
-      logger.info(s"Dumping data to temporary file $tmpFilePath...")
-
-      config.enginetype match {
-        case "itemrec" => {
-          val users = commonsConfig.getAppdataTrainingUsers
-          var userCount = 0
-          printToFile(tmpFile) { p =>
-            users.getByAppid(evalid) foreach { u =>
-              val topKItems = ItemRecAlgoOutput.output(u.id, k, None, None, None, None)(app, engine, algo, Some(offlineEval))
-              if (topKItems.length > 0) {
-                userCount += 1
-                val topKString = topKItems.map(iid => s"${evalid}_${iid}").mkString(",")
-                p.println(s"${evalid}_${u.id}\t${topKString}")
-              }
-            }
-            logger.info(s"Found $userCount user(s) with non-zero top-K items")
-          }
-        }
-        case "itemsim" => {
-          val items = commonsConfig.getAppdataTrainingItems
-          val scores = Seq.range(1, k + 1).reverse
-          var itemCount = 0
-          printToFile(tmpFile) { p =>
-            items.getByAppid(evalid) foreach { i =>
-              val topKItems = ItemSimAlgoOutput.output(i.id, k, None, None, None, None)(app, engine, algo, Some(offlineEval))
-              if (topKItems.length > 0) {
-                itemCount += 1
-                topKItems.zip(scores) foreach { tuple =>
-                  val (iid, score) = tuple
-                  p.println(s"${evalid}_${i.id}\t${evalid}_${iid}\t${score}")
-                }
-              }
-            }
-            logger.info(s"Found ${itemCount} item(s) with non-zero top-K items")
-          }
-        }
-      }
-
-      if (!config.local) {
-        tmpFile.deleteOnExit
-        val hdfsFilePath = OfflineMetricFile(hdfsRoot, engine.appid, engine.id, evalid, metricid, algoid, "topKItems.tsv")
-        val rmCommand = s"$hadoopCommand fs -rm $hdfsFilePath"
-        logger.info(s"Executing '${rmCommand}'...")
-        rmCommand.!
-        val copyCommand = s"$hadoopCommand fs -copyFromLocal $tmpFilePath $hdfsFilePath"
-        logger.info(s"Executing '${copyCommand}'...")
-        copyCommand.!
-      }
-
-      logger.info("Finished")
-    }
-  }
-
-  def printToFile(f: java.io.File)(op: java.io.PrintWriter => Unit) {
-    val p = new java.io.PrintWriter(f)
-    try { op(p) } finally { p.close() }
-  }
-}
diff --git a/process/engines/commons/evaluations/scala/u2isplit/build.sbt b/process/engines/commons/evaluations/scala/u2isplit/build.sbt
deleted file mode 100644
index 247d641..0000000
--- a/process/engines/commons/evaluations/scala/u2isplit/build.sbt
+++ /dev/null
@@ -1,23 +0,0 @@
-import xerial.sbt.Pack._
-
-name := "predictionio-process-commons-evaluations-scala-u2isplit"
-
-libraryDependencies ++= Seq(
-  "ch.qos.logback" % "logback-classic" % "1.1.1",
-  "ch.qos.logback" % "logback-core" % "1.1.1",
-  "com.github.scopt" %% "scopt" % "3.2.0",
-  "org.clapper" %% "grizzled-slf4j" % "1.0.1",
-  "org.json4s" %% "json4s-native" % "3.2.7",
-  "org.json4s" %% "json4s-ext" % "3.2.7")
-
-packSettings
-
-packJarNameConvention := "full"
-
-packExpandedClasspath := true
-
-packGenerateWindowsBatFile := false
-
-packMain := Map("u2isplit" -> "io.prediction.evaluations.commons.u2isplit.U2ISplit")
-
-packJvmOpts := Map("u2isplit" -> Common.packCommonJvmOpts)
diff --git a/process/engines/commons/evaluations/scala/u2isplit/src/main/resources/application.conf b/process/engines/commons/evaluations/scala/u2isplit/src/main/resources/application.conf
deleted file mode 100644
index c85803b..0000000
--- a/process/engines/commons/evaluations/scala/u2isplit/src/main/resources/application.conf
+++ /dev/null
@@ -1,30 +0,0 @@
-# Used by PredictionIO Commons
-io.prediction.base=.
-
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.host=localhost
-io.prediction.commons.appdata.db.port=27017
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.host=localhost
-io.prediction.commons.appdata.test.db.port=27017
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.host=localhost
-io.prediction.commons.appdata.training.db.port=27017
-
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.host=localhost
-io.prediction.commons.appdata.validation.db.port=27017
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.host=localhost
-io.prediction.commons.modeldata.db.port=27017
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.host=localhost
-io.prediction.commons.modeldata.training.db.port=27017
-
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.host=localhost
-io.prediction.commons.settings.db.port=27017
diff --git a/process/engines/commons/evaluations/scala/u2isplit/src/main/resources/logback.xml b/process/engines/commons/evaluations/scala/u2isplit/src/main/resources/logback.xml
deleted file mode 100644
index f8dd5fb..0000000
--- a/process/engines/commons/evaluations/scala/u2isplit/src/main/resources/logback.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<configuration>
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <encoder>
-      <pattern>%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>
-    </encoder>
-  </appender>
-  <root level="info">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
diff --git a/process/engines/commons/evaluations/scala/u2isplit/src/main/scala/U2ISplit.scala b/process/engines/commons/evaluations/scala/u2isplit/src/main/scala/U2ISplit.scala
deleted file mode 100644
index 5be8004..0000000
--- a/process/engines/commons/evaluations/scala/u2isplit/src/main/scala/U2ISplit.scala
+++ /dev/null
@@ -1,220 +0,0 @@
-package io.prediction.evaluations.commons.u2isplit
-
-import io.prediction.commons.Config
-import io.prediction.commons.appdata.{ Item, Items, U2IAction, U2IActions, User, Users }
-import io.prediction.commons.filepath.{ U2ITrainingTestSplitFile }
-
-import java.io.{ BufferedWriter, File, FileWriter }
-import scala.io.Source
-
-import com.github.nscala_time.time.Imports._
-import grizzled.slf4j.Logger
-import org.json4s.native.Serialization
-
-case class U2ISplitConfig(
-  sequenceNum: Int = 0,
-  appid: Int = 0,
-  engineid: Int = 0,
-  evalid: Int = 0,
-  itypes: Option[Seq[String]] = None,
-  trainingpercent: Double = 0,
-  validationpercent: Double = 0,
-  testpercent: Double = 0,
-  timeorder: Boolean = false)
-
-/**
- * User-to-Item Action Splitter for Single Machine
- *
- * TODO: Eliminate use of Config object. Let scheduler handles it all.
- */
-object U2ISplit {
-  def main(args: Array[String]) {
-    val parser = new scopt.OptionParser[U2ISplitConfig]("u2isplit") {
-      head("u2isplit")
-      opt[Int]("sequenceNum") required () action { (x, c) =>
-        c.copy(sequenceNum = x)
-      } text ("the sequence number (starts from 1 for the 1st iteration and then increment for later iterations)")
-      opt[Int]("appid") required () action { (x, c) =>
-        c.copy(appid = x)
-      } text ("the App ID to split data from")
-      opt[Int]("engineid") required () action { (x, c) =>
-        c.copy(engineid = x)
-      } text ("the Engine ID to split data to")
-      opt[Int]("evalid") required () action { (x, c) =>
-        c.copy(evalid = x)
-      } text ("the OfflineEval ID to split data to")
-      opt[String]("itypes") action { (x, c) =>
-        c.copy(itypes = Some(x.split(',')))
-      } text ("restrict use of certain itypes (comma-separated, e.g. --itypes type1,type2)")
-      opt[Double]("trainingpercent") required () action { (x, c) =>
-        c.copy(trainingpercent = x)
-      } validate { x =>
-        if (x >= 0.01 && x <= 1) success else failure("--trainingpercent must be between 0.01 and 1")
-      } text ("size of training set (0.01 to 1)")
-      opt[Double]("validationpercent") required () action { (x, c) =>
-        c.copy(validationpercent = x)
-      } validate { x =>
-        if (x >= 0 && x <= 1) success else failure("--validationpercent must be between 0 and 1")
-      } text ("size of validation set (0 to 1)")
-      opt[Double]("testpercent") required () action { (x, c) =>
-        c.copy(testpercent = x)
-      } validate { x =>
-        if (x >= 0.01 && x <= 1) success else failure("--testpercent must be between 0.01 and 1")
-      } text ("size of test set (0.01 to 1)")
-      opt[Boolean]("timeorder") action { (x, c) =>
-        c.copy(timeorder = x)
-      } text ("set to true to sort the sampled results in time order before splitting (default to false)")
-      checkConfig { c =>
-        if (c.trainingpercent + c.validationpercent + c.testpercent > 1) failure("sum of training, validation, and test sizes must not exceed 1") else success
-      }
-    }
-
-    parser.parse(args, U2ISplitConfig()) map { config =>
-      val logger = Logger(U2ISplit.getClass)
-      val commonsConfig = new Config()
-      val usersFilePath = U2ITrainingTestSplitFile(
-        rootDir = commonsConfig.settingsLocalTempRoot,
-        appId = config.appid,
-        engineId = config.engineid,
-        evalId = config.evalid,
-        name = "users")
-      val usersFile = new File(usersFilePath)
-      val itemsFilePath = U2ITrainingTestSplitFile(
-        rootDir = commonsConfig.settingsLocalTempRoot,
-        appId = config.appid,
-        engineId = config.engineid,
-        evalId = config.evalid,
-        name = "items")
-      val itemsFile = new File(itemsFilePath)
-      val u2iActionsFilePath = U2ITrainingTestSplitFile(
-        rootDir = commonsConfig.settingsLocalTempRoot,
-        appId = config.appid,
-        engineId = config.engineid,
-        evalId = config.evalid,
-        name = "u2iActions")
-      val u2iActionsFile = new File(u2iActionsFilePath)
-      implicit val formats = org.json4s.DefaultFormats ++ org.json4s.ext.JodaTimeSerializers.all
-
-      // If this is the first iteration (sequence), take a snapshot of appdata
-      if (config.sequenceNum == 1) {
-        logger.info("This is the first iteration. Taking snapshot of app's data...")
-
-        val usersDb = commonsConfig.getAppdataUsers
-        val itemsDb = commonsConfig.getAppdataItems
-        val u2iDb = commonsConfig.getAppdataU2IActions
-
-        // Create the output directory if does not yet exist
-        val outputDir = new File(U2ITrainingTestSplitFile(
-          rootDir = commonsConfig.settingsLocalTempRoot,
-          appId = config.appid,
-          engineId = config.engineid,
-          evalId = config.evalid,
-          name = ""))
-        outputDir.mkdirs()
-
-        // Dump all users and fix ID prefices
-        logger.info(s"Writing to: $usersFilePath")
-        val usersWriter = new BufferedWriter(new FileWriter(usersFile))
-        usersDb.getByAppid(config.appid) foreach { user =>
-          usersWriter.write(Serialization.write(user.copy(appid = config.evalid)))
-          usersWriter.newLine()
-        }
-        usersWriter.close()
-
-        // Dump all items and fix ID prefices
-        // Filtered by itypes
-        logger.info(s"Writing to: $itemsFilePath")
-        val itemsWriter = new BufferedWriter(new FileWriter(itemsFile))
-        val validIids = collection.mutable.Set[String]()
-        config.itypes map { t =>
-          val engineItypes = t.toSet
-          itemsDb.getByAppid(config.appid) foreach { item =>
-            if (item.itypes.toSet.intersect(engineItypes).size > 0) {
-              itemsWriter.write(Serialization.write(item.copy(appid = config.evalid)))
-              itemsWriter.newLine()
-              validIids += item.id
-            }
-          }
-        } getOrElse {
-          itemsDb.getByAppid(config.appid) foreach { item =>
-            itemsWriter.write(Serialization.write(item.copy(appid = config.evalid)))
-            itemsWriter.newLine()
-            validIids += item.id
-          }
-        }
-        itemsWriter.close()
-
-        // Dump all actions and fix ID prefices
-        // Filtered by itypes
-        logger.info(s"Writing to: $u2iActionsFilePath")
-        var u2iCount = 0
-        val u2iActionsWriter = new BufferedWriter(new FileWriter(u2iActionsFile))
-        u2iDb.getAllByAppid(config.appid) foreach { u2iAction =>
-          if (validIids(u2iAction.iid)) {
-            u2iActionsWriter.write(Serialization.write(u2iAction.copy(appid = config.evalid)))
-            u2iActionsWriter.newLine()
-            u2iCount += 1
-          }
-        }
-        u2iActionsWriter.close()
-
-        // Save the count of U2I actions
-        val u2iActionsCountWriter = new BufferedWriter(new FileWriter(new File(u2iActionsFilePath + "Count")))
-        u2iActionsCountWriter.write(u2iCount.toString)
-        u2iActionsCountWriter.close()
-      }
-
-      // Read snapshots
-      logger.info("Reading snapshots...")
-
-      val trainingUsersDb = commonsConfig.getAppdataTrainingUsers
-      val trainingItemsDb = commonsConfig.getAppdataTrainingItems
-      val trainingU2iDb = commonsConfig.getAppdataTrainingU2IActions
-      val validationU2iDb = commonsConfig.getAppdataValidationU2IActions
-      val testU2iDb = commonsConfig.getAppdataTestU2IActions
-
-      val totalCount = Source.fromFile(new File(u2iActionsFilePath + "Count")).mkString.toInt
-      val evaluationCount = (math.floor((config.trainingpercent + config.validationpercent + config.testpercent) * totalCount)).toInt
-      val trainingCount = (math.floor(config.trainingpercent * totalCount)).toInt
-      val validationCount = (math.floor(config.validationpercent * totalCount)).toInt
-      val trainingValidationCount = trainingCount + validationCount
-      val testCount = evaluationCount - trainingValidationCount
-
-      logger.info(s"Reading from: $usersFilePath")
-      trainingUsersDb.deleteByAppid(config.evalid)
-      Source.fromFile(usersFile).getLines() foreach { userJson =>
-        trainingUsersDb.insert(Serialization.read[User](userJson))
-      }
-
-      logger.info(s"Reading from: $itemsFilePath")
-      trainingItemsDb.deleteByAppid(config.evalid)
-      Source.fromFile(itemsFile).getLines() foreach { itemJson =>
-        trainingItemsDb.insert(Serialization.read[Item](itemJson))
-      }
-
-      /**
-       * Perform itypes filtering at this point because itypes is an
-       * engine-specific parameter, and we want the split percentage to
-       * be relative to the total number of items that is valid for this
-       * particular engine.
-       */
-      logger.info(s"Reading from: $u2iActionsFilePath")
-      trainingU2iDb.deleteByAppid(config.evalid)
-      validationU2iDb.deleteByAppid(config.evalid)
-      testU2iDb.deleteByAppid(config.evalid)
-      val allU2iActions = Source.fromFile(u2iActionsFile).getLines().map(Serialization.read[U2IAction](_))
-      val unsortedEvalU2iActions = util.Random.shuffle(allU2iActions).take(evaluationCount)
-      val evalU2iActions = if (config.timeorder) unsortedEvalU2iActions.toSeq.sortWith(_.t + 0.seconds < _.t + 0.seconds) else unsortedEvalU2iActions.toSeq
-      var count = 0
-      evalU2iActions foreach { u2iAction =>
-        if (count < trainingCount)
-          trainingU2iDb.insert(u2iAction)
-        else if (count >= trainingCount && count < trainingValidationCount)
-          validationU2iDb.insert(u2iAction)
-        else
-          testU2iDb.insert(u2iAction)
-        count += 1
-      }
-    }
-  }
-}
diff --git a/process/engines/commons/evaluations/scala/u2itrainingtestsplit/build.sbt b/process/engines/commons/evaluations/scala/u2itrainingtestsplit/build.sbt
deleted file mode 100644
index 39dbe29..0000000
--- a/process/engines/commons/evaluations/scala/u2itrainingtestsplit/build.sbt
+++ /dev/null
@@ -1,21 +0,0 @@
-import xerial.sbt.Pack._
-
-name := "predictionio-process-commons-evaluations-scala-u2itrainingtestsplittime"
-
-libraryDependencies ++= Seq(
-  "ch.qos.logback" % "logback-classic" % "1.1.1",
-  "ch.qos.logback" % "logback-core" % "1.1.1",
-  "com.github.scopt" %% "scopt" % "3.2.0",
-  "org.clapper" %% "grizzled-slf4j" % "1.0.1")
-
-packSettings
-
-packJarNameConvention := "full"
-
-packExpandedClasspath := true
-
-packGenerateWindowsBatFile := false
-
-packMain := Map("u2itrainingtestsplit" -> "io.prediction.evaluations.commons.trainingtestsplit.U2ITrainingTestSplitTime")
-
-packJvmOpts := Map("u2itrainingtestsplit" -> Common.packCommonJvmOpts)
diff --git a/process/engines/commons/evaluations/scala/u2itrainingtestsplit/src/main/scala/U2ITrainingTestSplitTime.scala b/process/engines/commons/evaluations/scala/u2itrainingtestsplit/src/main/scala/U2ITrainingTestSplitTime.scala
deleted file mode 100644
index e5d07c4..0000000
--- a/process/engines/commons/evaluations/scala/u2itrainingtestsplit/src/main/scala/U2ITrainingTestSplitTime.scala
+++ /dev/null
@@ -1,151 +0,0 @@
-package io.prediction.evaluations.commons.trainingtestsplit
-
-import io.prediction.commons.filepath.U2ITrainingTestSplitFile
-
-import java.io.File
-import scala.io.Source
-import scala.sys.process._
-
-import grizzled.slf4j.Logger
-
-case class U2ITrainingTestSplitTimeConfig(
-  hadoop: String = "",
-  pdioEvalJar: String = "",
-  hdfsRoot: String = "",
-  localTempRoot: String = "",
-  appid: Int = 0,
-  engineid: Int = 0,
-  evalid: Int = 0,
-  sequenceNum: Int = 0)
-
-/**
- * Wrapper for Scalding U2ITrainingTestSplitTime job
- *
- * Args:
- * --hadoop <string> hadoop command
- * --pdioEvalJar <string> the name of the Scalding U2ITrainingTestSplit job jar
- * --sequenceNum. <int>. the sequence number (starts from 1 for the 1st iteration and then increment for later iterations)
- *
- * --dbType: <string> appdata DB type
- * --dbName: <string>
- * --dbHost: <string>. optional. (eg. "localhost")
- * --dbPort: <int>. optional. (eg. 27017)
- *
- * --training_dbType: <string> training_appadta DB type
- * --training_dbName: <string>
- * --training_dbHost: <string>. optional
- * --training_dbPort: <int>. optional
- *
- * --validation_dbType: <string> validation_appdata DB type
- * --validation_dbName: <string>
- * --validation_dbHost: <string>. optional
- * --validation_dbPort: <int>. optional
- *
- * --test_dbType: <string> test_appdata DB type
- * --test_dbName: <string>
- * --test_dbHost: <string>. optional
- * --test_dbPort: <int>. optional
- *
- * --hdfsRoot: <string>. Root directory of the HDFS
- *
- * --appid: <int>
- * --engineid: <int>
- * --evalid: <int>
- *
- * --itypes: <string separated by white space>. eg "--itypes type1 type2". If no --itypes specified, then ALL itypes will be used.
- *
- * --trainingPercent: <double> (0.01 to 1). training set percentage
- * --validationPercent: <dboule> (0.01 to 1). validation set percentage
- * --testPercent: <double> (0.01 to 1). test set percentage
- * --timeorder: <boolean>. Require total percentage < 1
- *
- */
-object U2ITrainingTestSplitTime {
-  def main(args: Array[String]) {
-    val parser = new scopt.OptionParser[U2ITrainingTestSplitTimeConfig]("u2itrainingtestsplit") {
-      head("u2itrainingtestsplit")
-      opt[String]("hadoop") required () action { (x, c) =>
-        c.copy(hadoop = x)
-      } text ("path to the 'hadoop' command")
-      opt[String]("pdioEvalJar") required () action { (x, c) =>
-        c.copy(pdioEvalJar = x)
-      } text ("path to PredictionIO Hadoop job JAR")
-      opt[String]("hdfsRoot") required () action { (x, c) =>
-        c.copy(hdfsRoot = x)
-      } text ("PredictionIO root path in HDFS")
-      opt[String]("localTempRoot") required () action { (x, c) =>
-        c.copy(localTempRoot = x)
-      } text ("local directory for temporary storage")
-      opt[Int]("appid") required () action { (x, c) =>
-        c.copy(appid = x)
-      } text ("the App ID of this offline evaluation")
-      opt[Int]("engineid") required () action { (x, c) =>
-        c.copy(engineid = x)
-      } text ("the Engine ID of this offline evaluation")
-      opt[Int]("evalid") required () action { (x, c) =>
-        c.copy(evalid = x)
-      } text ("the OfflineEval ID of this offline evaluation")
-      opt[Int]("sequenceNum") required () action { (x, c) =>
-        c.copy(sequenceNum = x)
-      } validate { x =>
-        if (x >= 1) success else failure("--sequenceNum must be >= 1")
-      } text ("sequence (iteration) number of the offline evaluation")
-      override def errorOnUnknownArgument = false
-    }
-    val logger = Logger(U2ITrainingTestSplitTime.getClass)
-
-    parser.parse(args, U2ITrainingTestSplitTimeConfig()) map { config =>
-      val hadoop = config.hadoop
-      val pdioEvalJar = config.pdioEvalJar
-      val hdfsRoot = config.hdfsRoot
-      val localTempRoot = config.localTempRoot
-      val appid = config.appid
-      val engineid = config.engineid
-      val evalid = config.evalid
-      val sequenceNum = config.sequenceNum
-      val argsString = args.mkString(" ")
-      val resplit = sequenceNum > 1
-
-      /** command */
-      if (!resplit) {
-        // prep
-        val splitPrepCmd = hadoop + " jar " + pdioEvalJar + " io.prediction.evaluations.scalding.commons.u2itrainingtestsplit.U2ITrainingTestSplitTimePrep " + argsString
-        executeCommandAndCheck(splitPrepCmd)
-      }
-
-      // copy the count to local tmp
-      val hdfsCountPath = U2ITrainingTestSplitFile(hdfsRoot, appid, engineid, evalid, "u2iCount.tsv")
-      val localCountPath = localTempRoot + "eval-" + evalid + "-u2iCount.tsv"
-      val localCountFile = new File(localCountPath)
-
-      // create parent dir
-      localCountFile.getParentFile().mkdirs()
-
-      // delete existing file first
-      if (localCountFile.exists()) localCountFile.delete()
-
-      // get the count from hdfs
-      val getHdfsCountCmd = hadoop + " fs -getmerge " + hdfsCountPath + " " + localCountPath
-      executeCommandAndCheck(getHdfsCountCmd)
-
-      // read the local file and get the count
-      val lines = Source.fromFile(localCountPath).getLines
-      if (lines.isEmpty) throw new RuntimeException(s"Count file $localCountPath is empty")
-
-      val count = lines.next
-
-      // split
-      val splitCmd = hadoop + " jar " + pdioEvalJar + " io.prediction.evaluations.scalding.commons.u2itrainingtestsplit.U2ITrainingTestSplitTime " + argsString + " --totalCount " + count
-      executeCommandAndCheck(splitCmd)
-
-      // delete local tmp file
-      logger.info(s"Deleting temporary file $localCountPath...")
-      localCountFile.delete()
-    }
-
-    def executeCommandAndCheck(cmd: String) = {
-      logger.info(s"Executing $cmd...")
-      if ((cmd.!) != 0) throw new RuntimeException(s"Failed to execute '$cmd'")
-    }
-  }
-}
diff --git a/process/engines/itemrec/algorithms/hadoop/cascading/popularrank/build.gradle b/process/engines/itemrec/algorithms/hadoop/cascading/popularrank/build.gradle
deleted file mode 100644
index a2cc5e7..0000000
--- a/process/engines/itemrec/algorithms/hadoop/cascading/popularrank/build.gradle
+++ /dev/null
@@ -1,33 +0,0 @@
-
-apply plugin: 'java'
-
-sourceCompatibility = '1.6'
-targetCompatibility = '1.6'
- 
-repositories {
-  mavenLocal()
-  mavenCentral()
-  mavenRepo name: 'conjars', url: 'http://conjars.org/repo/'
-}
-
-ext.cascadingVersion = '2.1.0'
-
-dependencies {
-  compile( group: 'cascading', name: 'cascading-core', version: cascadingVersion )
-  compile( group: 'cascading', name: 'cascading-hadoop', version: cascadingVersion )
-  compile 'commons-cli:commons-cli:1.2'
-  compile( group: 'org.apache.hadoop', name: 'hadoop-core', version: '1.2.1')
-}
-
-jar {
-  description = "Assembles a Hadoop ready jar file"
-  doFirst {
-    into( 'lib' ) {
-      from configurations.compile
-    }
-  }
-
-  manifest {
-    attributes( "Main-Class": "io/prediction/algorithms/cascading/itemrec/popularrank/PopularRankAlgo" )
-  }
-}
diff --git a/process/engines/itemrec/algorithms/hadoop/cascading/popularrank/src/main/java/io/prediction/algorithms/cascading/itemrec/popularrank/PopularRankAlgo.java b/process/engines/itemrec/algorithms/hadoop/cascading/popularrank/src/main/java/io/prediction/algorithms/cascading/itemrec/popularrank/PopularRankAlgo.java
deleted file mode 100644
index 2b55d76..0000000
--- a/process/engines/itemrec/algorithms/hadoop/cascading/popularrank/src/main/java/io/prediction/algorithms/cascading/itemrec/popularrank/PopularRankAlgo.java
+++ /dev/null
@@ -1,196 +0,0 @@
-package io.prediction.algorithms.cascading.itemrec.popularrank;
-
-import java.util.Properties;
-
-import cascading.flow.Flow;
-import cascading.flow.FlowDef;
-import cascading.flow.hadoop.HadoopFlowConnector;
-import cascading.operation.aggregator.Count;
-import cascading.operation.aggregator.First;
-import cascading.operation.regex.RegexFilter;
-import cascading.operation.Insert;
-import cascading.pipe.Every;
-import cascading.pipe.Each;
-import cascading.pipe.GroupBy;
-import cascading.pipe.HashJoin;
-import cascading.pipe.Pipe;
-import cascading.pipe.assembly.SumBy;
-import cascading.pipe.assembly.Retain;
-import cascading.pipe.assembly.Unique;
-import cascading.pipe.assembly.Rename;
-import cascading.pipe.joiner.LeftJoin;
-import cascading.property.AppProps;
-import cascading.scheme.Scheme;
-import cascading.scheme.hadoop.TextDelimited;
-import cascading.tap.Tap;
-import cascading.tap.SinkMode;
-import cascading.tap.hadoop.Hfs;
-import cascading.tuple.Fields;
-
-import org.apache.commons.cli.OptionBuilder;
-import org.apache.commons.cli.Options;
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.CommandLineParser;
-import org.apache.commons.cli.HelpFormatter;
-import org.apache.commons.cli.BasicParser;
-import org.apache.commons.cli.ParseException;
-
-/**
- * Example to demonstrate how to integrate custom algo.
- *
- * This examlpe algo simply recommends items based on popularity, which is determined by summing of all ratings.
- */
-public class PopularRankAlgo {
-
-  private static Option createRequiredArgOption(String optName, String argName, Object argType, String desc) {
-    Option opt = OptionBuilder.withArgName(argName)
-      .hasArg()
-      .isRequired()
-      .withType(argType)
-      .withDescription(desc)
-      .create(optName);
-
-    return opt;
-  }
-
-  public static void main( String[] args ) {
-
-    /* arguments */
-    String ratingsPath = "";
-    String itemRecScoresPath = "";
-    int numRecommendations = 0;
-    boolean unseenOnly = false;
-
-    // example param
-    int intParam = 0;
-    double doubleParam = 0;
-    String stringParam = "";
-
-    Options options = new Options();
-
-    Option inputOpt = createRequiredArgOption("input", "input file", String.class, 
-      "Input file path in tsv (tab delimited) format (uid iid rating).");
-    Option outputOpt = createRequiredArgOption("output", "input file", String.class,
-      "Output file path in tsv (tab delimited) format (uid iid score).");
-    Option numRecommendationsOpt = createRequiredArgOption("numRecommendations", "Int", Number.class,
-      "Number of recommendations.");
-    Option unseenOnlyOpt = createRequiredArgOption("unseenOnly", "true/false", String.class,
-      "Recommend unseen items only.");
-    Option intParamOpt = createRequiredArgOption("intParam", "Int", Number.class,
-      "Integer param example.");
-    Option doubleParamOpt = createRequiredArgOption("doubleParam", "Double", Number.class,
-      "Double param example.");
-    Option stringParamOpt = createRequiredArgOption("stringParam", "String", String.class,
-      "String param example.");
-
-    options.addOption( inputOpt );
-    options.addOption( outputOpt );
-    options.addOption( numRecommendationsOpt );
-    options.addOption( unseenOnlyOpt );
-    options.addOption( intParamOpt );
-    options.addOption( doubleParamOpt );
-    options.addOption( stringParamOpt );
-
-    CommandLineParser parser = new BasicParser();
-    try {
-      CommandLine line = parser.parse( options, args );
-
-      ratingsPath = (String) line.getParsedOptionValue( "input" );
-      itemRecScoresPath = (String) line.getParsedOptionValue( "output" );
-      numRecommendations = ((Number) line.getParsedOptionValue( "numRecommendations" )).intValue();
-      unseenOnly = Boolean.parseBoolean((String) line.getParsedOptionValue( "unseenOnly" ));
-      // example param
-      intParam = ((Number) line.getParsedOptionValue( "intParam" )).intValue();
-      doubleParam = ((Number) line.getParsedOptionValue( "doubleParam" )).doubleValue();
-      stringParam = (String) line.getParsedOptionValue( "stringParam" );
-
-      System.out.println("Going to run the job with following arguments...");
-      System.out.println("input: " + ratingsPath);
-      System.out.println("output: " + itemRecScoresPath);
-      System.out.println("numRecommendations: " + numRecommendations);
-      System.out.println("unseenOnly: " + unseenOnly);
-      System.out.println("intParam: " + intParam);
-      System.out.println("doubleParam: " + doubleParam);
-      System.out.println("stringParam: " + stringParam);
-      
-    } catch( Exception exp ) {
-      System.err.println( "Invalid arguments: " + exp.getMessage() );
-      HelpFormatter formatter = new HelpFormatter();
-      formatter.printHelp( "arguments", options );
-
-      System.exit(1);
-    }
-
-    /* cascading job */
-    Properties properties = new Properties();
-    AppProps.setApplicationJarClass( properties, PopularRankAlgo.class );
-    HadoopFlowConnector flowConnector = new HadoopFlowConnector( properties );
-
-    Fields ratingsFields = new Fields( "uid", "iid", "rating" );
-    Fields uid = new Fields( "uid" );
-    Fields iid = new Fields( "iid" );
-    Fields rating = new Fields( "rating" );
-    Fields score = new Fields( "score" );
-    Fields lhs_join = new Fields( "lhs_join" );
-    Fields rhs_join = new Fields( "rhs_join" );
-    Fields itemRecScoresFields = new Fields( "uid", "iid", "score" );
-
-    Tap ratingsTap = new Hfs( new TextDelimited( ratingsFields, "\t" ), ratingsPath );
-    Tap itemRecScoresTap = new Hfs( new TextDelimited( itemRecScoresFields, "\t" ), itemRecScoresPath, SinkMode.REPLACE );
-    //Mode REPLACE will delete/remove the resource before any attempts to write.
-    //Tap tempTap = new Hfs( new TextDelimited( true, "\t" ), itemRecScoresPath, SinkMode.REPLACE );
-    
-    Pipe ratingsPipe = new Pipe("ratingsPipe");
-
-    // get all uid from ratings
-    Pipe userPipe = new Pipe( "user", ratingsPipe );
-    userPipe = new Unique( userPipe, uid );
-    userPipe = new Retain(userPipe, uid );
-    userPipe = new Each( userPipe, new Insert( rhs_join, 1 ), Fields.ALL );
-
-    // add all rating for each item to determin popularity
-    Pipe popPipe = new Pipe( "pop", ratingsPipe );
-    popPipe = new SumBy( popPipe, iid, rating, score, long.class );
-    popPipe = new Each( popPipe, new Insert( lhs_join, 1 ), Fields.ALL );
-
-    // typical application has less user than item
-    Pipe scorePipe = new HashJoin( "score", popPipe, lhs_join, userPipe, rhs_join );
-    scorePipe = new Retain( scorePipe, itemRecScoresFields );
-
-    if (unseenOnly) {
-      // left join with rating again, keep those raings==0 (unseenOnly)
-      Fields uid_iid = new Fields( "uid", "iid" );
-      Fields uidR_iidR = new Fields( "uidR", "iidR" );
-
-      // if there are any actions for this uid_iid, it means the items have been seen.
-      // uniquify the ratingsPipe by uid_iid in case there are multiple actions on same items by the same user.
-      Pipe uniqueRatingsPipe = new Pipe( "uniqueRatingsPipe", ratingsPipe );
-      uniqueRatingsPipe = new Unique( uniqueRatingsPipe, uid_iid );
-      uniqueRatingsPipe = new Rename( uniqueRatingsPipe, uid_iid, uidR_iidR );
-
-      scorePipe = new HashJoin( "unseen", scorePipe, uid_iid, uniqueRatingsPipe, uidR_iidR, new LeftJoin() );
-      scorePipe = new Each( scorePipe, rating, new RegexFilter( "^$" ) );
-      scorePipe = new Retain( scorePipe, itemRecScoresFields );
-    }
-
-    // sort by score for each uid
-    Pipe recPipe = new Pipe( "rec", scorePipe );
-    // group by uid, sort by score (reverse sort = true)
-    recPipe = new GroupBy( recPipe, uid, score, true );
-    // only take first numRecommendations for each uid
-    recPipe = new Every( recPipe, new First(numRecommendations), Fields.RESULTS );
-
-    FlowDef flowDef = FlowDef.flowDef()
-      .setName( "CustomAlgo" )
-      .addSource( ratingsPipe, ratingsTap )
-      .addTailSink( recPipe, itemRecScoresTap );
-      //.addTailSink( recPipe, tempTap );
-
-    // write a DOT file and run the flow
-    Flow wcFlow = flowConnector.connect( flowDef );
-    //wcFlow.writeDOT( "dot/wc.dot" );
-    wcFlow.complete();
-
-  }
-}
diff --git a/process/engines/itemrec/algorithms/hadoop/scalding/build.sbt b/process/engines/itemrec/algorithms/hadoop/scalding/build.sbt
deleted file mode 100644
index 05f0959..0000000
--- a/process/engines/itemrec/algorithms/hadoop/scalding/build.sbt
+++ /dev/null
@@ -1,42 +0,0 @@
-import AssemblyKeys._ // put this at the top of the file
-
-name := "predictionio-process-itemrec-algorithms-hadoop-scalding"
-
-packageOptions += Package.ManifestAttributes(java.util.jar.Attributes.Name.MAIN_CLASS -> "com.twitter.scalding.Tool")
-
-parallelExecution in Test := false
-
-libraryDependencies ++= Seq(
-  "org.apache.hadoop" % "hadoop-core" % "1.0.4",
-  "com.twitter" %% "scalding-core" % "0.8.6")
-
-resolvers ++= Seq("Concurrent Maven Repo" at "http://conjars.org/repo")
-
-assemblySettings
-
-test in assembly := {}
-
-assembleArtifact in packageScala := true
-
-excludedJars in assembly <<= (fullClasspath in assembly) map { cp =>
-  val excludes = Set(
-    "jsp-api-2.1-6.1.14.jar",
-    "jsp-2.1-6.1.14.jar",
-    "jasper-compiler-5.5.12.jar",
-    "janino-2.5.16.jar",
-    "minlog-1.2.jar",
-    "hadoop-core-1.0.4.jar")
-  cp filter { jar => excludes(jar.data.getName)}
-}
-
-// Some of these files have duplicates, let's ignore:
-mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) =>
-  {
-    case s if s.endsWith(".class") => MergeStrategy.last
-    case s if s.endsWith("project.clj") => MergeStrategy.concat
-    case s if s.endsWith(".html") => MergeStrategy.last
-    case s if s.endsWith(".properties") => MergeStrategy.last
-    case s if s.endsWith(".xml") => MergeStrategy.last
-    case x => old(x)
-  }
-}
diff --git a/process/engines/itemrec/algorithms/hadoop/scalding/generic/src/main/scala/io/prediction/algorithms/scalding/itemrec/generic/DataPreparator.scala b/process/engines/itemrec/algorithms/hadoop/scalding/generic/src/main/scala/io/prediction/algorithms/scalding/itemrec/generic/DataPreparator.scala
deleted file mode 100644
index 28753cc..0000000
--- a/process/engines/itemrec/algorithms/hadoop/scalding/generic/src/main/scala/io/prediction/algorithms/scalding/itemrec/generic/DataPreparator.scala
+++ /dev/null
@@ -1,216 +0,0 @@
-package io.prediction.algorithms.scalding.itemrec.generic
-
-import com.twitter.scalding._
-
-import io.prediction.commons.scalding.appdata.{ Items, U2iActions }
-import io.prediction.commons.filepath.DataFile
-
-/**
- * Source: appdata DB (items, u2iActions)
- * Sink: selectedItems.tsv, ratings.tsv
- * Descripton:
- *   Generic data preparator. Read from appdata DB and store selected items
- *   and ratings into a file.
- *   (appdata store -> DataPreparator -> HDFS)
- *
- * Required args:
- * --dbType: <string> (eg. mongodb) (see --dbHost, --dbPort)
- * --dbName: <string> appdata database name. (eg predictionio_appdata, or predictionio_training_appdata)
- *
- * --hdfsRoot: <string>. Root directory of the HDFS
- *
- * --appid: <int>
- * --engineid: <int>
- * --algoid: <int>
- *
- * --viewParam: <string>. (number 1 to 5, or "ignore")
- * --likeParam: <string>
- * --dislikeParam: <string>
- * --conversionParam: <string>
- * --conflictParam: <string>. (latest/highest/lowest)
- *
- * Optional args:
- * --dbHost: <string> (eg. "127.0.0.1")
- * --dbPort: <int> (eg. 27017)
- *
- * --itypes: <string separated by white space>. eg "--itypes type1 type2". If no --itypes specified, then ALL itypes will be used.
- * --evalid: <int>. Offline Evaluation if evalid is specified
- * --debug: <String>. "test" - for testing purpose
- *
- * Example:
- * Batch:
- * scald.rb --hdfs-local io.prediction.algorithms.scalding.itemrec.generic.DataPreparator --dbType mongodb --dbName appdata --dbHost 127.0.0.1 --dbPort 27017 --hdfsRoot hdfs/predictionio/ --appid 34 --engineid 3 --algoid 9 --itypes t2 --viewParam 2 --likeParam 5 --dislikeParam 1 --conversionParam 4 --conflictParam latest
- *
- * Offline Eval:
- * scald.rb --hdfs-local io.prediction.algorithms.scalding.itemrec.generic.DataPreparator --dbType mongodb --dbName training_appdata --dbHost 127.0.0.1 --dbPort 27017 --hdfsRoot hdfs/predictionio/ --appid 34 --engineid 3 --algoid 9 --itypes t2 --viewParam 2 --likeParam 5 --dislikeParam 1 --conversionParam 4 --conflictParam latest --evalid 15
- *
- */
-class DataPreparator(args: Args) extends Job(args) {
-
-  /**
-   * parse arguments
-   */
-  val dbTypeArg = args("dbType")
-  val dbNameArg = args("dbName")
-  val dbHostArg = args.list("dbHost")
-  val dbPortArg = args.list("dbPort") map (x => x.toInt) // becomes Option[Int]
-
-  val hdfsRootArg = args("hdfsRoot")
-
-  val appidArg = args("appid").toInt
-  val engineidArg = args("engineid").toInt
-  val algoidArg = args("algoid").toInt
-  val evalidArg = args.optional("evalid") map (x => x.toInt)
-  val OFFLINE_EVAL = (evalidArg != None) // offline eval mode
-
-  val preItypesArg = args.list("itypes")
-  val itypesArg: Option[List[String]] = if (preItypesArg.mkString(",").length == 0) None else Option(preItypesArg)
-
-  // determine how to map actions to rating values
-  def getActionParam(name: String): Option[Int] = {
-    val actionParam: Option[Int] = args(name) match {
-      case "ignore" => None
-      case x => Some(x.toInt)
-    }
-    actionParam
-  }
-
-  val viewParamArg: Option[Int] = getActionParam("viewParam")
-  val likeParamArg: Option[Int] = getActionParam("likeParam")
-  val dislikeParamArg: Option[Int] = getActionParam("dislikeParam")
-  val conversionParamArg: Option[Int] = getActionParam("conversionParam")
-
-  // When there are conflicting actions, e.g. a user gives an item a rating 5 but later dislikes it,
-  // determine which action will be considered as final preference.
-  final val CONFLICT_LATEST: String = "latest" // use latest action
-  final val CONFLICT_HIGHEST: String = "highest" // use the one with highest score
-  final val CONFLICT_LOWEST: String = "lowest" // use the one with lowest score
-
-  val conflictParamArg: String = args("conflictParam")
-
-  // check if the conflictParam is valid
-  require(List(CONFLICT_LATEST, CONFLICT_HIGHEST, CONFLICT_LOWEST).contains(conflictParamArg), "conflict param " + conflictParamArg + " is not valid.")
-
-  val debugArg = args.list("debug")
-  val DEBUG_TEST = debugArg.contains("test") // test mode
-
-  /**
-   * constants
-   */
-
-  final val ACTION_RATE = "rate"
-  final val ACTION_LIKE = "like"
-  final val ACTION_DISLIKE = "dislike"
-  final val ACTION_VIEW = "view"
-  //final val ACTION_VIEWDETAILS = "viewDetails"
-  final val ACTION_CONVERSION = "conversion"
-
-  /**
-   * source
-   */
-  // get appdata
-  // NOTE: if OFFLINE_EVAL, read from training set, and use evalid as appid when read Items and U2iActions
-  val trainingAppid = if (OFFLINE_EVAL) evalidArg.get else appidArg
-
-  // get items data
-  val items = Items(appId = trainingAppid, itypes = itypesArg,
-    dbType = dbTypeArg, dbName = dbNameArg, dbHost = dbHostArg, dbPort = dbPortArg).readStartEndtime('iidx, 'itypes, 'starttime, 'endtime)
-
-  val u2i = U2iActions(appId = trainingAppid,
-    dbType = dbTypeArg, dbName = dbNameArg, dbHost = dbHostArg, dbPort = dbPortArg).readData('action, 'uid, 'iid, 't, 'v)
-
-  /**
-   * sink
-   */
-
-  // write ratings to a file
-  val ratingsSink = Tsv(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "ratings.tsv"))
-
-  val selectedItemsSink = Tsv(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "selectedItems.tsv"))
-
-  /**
-   * computation
-   */
-  u2i.joinWithSmaller('iid -> 'iidx, items) // only select actions of these items
-    .filter('action, 'v) { fields: (String, Option[String]) =>
-      val (action, v) = fields
-
-      val keepThis: Boolean = action match {
-        case ACTION_RATE => true
-        case ACTION_LIKE => (likeParamArg != None)
-        case ACTION_DISLIKE => (dislikeParamArg != None)
-        case ACTION_VIEW => (viewParamArg != None)
-        case ACTION_CONVERSION => (conversionParamArg != None)
-        case _ => {
-          assert(false, "Action type " + action + " in u2iActions appdata is not supported!")
-          false // all other unsupported actions
-        }
-      }
-      keepThis
-    }
-    .map(('action, 'v, 't) -> ('rating, 'tLong)) { fields: (String, Option[String], String) =>
-      val (action, v, t) = fields
-
-      // convert actions into rating value based on "action" and "v" fields
-      val rating: Int = action match {
-        case ACTION_RATE => try {
-          v.get.toInt
-        } catch {
-          case e: Exception => {
-            assert(false, s"Failed to convert v field ${v} to integer for ${action} action. Exception:" + e)
-            1
-          }
-        }
-        case ACTION_LIKE => likeParamArg.getOrElse {
-          assert(false, "Action type " + action + " should have been filtered out!")
-          1
-        }
-        case ACTION_DISLIKE => dislikeParamArg.getOrElse {
-          assert(false, "Action type " + action + " should have been filtered out!")
-          1
-        }
-        case ACTION_VIEW => viewParamArg.getOrElse {
-          assert(false, "Action type " + action + " should have been filtered out!")
-          1
-        }
-        case ACTION_CONVERSION => conversionParamArg.getOrElse {
-          assert(false, "Action type " + action + " should have been filtered out!")
-          1
-        }
-        case _ => { // all other unsupported actions
-          assert(false, "Action type " + action + " in u2iActions appdata is not supported!")
-          1
-        }
-      }
-
-      (rating, t.toLong)
-    }
-    .then(resolveConflict('uid, 'iid, 'tLong, 'rating, conflictParamArg) _)
-    .project('uid, 'iid, 'rating)
-    .write(ratingsSink)
-
-  // Also store the selected items into DataFile for later model construction usage.
-  items.mapTo(('iidx, 'itypes, 'starttime, 'endtime) -> ('iidx, 'itypes, 'starttime, 'endtime)) { fields: (String, List[String], Long, Option[Long]) =>
-    val (iidx, itypes, starttime, endtime) = fields
-
-    // NOTE: convert List[String] into comma-separated String
-    // NOTE: endtime is optional
-    (iidx, itypes.mkString(","), starttime, endtime.map(_.toString).getOrElse("PIO_NONE"))
-  }.write(selectedItemsSink)
-
-  /**
-   * function to resolve conflicting actions of same uid-iid pair.
-   */
-  def resolveConflict(uidField: Symbol, iidField: Symbol, tfield: Symbol, ratingField: Symbol, conflictSolution: String)(p: RichPipe): RichPipe = {
-
-    // NOTE: sortBy() sort from smallest to largest. use reverse to pick the largest one.
-    val dataPipe = conflictSolution match {
-      case CONFLICT_LATEST => p.groupBy(uidField, iidField) { _.sortBy(tfield).reverse.take(1) } // take latest one (largest t)
-      case CONFLICT_HIGHEST => p.groupBy(uidField, iidField) { _.sortBy(ratingField).reverse.take(1) } // take highest rating
-      case CONFLICT_LOWEST => p.groupBy(uidField, iidField) { _.sortBy(ratingField).take(1) } // take lowest rating
-    }
-
-    dataPipe
-  }
-
-}
diff --git a/process/engines/itemrec/algorithms/hadoop/scalding/generic/src/main/scala/io/prediction/algorithms/scalding/itemrec/generic/ModelConstructor.scala b/process/engines/itemrec/algorithms/hadoop/scalding/generic/src/main/scala/io/prediction/algorithms/scalding/itemrec/generic/ModelConstructor.scala
deleted file mode 100644
index e50502e..0000000
--- a/process/engines/itemrec/algorithms/hadoop/scalding/generic/src/main/scala/io/prediction/algorithms/scalding/itemrec/generic/ModelConstructor.scala
+++ /dev/null
@@ -1,119 +0,0 @@
-package io.prediction.algorithms.scalding.itemrec.generic
-
-import com.twitter.scalding._
-
-import io.prediction.commons.filepath.{ DataFile, AlgoFile }
-import io.prediction.commons.scalding.modeldata.ItemRecScores
-
-/**
- * Source:
- *   selectedItems.tsv
- *   itemRecScores.tsv
- * Sink:
- *   itemRecScores DB
- * Description:
- *   Read the itemRecScores.tsv and get additional attributes from selectedItems.tsv for each similiar items.
- *   Then write the result to model DB.
- *
- * Required args:
- * --dbType: <string> modeldata DB type (eg. mongodb) (see --dbHost, --dbPort)
- * --dbName: <string> (eg. predictionio_modeldata)
- *
- * --hdfsRoot: <string>. Root directory of the HDFS
- *
- * --appid: <int>
- * --engineid: <int>
- * --algoid: <int>
- * --modelSet: <boolean> (true/false). flag to indicate which set
- * --recommendationTime: <long> (eg. 9876543210). recommend items with starttime <= recommendationTime and endtime > recommendationTime
- *
- * Optionsl args:
- * --dbHost: <string> (eg. "127.0.0.1")
- * --dbPort: <int> (eg. 27017)
- *
- * --evalid: <int>. Offline Evaluation if evalid is specified
- * --debug: <String>. "test" - for testing purpose
- *
- * Example:
- * batch:
- * scald.rb --hdfs-local io.prediction.algorithms.scalding.itemrec.generic.ModelConstructor --dbType mongodb --dbName modeldata --dbHost 127.0.0.1 --dbPort 27017 --hdfsRoot hdfs/predictionio/ --appid 34 --engineid 3 --algoid 9 --modelSet false
- *
- * offline eval
- * scald.rb --hdfs-local io.prediction.algorithms.scalding.itemrec.generic.ModelConstructor --dbType file --dbName modeldata_path/ --hdfsRoot hdfs/predictionio/ --appid 34 --engineid 3 --algoid 9 --modelSet false --evalid 15
- */
-class ModelConstructor(args: Args) extends Job(args) {
-
-  /**
-   * parse args
-   */
-  val dbTypeArg = args("dbType")
-  val dbNameArg = args("dbName")
-  val dbHostArg = args.list("dbHost")
-  val dbPortArg = args.list("dbPort") map (x => x.toInt)
-
-  val hdfsRootArg = args("hdfsRoot")
-
-  val appidArg = args("appid").toInt
-  val engineidArg = args("engineid").toInt
-  val algoidArg = args("algoid").toInt
-  val evalidArg = args.optional("evalid") map (x => x.toInt)
-  val OFFLINE_EVAL = (evalidArg != None) // offline eval mode
-
-  val debugArg = args.list("debug")
-  val DEBUG_TEST = debugArg.contains("test") // test mode
-
-  val modelSetArg = args("modelSet").toBoolean
-  val recommendationTimeArg = args("recommendationTime").toLong
-
-  /**
-   * input
-   */
-  val score = Tsv(AlgoFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "itemRecScores.tsv")).read
-    .mapTo((0, 1, 2) -> ('uid, 'iid, 'score)) { fields: (String, String, Double) => fields }
-
-  val items = Tsv(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "selectedItems.tsv")).read
-    .mapTo((0, 1, 2, 3) -> ('iidx, 'itypes, 'starttime, 'endtime)) { fields: (String, String, Long, String) =>
-      val (iidx, itypes, starttime, endtime) = fields // itypes are comma-separated String
-
-      val endtimeOpt: Option[Long] = endtime match {
-        case "PIO_NONE" => None
-        case x: String => {
-          try {
-            Some(x.toLong)
-          } catch {
-            case e: Exception => {
-              assert(false, s"Failed to convert ${x} to Long. Exception: " + e)
-              Some(0)
-            }
-          }
-        }
-      }
-
-      (iidx, itypes.split(",").toList, starttime, endtimeOpt)
-    }
-
-  /**
-   * process & output
-   */
-  val p = score.joinWithSmaller('iid -> 'iidx, items) // get items info for each iid
-    .filter('starttime, 'endtime) { fields: (Long, Option[Long]) =>
-      val (starttimeI, endtimeI) = fields
-
-      val keepThis: Boolean = (starttimeI, endtimeI) match {
-        case (start, None) => (recommendationTimeArg >= start)
-        case (start, Some(end)) => ((recommendationTimeArg >= start) && (recommendationTimeArg < end))
-        case _ => {
-          assert(false, s"Unexpected item starttime ${starttimeI} and endtime ${endtimeI}")
-          false
-        }
-      }
-      keepThis
-    }
-    .project('uid, 'iid, 'score, 'itypes)
-    .groupBy('uid) { _.sortBy('score).reverse.toList[(String, Double, List[String])](('iid, 'score, 'itypes) -> 'iidsList) }
-
-  val src = ItemRecScores(dbType = dbTypeArg, dbName = dbNameArg, dbHost = dbHostArg, dbPort = dbPortArg, algoid = algoidArg, modelset = modelSetArg)
-
-  p.then(src.writeData('uid, 'iidsList, algoidArg, modelSetArg) _)
-
-}
diff --git a/process/engines/itemrec/algorithms/hadoop/scalding/generic/src/test/scala/io/prediction/algorithms/scalding/itemrec/generic/DataPreparatorTest.scala b/process/engines/itemrec/algorithms/hadoop/scalding/generic/src/test/scala/io/prediction/algorithms/scalding/itemrec/generic/DataPreparatorTest.scala
deleted file mode 100644
index 6e91a76..0000000
--- a/process/engines/itemrec/algorithms/hadoop/scalding/generic/src/test/scala/io/prediction/algorithms/scalding/itemrec/generic/DataPreparatorTest.scala
+++ /dev/null
@@ -1,414 +0,0 @@
-package io.prediction.algorithms.scalding.itemrec.generic
-
-import org.specs2.mutable._
-
-import com.twitter.scalding._
-
-import io.prediction.commons.scalding.appdata.{ Items, U2iActions }
-import io.prediction.commons.filepath.DataFile
-
-class DataPreparatorTest extends Specification with TupleConversions {
-
-  val Rate = "rate"
-  val Like = "like"
-  val Dislike = "dislike"
-  val View = "view"
-  //val ViewDetails = "viewDetails"
-  val Conversion = "conversion"
-
-  val appid = 2
-
-  def test(itypes: List[String], params: Map[String, String],
-    items: List[(String, String, String, String, String, String)], // id, itypes, appid, starttime, ct, endtime
-    u2iActions: List[(String, String, String, String, String)],
-    ratings: List[(String, String, Int)],
-    selectedItems: List[(String, String, String, String)] // id, itypes, starttime, endtime
-    ) = {
-
-    val dbType = "file"
-    val dbName = "testpath/"
-    val dbHost = Seq() //Option("testhost")
-    val dbPort = Seq() //Option(27017)
-    val hdfsRoot = "testroot/"
-
-    JobTest("io.prediction.algorithms.scalding.itemrec.generic.DataPreparator")
-      .arg("dbType", dbType)
-      .arg("dbName", dbName)
-      //.arg("dbHost", dbHost.get)
-      //.arg("dbPort", dbPort.get.toString)
-      .arg("hdfsRoot", hdfsRoot)
-      .arg("appid", appid.toString)
-      .arg("engineid", "4")
-      .arg("algoid", "5")
-      .arg("itypes", itypes)
-      .arg("viewParam", params("viewParam"))
-      .arg("likeParam", params("likeParam"))
-      .arg("dislikeParam", params("dislikeParam"))
-      .arg("conversionParam", params("conversionParam"))
-      .arg("conflictParam", params("conflictParam"))
-      //.arg("debug", List("test")) // NOTE: test mode
-      .source(Items(appId = appid, itypes = Some(itypes), dbType = dbType, dbName = dbName, dbHost = dbHost, dbPort = dbPort).getSource, items)
-      .source(U2iActions(appId = appid, dbType = dbType, dbName = dbName, dbHost = dbHost, dbPort = dbPort).getSource, u2iActions)
-      .sink[(String, String, Int)](Tsv(DataFile(hdfsRoot, 2, 4, 5, None, "ratings.tsv"))) { outputBuffer =>
-        "correctly process and write data to ratings.tsv" in {
-          outputBuffer.toList must containTheSameElementsAs(ratings)
-        }
-      }
-      .sink[(String, String, String, String)](Tsv(DataFile(hdfsRoot, 2, 4, 5, None, "selectedItems.tsv"))) { outputBuffer =>
-        "correctly write selectedItems.tsv" in {
-          outputBuffer.toList must containTheSameElementsAs(selectedItems)
-        }
-      }
-      .run
-      .finish
-
-  }
-
-  /** no itypes specified */
-  def testWithoutItypes(params: Map[String, String],
-    items: List[(String, String, String, String, String, String)], // id, itypes, appid, starttime, ct, endtime
-    u2iActions: List[(String, String, String, String, String)],
-    ratings: List[(String, String, Int)],
-    selectedItems: List[(String, String, String, String)] // id, itypes, starttime, endtime
-    ) = {
-
-    val dbType = "file"
-    val dbName = "testpath/"
-    val dbHost = Seq() //Option("testhost")
-    val dbPort = Seq() //Option(27017)
-    val hdfsRoot = "testroot/"
-
-    JobTest("io.prediction.algorithms.scalding.itemrec.generic.DataPreparator")
-      .arg("dbType", dbType)
-      .arg("dbName", dbName)
-      //.arg("dbHost", dbHost.get)
-      //.arg("dbPort", dbPort.get.toString)
-      .arg("hdfsRoot", hdfsRoot)
-      .arg("appid", appid.toString)
-      .arg("engineid", "4")
-      .arg("algoid", "5")
-      //.arg("itypes", itypes) // NOTE: no itypes args!
-      .arg("viewParam", params("viewParam"))
-      .arg("likeParam", params("likeParam"))
-      .arg("dislikeParam", params("dislikeParam"))
-      .arg("conversionParam", params("conversionParam"))
-      .arg("conflictParam", params("conflictParam"))
-      //.arg("debug", List("test")) // NOTE: test mode
-      .source(Items(appId = appid, itypes = None, dbType = dbType, dbName = dbName, dbHost = dbHost, dbPort = dbPort).getSource, items)
-      .source(U2iActions(appId = appid, dbType = dbType, dbName = dbName, dbHost = dbHost, dbPort = dbPort).getSource, u2iActions)
-      .sink[(String, String, Int)](Tsv(DataFile(hdfsRoot, 2, 4, 5, None, "ratings.tsv"))) { outputBuffer =>
-        "correctly process and write data to ratings.tsv" in {
-          outputBuffer.toList must containTheSameElementsAs(ratings)
-        }
-      }
-      .sink[(String, String, String, String)](Tsv(DataFile(hdfsRoot, 2, 4, 5, None, "selectedItems.tsv"))) { outputBuffer =>
-        "correctly write selectedItems.tsv" in {
-          outputBuffer.toList must containTheSameElementsAs(selectedItems)
-        }
-      }
-      .run
-      .finish
-
-  }
-
-  val noEndtime = "PIO_NONE"
-  /**
-   * Test 1. basic. Rate actions only without conflicts
-   */
-  val test1AllItypes = List("t1", "t2", "t3", "t4")
-  val test1ItemsMap = Map(
-    // id, itypes, appid, starttime, ct, endtime
-    "i0" -> ("i0", "t1,t2,t3", appid.toString, "12345", "12346", noEndtime),
-    "i1" -> ("i1", "t2,t3", appid.toString, "12347", "12348", noEndtime),
-    "i2" -> ("i2", "t4", appid.toString, "12349", "12350", noEndtime),
-    "i3" -> ("i3", "t3,t4", appid.toString, "12351", "12352", noEndtime))
-
-  val test1Items = List(
-    test1ItemsMap("i0"),
-    test1ItemsMap("i1"),
-    test1ItemsMap("i2"),
-    test1ItemsMap("i3"))
-
-  def genSelectedItems(items: List[(String, String, String, String, String, String)]) = {
-    items map { x =>
-      val (id, itypes, appid, starttime, ct, endtime) = x
-      (id, itypes, starttime, endtime)
-    }
-  }
-
-  val test1U2i = List(
-    (Rate, "u0", "i0", "123450", "3"),
-    (Rate, "u0", "i1", "123457", "1"),
-    (Rate, "u0", "i2", "123458", "4"),
-    (Rate, "u0", "i3", "123459", "2"),
-    (Rate, "u1", "i0", "123457", "5"),
-    (Rate, "u1", "i1", "123458", "2"))
-
-  val test1Ratings = List(
-    ("u0", "i0", 3),
-    ("u0", "i1", 1),
-    ("u0", "i2", 4),
-    ("u0", "i3", 2),
-    ("u1", "i0", 5),
-    ("u1", "i1", 2))
-
-  val test1Params: Map[String, String] = Map("viewParam" -> "3", "likeParam" -> "4", "dislikeParam" -> "1", "conversionParam" -> "5",
-    "conflictParam" -> "latest")
-
-  "itemrec.generic DataPreparator with only rate actions, all itypes, no conflict" should {
-    test(test1AllItypes, test1Params, test1Items, test1U2i, test1Ratings, genSelectedItems(test1Items))
-  }
-
-  "itemrec.generic DataPreparator with only rate actions, no itypes specified, no conflict" should {
-    testWithoutItypes(test1Params, test1Items, test1U2i, test1Ratings, genSelectedItems(test1Items))
-  }
-
-  /**
-   * Test 2. rate actions only with conflicts
-   */
-  val test2AllItypes = List("t1", "t2", "t3", "t4")
-  val test2ItemsMap = Map(
-    // id, itypes, appid, starttime, ct, endtime
-    "i0" -> ("i0", "t1,t2,t3", appid.toString, "12345", "12346", noEndtime),
-    "i1" -> ("i1", "t2,t3", appid.toString, "12347", "12348", noEndtime),
-    "i2" -> ("i2", "t4", appid.toString, "12349", "12350", noEndtime),
-    "i3" -> ("i3", "t3,t4", appid.toString, "12351", "12352", noEndtime))
-
-  val test2Items = List(
-    test2ItemsMap("i0"),
-    test2ItemsMap("i1"),
-    test2ItemsMap("i2"),
-    test2ItemsMap("i3"))
-
-  val test2U2i = List(
-    (Rate, "u0", "i0", "123448", "3"),
-    (Rate, "u0", "i0", "123449", "4"), // highest
-    (Rate, "u0", "i0", "123451", "2"), // latest
-    (Rate, "u0", "i0", "123450", "1"), // lowest
-
-    (Rate, "u0", "i1", "123456", "1"), // lowest
-    (Rate, "u0", "i1", "123457", "2"),
-    (Rate, "u0", "i1", "123458", "3"), // latest, highest
-
-    (Rate, "u0", "i2", "123461", "2"), // latest, lowest
-    (Rate, "u0", "i2", "123459", "3"),
-    (Rate, "u0", "i2", "123460", "5"), // highest
-
-    (Rate, "u0", "i3", "123459", "2"),
-    (Rate, "u1", "i0", "123457", "5"),
-
-    (Rate, "u1", "i1", "123458", "3"), // lowest
-    (Rate, "u1", "i1", "123459", "4"), // highest
-    (Rate, "u1", "i1", "123460", "3")) // latest, lowest
-
-  val test2RatingsLatest = List(
-    ("u0", "i0", 2),
-    ("u0", "i1", 3),
-    ("u0", "i2", 2),
-    ("u0", "i3", 2),
-    ("u1", "i0", 5),
-    ("u1", "i1", 3))
-
-  val test2RatingsHighest = List(
-    ("u0", "i0", 4),
-    ("u0", "i1", 3),
-    ("u0", "i2", 5),
-    ("u0", "i3", 2),
-    ("u1", "i0", 5),
-    ("u1", "i1", 4))
-
-  val test2RatingsLowest = List(
-    ("u0", "i0", 1),
-    ("u0", "i1", 1),
-    ("u0", "i2", 2),
-    ("u0", "i3", 2),
-    ("u1", "i0", 5),
-    ("u1", "i1", 3))
-
-  val test2Itypes_t1t4 = List("t1", "t4")
-  val test2Items_t1t4 = List(
-    test2ItemsMap("i0"),
-    test2ItemsMap("i2"),
-    test2ItemsMap("i3"))
-  val test2RatingsHighest_t1t4 = List(
-    ("u0", "i0", 4),
-    ("u0", "i2", 5),
-    ("u0", "i3", 2),
-    ("u1", "i0", 5))
-
-  val test2Params: Map[String, String] = Map("viewParam" -> "3", "likeParam" -> "4", "dislikeParam" -> "1", "conversionParam" -> "5",
-    "conflictParam" -> "latest")
-  val test2ParamsHighest = test2Params + ("conflictParam" -> "highest")
-  val test2ParamsLowest = test2Params + ("conflictParam" -> "lowest")
-
-  "itemrec.generic DataPreparator with only rate actions, all itypes, conflict=latest" should {
-    test(test2AllItypes, test2Params, test2Items, test2U2i, test2RatingsLatest, genSelectedItems(test2Items))
-  }
-
-  "itemrec.generic DataPreparator with only rate actions, all itypes, conflict=highest" should {
-    test(test2AllItypes, test2ParamsHighest, test2Items, test2U2i, test2RatingsHighest, genSelectedItems(test2Items))
-  }
-
-  "itemrec.generic DataPreparator with only rate actions, all itypes, conflict=lowest" should {
-    test(test2AllItypes, test2ParamsLowest, test2Items, test2U2i, test2RatingsLowest, genSelectedItems(test2Items))
-  }
-
-  "itemrec.generic DataPreparator with only rate actions, some itypes, conflict=highest" should {
-    test(test2Itypes_t1t4, test2ParamsHighest, test2Items, test2U2i, test2RatingsHighest_t1t4, genSelectedItems(test2Items_t1t4))
-  }
-
-  /**
-   * Test 3. Different Actions without conflicts
-   */
-  val test3AllItypes = List("t1", "t2", "t3", "t4")
-  val test3ItemsMap = Map(
-    // id, itypes, appid, starttime, ct, endtime
-    "i0" -> ("i0", "t1,t2,t3", appid.toString, "12345", "12346", "56789"),
-    "i1" -> ("i1", "t2,t3", appid.toString, "12347", "12348", noEndtime),
-    "i2" -> ("i2", "t4", appid.toString, "12349", "12350", "56790"),
-    "i3" -> ("i3", "t3,t4", appid.toString, "12351", "12352", noEndtime))
-
-  val test3Items = List(
-    test3ItemsMap("i0"),
-    test3ItemsMap("i1"),
-    test3ItemsMap("i2"),
-    test3ItemsMap("i3"))
-
-  val test3U2i = List(
-    (Rate, "u0", "i0", "123450", "4"),
-    (Like, "u0", "i1", "123457", "PIO_NONE"),
-    (Dislike, "u0", "i2", "123458", "PIO_NONE"),
-    (View, "u0", "i3", "123459", "PIO_NONE"), // NOTE: assume v field won't be missing
-    (Rate, "u1", "i0", "123457", "2"),
-    (Conversion, "u1", "i1", "123458", "PIO_NONE"))
-
-  val test3Ratings = List(
-    ("u0", "i0", 4),
-    ("u0", "i1", 4),
-    ("u0", "i2", 2),
-    ("u0", "i3", 1),
-    ("u1", "i0", 2),
-    ("u1", "i1", 5))
-
-  val test3Params: Map[String, String] = Map("viewParam" -> "1", "likeParam" -> "4", "dislikeParam" -> "2", "conversionParam" -> "5",
-    "conflictParam" -> "latest")
-
-  "itemrec.generic DataPreparator with only all actions, all itypes, no conflict" should {
-    test(test3AllItypes, test3Params, test3Items, test3U2i, test3Ratings, genSelectedItems(test3Items))
-  }
-
-  /**
-   * test 4. Different Actions with conflicts
-   */
-  val test4Params: Map[String, String] = Map("viewParam" -> "2", "likeParam" -> "5", "dislikeParam" -> "1", "conversionParam" -> "4",
-    "conflictParam" -> "latest")
-
-  val test4AllItypes = List("t1", "t2", "t3", "t4")
-  val test4ItemsMap = Map(
-    // id, itypes, appid, starttime, ct, endtime
-    "i0" -> ("i0", "t1,t2,t3", appid.toString, "12345", "12346", "56789"),
-    "i1" -> ("i1", "t2,t3", appid.toString, "12347", "12348", noEndtime),
-    "i2" -> ("i2", "t4", appid.toString, "12349", "12350", "56790"),
-    "i3" -> ("i3", "t3,t4", appid.toString, "12351", "12352", noEndtime))
-
-  val test4Items = List(
-    test4ItemsMap("i0"),
-    test4ItemsMap("i1"),
-    test4ItemsMap("i2"),
-    test4ItemsMap("i3"))
-
-  val test4U2i = List(
-    (Rate, "u0", "i0", "123448", "3"),
-    (View, "u0", "i0", "123449", "PIO_NONE"), // lowest (2)
-    (Like, "u0", "i0", "123451", "PIO_NONE"), // latest, highest (5)
-    (Conversion, "u0", "i0", "123450", "PIO_NONE"),
-
-    (Rate, "u0", "i1", "123456", "1"), // lowest
-    (Rate, "u0", "i1", "123457", "4"), // highest
-    (View, "u0", "i1", "123458", "PIO_NONE"), // latest (2)
-
-    (Conversion, "u0", "i2", "123461", "PIO_NONE"), // latest, highest  (4)
-    (Rate, "u0", "i2", "123459", "3"),
-    (View, "u0", "i2", "123460", "PIO_NONE"), // lowest
-
-    (Rate, "u0", "i3", "123459", "2"),
-    (View, "u1", "i0", "123457", "PIO_NONE"), // (2)
-
-    (Rate, "u1", "i1", "123458", "5"), // highest
-    (Conversion, "u1", "i1", "123459", "PIO_NONE"), // (4)
-    (Dislike, "u1", "i1", "123460", "PIO_NONE")) // latest, lowest (1)
-
-  val test4RatingsLatest = List(
-    ("u0", "i0", 5),
-    ("u0", "i1", 2),
-    ("u0", "i2", 4),
-    ("u0", "i3", 2),
-    ("u1", "i0", 2),
-    ("u1", "i1", 1))
-
-  "itemrec.generic DataPreparator with all actions, all itypes, and conflicts=latest" should {
-    test(test4AllItypes, test4Params, test4Items, test4U2i, test4RatingsLatest, genSelectedItems(test4Items))
-  }
-
-  val test4ParamsIgnoreView = test4Params + ("viewParam" -> "ignore")
-
-  val test4RatingsIgnoreViewLatest = List(
-    ("u0", "i0", 5),
-    ("u0", "i1", 4),
-    ("u0", "i2", 4),
-    ("u0", "i3", 2),
-    ("u1", "i1", 1))
-
-  "itemrec.generic DataPreparator with all actions, all itypes, ignore View actions and conflicts=latest" should {
-    test(test4AllItypes, test4ParamsIgnoreView, test4Items, test4U2i, test4RatingsIgnoreViewLatest, genSelectedItems(test4Items))
-  }
-
-  // note: currently rate action can't be ignored
-  val test4ParamsIgnoreAllExceptView = test4Params + ("viewParam" -> "1", "likeParam" -> "ignore", "dislikeParam" -> "ignore", "conversionParam" -> "ignore")
-
-  val test4RatingsIgnoreAllExceptViewLatest = List(
-    ("u0", "i0", 1),
-    ("u0", "i1", 1),
-    ("u0", "i2", 1),
-    ("u0", "i3", 2),
-    ("u1", "i0", 1),
-    ("u1", "i1", 5))
-
-  "itemrec.generic DataPreparator with all actions, all itypes, ignore all actions except View (and Rate) and conflicts=latest" should {
-    test(test4AllItypes, test4ParamsIgnoreAllExceptView, test4Items, test4U2i, test4RatingsIgnoreAllExceptViewLatest, genSelectedItems(test4Items))
-  }
-
-  // note: meaning rate action only
-  val test4ParamsIgnoreAll = test4Params + ("viewParam" -> "ignore", "likeParam" -> "ignore", "dislikeParam" -> "ignore", "conversionParam" -> "ignore")
-
-  val test4RatingsIgnoreAllLatest = List(
-    ("u0", "i0", 3),
-    ("u0", "i1", 4),
-    ("u0", "i2", 3),
-    ("u0", "i3", 2),
-    ("u1", "i1", 5))
-
-  "itemrec.generic DataPreparator with all actions, all itypes, ignore all actions (except Rate) and conflicts=latest" should {
-    test(test4AllItypes, test4ParamsIgnoreAll, test4Items, test4U2i, test4RatingsIgnoreAllLatest, genSelectedItems(test4Items))
-  }
-
-  val test4ParamsLowest: Map[String, String] = test4Params + ("conflictParam" -> "lowest")
-
-  val test4Itypes_t3 = List("t3")
-  val test4Items_t3 = List(
-    test4ItemsMap("i0"),
-    test4ItemsMap("i1"),
-    test4ItemsMap("i3"))
-
-  val test4RatingsLowest_t3 = List(
-    ("u0", "i0", 2),
-    ("u0", "i1", 1),
-    ("u0", "i3", 2),
-    ("u1", "i0", 2),
-    ("u1", "i1", 1))
-
-  "itemrec.generic DataPreparator with all actions, some itypes, and conflicts=lowest" should {
-    test(test4Itypes_t3, test4ParamsLowest, test4Items, test4U2i, test4RatingsLowest_t3, genSelectedItems(test4Items_t3))
-  }
-
-}
diff --git a/process/engines/itemrec/algorithms/hadoop/scalding/generic/src/test/scala/io/prediction/algorithms/scalding/itemrec/generic/ModelConstructorTest.scala b/process/engines/itemrec/algorithms/hadoop/scalding/generic/src/test/scala/io/prediction/algorithms/scalding/itemrec/generic/ModelConstructorTest.scala
deleted file mode 100644
index 1d0ad30..0000000
--- a/process/engines/itemrec/algorithms/hadoop/scalding/generic/src/test/scala/io/prediction/algorithms/scalding/itemrec/generic/ModelConstructorTest.scala
+++ /dev/null
@@ -1,143 +0,0 @@
-package io.prediction.algorithms.scalding.itemrec.generic
-
-import org.specs2.mutable._
-
-import com.twitter.scalding._
-
-import io.prediction.commons.filepath.{ AlgoFile, DataFile }
-import io.prediction.commons.scalding.modeldata.ItemRecScores
-
-class ModelConstructorTest extends Specification with TupleConversions {
-
-  def test(recommendationTime: Long,
-    items: List[(String, String, String, String)], //iid, itypes, starttime, endtime
-    itemRecScores: List[(String, String, String)],
-    output: List[(String, String, String, String)]) = {
-
-    val appid = 3
-    val engineid = 4
-    val algoid = 7
-    val modelSet = true
-
-    val dbType = "file"
-    val dbName = "testpath/"
-    val dbHost = Seq()
-    val dbPort = Seq()
-    val hdfsRoot = "testroot/"
-
-    val outputItemRecScores = output map { case (uid, iid, score, itypes) => (uid, iid, score, itypes, algoid, modelSet) }
-
-    JobTest("io.prediction.algorithms.scalding.itemrec.generic.ModelConstructor")
-      .arg("dbType", dbType)
-      .arg("dbName", dbName)
-      .arg("hdfsRoot", hdfsRoot)
-      .arg("appid", appid.toString)
-      .arg("engineid", engineid.toString)
-      .arg("algoid", algoid.toString)
-      .arg("modelSet", modelSet.toString)
-      .arg("recommendationTime", recommendationTime.toString)
-      //.arg("debug", "test") // NOTE: test mode
-      .source(Tsv(AlgoFile(hdfsRoot, appid, engineid, algoid, None, "itemRecScores.tsv")), itemRecScores)
-      .source(Tsv(DataFile(hdfsRoot, appid, engineid, algoid, None, "selectedItems.tsv")), items)
-      .sink[(String, String, String, String, Int, Boolean)](ItemRecScores(dbType = dbType, dbName = dbName, dbHost = dbHost, dbPort = dbPort, algoid = algoid, modelset = modelSet).getSource) { outputBuffer =>
-        "correctly write model data to a file" in {
-          outputBuffer.toList must containTheSameElementsAs(outputItemRecScores)
-        }
-      }
-      .run
-      .finish
-  }
-
-  val largeNumber = 1234567890 // larger than any item starttime
-  val noEndtime = "PIO_NONE"
-
-  /* test 1 */
-  val test1ItemRecScores = List(("u0", "i1", "0.123"), ("u0", "i2", "0.456"), ("u1", "i0", "1.23"))
-  val test1Items = List(
-    ("i0", "t1,t2,t3", "12346", noEndtime),
-    ("i1", "t1,t2", "12347", noEndtime),
-    ("i2", "t2,t3", "12348", noEndtime))
-
-  val test1Output = List(
-    ("u0", "i2,i1", "0.456,0.123", "[t2,t3],[t1,t2]"),
-    ("u1", "i0", "1.23", "[t1,t2,t3]"))
-
-  "itemrec.generic ModelConstructor" should {
-    test(largeNumber, test1Items, test1ItemRecScores, test1Output)
-  }
-
-  /* test 2: test starttime and endtime */
-  // starttime, endtime
-  // i0  A |---------|
-  // i1    B |---------|E
-  // i2       C|---------|
-  // i3           |---------|
-  //               D        F G
-
-  val tA = 123122
-  val tB = 123123
-  val tC = 123457
-  val tD = 123679
-  val tE = 543322
-  val tF = 543654
-  val tG = 543655
-
-  val test2ItemRecScores = List(
-    ("u0", "i1", "0.123"),
-    ("u0", "i2", "0.456"),
-    ("u0", "i3", "0.2"),
-    ("u1", "i0", "12"),
-    ("u1", "i2", "2"))
-
-  val test2Items = List(
-    ("i0", "t1,t2,t3", "123123", "543210"),
-    ("i1", "t1,t2", "123456", "543321"),
-    ("i2", "t2,t3", "123567", "543432"),
-    ("i3", "t2", "123678", "543654"))
-
-  val test2Output = List(
-    ("u0", "i2,i3,i1", "0.456,0.2,0.123", "[t2,t3],[t2],[t1,t2]"),
-    ("u1", "i0,i2", "12.0,2.0", "[t1,t2,t3],[t2,t3]"))
-
-  val test2OutputEmpty = List()
-
-  val test2Outputi0 = List(
-    ("u1", "i0", "12.0", "[t1,t2,t3]"))
-
-  val test2Outputi0i1 = List(
-    ("u0", "i1", "0.123", "[t1,t2]"),
-    ("u1", "i0", "12.0", "[t1,t2,t3]"))
-
-  val test2Outputi2i3 = List(
-    ("u0", "i2,i3", "0.456,0.2", "[t2,t3],[t2]"),
-    ("u1", "i2", "2.0", "[t2,t3]"))
-
-  "recommendationTime < all item starttime" should {
-    test(tA, test2Items, test2ItemRecScores, test2OutputEmpty)
-  }
-
-  "recommendationTime == earliest starttime" should {
-    test(tB, test2Items, test2ItemRecScores, test2Outputi0)
-  }
-
-  "recommendationTime > some items starttime" should {
-    test(tC, test2Items, test2ItemRecScores, test2Outputi0i1)
-  }
-
-  "recommendationTime > all item starttime and < all item endtime" should {
-    test(tD, test2Items, test2ItemRecScores, test2Output)
-  }
-
-  "recommendationTime > some item endtime" should {
-    test(tE, test2Items, test2ItemRecScores, test2Outputi2i3)
-  }
-
-  "recommendationTime == last item endtime" should {
-    test(tF, test2Items, test2ItemRecScores, test2OutputEmpty)
-  }
-
-  "recommendationTime > last item endtime" should {
-    test(tG, test2Items, test2ItemRecScores, test2OutputEmpty)
-  }
-
-}
diff --git a/process/engines/itemrec/algorithms/hadoop/scalding/knnitembased/src/main/scala/io/prediction/algorithms/scalding/itemrec/knnitembased/DataPreparator.scala b/process/engines/itemrec/algorithms/hadoop/scalding/knnitembased/src/main/scala/io/prediction/algorithms/scalding/itemrec/knnitembased/DataPreparator.scala
deleted file mode 100644
index 49d7274..0000000
--- a/process/engines/itemrec/algorithms/hadoop/scalding/knnitembased/src/main/scala/io/prediction/algorithms/scalding/itemrec/knnitembased/DataPreparator.scala
+++ /dev/null
@@ -1,216 +0,0 @@
-package io.prediction.algorithms.scalding.itemrec.knnitembased
-
-import com.twitter.scalding._
-
-import io.prediction.commons.scalding.appdata.{ Items, U2iActions }
-import io.prediction.commons.filepath.DataFile
-
-/**
- * Source: appdata DB (items, u2iActions)
- * Sink: selectedItems.tsv, ratings.tsv
- * Descripton:
- *   Prepare data for itemrec.knnitembased algo. Read from appdata DB and store selected items
- *   and ratings into a file.
- *   (appdata store -> DataPreparator -> HDFS)
- *
- * Required args:
- * --dbType: <string> (eg. mongodb) (see --dbHost, --dbPort)
- * --dbName: <string> appdata database name. (eg predictionio_appdata, or predictionio_training_appdata)
- *
- * --hdfsRoot: <string>. Root directory of the HDFS
- *
- * --appid: <int>
- * --engineid: <int>
- * --algoid: <int>
- *
- * --viewParam: <string>. (number 1 to 5, or "ignore")
- * --likeParam: <string>
- * --dislikeParam: <string>
- * --conversionParam: <string>
- * --conflictParam: <string>. (latest/highest/lowest)
- *
- * Optional args:
- * --dbHost: <string> (eg. "127.0.0.1")
- * --dbPort: <int> (eg. 27017)
- *
- * --itypes: <string separated by white space>. eg "--itypes type1 type2". If no --itypes specified, then ALL itypes will be used.
- * --evalid: <int>. Offline Evaluation if evalid is specified
- * --debug: <String>. "test" - for testing purpose
- *
- * Example:
- * Batch:
- * scald.rb --hdfs-local io.prediction.algorithms.scalding.itemrec.knnitembased.DataPreparator --dbType mongodb --dbName appdata --dbHost 127.0.0.1 --dbPort 27017 --hdfsRoot hdfs/predictionio/ --appid 34 --engineid 3 --algoid 9 --itypes t2 --viewParam 2 --likeParam 5 --dislikeParam 1 --conversionParam 4 --conflictParam latest
- *
- * Offline Eval:
- * scald.rb --hdfs-local io.prediction.algorithms.scalding.itemrec.knnitembased.DataPreparator --dbType mongodb --dbName training_appdata --dbHost 127.0.0.1 --dbPort 27017 --hdfsRoot hdfs/predictionio/ --appid 34 --engineid 3 --algoid 9 --itypes t2 --viewParam 2 --likeParam 5 --dislikeParam 1 --conversionParam 4 --conflictParam latest --evalid 15
- *
- */
-class DataPreparator(args: Args) extends Job(args) {
-
-  /**
-   * parse arguments
-   */
-  val dbTypeArg = args("dbType")
-  val dbNameArg = args("dbName")
-  val dbHostArg = args.list("dbHost")
-  val dbPortArg = args.list("dbPort") map (x => x.toInt) // becomes Option[Int]
-
-  val hdfsRootArg = args("hdfsRoot")
-
-  val appidArg = args("appid").toInt
-  val engineidArg = args("engineid").toInt
-  val algoidArg = args("algoid").toInt
-  val evalidArg = args.optional("evalid") map (x => x.toInt)
-  val OFFLINE_EVAL = (evalidArg != None) // offline eval mode
-
-  val preItypesArg = args.list("itypes")
-  val itypesArg: Option[List[String]] = if (preItypesArg.mkString(",").length == 0) None else Option(preItypesArg)
-
-  // determine how to map actions to rating values
-  def getActionParam(name: String): Option[Int] = {
-    val actionParam: Option[Int] = args(name) match {
-      case "ignore" => None
-      case x => Some(x.toInt)
-    }
-    actionParam
-  }
-
-  val viewParamArg: Option[Int] = getActionParam("viewParam")
-  val likeParamArg: Option[Int] = getActionParam("likeParam")
-  val dislikeParamArg: Option[Int] = getActionParam("dislikeParam")
-  val conversionParamArg: Option[Int] = getActionParam("conversionParam")
-
-  // When there are conflicting actions, e.g. a user gives an item a rating 5 but later dislikes it,
-  // determine which action will be considered as final preference.
-  final val CONFLICT_LATEST: String = "latest" // use latest action
-  final val CONFLICT_HIGHEST: String = "highest" // use the one with highest score
-  final val CONFLICT_LOWEST: String = "lowest" // use the one with lowest score
-
-  val conflictParamArg: String = args("conflictParam")
-
-  // check if the conflictParam is valid
-  require(List(CONFLICT_LATEST, CONFLICT_HIGHEST, CONFLICT_LOWEST).contains(conflictParamArg), "conflict param " + conflictParamArg + " is not valid.")
-
-  val debugArg = args.list("debug")
-  val DEBUG_TEST = debugArg.contains("test") // test mode
-
-  /**
-   * constants
-   */
-
-  final val ACTION_RATE = "rate"
-  final val ACTION_LIKE = "like"
-  final val ACTION_DISLIKE = "dislike"
-  final val ACTION_VIEW = "view"
-  //final val ACTION_VIEWDETAILS = "viewDetails"
-  final val ACTION_CONVERSION = "conversion"
-
-  /**
-   * source
-   */
-  // get appdata
-  // NOTE: if OFFLINE_EVAL, read from training set, and use evalid as appid when read Items and U2iActions
-  val trainingAppid = if (OFFLINE_EVAL) evalidArg.get else appidArg
-
-  // get items data
-  val items = Items(appId = trainingAppid, itypes = itypesArg,
-    dbType = dbTypeArg, dbName = dbNameArg, dbHost = dbHostArg, dbPort = dbPortArg).readStartEndtime('iidx, 'itypes, 'starttime, 'endtime)
-
-  val u2i = U2iActions(appId = trainingAppid,
-    dbType = dbTypeArg, dbName = dbNameArg, dbHost = dbHostArg, dbPort = dbPortArg).readData('action, 'uid, 'iid, 't, 'v)
-
-  /**
-   * sink
-   */
-
-  // write ratings to a file
-  val ratingsSink = Tsv(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "ratings.tsv"))
-
-  val selectedItemsSink = Tsv(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "selectedItems.tsv"))
-
-  /**
-   * computation
-   */
-  u2i.joinWithSmaller('iid -> 'iidx, items) // only select actions of these items
-    .filter('action, 'v) { fields: (String, Option[String]) =>
-      val (action, v) = fields
-
-      val keepThis: Boolean = action match {
-        case ACTION_RATE => true
-        case ACTION_LIKE => (likeParamArg != None)
-        case ACTION_DISLIKE => (dislikeParamArg != None)
-        case ACTION_VIEW => (viewParamArg != None)
-        case ACTION_CONVERSION => (conversionParamArg != None)
-        case _ => {
-          assert(false, "Action type " + action + " in u2iActions appdata is not supported!")
-          false // all other unsupported actions
-        }
-      }
-      keepThis
-    }
-    .map(('action, 'v, 't) -> ('rating, 'tLong)) { fields: (String, Option[String], String) =>
-      val (action, v, t) = fields
-
-      // convert actions into rating value based on "action" and "v" fields
-      val rating: Int = action match {
-        case ACTION_RATE => try {
-          v.get.toInt
-        } catch {
-          case e: Exception => {
-            assert(false, s"Failed to convert v field ${v} to integer for ${action} action. Exception:" + e)
-            1
-          }
-        }
-        case ACTION_LIKE => likeParamArg.getOrElse {
-          assert(false, "Action type " + action + " should have been filtered out!")
-          1
-        }
-        case ACTION_DISLIKE => dislikeParamArg.getOrElse {
-          assert(false, "Action type " + action + " should have been filtered out!")
-          1
-        }
-        case ACTION_VIEW => viewParamArg.getOrElse {
-          assert(false, "Action type " + action + " should have been filtered out!")
-          1
-        }
-        case ACTION_CONVERSION => conversionParamArg.getOrElse {
-          assert(false, "Action type " + action + " should have been filtered out!")
-          1
-        }
-        case _ => { // all other unsupported actions
-          assert(false, "Action type " + action + " in u2iActions appdata is not supported!")
-          1
-        }
-      }
-
-      (rating, t.toLong)
-    }
-    .then(resolveConflict('uid, 'iid, 'tLong, 'rating, conflictParamArg) _)
-    .project('uid, 'iid, 'rating)
-    .write(ratingsSink)
-
-  // Also store the selected items into DataFile for later model construction usage.
-  items.mapTo(('iidx, 'itypes, 'starttime, 'endtime) -> ('iidx, 'itypes, 'starttime, 'endtime)) { fields: (String, List[String], Long, Option[Long]) =>
-    val (iidx, itypes, starttime, endtime) = fields
-
-    // NOTE: convert List[String] into comma-separated String
-    // NOTE: endtime is optional
-    (iidx, itypes.mkString(","), starttime, endtime.map(_.toString).getOrElse("PIO_NONE"))
-  }.write(selectedItemsSink)
-
-  /**
-   * function to resolve conflicting actions of same uid-iid pair.
-   */
-  def resolveConflict(uidField: Symbol, iidField: Symbol, tfield: Symbol, ratingField: Symbol, conflictSolution: String)(p: RichPipe): RichPipe = {
-
-    // NOTE: sortBy() sort from smallest to largest. use reverse to pick the largest one.
-    val dataPipe = conflictSolution match {
-      case CONFLICT_LATEST => p.groupBy(uidField, iidField) { _.sortBy(tfield).reverse.take(1) } // take latest one (largest t)
-      case CONFLICT_HIGHEST => p.groupBy(uidField, iidField) { _.sortBy(ratingField).reverse.take(1) } // take highest rating
-      case CONFLICT_LOWEST => p.groupBy(uidField, iidField) { _.sortBy(ratingField).take(1) } // take lowest rating
-    }
-
-    dataPipe
-  }
-
-}
diff --git a/process/engines/itemrec/algorithms/hadoop/scalding/knnitembased/src/main/scala/io/prediction/algorithms/scalding/itemrec/knnitembased/KNNItemBased.scala b/process/engines/itemrec/algorithms/hadoop/scalding/knnitembased/src/main/scala/io/prediction/algorithms/scalding/itemrec/knnitembased/KNNItemBased.scala
deleted file mode 100644
index 2f83594..0000000
--- a/process/engines/itemrec/algorithms/hadoop/scalding/knnitembased/src/main/scala/io/prediction/algorithms/scalding/itemrec/knnitembased/KNNItemBased.scala
+++ /dev/null
@@ -1,176 +0,0 @@
-package io.prediction.algorithms.scalding.itemrec.knnitembased
-
-import com.twitter.scalding._
-import com.twitter.scalding.mathematics.Matrix
-import io.prediction.commons.filepath.{ DataFile, AlgoFile }
-
-import cascading.pipe.Pipe
-
-/**
- * Source: ratings.tsv
- * Sink: itemRecScores.tsv
- * Descripton:
- *   predict and compute the scores of every predictable user-item pair.
- *
- * Required args:
- * --hdfsRoot: <string>. Root directory of the HDFS
- *
- * --appid: <int>
- * --engineid: <int>
- * --algoid: <int>
- *
- * --measureParam: <string>. distance measurement function. select one of "correl", "cosine", "jaccard"
- * --priorCountParam: <int>. for regularization. number of virtual pairs
- * --priorCorrelParam: <double>. for regularization. correlation of these virtual pairs
- * --minNumRatersParam: <int>. min number of raters of the item
- * --maxNumRatersParam: <int> max number of raters of the item
- * --minIntersectionParam: <int>. min number of co-rater users between 2 simliar items
- * --minNumRatedSimParam: <int>. minimum number of rated similar items for valid prediction
- * --numRecommendations: <int>. number of recommendations to be generated
- * --unseenOnly: <boolean> (true/false). only recommend unseen items if this is true.
- *
- * Optional args:
- * --evalid: <int>. Offline Evaluation if evalid is specified
- * --mergeRatingParam: If defined, merge known rating into final predicted scores
- *
- * Example:
- * scald.rb --hdfs-local io.prediction.algorithms.scalding.itemrec.knnitembased.KNNItemBased --hdfsRoot hdfs/predictionio/ --appid 34 --engineid 3 --algoid 9 --measureParam correl --priorCountParam 20 --priorCorrelParam 0.05 --minNumRatersParam 1 --maxNumRatersParam 10000 --minIntersectionParam 1 --minNumRatedSimParam 1
- */
-class KNNItemBased(args: Args) extends VectorSimilarities(args) {
-
-  // args
-  val hdfsRootArg = args("hdfsRoot")
-
-  val appidArg = args("appid").toInt
-  val engineidArg = args("engineid").toInt
-  val algoidArg = args("algoid").toInt
-  val evalidArg = args.optional("evalid") map (x => x.toInt)
-
-  val measureParamArg = args("measureParam")
-  val priorCountParamArg = args("priorCountParam").toInt
-  val priorCorrelParamArg = args("priorCorrelParam").toDouble
-
-  val minNumRatersParamArg = args("minNumRatersParam").toInt
-  val maxNumRatersParamArg = args("maxNumRatersParam").toInt
-  val minIntersectionParamArg = args("minIntersectionParam").toInt
-  val minNumRatedSimParamArg = args("minNumRatedSimParam").toInt
-  val numRecommendationsArg = args("numRecommendations").toInt
-  val unseenOnlyArg = args("unseenOnly").toBoolean
-
-  val mergeRatingParamArg = args.boolean("mergeRatingParam") // true if it's defined.
-
-  // override VectorSimilarities param
-  override val MEASURE: String = measureParamArg
-
-  override val PRIOR_COUNT: Int = priorCountParamArg
-
-  override val PRIOR_CORRELATION: Double = priorCorrelParamArg
-
-  override val MIN_NUM_RATERS: Int = minNumRatersParamArg
-
-  override val MAX_NUM_RATERS: Int = maxNumRatersParamArg
-
-  override val MIN_INTERSECTION: Int = minIntersectionParamArg
-
-  val ratingsRaw = Tsv(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "ratings.tsv")).read
-
-  override def input(userField: Symbol, itemField: Symbol, ratingField: Symbol): Pipe = {
-    ratingsRaw
-      .mapTo((0, 1, 2) -> (userField, itemField, ratingField)) { fields: (String, String, Double) => fields }
-
-  }
-
-  // TODO: may add feature to load intermediate itemSimScores result without
-  // computing vectorSimilaritiesAlgo() again
-
-  val MIN_NUM_RATED_SIMILAR: Int = minNumRatedSimParamArg
-
-  val SCORE_ONLY: Boolean = !mergeRatingParamArg
-
-  // start computation  
-  val ratings = ratingsRaw.mapTo((0, 1, 2) -> ('uid, 'iid, 'rating)) { fields: (String, String, Double) => fields }
-
-  vectorSimilaritiesAlgo('iid, 'simiid, 'score) //.write(Tsv(AlgoFile(engineidArg, algoidArg, evalidArg, "itemSimScores.tsv").path))
-    .then(weightedSumAlgo(ratings, MIN_NUM_RATED_SIMILAR, SCORE_ONLY) _)
-    .write(Tsv(AlgoFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "itemRecScores.tsv")))
-
-  /*
-   * Weighted Sum Algo
-   * parameters
-   * 	itemSimScores Pipe: 'iid 'simiid 'score
-   * 	ratings Pipe: 'uid 'iid 'rating
-   * returns
-   * 	itemRecScores Pipe: 'uid 'iid 'score
-   */
-  def weightedSumAlgo(ratings: Pipe, minNumRatedSimiid: Int = 1, scoreOnly: Boolean = false)(itemSimScores: Pipe): Pipe = {
-
-    import Matrix._
-
-    // predict user u's rating of item i = sum(rating of u-j * score of i-j) / sum(abs(score of i-j)) 
-    // where j is all similar items of item i. score of i-j is the similarity score between i and j.
-    // rating of u-j is the known rating of item j rated by user u.
-
-    // convert rating and itemSimScores to matrix
-    // construct a uid x iid matrix
-    val ratingsMat = ratings.toMatrix[String, String, Double]('uid, 'iid, 'rating)
-
-    // construct a simiid x iid matrx
-    val itemSimScoresMat = itemSimScores.toMatrix[String, String, Double]('simiid, 'iid, 'score)
-
-    // matrix dot product
-    // this has the numerator value for each u-i
-    val weightedRatingSumMat = (ratingsMat * itemSimScoresMat)
-
-    // make all exisiting rating become 1
-    val ratingsBinMat = ratingsMat.binarizeAs[Double]
-
-    // calculate the absolute value of itemSimScores score
-    val absItemsimscoresMat = itemSimScoresMat.mapValues { score: Double => if (score < 0) -score else score }
-
-    // this is the denominator of the prediction formular
-    val absScoreSumMat = (ratingsBinMat * absItemsimscoresMat)
-
-    val predictScoreMat = weightedRatingSumMat.elemWiseOp(absScoreSumMat) { (x, y) => x / y }
-
-    // do filtering with number of rated simiid
-    val itemSimScoresBinMat = itemSimScoresMat.binarizeAs[Double] // setting non-zero itemSimScores to 1
-
-    val numRatedSimiidMat = (ratingsBinMat * itemSimScoresBinMat) // the number of rated simiid for each uid-iid pair
-
-    // create matrix of ((numRatedSimiid, predictScore), rating)
-    // eg. ((0, 0), x1). no prediction but with known rating
-    //     ((x1, x2), x3). with prediction of x2 (note: x2 could be 0) and known rating of x3
-    //     ((x1, x2), 0). with prediction of x2 (note: x2 could be 0) and no known rating
-
-    val predictMat = numRatedSimiidMat.zip(predictScoreMat).zip(ratingsMat)
-
-    // convert back to Pipe
-    val predict = predictMat.pipeAs('uid, 'iid, 'data)
-      .mapTo(('uid, 'iid, 'data) -> ('uid, 'iid, 'numRatedSimiid, 'predict, 'rating)) { fields: (String, String, ((Double, Double), Double)) =>
-        val (uid, iid, ((numRatedSimiid, predict), rating)) = fields
-
-        (uid, iid, numRatedSimiid, predict, rating)
-      }
-
-    val itemRecScores = predict.filter('numRatedSimiid, 'predict, 'rating) { fields: (Double, Double, Double) =>
-      val (numRatedSimiid, predict, rating) = fields
-
-      if (unseenOnlyArg)
-        ((numRatedSimiid >= minNumRatedSimiid) && (rating == 0)) // rating==0 means there's no known rating (ie. unseen)
-      else
-        ((numRatedSimiid >= minNumRatedSimiid) || ((!scoreOnly) && (rating != 0)))
-
-    }.mapTo(('uid, 'iid, 'numRatedSimiid, 'predict, 'rating) -> ('uid, 'iid, 'score)) { fields: (String, String, Double, Double, Double) =>
-      val (uid, iid, numRatedSimiid, predict, rating) = fields
-
-      val score = if ((!scoreOnly) && (rating != 0)) rating else predict
-
-      (uid, iid, score)
-    } // NOTE: sortBy is from small to large. so need to do reverse since higher score means better.
-      //.groupBy('uid) { _.sortedReverseTake[(Double, String)](('score, 'iid) -> 'scoreList, numRecommendationsArg) }
-      .groupBy('uid) { _.sortBy('score).reverse.take(numRecommendationsArg) }
-
-    itemRecScores
-  }
-
-}
\ No newline at end of file
diff --git a/process/engines/itemrec/algorithms/hadoop/scalding/knnitembased/src/main/scala/io/prediction/algorithms/scalding/itemrec/knnitembased/ModelConstructor.scala b/process/engines/itemrec/algorithms/hadoop/scalding/knnitembased/src/main/scala/io/prediction/algorithms/scalding/itemrec/knnitembased/ModelConstructor.scala
deleted file mode 100644
index 6bcdbae..0000000
--- a/process/engines/itemrec/algorithms/hadoop/scalding/knnitembased/src/main/scala/io/prediction/algorithms/scalding/itemrec/knnitembased/ModelConstructor.scala
+++ /dev/null
@@ -1,119 +0,0 @@
-package io.prediction.algorithms.scalding.itemrec.knnitembased
-
-import com.twitter.scalding._
-
-import io.prediction.commons.filepath.{ DataFile, AlgoFile }
-import io.prediction.commons.scalding.modeldata.ItemRecScores
-
-/**
- * Source:
- *   selectedItems.tsv
- *   itemRecScores.tsv
- * Sink:
- *   itemRecScores DB
- * Description:
- *   Read the itemRecScores.tsv and get additional attributes from selectedItems.tsv for each similiar items.
- *   Then write the result to model DB.
- *
- * Required args:
- * --dbType: <string> modeldata DB type (eg. mongodb) (see --dbHost, --dbPort)
- * --dbName: <string> (eg. predictionio_modeldata)
- *
- * --hdfsRoot: <string>. Root directory of the HDFS
- *
- * --appid: <int>
- * --engineid: <int>
- * --algoid: <int>
- * --modelSet: <boolean> (true/false). flag to indicate which set
- * --recommendationTime: <long> (eg. 9876543210). recommend items with starttime <= recommendationTime and endtime > recommendationTime
- *
- * Optionsl args:
- * --dbHost: <string> (eg. "127.0.0.1")
- * --dbPort: <int> (eg. 27017)
- *
- * --evalid: <int>. Offline Evaluation if evalid is specified
- * --debug: <String>. "test" - for testing purpose
- *
- * Example:
- * batch:
- * scald.rb --hdfs-local io.prediction.algorithms.scalding.itemrec.knnitembased.ModelConstructor --dbType mongodb --dbName modeldata --dbHost 127.0.0.1 --dbPort 27017 --hdfsRoot hdfs/predictionio/ --appid 34 --engineid 3 --algoid 9 --modelSet false
- *
- * offline eval
- * scald.rb --hdfs-local io.prediction.algorithms.scalding.itemrec.knnitembased.ModelConstructor --dbType file --dbName modeldata_path/ --hdfsRoot hdfs/predictionio/ --appid 34 --engineid 3 --algoid 9 --modelSet false --evalid 15
- */
-class ModelConstructor(args: Args) extends Job(args) {
-
-  /**
-   * parse args
-   */
-  val dbTypeArg = args("dbType")
-  val dbNameArg = args("dbName")
-  val dbHostArg = args.list("dbHost")
-  val dbPortArg = args.list("dbPort") map (x => x.toInt)
-
-  val hdfsRootArg = args("hdfsRoot")
-
-  val appidArg = args("appid").toInt
-  val engineidArg = args("engineid").toInt
-  val algoidArg = args("algoid").toInt
-  val evalidArg = args.optional("evalid") map (x => x.toInt)
-  val OFFLINE_EVAL = (evalidArg != None) // offline eval mode
-
-  val debugArg = args.list("debug")
-  val DEBUG_TEST = debugArg.contains("test") // test mode
-
-  val modelSetArg = args("modelSet").toBoolean
-  val recommendationTimeArg = args("recommendationTime").toLong
-
-  /**
-   * input
-   */
-  val score = Tsv(AlgoFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "itemRecScores.tsv")).read
-    .mapTo((0, 1, 2) -> ('uid, 'iid, 'score)) { fields: (String, String, Double) => fields }
-
-  val items = Tsv(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "selectedItems.tsv")).read
-    .mapTo((0, 1, 2, 3) -> ('iidx, 'itypes, 'starttime, 'endtime)) { fields: (String, String, Long, String) =>
-      val (iidx, itypes, starttime, endtime) = fields // itypes are comma-separated String
-
-      val endtimeOpt: Option[Long] = endtime match {
-        case "PIO_NONE" => None
-        case x: String => {
-          try {
-            Some(x.toLong)
-          } catch {
-            case e: Exception => {
-              assert(false, s"Failed to convert ${x} to Long. Exception: " + e)
-              Some(0)
-            }
-          }
-        }
-      }
-
-      (iidx, itypes.split(",").toList, starttime, endtimeOpt)
-    }
-
-  /**
-   * process & output
-   */
-  val p = score.joinWithSmaller('iid -> 'iidx, items) // get items info for each iid
-    .filter('starttime, 'endtime) { fields: (Long, Option[Long]) =>
-      val (starttimeI, endtimeI) = fields
-
-      val keepThis: Boolean = (starttimeI, endtimeI) match {
-        case (start, None) => (recommendationTimeArg >= start)
-        case (start, Some(end)) => ((recommendationTimeArg >= start) && (recommendationTimeArg < end))
-        case _ => {
-          assert(false, s"Unexpected item starttime ${starttimeI} and endtime ${endtimeI}")
-          false
-        }
-      }
-      keepThis
-    }
-    .project('uid, 'iid, 'score, 'itypes)
-    .groupBy('uid) { _.sortBy('score).reverse.toList[(String, Double, List[String])](('iid, 'score, 'itypes) -> 'iidsList) }
-
-  val src = ItemRecScores(dbType = dbTypeArg, dbName = dbNameArg, dbHost = dbHostArg, dbPort = dbPortArg, algoid = algoidArg, modelset = modelSetArg)
-
-  p.then(src.writeData('uid, 'iidsList, algoidArg, modelSetArg) _)
-
-}
diff --git a/process/engines/itemrec/algorithms/hadoop/scalding/knnitembased/src/main/scala/io/prediction/algorithms/scalding/itemrec/knnitembased/VectorSimilarities.scala b/process/engines/itemrec/algorithms/hadoop/scalding/knnitembased/src/main/scala/io/prediction/algorithms/scalding/itemrec/knnitembased/VectorSimilarities.scala
deleted file mode 100644
index a7bde92..0000000
--- a/process/engines/itemrec/algorithms/hadoop/scalding/knnitembased/src/main/scala/io/prediction/algorithms/scalding/itemrec/knnitembased/VectorSimilarities.scala
+++ /dev/null
@@ -1,222 +0,0 @@
-package io.prediction.algorithms.scalding.itemrec.knnitembased
-
-/**
- * CREDIT: this file is based on Edwin Chen's VectorSimliarities.scala
- * with minor modifications. Thanks Edwin Chen for posting this awesome code!
- * https://github.com/echen/scaldingale
- */
-
-import com.twitter.scalding._
-
-import cascading.pipe.Pipe
-
-/**
- * Given a dataset of ratings, how can we compute the similarity
- * between pairs of items?
- *
- * This class defines an abstract ratings input format. Subclasses
- * that provide a concrete implementation of the input (in the form of
- * a tuple stream containing: a user, the item being rated, and the numeric
- * rating of the item by the user) will automatically calculate
- * similarities of items.
- *
- * In more detail, each item is represented as a (sparse) vector of all
- * its ratings. Similarity measures (such as correlation, cosine similarity,
- * and Jaccard similarity) are then applied to these vectors.
- *
- * @author Edwin Chen
- *
- * modified by Tappingstone
- */
-abstract class VectorSimilarities(args: Args) extends Job(args) {
-
-  // parameter to configure simliarity measurement functions
-  final val CORREL_MEASURE: String = "correl" // this is Pearson
-  final val COSINE_MEASURE: String = "cosine"
-  final val JACCARD_MEASURE: String = "jaccard"
-
-  // subclass should override this to change measurement function
-  val MEASURE: String = CORREL_MEASURE //default measure
-
-  /**
-   * Parameters to regularize correlation.
-   */
-  val PRIOR_COUNT: Int = 10 // default
-  val PRIOR_CORRELATION: Double = 0
-
-  /**
-   * Filters to speed up computation and reduce noise.
-   * Subclasses should probably override these, based on the actual data.
-   */
-  val MIN_NUM_RATERS: Int = 3
-  val MAX_NUM_RATERS: Int = 10000
-  val MIN_INTERSECTION: Int = 1
-
-  /**
-   * Subclasses should override this to define their own input.
-   * This method should return a Pipe using the Symbols in parameters
-   */
-  def input(userField: Symbol, itemField: Symbol, ratingField: Symbol): Pipe
-
-  // *************************
-  // * STEPS OF THE COMPUTATION
-  // *************************  
-
-  def vectorSimilaritiesAlgo(itemField: Symbol, simItemField: Symbol, scoreField: Symbol): Pipe = {
-    /**
-     * Read in the input and give each field a type and name.
-     */
-    val ratings = input('user, 'item, 'rating)
-
-    /**
-     * Also keep track of the total number of people who rated an item.
-     */
-    val ratingsWithSize =
-      ratings
-        // Put the size of each group in a field called "numRaters".  
-        .groupBy('item) { _.size('numRaters) }
-        // Rename, since Scalding currently requires both sides of a join to have distinctly named fields.
-        .rename('item -> 'itemX)
-        .joinWithLarger('itemX -> 'item, ratings).discard('itemX)
-        .filter('numRaters) { numRaters: Long => numRaters >= MIN_NUM_RATERS && numRaters <= MAX_NUM_RATERS }
-
-    /**
-     * Make a dummy copy of the ratings, so we can do a self-join.
-     */
-    val ratings2 =
-      ratingsWithSize
-        .rename(('user, 'item, 'rating, 'numRaters) -> ('user2, 'item2, 'rating2, 'numRaters2))
-
-    /**
-     * Join the two rating streams on their user fields,
-     * in order to find all pairs of items that a user has rated.
-     */
-    val ratingPairs =
-      ratingsWithSize
-        .joinWithSmaller('user -> 'user2, ratings2)
-        // De-dupe so that we don't calculate similarity of both (A, B) and (B, A).
-        .filter('item, 'item2) { items: (String, String) => items._1 < items._2 }
-        .project('item, 'rating, 'numRaters, 'item2, 'rating2, 'numRaters2)
-
-    /**
-     * Compute dot products, norms, sums, and sizes of the rating vectors.
-     */
-    val vectorCalcs =
-      ratingPairs
-        // Compute (x*y, x^2, y^2), which we need for dot products and norms.
-        .map(('rating, 'rating2) -> ('ratingProd, 'ratingSq, 'rating2Sq)) {
-          ratings: (Double, Double) =>
-            (ratings._1 * ratings._2, scala.math.pow(ratings._1, 2), scala.math.pow(ratings._2, 2))
-        }
-        .groupBy('item, 'item2) {
-          _
-            .size
-            .sum('ratingProd -> 'dotProduct)
-            .sum('rating -> 'ratingSum)
-            .sum('rating2 -> 'rating2Sum)
-            .sum('ratingSq -> 'ratingNormSq)
-            .sum('rating2Sq -> 'rating2NormSq)
-            .max('numRaters) // Simply an easy way to make sure the numRaters field stays.
-            .max('numRaters2)
-        }
-        .filter('size) { size: Long => size >= MIN_INTERSECTION }
-
-    /**
-     * Calculate similarity between rating vectors using similarity measures
-     * like correlation, cosine similarity, and Jaccard similarity.
-     */
-    val similaritiesScore =
-      vectorCalcs
-        .map(('size, 'dotProduct, 'ratingSum, 'rating2Sum, 'ratingNormSq, 'rating2NormSq, 'numRaters, 'numRaters2) ->
-          'score) {
-
-          fields: (Double, Double, Double, Double, Double, Double, Double, Double) =>
-
-            val (size, dotProduct, ratingSum, rating2Sum, ratingNormSq, rating2NormSq, numRaters, numRaters2) = fields
-
-            val score = MEASURE match {
-              case CORREL_MEASURE => correlation(size, dotProduct, ratingSum, rating2Sum, ratingNormSq, rating2NormSq)
-              case COSINE_MEASURE => cosineSimilarity(dotProduct, scala.math.sqrt(ratingNormSq), scala.math.sqrt(rating2NormSq))
-              case JACCARD_MEASURE => jaccardSimilarity(size, numRaters, numRaters2)
-              case _ => 0.0 // all other invalid cases
-
-            }
-
-            // regularization
-            // TODO: different measurement may have different way to do regularization
-            val regScore = regularized(size, score, PRIOR_COUNT, PRIOR_CORRELATION)
-
-            regScore
-        }
-
-    // return score for each pair.
-    val simScore1 = similaritiesScore
-      .mapTo(('item, 'item2, 'score) -> (itemField, simItemField, scoreField)) { fields: (String, String, Double) => fields }
-
-    val simScore2 = similaritiesScore
-      .mapTo(('item2, 'item, 'score) -> (itemField, simItemField, scoreField)) { fields: (String, String, Double) => fields }
-
-    // concatenate 2 simScore
-    val simScoreCat = simScore1 ++ simScore2
-
-    simScoreCat
-
-  }
-  // *************************
-  // * SIMILARITY MEASURES
-  // *************************
-
-  /**
-   * The correlation between two vectors A, B is
-   *   cov(A, B) / (stdDev(A) * stdDev(B))
-   *
-   * This is equivalent to
-   *   [n * dotProduct(A, B) - sum(A) * sum(B)] /
-   *     sqrt{ [n * norm(A)^2 - sum(A)^2] [n * norm(B)^2 - sum(B)^2] }
-   */
-  def correlation(size: Double, dotProduct: Double, ratingSum: Double,
-    rating2Sum: Double, ratingNormSq: Double, rating2NormSq: Double) = {
-
-    val numerator = size * dotProduct - ratingSum * rating2Sum
-    val denominator = scala.math.sqrt(size * ratingNormSq - ratingSum * ratingSum) * scala.math.sqrt(size * rating2NormSq - rating2Sum * rating2Sum)
-
-    // NOTE: check if denominator == 0
-    if (denominator == 0)
-      0.0
-    else
-      numerator / denominator
-  }
-
-  /**
-   * Regularize correlation by adding virtual pseudocounts over a prior:
-   *   RegularizedCorrelation = w * ActualCorrelation + (1 - w) * PriorCorrelation
-   * where w = # actualPairs / (# actualPairs + # virtualPairs).
-   */
-  def regularized(size: Double, score: Double, virtualCount: Double, priorCorrelation: Double): Double = {
-    if (virtualCount != 0) {
-      val w = size / (size + virtualCount)
-
-      w * score + (1 - w) * priorCorrelation
-    } else {
-
-      score
-    }
-  }
-
-  /**
-   * The cosine similarity between two vectors A, B is
-   *   dotProduct(A, B) / (norm(A) * norm(B))
-   */
-  def cosineSimilarity(dotProduct: Double, ratingNorm: Double, rating2Norm: Double) = {
-    dotProduct / (ratingNorm * rating2Norm)
-  }
-
-  /**
-   * The Jaccard Similarity between two sets A, B is
-   *   |Intersection(A, B)| / |Union(A, B)|
-   */
-  def jaccardSimilarity(usersInCommon: Double, totalUsers1: Double, totalUsers2: Double) = {
-    val union = totalUsers1 + totalUsers2 - usersInCommon
-    usersInCommon / union
-  }
-}
diff --git a/process/engines/itemrec/algorithms/hadoop/scalding/knnitembased/src/test/scala/io/prediction/algorithms/scalding/itemrec/knnitembased/DataPreparatorTest.scala b/process/engines/itemrec/algorithms/hadoop/scalding/knnitembased/src/test/scala/io/prediction/algorithms/scalding/itemrec/knnitembased/DataPreparatorTest.scala
deleted file mode 100644
index 2d3bae0..0000000
--- a/process/engines/itemrec/algorithms/hadoop/scalding/knnitembased/src/test/scala/io/prediction/algorithms/scalding/itemrec/knnitembased/DataPreparatorTest.scala
+++ /dev/null
@@ -1,414 +0,0 @@
-package io.prediction.algorithms.scalding.itemrec.knnitembased
-
-import org.specs2.mutable._
-
-import com.twitter.scalding._
-
-import io.prediction.commons.scalding.appdata.{ Items, U2iActions }
-import io.prediction.commons.filepath.DataFile
-
-class DataPreparatorTest extends Specification with TupleConversions {
-
-  val Rate = "rate"
-  val Like = "like"
-  val Dislike = "dislike"
-  val View = "view"
-  //val ViewDetails = "viewDetails"
-  val Conversion = "conversion"
-
-  val appid = 2
-
-  def test(itypes: List[String], params: Map[String, String],
-    items: List[(String, String, String, String, String, String)], // id, itypes, appid, starttime, ct, endtime
-    u2iActions: List[(String, String, String, String, String)],
-    ratings: List[(String, String, Int)],
-    selectedItems: List[(String, String, String, String)] // id, itypes, starttime, endtime
-    ) = {
-
-    val dbType = "file"
-    val dbName = "testpath/"
-    val dbHost = Seq() //Option("testhost")
-    val dbPort = Seq() //Option(27017)
-    val hdfsRoot = "testroot/"
-
-    JobTest("io.prediction.algorithms.scalding.itemrec.knnitembased.DataPreparator")
-      .arg("dbType", dbType)
-      .arg("dbName", dbName)
-      //.arg("dbHost", dbHost.get)
-      //.arg("dbPort", dbPort.get.toString)
-      .arg("hdfsRoot", hdfsRoot)
-      .arg("appid", appid.toString)
-      .arg("engineid", "4")
-      .arg("algoid", "5")
-      .arg("itypes", itypes)
-      .arg("viewParam", params("viewParam"))
-      .arg("likeParam", params("likeParam"))
-      .arg("dislikeParam", params("dislikeParam"))
-      .arg("conversionParam", params("conversionParam"))
-      .arg("conflictParam", params("conflictParam"))
-      //.arg("debug", List("test")) // NOTE: test mode
-      .source(Items(appId = appid, itypes = Some(itypes), dbType = dbType, dbName = dbName, dbHost = dbHost, dbPort = dbPort).getSource, items)
-      .source(U2iActions(appId = appid, dbType = dbType, dbName = dbName, dbHost = dbHost, dbPort = dbPort).getSource, u2iActions)
-      .sink[(String, String, Int)](Tsv(DataFile(hdfsRoot, 2, 4, 5, None, "ratings.tsv"))) { outputBuffer =>
-        "correctly process and write data to ratings.tsv" in {
-          outputBuffer.toList must containTheSameElementsAs(ratings)
-        }
-      }
-      .sink[(String, String, String, String)](Tsv(DataFile(hdfsRoot, 2, 4, 5, None, "selectedItems.tsv"))) { outputBuffer =>
-        "correctly write selectedItems.tsv" in {
-          outputBuffer.toList must containTheSameElementsAs(selectedItems)
-        }
-      }
-      .run
-      .finish
-
-  }
-
-  /** no itypes specified */
-  def testWithoutItypes(params: Map[String, String],
-    items: List[(String, String, String, String, String, String)], // id, itypes, appid, starttime, ct, endtime
-    u2iActions: List[(String, String, String, String, String)],
-    ratings: List[(String, String, Int)],
-    selectedItems: List[(String, String, String, String)] // id, itypes, starttime, endtime
-    ) = {
-
-    val dbType = "file"
-    val dbName = "testpath/"
-    val dbHost = Seq() //Option("testhost")
-    val dbPort = Seq() //Option(27017)
-    val hdfsRoot = "testroot/"
-
-    JobTest("io.prediction.algorithms.scalding.itemrec.knnitembased.DataPreparator")
-      .arg("dbType", dbType)
-      .arg("dbName", dbName)
-      //.arg("dbHost", dbHost.get)
-      //.arg("dbPort", dbPort.get.toString)
-      .arg("hdfsRoot", hdfsRoot)
-      .arg("appid", appid.toString)
-      .arg("engineid", "4")
-      .arg("algoid", "5")
-      //.arg("itypes", itypes) // NOTE: no itypes args!
-      .arg("viewParam", params("viewParam"))
-      .arg("likeParam", params("likeParam"))
-      .arg("dislikeParam", params("dislikeParam"))
-      .arg("conversionParam", params("conversionParam"))
-      .arg("conflictParam", params("conflictParam"))
-      //.arg("debug", List("test")) // NOTE: test mode
-      .source(Items(appId = appid, itypes = None, dbType = dbType, dbName = dbName, dbHost = dbHost, dbPort = dbPort).getSource, items)
-      .source(U2iActions(appId = appid, dbType = dbType, dbName = dbName, dbHost = dbHost, dbPort = dbPort).getSource, u2iActions)
-      .sink[(String, String, Int)](Tsv(DataFile(hdfsRoot, 2, 4, 5, None, "ratings.tsv"))) { outputBuffer =>
-        "correctly process and write data to ratings.tsv" in {
-          outputBuffer.toList must containTheSameElementsAs(ratings)
-        }
-      }
-      .sink[(String, String, String, String)](Tsv(DataFile(hdfsRoot, 2, 4, 5, None, "selectedItems.tsv"))) { outputBuffer =>
-        "correctly write selectedItems.tsv" in {
-          outputBuffer.toList must containTheSameElementsAs(selectedItems)
-        }
-      }
-      .run
-      .finish
-
-  }
-
-  val noEndtime = "PIO_NONE"
-  /**
-   * Test 1. basic. Rate actions only without conflicts
-   */
-  val test1AllItypes = List("t1", "t2", "t3", "t4")
-  val test1ItemsMap = Map(
-    // id, itypes, appid, starttime, ct, endtime
-    "i0" -> ("i0", "t1,t2,t3", appid.toString, "12345", "12346", noEndtime),
-    "i1" -> ("i1", "t2,t3", appid.toString, "12347", "12348", noEndtime),
-    "i2" -> ("i2", "t4", appid.toString, "12349", "12350", noEndtime),
-    "i3" -> ("i3", "t3,t4", appid.toString, "12351", "12352", noEndtime))
-
-  val test1Items = List(
-    test1ItemsMap("i0"),
-    test1ItemsMap("i1"),
-    test1ItemsMap("i2"),
-    test1ItemsMap("i3"))
-
-  def genSelectedItems(items: List[(String, String, String, String, String, String)]) = {
-    items map { x =>
-      val (id, itypes, appid, starttime, ct, endtime) = x
-      (id, itypes, starttime, endtime)
-    }
-  }
-
-  val test1U2i = List(
-    (Rate, "u0", "i0", "123450", "3"),
-    (Rate, "u0", "i1", "123457", "1"),
-    (Rate, "u0", "i2", "123458", "4"),
-    (Rate, "u0", "i3", "123459", "2"),
-    (Rate, "u1", "i0", "123457", "5"),
-    (Rate, "u1", "i1", "123458", "2"))
-
-  val test1Ratings = List(
-    ("u0", "i0", 3),
-    ("u0", "i1", 1),
-    ("u0", "i2", 4),
-    ("u0", "i3", 2),
-    ("u1", "i0", 5),
-    ("u1", "i1", 2))
-
-  val test1Params: Map[String, String] = Map("viewParam" -> "3", "likeParam" -> "4", "dislikeParam" -> "1", "conversionParam" -> "5",
-    "conflictParam" -> "latest")
-
-  "itemrec.knnitembased DataPreparator with only rate actions, all itypes, no conflict" should {
-    test(test1AllItypes, test1Params, test1Items, test1U2i, test1Ratings, genSelectedItems(test1Items))
-  }
-
-  "itemrec.knnitembased DataPreparator with only rate actions, no itypes specified, no conflict" should {
-    testWithoutItypes(test1Params, test1Items, test1U2i, test1Ratings, genSelectedItems(test1Items))
-  }
-
-  /**
-   * Test 2. rate actions only with conflicts
-   */
-  val test2AllItypes = List("t1", "t2", "t3", "t4")
-  val test2ItemsMap = Map(
-    // id, itypes, appid, starttime, ct, endtime
-    "i0" -> ("i0", "t1,t2,t3", appid.toString, "12345", "12346", noEndtime),
-    "i1" -> ("i1", "t2,t3", appid.toString, "12347", "12348", noEndtime),
-    "i2" -> ("i2", "t4", appid.toString, "12349", "12350", noEndtime),
-    "i3" -> ("i3", "t3,t4", appid.toString, "12351", "12352", noEndtime))
-
-  val test2Items = List(
-    test2ItemsMap("i0"),
-    test2ItemsMap("i1"),
-    test2ItemsMap("i2"),
-    test2ItemsMap("i3"))
-
-  val test2U2i = List(
-    (Rate, "u0", "i0", "123448", "3"),
-    (Rate, "u0", "i0", "123449", "4"), // highest
-    (Rate, "u0", "i0", "123451", "2"), // latest
-    (Rate, "u0", "i0", "123450", "1"), // lowest
-
-    (Rate, "u0", "i1", "123456", "1"), // lowest
-    (Rate, "u0", "i1", "123457", "2"),
-    (Rate, "u0", "i1", "123458", "3"), // latest, highest
-
-    (Rate, "u0", "i2", "123461", "2"), // latest, lowest
-    (Rate, "u0", "i2", "123459", "3"),
-    (Rate, "u0", "i2", "123460", "5"), // highest
-
-    (Rate, "u0", "i3", "123459", "2"),
-    (Rate, "u1", "i0", "123457", "5"),
-
-    (Rate, "u1", "i1", "123458", "3"), // lowest
-    (Rate, "u1", "i1", "123459", "4"), // highest
-    (Rate, "u1", "i1", "123460", "3")) // latest, lowest
-
-  val test2RatingsLatest = List(
-    ("u0", "i0", 2),
-    ("u0", "i1", 3),
-    ("u0", "i2", 2),
-    ("u0", "i3", 2),
-    ("u1", "i0", 5),
-    ("u1", "i1", 3))
-
-  val test2RatingsHighest = List(
-    ("u0", "i0", 4),
-    ("u0", "i1", 3),
-    ("u0", "i2", 5),
-    ("u0", "i3", 2),
-    ("u1", "i0", 5),
-    ("u1", "i1", 4))
-
-  val test2RatingsLowest = List(
-    ("u0", "i0", 1),
-    ("u0", "i1", 1),
-    ("u0", "i2", 2),
-    ("u0", "i3", 2),
-    ("u1", "i0", 5),
-    ("u1", "i1", 3))
-
-  val test2Itypes_t1t4 = List("t1", "t4")
-  val test2Items_t1t4 = List(
-    test2ItemsMap("i0"),
-    test2ItemsMap("i2"),
-    test2ItemsMap("i3"))
-  val test2RatingsHighest_t1t4 = List(
-    ("u0", "i0", 4),
-    ("u0", "i2", 5),
-    ("u0", "i3", 2),
-    ("u1", "i0", 5))
-
-  val test2Params: Map[String, String] = Map("viewParam" -> "3", "likeParam" -> "4", "dislikeParam" -> "1", "conversionParam" -> "5",
-    "conflictParam" -> "latest")
-  val test2ParamsHighest = test2Params + ("conflictParam" -> "highest")
-  val test2ParamsLowest = test2Params + ("conflictParam" -> "lowest")
-
-  "itemrec.knnitembased DataPreparator with only rate actions, all itypes, conflict=latest" should {
-    test(test2AllItypes, test2Params, test2Items, test2U2i, test2RatingsLatest, genSelectedItems(test2Items))
-  }
-
-  "itemrec.knnitembased DataPreparator with only rate actions, all itypes, conflict=highest" should {
-    test(test2AllItypes, test2ParamsHighest, test2Items, test2U2i, test2RatingsHighest, genSelectedItems(test2Items))
-  }
-
-  "itemrec.knnitembased DataPreparator with only rate actions, all itypes, conflict=lowest" should {
-    test(test2AllItypes, test2ParamsLowest, test2Items, test2U2i, test2RatingsLowest, genSelectedItems(test2Items))
-  }
-
-  "itemrec.knnitembased DataPreparator with only rate actions, some itypes, conflict=highest" should {
-    test(test2Itypes_t1t4, test2ParamsHighest, test2Items, test2U2i, test2RatingsHighest_t1t4, genSelectedItems(test2Items_t1t4))
-  }
-
-  /**
-   * Test 3. Different Actions without conflicts
-   */
-  val test3AllItypes = List("t1", "t2", "t3", "t4")
-  val test3ItemsMap = Map(
-    // id, itypes, appid, starttime, ct, endtime
-    "i0" -> ("i0", "t1,t2,t3", appid.toString, "12345", "12346", "56789"),
-    "i1" -> ("i1", "t2,t3", appid.toString, "12347", "12348", noEndtime),
-    "i2" -> ("i2", "t4", appid.toString, "12349", "12350", "56790"),
-    "i3" -> ("i3", "t3,t4", appid.toString, "12351", "12352", noEndtime))
-
-  val test3Items = List(
-    test3ItemsMap("i0"),
-    test3ItemsMap("i1"),
-    test3ItemsMap("i2"),
-    test3ItemsMap("i3"))
-
-  val test3U2i = List(
-    (Rate, "u0", "i0", "123450", "4"),
-    (Like, "u0", "i1", "123457", "PIO_NONE"),
-    (Dislike, "u0", "i2", "123458", "PIO_NONE"),
-    (View, "u0", "i3", "123459", "PIO_NONE"), // NOTE: assume v field won't be missing
-    (Rate, "u1", "i0", "123457", "2"),
-    (Conversion, "u1", "i1", "123458", "PIO_NONE"))
-
-  val test3Ratings = List(
-    ("u0", "i0", 4),
-    ("u0", "i1", 4),
-    ("u0", "i2", 2),
-    ("u0", "i3", 1),
-    ("u1", "i0", 2),
-    ("u1", "i1", 5))
-
-  val test3Params: Map[String, String] = Map("viewParam" -> "1", "likeParam" -> "4", "dislikeParam" -> "2", "conversionParam" -> "5",
-    "conflictParam" -> "latest")
-
-  "itemrec.knnitembased DataPreparator with only all actions, all itypes, no conflict" should {
-    test(test3AllItypes, test3Params, test3Items, test3U2i, test3Ratings, genSelectedItems(test3Items))
-  }
-
-  /**
-   * test 4. Different Actions with conflicts
-   */
-  val test4Params: Map[String, String] = Map("viewParam" -> "2", "likeParam" -> "5", "dislikeParam" -> "1", "conversionParam" -> "4",
-    "conflictParam" -> "latest")
-
-  val test4AllItypes = List("t1", "t2", "t3", "t4")
-  val test4ItemsMap = Map(
-    // id, itypes, appid, starttime, ct, endtime
-    "i0" -> ("i0", "t1,t2,t3", appid.toString, "12345", "12346", "56789"),
-    "i1" -> ("i1", "t2,t3", appid.toString, "12347", "12348", noEndtime),
-    "i2" -> ("i2", "t4", appid.toString, "12349", "12350", "56790"),
-    "i3" -> ("i3", "t3,t4", appid.toString, "12351", "12352", noEndtime))
-
-  val test4Items = List(
-    test4ItemsMap("i0"),
-    test4ItemsMap("i1"),
-    test4ItemsMap("i2"),
-    test4ItemsMap("i3"))
-
-  val test4U2i = List(
-    (Rate, "u0", "i0", "123448", "3"),
-    (View, "u0", "i0", "123449", "PIO_NONE"), // lowest (2)
-    (Like, "u0", "i0", "123451", "PIO_NONE"), // latest, highest (5)
-    (Conversion, "u0", "i0", "123450", "PIO_NONE"),
-
-    (Rate, "u0", "i1", "123456", "1"), // lowest
-    (Rate, "u0", "i1", "123457", "4"), // highest
-    (View, "u0", "i1", "123458", "PIO_NONE"), // latest (2)
-
-    (Conversion, "u0", "i2", "123461", "PIO_NONE"), // latest, highest  (4)
-    (Rate, "u0", "i2", "123459", "3"),
-    (View, "u0", "i2", "123460", "PIO_NONE"), // lowest
-
-    (Rate, "u0", "i3", "123459", "2"),
-    (View, "u1", "i0", "123457", "PIO_NONE"), // (2)
-
-    (Rate, "u1", "i1", "123458", "5"), // highest
-    (Conversion, "u1", "i1", "123459", "PIO_NONE"), // (4)
-    (Dislike, "u1", "i1", "123460", "PIO_NONE")) // latest, lowest (1)
-
-  val test4RatingsLatest = List(
-    ("u0", "i0", 5),
-    ("u0", "i1", 2),
-    ("u0", "i2", 4),
-    ("u0", "i3", 2),
-    ("u1", "i0", 2),
-    ("u1", "i1", 1))
-
-  "itemrec.knnitembased DataPreparator with all actions, all itypes, and conflicts=latest" should {
-    test(test4AllItypes, test4Params, test4Items, test4U2i, test4RatingsLatest, genSelectedItems(test4Items))
-  }
-
-  val test4ParamsIgnoreView = test4Params + ("viewParam" -> "ignore")
-
-  val test4RatingsIgnoreViewLatest = List(
-    ("u0", "i0", 5),
-    ("u0", "i1", 4),
-    ("u0", "i2", 4),
-    ("u0", "i3", 2),
-    ("u1", "i1", 1))
-
-  "itemrec.knnitembased DataPreparator with all actions, all itypes, ignore View actions and conflicts=latest" should {
-    test(test4AllItypes, test4ParamsIgnoreView, test4Items, test4U2i, test4RatingsIgnoreViewLatest, genSelectedItems(test4Items))
-  }
-
-  // note: currently rate action can't be ignored
-  val test4ParamsIgnoreAllExceptView = test4Params + ("viewParam" -> "1", "likeParam" -> "ignore", "dislikeParam" -> "ignore", "conversionParam" -> "ignore")
-
-  val test4RatingsIgnoreAllExceptViewLatest = List(
-    ("u0", "i0", 1),
-    ("u0", "i1", 1),
-    ("u0", "i2", 1),
-    ("u0", "i3", 2),
-    ("u1", "i0", 1),
-    ("u1", "i1", 5))
-
-  "itemrec.knnitembased DataPreparator with all actions, all itypes, ignore all actions except View (and Rate) and conflicts=latest" should {
-    test(test4AllItypes, test4ParamsIgnoreAllExceptView, test4Items, test4U2i, test4RatingsIgnoreAllExceptViewLatest, genSelectedItems(test4Items))
-  }
-
-  // note: meaning rate action only
-  val test4ParamsIgnoreAll = test4Params + ("viewParam" -> "ignore", "likeParam" -> "ignore", "dislikeParam" -> "ignore", "conversionParam" -> "ignore")
-
-  val test4RatingsIgnoreAllLatest = List(
-    ("u0", "i0", 3),
-    ("u0", "i1", 4),
-    ("u0", "i2", 3),
-    ("u0", "i3", 2),
-    ("u1", "i1", 5))
-
-  "itemrec.knnitembased DataPreparator with all actions, all itypes, ignore all actions (except Rate) and conflicts=latest" should {
-    test(test4AllItypes, test4ParamsIgnoreAll, test4Items, test4U2i, test4RatingsIgnoreAllLatest, genSelectedItems(test4Items))
-  }
-
-  val test4ParamsLowest: Map[String, String] = test4Params + ("conflictParam" -> "lowest")
-
-  val test4Itypes_t3 = List("t3")
-  val test4Items_t3 = List(
-    test4ItemsMap("i0"),
-    test4ItemsMap("i1"),
-    test4ItemsMap("i3"))
-
-  val test4RatingsLowest_t3 = List(
-    ("u0", "i0", 2),
-    ("u0", "i1", 1),
-    ("u0", "i3", 2),
-    ("u1", "i0", 2),
-    ("u1", "i1", 1))
-
-  "itemrec.knnitembased DataPreparator with all actions, some itypes, and conflicts=lowest" should {
-    test(test4Itypes_t3, test4ParamsLowest, test4Items, test4U2i, test4RatingsLowest_t3, genSelectedItems(test4Items_t3))
-  }
-
-}
diff --git a/process/engines/itemrec/algorithms/hadoop/scalding/knnitembased/src/test/scala/io/prediction/algorithms/scalding/itemrec/knnitembased/KNNItemBasedTest.scala b/process/engines/itemrec/algorithms/hadoop/scalding/knnitembased/src/test/scala/io/prediction/algorithms/scalding/itemrec/knnitembased/KNNItemBasedTest.scala
deleted file mode 100644
index 6503129..0000000
--- a/process/engines/itemrec/algorithms/hadoop/scalding/knnitembased/src/test/scala/io/prediction/algorithms/scalding/itemrec/knnitembased/KNNItemBasedTest.scala
+++ /dev/null
@@ -1,306 +0,0 @@
-package io.prediction.algorithms.scalding.itemrec.knnitembased
-
-import org.specs2.mutable._
-
-import com.twitter.scalding._
-
-import io.prediction.commons.filepath.{ DataFile, AlgoFile }
-
-class KNNItemBasedTest extends Specification with TupleConversions {
-
-  // helper function
-  // only compare double up to 9 decimal places
-  def roundingData(orgList: List[(String, String, Double)]) = {
-    orgList map { x =>
-      val (t1, t2, t3) = x
-
-      // NOTE: use HALF_UP mode to avoid error caused by rounding when compare data
-      // (eg. 3.5 vs 3.499999999999).
-      // (eg. 0.6666666666 vs 0.666666667)
-
-      (t1, t2, BigDecimal(t3).setScale(9, BigDecimal.RoundingMode.HALF_UP).toDouble)
-    }
-  }
-
-  def testWithMerge(testArgs: Map[String, String],
-    testInput: List[(String, String, Int)],
-    testOutput: List[(String, String, Double)]) = {
-
-    val appid = 1
-    val engineid = 2
-    val algoid = 3
-    val hdfsRoot = "testroot/"
-
-    JobTest("io.prediction.algorithms.scalding.itemrec.knnitembased.KNNItemBased")
-      .arg("appid", appid.toString)
-      .arg("engineid", engineid.toString)
-      .arg("algoid", algoid.toString)
-      .arg("hdfsRoot", hdfsRoot)
-      .arg("measureParam", testArgs("measureParam"))
-      .arg("priorCountParam", testArgs("priorCountParam"))
-      .arg("priorCorrelParam", testArgs("priorCorrelParam"))
-      .arg("minNumRatersParam", testArgs("minNumRatersParam"))
-      .arg("maxNumRatersParam", testArgs("maxNumRatersParam"))
-      .arg("minIntersectionParam", testArgs("minIntersectionParam"))
-      .arg("minNumRatedSimParam", testArgs("minNumRatedSimParam"))
-      .arg("mergeRatingParam", "")
-      .arg("unseenOnly", testArgs("unseenOnly"))
-      .arg("numRecommendations", testArgs("numRecommendations"))
-      .source(Tsv(DataFile(hdfsRoot, appid, engineid, algoid, None, "ratings.tsv")), testInput)
-      .sink[(String, String, Double)](Tsv(AlgoFile(hdfsRoot, appid, engineid, algoid, None, "itemRecScores.tsv"))) { outputBuffer =>
-        "correctly calculate itemRecScores" in {
-          roundingData(outputBuffer.toList) must containTheSameElementsAs(roundingData(testOutput))
-        }
-      }
-      .run
-      .finish
-  }
-
-  def testWithoutMerge(testArgs: Map[String, String],
-    testInput: List[(String, String, Int)],
-    testOutput: List[(String, String, Double)]) = {
-
-    val appid = 1
-    val engineid = 2
-    val algoid = 3
-    val hdfsRoot = "testroot/"
-
-    JobTest("io.prediction.algorithms.scalding.itemrec.knnitembased.KNNItemBased")
-      .arg("appid", appid.toString)
-      .arg("engineid", engineid.toString)
-      .arg("algoid", algoid.toString)
-      .arg("hdfsRoot", hdfsRoot)
-      .arg("measureParam", testArgs("measureParam"))
-      .arg("priorCountParam", testArgs("priorCountParam"))
-      .arg("priorCorrelParam", testArgs("priorCorrelParam"))
-      .arg("minNumRatersParam", testArgs("minNumRatersParam"))
-      .arg("maxNumRatersParam", testArgs("maxNumRatersParam"))
-      .arg("minIntersectionParam", testArgs("minIntersectionParam"))
-      .arg("minNumRatedSimParam", testArgs("minNumRatedSimParam"))
-      .arg("unseenOnly", testArgs("unseenOnly"))
-      .arg("numRecommendations", testArgs("numRecommendations"))
-      .source(Tsv(DataFile(hdfsRoot, appid, engineid, algoid, None, "ratings.tsv")), testInput)
-      .sink[(String, String, Double)](Tsv(AlgoFile(hdfsRoot, appid, engineid, algoid, None, "itemRecScores.tsv"))) { outputBuffer =>
-        "correctly calculate itemRecScores" in {
-          roundingData(outputBuffer.toList) must containTheSameElementsAs(roundingData(testOutput))
-        }
-      }
-      .run
-      .finish
-  }
-
-  // test1
-  val test1args = Map[String, String]("measureParam" -> "correl",
-    "priorCountParam" -> "10",
-    "priorCorrelParam" -> "0",
-    "minNumRatersParam" -> "1",
-    "maxNumRatersParam" -> "100000",
-    "minIntersectionParam" -> "1",
-    "minNumRatedSimParam" -> "1",
-    "unseenOnly" -> "false",
-    "numRecommendations" -> "500"
-  )
-
-  val test1Input = List(
-    ("u0", "i0", 1),
-    ("u0", "i1", 2),
-    ("u0", "i2", 3),
-    ("u1", "i1", 4),
-    ("u1", "i2", 4),
-    ("u1", "i3", 2),
-    ("u2", "i0", 3),
-    ("u2", "i1", 2),
-    ("u2", "i3", 1),
-    ("u3", "i0", 2),
-    ("u3", "i2", 1),
-    ("u3", "i3", 5))
-
-  val test1ItemSimScore = List(
-    ("i0", "i1", 0.0),
-    ("i1", "i0", 0.0),
-    ("i0", "i2", -0.16666666666666666),
-    ("i2", "i0", -0.16666666666666666),
-    ("i0", "i3", -0.16666666666666666),
-    ("i3", "i0", -0.16666666666666666),
-    ("i1", "i2", 0.16666666666666666),
-    ("i2", "i1", 0.16666666666666666),
-    ("i1", "i3", 0.16666666666666666),
-    ("i3", "i1", 0.16666666666666666),
-    ("i2", "i3", -0.16666666666666666),
-    ("i3", "i2", -0.16666666666666666))
-
-  val test1Output = List[(String, String, Double)](
-    ("u0", "i0", 1),
-    ("u0", "i1", 2),
-    ("u0", "i2", 3),
-    ("u0", "i3", -0.666666666666667),
-    ("u1", "i0", -3.0),
-    ("u1", "i1", 4),
-    ("u1", "i2", 4),
-    ("u1", "i3", 2),
-    ("u2", "i0", 3),
-    ("u2", "i1", 2),
-    ("u2", "i2", -0.666666666666667),
-    ("u2", "i3", 1),
-    ("u3", "i0", 2),
-    ("u3", "i1", 3.0),
-    ("u3", "i2", 1),
-    ("u3", "i3", 5))
-
-  "KNNItemBasedTest minNumRatedSimParam=1 and mergeRatingParam defined" should {
-    testWithMerge(test1args, test1Input, test1Output)
-  }
-
-  // test2
-  val test2args = Map[String, String]("measureParam" -> "correl",
-    "priorCountParam" -> "10",
-    "priorCorrelParam" -> "0",
-    "minNumRatersParam" -> "1",
-    "maxNumRatersParam" -> "100000",
-    "minIntersectionParam" -> "1",
-    "minNumRatedSimParam" -> "3",
-    "unseenOnly" -> "false",
-    "numRecommendations" -> "500"
-  )
-
-  val test2Input = List(
-    ("u0", "i0", 1),
-    ("u0", "i1", 2),
-    ("u0", "i2", 3),
-    ("u1", "i1", 4),
-    ("u1", "i2", 4),
-    ("u1", "i3", 2),
-    ("u2", "i0", 3),
-    ("u2", "i1", 2),
-    ("u2", "i3", 1),
-    ("u3", "i0", 2),
-    ("u3", "i2", 1),
-    ("u3", "i3", 5))
-
-  val test2ItemSimScore = List(
-    ("i0", "i1", 0.0),
-    ("i1", "i0", 0.0),
-    ("i0", "i2", -0.16666666666666666),
-    ("i2", "i0", -0.16666666666666666),
-    ("i0", "i3", -0.16666666666666666),
-    ("i3", "i0", -0.16666666666666666),
-    ("i1", "i2", 0.16666666666666666),
-    ("i2", "i1", 0.16666666666666666),
-    ("i1", "i3", 0.16666666666666666),
-    ("i3", "i1", 0.16666666666666666),
-    ("i2", "i3", -0.16666666666666666),
-    ("i3", "i2", -0.16666666666666666))
-
-  val test2Output = List[(String, String, Double)](
-    ("u0", "i0", 1),
-    ("u0", "i1", 2),
-    ("u0", "i2", 3),
-    ("u0", "i3", -0.666666666666667),
-    // u1, i0, won't be predicted because num of similar items is < minNumRatedSimParam
-    ("u1", "i1", 4),
-    ("u1", "i2", 4),
-    ("u1", "i3", 2),
-    ("u2", "i0", 3),
-    ("u2", "i1", 2),
-    ("u2", "i2", -0.666666666666667),
-    ("u2", "i3", 1),
-    ("u3", "i0", 2),
-    // u3, i1, won't be predicted because num of similar items is < minNumRatedSimParam
-    ("u3", "i2", 1),
-    ("u3", "i3", 5))
-
-  "KNNItemBasedTest minNumRatedSimParam=3 and mergeRatingParam defined" should {
-    testWithMerge(test2args, test2Input, test2Output)
-  }
-
-  // test3
-  val test3args = Map[String, String]("measureParam" -> "correl",
-    "priorCountParam" -> "10",
-    "priorCorrelParam" -> "0",
-    "minNumRatersParam" -> "1",
-    "maxNumRatersParam" -> "100000",
-    "minIntersectionParam" -> "1",
-    "minNumRatedSimParam" -> "1",
-    "unseenOnly" -> "false",
-    "numRecommendations" -> "500"
-  )
-
-  val test3Input = List(
-    ("u0", "i0", 1),
-    ("u0", "i1", 2),
-    ("u0", "i2", 3),
-    ("u1", "i1", 4),
-    ("u1", "i2", 4),
-    ("u1", "i3", 2),
-    ("u2", "i0", 3),
-    ("u2", "i1", 2),
-    ("u2", "i3", 1),
-    ("u3", "i0", 2),
-    ("u3", "i2", 1),
-    ("u3", "i3", 5))
-
-  val test3ItemSimScore = List(
-    ("i0", "i1", 0.0),
-    ("i1", "i0", 0.0),
-    ("i0", "i2", -0.16666666666666666),
-    ("i2", "i0", -0.16666666666666666),
-    ("i0", "i3", -0.16666666666666666),
-    ("i3", "i0", -0.16666666666666666),
-    ("i1", "i2", 0.16666666666666666),
-    ("i2", "i1", 0.16666666666666666),
-    ("i1", "i3", 0.16666666666666666),
-    ("i3", "i1", 0.16666666666666666),
-    ("i2", "i3", -0.16666666666666666),
-    ("i3", "i2", -0.16666666666666666))
-
-  val test3Output = List[(String, String, Double)](
-    ("u0", "i0", -3.0),
-    ("u0", "i1", 3.0),
-    ("u0", "i2", 0.5),
-    ("u0", "i3", -0.666666666666667),
-    ("u1", "i0", -3.0),
-    ("u1", "i1", 3.0),
-    ("u1", "i2", 1.0),
-    ("u1", "i3", 0.0),
-    ("u2", "i0", -1.0),
-    ("u2", "i1", 1.0),
-    ("u2", "i2", -0.666666666666667),
-    ("u2", "i3", -0.5),
-    ("u3", "i0", -3.0),
-    ("u3", "i1", 3.0),
-    ("u3", "i2", -3.5),
-    ("u3", "i3", -1.5))
-
-  "KNNItemBasedTest with large numRecommendations and mergeRatingParam undefined" should {
-    testWithoutMerge(test3args, test3Input, test3Output)
-  }
-
-  val test3OutputTop3 = List[(String, String, Double)](
-    ("u0", "i1", 3.0),
-    ("u0", "i2", 0.5),
-    ("u0", "i3", -0.666666666666667),
-    ("u1", "i1", 3.0),
-    ("u1", "i2", 1.0),
-    ("u1", "i3", 0.0),
-    ("u2", "i1", 1.0),
-    ("u2", "i2", -0.666666666666667),
-    ("u2", "i3", -0.5),
-    ("u3", "i0", -3.0),
-    ("u3", "i1", 3.0),
-    ("u3", "i3", -1.5))
-
-  "KNNItemBasedTest with small numRecommendations and mergeRatingParam undefined" should {
-    testWithoutMerge(test3args ++ Map("numRecommendations" -> "3"), test3Input, test3OutputTop3)
-  }
-
-  val test3OutputUnseenOnly = List[(String, String, Double)](
-    ("u0", "i3", -0.666666666666667),
-    ("u1", "i0", -3.0),
-    ("u2", "i2", -0.666666666666667),
-    ("u3", "i1", 3.0))
-
-  "KNNItemBasedTest with unseenOnly=true and mergeRatingParam undefined" should {
-    testWithoutMerge(test3args ++ Map("unseenOnly" -> "true"), test3Input, test3OutputUnseenOnly)
-  }
-
-}
\ No newline at end of file
diff --git a/process/engines/itemrec/algorithms/hadoop/scalding/knnitembased/src/test/scala/io/prediction/algorithms/scalding/itemrec/knnitembased/ModelConstructorTest.scala b/process/engines/itemrec/algorithms/hadoop/scalding/knnitembased/src/test/scala/io/prediction/algorithms/scalding/itemrec/knnitembased/ModelConstructorTest.scala
deleted file mode 100644
index c21e757..0000000
--- a/process/engines/itemrec/algorithms/hadoop/scalding/knnitembased/src/test/scala/io/prediction/algorithms/scalding/itemrec/knnitembased/ModelConstructorTest.scala
+++ /dev/null
@@ -1,143 +0,0 @@
-package io.prediction.algorithms.scalding.itemrec.knnitembased
-
-import org.specs2.mutable._
-
-import com.twitter.scalding._
-
-import io.prediction.commons.filepath.{ AlgoFile, DataFile }
-import io.prediction.commons.scalding.modeldata.ItemRecScores
-
-class ModelConstructorTest extends Specification with TupleConversions {
-
-  def test(recommendationTime: Long,
-    items: List[(String, String, String, String)], //iid, itypes, starttime, endtime
-    itemRecScores: List[(String, String, String)],
-    output: List[(String, String, String, String)]) = {
-
-    val appid = 3
-    val engineid = 4
-    val algoid = 7
-    val modelSet = true
-
-    val dbType = "file"
-    val dbName = "testpath/"
-    val dbHost = Seq()
-    val dbPort = Seq()
-    val hdfsRoot = "testroot/"
-
-    val outputItemRecScores = output map { case (uid, iid, score, itypes) => (uid, iid, score, itypes, algoid, modelSet) }
-
-    JobTest("io.prediction.algorithms.scalding.itemrec.knnitembased.ModelConstructor")
-      .arg("dbType", dbType)
-      .arg("dbName", dbName)
-      .arg("hdfsRoot", hdfsRoot)
-      .arg("appid", appid.toString)
-      .arg("engineid", engineid.toString)
-      .arg("algoid", algoid.toString)
-      .arg("modelSet", modelSet.toString)
-      .arg("recommendationTime", recommendationTime.toString)
-      //.arg("debug", "test") // NOTE: test mode
-      .source(Tsv(AlgoFile(hdfsRoot, appid, engineid, algoid, None, "itemRecScores.tsv")), itemRecScores)
-      .source(Tsv(DataFile(hdfsRoot, appid, engineid, algoid, None, "selectedItems.tsv")), items)
-      .sink[(String, String, String, String, Int, Boolean)](ItemRecScores(dbType = dbType, dbName = dbName, dbHost = dbHost, dbPort = dbPort, algoid = algoid, modelset = modelSet).getSource) { outputBuffer =>
-        "correctly write model data to a file" in {
-          outputBuffer.toList must containTheSameElementsAs(outputItemRecScores)
-        }
-      }
-      .run
-      .finish
-  }
-
-  val largeNumber = 1234567890 // larger than any item starttime
-  val noEndtime = "PIO_NONE"
-
-  /* test 1 */
-  val test1ItemRecScores = List(("u0", "i1", "0.123"), ("u0", "i2", "0.456"), ("u1", "i0", "1.23"))
-  val test1Items = List(
-    ("i0", "t1,t2,t3", "12346", noEndtime),
-    ("i1", "t1,t2", "12347", noEndtime),
-    ("i2", "t2,t3", "12348", noEndtime))
-
-  val test1Output = List(
-    ("u0", "i2,i1", "0.456,0.123", "[t2,t3],[t1,t2]"),
-    ("u1", "i0", "1.23", "[t1,t2,t3]"))
-
-  "itemrec.knnitembased ModelConstructor" should {
-    test(largeNumber, test1Items, test1ItemRecScores, test1Output)
-  }
-
-  /* test 2: test starttime and endtime */
-  // starttime, endtime
-  // i0  A |---------|
-  // i1    B |---------|E
-  // i2       C|---------|
-  // i3           |---------|
-  //               D        F G
-
-  val tA = 123122
-  val tB = 123123
-  val tC = 123457
-  val tD = 123679
-  val tE = 543322
-  val tF = 543654
-  val tG = 543655
-
-  val test2ItemRecScores = List(
-    ("u0", "i1", "0.123"),
-    ("u0", "i2", "0.456"),
-    ("u0", "i3", "0.2"),
-    ("u1", "i0", "12"),
-    ("u1", "i2", "2"))
-
-  val test2Items = List(
-    ("i0", "t1,t2,t3", "123123", "543210"),
-    ("i1", "t1,t2", "123456", "543321"),
-    ("i2", "t2,t3", "123567", "543432"),
-    ("i3", "t2", "123678", "543654"))
-
-  val test2Output = List(
-    ("u0", "i2,i3,i1", "0.456,0.2,0.123", "[t2,t3],[t2],[t1,t2]"),
-    ("u1", "i0,i2", "12.0,2.0", "[t1,t2,t3],[t2,t3]"))
-
-  val test2OutputEmpty = List()
-
-  val test2Outputi0 = List(
-    ("u1", "i0", "12.0", "[t1,t2,t3]"))
-
-  val test2Outputi0i1 = List(
-    ("u0", "i1", "0.123", "[t1,t2]"),
-    ("u1", "i0", "12.0", "[t1,t2,t3]"))
-
-  val test2Outputi2i3 = List(
-    ("u0", "i2,i3", "0.456,0.2", "[t2,t3],[t2]"),
-    ("u1", "i2", "2.0", "[t2,t3]"))
-
-  "recommendationTime < all item starttime" should {
-    test(tA, test2Items, test2ItemRecScores, test2OutputEmpty)
-  }
-
-  "recommendationTime == earliest starttime" should {
-    test(tB, test2Items, test2ItemRecScores, test2Outputi0)
-  }
-
-  "recommendationTime > some items starttime" should {
-    test(tC, test2Items, test2ItemRecScores, test2Outputi0i1)
-  }
-
-  "recommendationTime > all item starttime and < all item endtime" should {
-    test(tD, test2Items, test2ItemRecScores, test2Output)
-  }
-
-  "recommendationTime > some item endtime" should {
-    test(tE, test2Items, test2ItemRecScores, test2Outputi2i3)
-  }
-
-  "recommendationTime == last item endtime" should {
-    test(tF, test2Items, test2ItemRecScores, test2OutputEmpty)
-  }
-
-  "recommendationTime > last item endtime" should {
-    test(tG, test2Items, test2ItemRecScores, test2OutputEmpty)
-  }
-
-}
diff --git a/process/engines/itemrec/algorithms/hadoop/scalding/latestrank/src/main/scala/io/prediction/algorithms/scalding/itemrec/latestrank/LatestRank.scala b/process/engines/itemrec/algorithms/hadoop/scalding/latestrank/src/main/scala/io/prediction/algorithms/scalding/itemrec/latestrank/LatestRank.scala
deleted file mode 100644
index a39eb85..0000000
--- a/process/engines/itemrec/algorithms/hadoop/scalding/latestrank/src/main/scala/io/prediction/algorithms/scalding/itemrec/latestrank/LatestRank.scala
+++ /dev/null
@@ -1,133 +0,0 @@
-package io.prediction.algorithms.scalding.itemrec.latestrank
-
-import com.twitter.scalding._
-
-import io.prediction.commons.scalding.appdata.{ Items, Users }
-import io.prediction.commons.scalding.modeldata.ItemRecScores
-import io.prediction.commons.filepath.{ AlgoFile }
-import io.prediction.commons.appdata.{ Item }
-
-/**
- * Source:
- *
- * Sink:
- *
- * Description:
- *
- * Args:
- * --training_dbType: <string> training_appdata DB type
- * --training_dbName: <string>
- * --training_dbHost: <string> optional
- * --training_dbPort: <int> optional
- *
- * --modeldata_dbType: <string> modeldata DB type
- * --modeldata_dbName: <string>
- * --modeldata_dbHost: <string> optional
- * --modeldata_dbPort <int> optional
- *
- * --hdfsRoot: <string>. Root directory of the HDFS
- *
- * --appid: <int>
- * --engineid: <int>
- * --algoid: <int>
- * --evalid: <int>. optional. Offline Evaluation if evalid is specified
- *
- * --itypes: <string separated by white space>. optional. eg "--itypes type1 type2". If no --itypes specified, then ALL itypes will be used.
- * --numRecommendations: <int>. number of recommendations to be generated
- * --modelSet: <boolean> (true/false). flag to indicate which set
- * --recommendationTime: <long> (eg. 9876543210). recommend items with starttime <= recommendationTime and endtime > recommendationTime
- *
- * Example:
- * hadoop jar PredictionIO-Process-Hadoop-Scala-assembly-0.1.jar io.prediction.algorithms.scalding.itemrec.latestrank.LatestRank --hdfs --training_dbType mongodb --training_dbName predictionio_appdata --training_dbHost localhost --training_dbPort 27017 --modeldata_dbType mongodb --modeldata_dbName predictionio_modeldata --modeldata_dbHost localhost --modeldata_dbPort 27017 --hdfsRoot predictionio/ --appid 1 --engineid 1 --algoid 18 --modelSet true
- */
-class LatestRank(args: Args) extends Job(args) {
-
-  /**
-   * parse args
-   */
-  val training_dbTypeArg = args("training_dbType")
-  val training_dbNameArg = args("training_dbName")
-  val training_dbHostArg = args.list("training_dbHost")
-  val training_dbPortArg = args.list("training_dbPort") map (x => x.toInt)
-
-  val modeldata_dbTypeArg = args("modeldata_dbType")
-  val modeldata_dbNameArg = args("modeldata_dbName")
-  val modeldata_dbHostArg = args.list("modeldata_dbHost")
-  val modeldata_dbPortArg = args.list("modeldata_dbPort") map (x => x.toInt)
-
-  val hdfsRootArg = args("hdfsRoot")
-
-  val appidArg = args("appid").toInt
-  val engineidArg = args("engineid").toInt
-  val algoidArg = args("algoid").toInt
-  val evalidArg = args.optional("evalid") map (x => x.toInt)
-  val OFFLINE_EVAL = (evalidArg != None) // offline eval mode
-
-  val preItypesArg = args.list("itypes")
-  val itypesArg: Option[List[String]] = if (preItypesArg.mkString(",").length == 0) None else Option(preItypesArg)
-
-  val numRecommendationsArg = args("numRecommendations").toInt
-
-  val modelSetArg = args("modelSet").toBoolean
-  val recommendationTimeArg = args("recommendationTime").toLong
-
-  /**
-   * source
-   */
-
-  // get appdata
-  // NOTE: if OFFLINE_EVAL, read from training set, and use evalid as appid when read Items and U2iActions
-  val trainingAppid = if (OFFLINE_EVAL) evalidArg.get else appidArg
-
-  // get items data
-  val items = Items(appId = trainingAppid, itypes = itypesArg,
-    dbType = training_dbTypeArg, dbName = training_dbNameArg, dbHost = training_dbHostArg, dbPort = training_dbPortArg).readObj('item)
-    .mapTo('item -> ('iidx, 'itypes, 'starttime, 'endtime, 'inactive)) {
-      item: Item =>
-        (item.id,
-          item.itypes,
-          item.starttime.map(_.getMillis()).get,
-          item.endtime.map(_.getMillis()),
-          item.inactive.getOrElse(false)
-        )
-    }
-
-  val users = Users(appId = trainingAppid,
-    dbType = training_dbTypeArg, dbName = training_dbNameArg, dbHost = training_dbHostArg, dbPort = training_dbPortArg).readData('uid)
-
-  /**
-   * sink
-   */
-  val itemRecScores = ItemRecScores(dbType = modeldata_dbTypeArg, dbName = modeldata_dbNameArg, dbHost = modeldata_dbHostArg, dbPort = modeldata_dbPortArg, algoid = algoidArg, modelset = modelSetArg)
-
-  /**
-   * computation
-   */
-  val itemsWithKey = items
-    .filter('starttime, 'endtime, 'inactive) { fields: (Long, Option[Long], Boolean) =>
-      // only keep items with valid starttime and endtime
-      val (starttimeI, endtimeI, inactive) = fields
-
-      val keepThis: Boolean = (starttimeI, endtimeI) match {
-        case (start, None) => (recommendationTimeArg >= start)
-        case (start, Some(end)) => ((recommendationTimeArg >= start) && (recommendationTimeArg < end))
-        case _ => {
-          assert(false, s"Unexpected item starttime ${starttimeI} and endtime ${endtimeI}")
-          false
-        }
-      }
-      keepThis && (!inactive)
-    }
-    .map(() -> 'itemKey) { u: Unit => 1 }
-  val usersWithKey = users.map(() -> 'userKey) { u: Unit => 1 }
-
-  val scores = usersWithKey.joinWithSmaller('userKey -> 'itemKey, itemsWithKey)
-    .map('starttime -> 'score) { t: Long => t.toDouble }
-    .project('uid, 'iidx, 'score, 'itypes)
-    .groupBy('uid) { _.sortBy('score).reverse.take(numRecommendationsArg) }
-    // another way to is to do toList then take top n from List. But then it would create an unncessary long List
-    // for each group first. not sure which way is better.
-    .groupBy('uid) { _.sortBy('score).reverse.toList[(String, Double, List[String])](('iidx, 'score, 'itypes) -> 'iidsList) }
-    .then(itemRecScores.writeData('uid, 'iidsList, algoidArg, modelSetArg) _)
-
-}
diff --git a/process/engines/itemrec/algorithms/hadoop/scalding/latestrank/src/test/scala/io/prediction/algorithms/scalding/itemrec/latestrank/LatestRankTest.scala b/process/engines/itemrec/algorithms/hadoop/scalding/latestrank/src/test/scala/io/prediction/algorithms/scalding/itemrec/latestrank/LatestRankTest.scala
deleted file mode 100644
index 5fe5602..0000000
--- a/process/engines/itemrec/algorithms/hadoop/scalding/latestrank/src/test/scala/io/prediction/algorithms/scalding/itemrec/latestrank/LatestRankTest.scala
+++ /dev/null
@@ -1,234 +0,0 @@
-package io.prediction.algorithms.scalding.itemrec.latestrank
-
-import org.specs2.mutable._
-
-import com.twitter.scalding._
-
-import io.prediction.commons.scalding.appdata.{ Items, Users }
-import io.prediction.commons.scalding.modeldata.{ ItemRecScores }
-import io.prediction.commons.filepath.{ AlgoFile }
-
-class LatestRankTest extends Specification with TupleConversions {
-
-  def test(algoid: Int, modelSet: Boolean,
-    itypes: List[String],
-    numRecommendations: Int,
-    recommendationTime: Long,
-    items: List[(String, String, String, String, String, String, String)], // id, itypes, appid, starttime, ct, endtime, inactive
-    users: List[(String, String)],
-    itemRecScores: List[(String, String, String, String, Int, Boolean)]) = {
-
-    val training_dbType = "file"
-    val training_dbName = "testpath/"
-
-    val modeldata_dbType = "file"
-    val modeldata_dbName = "testpath/"
-
-    val hdfsRoot = "testpath/"
-
-    val appid = 7
-    val engineid = 10
-    val evalid = None
-
-    JobTest("io.prediction.algorithms.scalding.itemrec.latestrank.LatestRank")
-      .arg("training_dbType", training_dbType)
-      .arg("training_dbName", training_dbName)
-      .arg("modeldata_dbType", modeldata_dbType)
-      .arg("modeldata_dbName", modeldata_dbName)
-      .arg("hdfsRoot", hdfsRoot)
-      .arg("appid", appid.toString)
-      .arg("engineid", engineid.toString)
-      .arg("algoid", algoid.toString)
-      .arg("itypes", itypes)
-      .arg("numRecommendations", numRecommendations.toString)
-      .arg("modelSet", modelSet.toString)
-      .arg("recommendationTime", recommendationTime.toString)
-      .source(Items(appId = appid, itypes = Some(itypes),
-        dbType = training_dbType, dbName = training_dbName, dbHost = Seq(), dbPort = Seq()).getSource, items)
-      .source(Users(appId = appid,
-        dbType = training_dbType, dbName = training_dbName, dbHost = Seq(), dbPort = Seq()).getSource, users)
-      .sink[(String, String, String, String, Int, Boolean)](ItemRecScores(dbType = modeldata_dbType, dbName = modeldata_dbName, dbHost = Seq(), dbPort = Seq(), algoid = algoid, modelset = modelSet).getSource) { outputBuffer =>
-
-        "correctly write ItemRecScores" in {
-          val outputList = outputBuffer.toList
-
-          // convert score to double and compare
-          // because double have different string representation
-          // eg 9.87654321E9 vs 9876543210.0
-          val outputListDouble = outputList.map { x => (x._1, x._2, x._3.split(",").toList.map(_.toDouble), x._4, x._5, x._6) }
-          val expectedDouble = itemRecScores.map { x => (x._1, x._2, x._3.split(",").toList.map(_.toDouble), x._4, x._5, x._6) }
-
-          outputListDouble must containTheSameElementsAs(expectedDouble)
-        }
-
-      }
-      .run
-      .finish
-  }
-
-  val largeNumber: Long = scala.Long.MaxValue // larger than any item starttime
-  val noEndtime = "PIO_NONE"
-  val noInactive = "PIO_NONE"
-
-  /* test 1 */
-  val test1Algoid = 12
-  val test1ModelSet = false
-  val test1ItypesT1T2 = List("t1", "t2")
-  val test1ItypesAll = List("t1", "t2", "t3", "t4")
-  val test1Items = List(
-    ("i0", "t1,t2,t3", "19", "123456", "345678", noEndtime, noInactive),
-    ("i1", "t2,t3", "19", "123457", "567890", noEndtime, noInactive),
-    ("i2", "t4", "19", "21", "88", noEndtime, noInactive),
-    ("i3", "t3,t4", "19", "9876543210", "67890", noEndtime, noInactive))
-  val test1Users = List(("u0", "3"), ("u1", "3"), ("u2", "3"), ("u3", "3"))
-  val test1ItemRecScoresT1T2 = List(
-    ("u0", "i1,i0", "123457.0,123456.0", "[t2,t3],[t1,t2,t3]", test1Algoid, test1ModelSet),
-    ("u1", "i1,i0", "123457.0,123456.0", "[t2,t3],[t1,t2,t3]", test1Algoid, test1ModelSet),
-    ("u2", "i1,i0", "123457.0,123456.0", "[t2,t3],[t1,t2,t3]", test1Algoid, test1ModelSet),
-    ("u3", "i1,i0", "123457.0,123456.0", "[t2,t3],[t1,t2,t3]", test1Algoid, test1ModelSet))
-
-  val test1ItemRecScoresAll = List(
-    ("u0", "i3,i1,i0,i2", "9876543210.0,123457.0,123456.0,21.0", "[t3,t4],[t2,t3],[t1,t2,t3],[t4]", test1Algoid, test1ModelSet),
-    ("u1", "i3,i1,i0,i2", "9876543210.0,123457.0,123456.0,21.0", "[t3,t4],[t2,t3],[t1,t2,t3],[t4]", test1Algoid, test1ModelSet),
-    ("u2", "i3,i1,i0,i2", "9876543210.0,123457.0,123456.0,21.0", "[t3,t4],[t2,t3],[t1,t2,t3],[t4]", test1Algoid, test1ModelSet),
-    ("u3", "i3,i1,i0,i2", "9876543210.0,123457.0,123456.0,21.0", "[t3,t4],[t2,t3],[t1,t2,t3],[t4]", test1Algoid, test1ModelSet))
-
-  val test1ItemRecScoresAllTop2 = List(
-    ("u0", "i3,i1", "9876543210.0,123457.0", "[t3,t4],[t2,t3]", test1Algoid, test1ModelSet),
-    ("u1", "i3,i1", "9876543210.0,123457.0", "[t3,t4],[t2,t3]", test1Algoid, test1ModelSet),
-    ("u2", "i3,i1", "9876543210.0,123457.0", "[t3,t4],[t2,t3]", test1Algoid, test1ModelSet),
-    ("u3", "i3,i1", "9876543210.0,123457.0", "[t3,t4],[t2,t3]", test1Algoid, test1ModelSet))
-
-  "latestrank.LatestRank with some itypes and numRecommendations larger than number of items" should {
-
-    test(test1Algoid, test1ModelSet, test1ItypesT1T2, 500, largeNumber, test1Items, test1Users, test1ItemRecScoresT1T2)
-
-  }
-
-  "latestrank.LatestRank with all itypes and numRecommendations larger than number of items" should {
-
-    test(test1Algoid, test1ModelSet, test1ItypesAll, 500, largeNumber, test1Items, test1Users, test1ItemRecScoresAll)
-
-  }
-
-  "latestrank.LatestRank with all itypes numRecommendations smaller than number of items" should {
-
-    test(test1Algoid, test1ModelSet, test1ItypesAll, 2, largeNumber, test1Items, test1Users, test1ItemRecScoresAllTop2)
-
-  }
-
-  /* test 2: test starttime and endtime */
-  // starttime, endtime
-  // i0  A |---------|
-  // i1    B |---------|E
-  // i2       C|---------|
-  // i3           |---------|
-  //               D        F G
-
-  val tA = 123122
-  val tB = 123123
-  val tC = 123457
-  val tD = 123679
-  val tE = 543322
-  val tF = 543654
-  val tG = 543655
-
-  val test2Algoid = 12
-  val test2ModelSet = false
-
-  val test2ItypesAll = List("t1", "t2", "t3", "t4")
-  val test2Items = List(
-    ("i0", "t1,t2,t3", "19", "123123", "4", "543210", noInactive),
-    ("i1", "t2,t3", "19", "123456", "5", "543321", noInactive),
-    ("i2", "t4", "19", "123567", "6", "543432", noInactive),
-    ("i3", "t3,t4", "19", "123678", "7", "543654", noInactive))
-
-  val test2ItemsInactive = List(
-    ("i0", "t1,t2,t3", "19", "123123", "4", "543210", "false"),
-    ("i1", "t2,t3", "19", "123456", "5", "543321", "true"),
-    ("i2", "t4", "19", "123567", "6", "543432", "true"),
-    ("i3", "t3,t4", "19", "123678", "7", "543654", noInactive))
-
-  val test2Users = List(("u0", "3"), ("u1", "3"), ("u2", "3"), ("u3", "3"))
-
-  val test2ItemRecScoresAll = List(
-    ("u0", "i3,i2,i1,i0", "123678.0,123567.0,123456.0,123123.0", "[t3,t4],[t4],[t2,t3],[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("u1", "i3,i2,i1,i0", "123678.0,123567.0,123456.0,123123.0", "[t3,t4],[t4],[t2,t3],[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("u2", "i3,i2,i1,i0", "123678.0,123567.0,123456.0,123123.0", "[t3,t4],[t4],[t2,t3],[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("u3", "i3,i2,i1,i0", "123678.0,123567.0,123456.0,123123.0", "[t3,t4],[t4],[t2,t3],[t1,t2,t3]", test2Algoid, test2ModelSet))
-
-  val test2ItemRecScoresAllInactive = List(
-    ("u0", "i3,i0", "123678.0,123123.0", "[t3,t4],[t1,t2,t3]",
-      test2Algoid, test2ModelSet),
-    ("u1", "i3,i0", "123678.0,123123.0", "[t3,t4],[t1,t2,t3]",
-      test2Algoid, test2ModelSet),
-    ("u2", "i3,i0", "123678.0,123123.0", "[t3,t4],[t1,t2,t3]",
-      test2Algoid, test2ModelSet),
-    ("u3", "i3,i0", "123678.0,123123.0", "[t3,t4],[t1,t2,t3]",
-      test2Algoid, test2ModelSet))
-
-  val test2ItemRecScoresEmpty = List()
-
-  val test2ItemRecScoresi0 = List(
-    ("u0", "i0", "123123.0", "[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("u1", "i0", "123123.0", "[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("u2", "i0", "123123.0", "[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("u3", "i0", "123123.0", "[t1,t2,t3]", test2Algoid, test2ModelSet))
-
-  val test2ItemRecScoresi0i1 = List(
-    ("u0", "i1,i0", "123456.0,123123.0", "[t2,t3],[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("u1", "i1,i0", "123456.0,123123.0", "[t2,t3],[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("u2", "i1,i0", "123456.0,123123.0", "[t2,t3],[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("u3", "i1,i0", "123456.0,123123.0", "[t2,t3],[t1,t2,t3]", test2Algoid, test2ModelSet))
-
-  val test2ItemRecScoresi0i1Inactive = List(
-    ("u0", "i0", "123123.0", "[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("u1", "i0", "123123.0", "[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("u2", "i0", "123123.0", "[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("u3", "i0", "123123.0", "[t1,t2,t3]", test2Algoid, test2ModelSet))
-
-  val test2ItemRecScoresi2i3 = List(
-    ("u0", "i3,i2", "123678.0,123567.0", "[t3,t4],[t4]", test2Algoid, test2ModelSet),
-    ("u1", "i3,i2", "123678.0,123567.0", "[t3,t4],[t4]", test2Algoid, test2ModelSet),
-    ("u2", "i3,i2", "123678.0,123567.0", "[t3,t4],[t4]", test2Algoid, test2ModelSet),
-    ("u3", "i3,i2", "123678.0,123567.0", "[t3,t4],[t4]", test2Algoid, test2ModelSet))
-
-  "recommendationTime < all item starttime" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tA, test2Items, test2Users, test2ItemRecScoresEmpty)
-  }
-
-  "recommendationTime == earliest starttime" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tB, test2Items, test2Users, test2ItemRecScoresi0)
-  }
-
-  "recommendationTime > some items starttime" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tC, test2Items, test2Users, test2ItemRecScoresi0i1)
-  }
-
-  "recommendationTime > some items starttime with some inactive" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tC,
-      test2ItemsInactive, test2Users, test2ItemRecScoresi0i1Inactive)
-  }
-
-  "recommendationTime > all item starttime and < all item endtime" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tD, test2Items, test2Users, test2ItemRecScoresAll)
-  }
-
-  "recommendationTime > all item starttime and < all item endtime with some inactive" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tD,
-      test2ItemsInactive, test2Users, test2ItemRecScoresAllInactive)
-  }
-
-  "recommendationTime > some item endtime" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tE, test2Items, test2Users, test2ItemRecScoresi2i3)
-  }
-
-  "recommendationTime == last item endtime" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tA, test2Items, test2Users, test2ItemRecScoresEmpty)
-  }
-
-  "recommendationTime > last item endtime" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tA, test2Items, test2Users, test2ItemRecScoresEmpty)
-  }
-
-}
diff --git a/process/engines/itemrec/algorithms/hadoop/scalding/mahout/src/main/scala/io/prediction/algorithms/scalding/mahout/itemrec/DataPreparator.scala b/process/engines/itemrec/algorithms/hadoop/scalding/mahout/src/main/scala/io/prediction/algorithms/scalding/mahout/itemrec/DataPreparator.scala
deleted file mode 100644
index 42d386f..0000000
--- a/process/engines/itemrec/algorithms/hadoop/scalding/mahout/src/main/scala/io/prediction/algorithms/scalding/mahout/itemrec/DataPreparator.scala
+++ /dev/null
@@ -1,372 +0,0 @@
-package io.prediction.algorithms.scalding.mahout.itemrec
-
-import com.twitter.scalding._
-
-import io.prediction.commons.scalding.appdata.{ Users, Items, U2iActions }
-import io.prediction.commons.filepath.DataFile
-import io.prediction.commons.appdata.{ Item }
-import org.slf4j.{ Logger, LoggerFactory }
-
-/**
- * Source:
- *
- * Sink:
- *
- * Descripton:
- *   Prepare data for Mahout itembased Recommendation algo
- *
- * Required args:
- * --dbType: <string> (eg. mongodb) (see --dbHost, --dbPort)
- * --dbName: <string> appdata database name. (eg predictionio_appdata, or predictionio_training_appdata)
- *
- * --hdfsRoot: <string>. Root directory of the HDFS
- *
- * --appid: <int>
- * --engineid: <int>
- * --algoid: <int>
- *
- * --viewParam: <string>. (number 1 to 5, or "ignore")
- * --likeParam: <string>
- * --dislikeParam: <string>
- * --conversionParam: <string>
- * --conflictParam: <string>. (latest/highest/lowest)
- *
- * --unseenOnly: <boolean>. (true/false)
- *     generate seen.csv. Empty seen.csv is generated if this is false.
- *
- * Optional args:
- * --dbHost: <string> (eg. "127.0.0.1")
- * --dbPort: <int> (eg. 27017)
- * --seenActions: <string separated by white space>. eg --seenActions view dislike (treat these actions as seen item actions)
- *   all actions used in training are considered as seen action if it's not specified or empty
- *
- * --itypes: <string separated by white space>. eg "--itypes type1 type2". If no --itypes specified, then ALL itypes will be used.
- * --evalid: <int>. Offline Evaluation if evalid is specified
- * --recommendationTime: <long> (eg. 9876543210). generate extra file (recommendItems.csv) which includes items with starttime <= recommendationTime and endtime > recommendationTime
- * --debug: <String>. "test" - for testing purpose
- *
- * Example:
- *
- */
-class DataPreparatorCommon(args: Args) extends Job(args) {
-  /**
-   * parse arguments
-   */
-  val dbTypeArg = args("dbType")
-  val dbNameArg = args("dbName")
-  val dbHostArg = args.list("dbHost")
-  val dbPortArg = args.list("dbPort") map (x => x.toInt) // becomes Option[Int]
-
-  val hdfsRootArg = args("hdfsRoot")
-
-  val appidArg = args("appid").toInt
-  val engineidArg = args("engineid").toInt
-  val algoidArg = args("algoid").toInt
-  val evalidArg = args.optional("evalid") map (x => x.toInt)
-  val OFFLINE_EVAL = (evalidArg != None) // offline eval mode
-
-  val preItypesArg = args.list("itypes")
-  val itypesArg: Option[List[String]] = if (preItypesArg.mkString(",").length == 0) None else Option(preItypesArg)
-
-  val unseenOnlyArg = args("unseenOnly").toBoolean
-  val preSeenActionsArg = args.list("seenActions")
-  val seenActionsArg: Option[List[String]] = if (preSeenActionsArg.mkString(",").length == 0) None else Option(preSeenActionsArg)
-
-  // determine how to map actions to rating values
-  def getActionParam(name: String): Option[Int] = {
-    val actionParam: Option[Int] = args(name) match {
-      case "ignore" => None
-      case x => Some(x.toInt)
-    }
-    actionParam
-  }
-
-  val viewParamArg: Option[Int] = getActionParam("viewParam")
-  val likeParamArg: Option[Int] = getActionParam("likeParam")
-  val dislikeParamArg: Option[Int] = getActionParam("dislikeParam")
-  val conversionParamArg: Option[Int] = getActionParam("conversionParam")
-
-  // When there are conflicting actions, e.g. a user gives an item a rating 5 but later dislikes it,
-  // determine which action will be considered as final preference.
-  final val CONFLICT_LATEST: String = "latest" // use latest action
-  final val CONFLICT_HIGHEST: String = "highest" // use the one with highest score
-  final val CONFLICT_LOWEST: String = "lowest" // use the one with lowest score
-
-  val conflictParamArg: String = args("conflictParam")
-
-  // check if the conflictParam is valid
-  require(List(CONFLICT_LATEST, CONFLICT_HIGHEST, CONFLICT_LOWEST).contains(conflictParamArg), "conflict param " + conflictParamArg + " is not valid.")
-
-  val debugArg = args.list("debug")
-  val DEBUG_TEST = debugArg.contains("test") // test mode
-
-  val recommendationTimeArg = args.optional("recommendationTime").map(_.toLong)
-
-  // NOTE: if OFFLINE_EVAL, read from training set, and use evalid as appid when read Items and U2iActions
-  val trainingAppid = if (OFFLINE_EVAL) evalidArg.get else appidArg
-
-  lazy val logger: Logger = LoggerFactory.getLogger(this.getClass)
-}
-
-class DataCopy(args: Args) extends DataPreparatorCommon(args) {
-
-  /**
-   * source
-   */
-
-  val items = Items(appId = trainingAppid, itypes = itypesArg,
-    dbType = dbTypeArg, dbName = dbNameArg, dbHost = dbHostArg, dbPort = dbPortArg).readObj('item)
-
-  val users = Users(appId = trainingAppid,
-    dbType = dbTypeArg, dbName = dbNameArg, dbHost = dbHostArg, dbPort = dbPortArg).readData('uid)
-
-  /**
-   * sink
-   */
-  val userIdSink = Tsv(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "userIds.tsv"))
-
-  val selectedItemSink = Tsv(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "selectedItems.tsv"))
-
-  /**
-   * computation
-   */
-
-  users.write(userIdSink)
-
-  items.mapTo('item -> ('iidx, 'itypes, 'starttime, 'endtime, 'inactive)) {
-    item: Item =>
-
-      // NOTE: convert List[String] into comma-separated String
-      // NOTE: endtime is optional
-      (item.id,
-        item.itypes.mkString(","),
-        item.starttime.map(_.getMillis().toString).getOrElse("PIO_NONE"),
-        item.endtime.map(_.getMillis().toString).getOrElse("PIO_NONE"),
-        item.inactive.map(_.toString).getOrElse("PIO_NONE"))
-  }.write(selectedItemSink)
-
-}
-
-/**
- * itemsIndex.tsv
- * usersIndex.tsv
- * ratings.csv:
- * recommendItems.csv: only recommend these items
- * seen.csv: personalized seen item list that will be not be recommended
- */
-class DataPreparator(args: Args) extends DataPreparatorCommon(args) {
-
-  /**
-   * constants
-   */
-  final val ACTION_RATE = "rate"
-  final val ACTION_LIKE = "like"
-  final val ACTION_DISLIKE = "dislike"
-  final val ACTION_VIEW = "view"
-  //final val ACTION_VIEWDETAILS = "viewDetails"
-  final val ACTION_CONVERSION = "conversion"
-
-  /**
-   * source
-   */
-
-  val u2i = U2iActions(appId = trainingAppid,
-    dbType = dbTypeArg, dbName = dbNameArg, dbHost = dbHostArg, dbPort = dbPortArg).readData('action, 'uid, 'iid, 't, 'v)
-
-  // use byte offset as index for Mahout algo
-  val itemsIndex = TextLine(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "selectedItems.tsv")).read
-    .mapTo(('offset, 'line) -> ('iindex, 'iidx, 'itypes, 'starttime, 'endtime, 'inactive)) { fields: (String, String) =>
-      val (offset, line) = fields
-
-      val lineArray = line.split("\t")
-
-      val (iidx, itypes, starttime, endtime, inactive) = try {
-        (lineArray(0), lineArray(1), lineArray(2), lineArray(3), lineArray(4))
-      } catch {
-        case e: Exception => {
-          assert(false, "Failed to extract iidx, itypes, starttime and endtime from the line: " + line + ". Exception: " + e)
-          (0, "dummy", "dummy", "dummy", "dummy")
-        }
-      }
-
-      (offset, iidx, itypes, starttime, endtime, inactive)
-    }
-
-  val usersIndex = TextLine(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "userIds.tsv")).read
-    .rename(('offset, 'line) -> ('uindex, 'uidx))
-
-  /**
-   * sink
-   */
-
-  val itemsIndexSink = Tsv(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "itemsIndex.tsv"))
-
-  val usersIndexSink = Tsv(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "usersIndex.tsv"))
-
-  val ratingsSink = Csv(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "ratings.csv"))
-
-  // only recommend these items
-  val recommendItemsSink = Csv(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "recommendItems.csv"))
-
-  val seenSink = Csv(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "seen.csv"))
-
-  /**
-   * computation
-   */
-
-  itemsIndex.write(itemsIndexSink) // all items
-
-  usersIndex.write(usersIndexSink)
-
-  // Note: for u2i, use all items of the specified itypes.
-  // but recommendItems only include items to be recommended:
-  // - with valid starttime and endtime, and inactive=false
-  itemsIndex
-    .filter('starttime, 'endtime, 'inactive) { fields: (Long, String, String) =>
-      val (starttimeI, endtime, inactiveString) = fields
-
-      val endtimeI: Option[Long] = endtime match {
-        case "PIO_NONE" => None
-        case x: String => {
-          try {
-            Some(x.toLong)
-          } catch {
-            case e: Exception => {
-              assert(false, s"Failed to convert ${x} to Long. Exception: " + e)
-              Some(0)
-            }
-          }
-        }
-      }
-
-      val inactive: Boolean = inactiveString match {
-        case "PIO_NONE" => false
-        case x: String => {
-          try {
-            x.toBoolean
-          } catch {
-            case e: Exception => {
-              assert(false, s"Failed to convert ${x} to Boolean. Exception: " + e)
-              false
-            }
-          }
-        }
-      }
-
-      val validTime = recommendationTimeArg.map { recTime =>
-        val keepThis: Boolean = (starttimeI, endtimeI) match {
-          case (start, None) => (recTime >= start)
-          case (start, Some(end)) => ((recTime >= start) && (recTime < end))
-          case _ => {
-            assert(false, s"Unexpected item starttime ${starttimeI} and endtime ${endtimeI}")
-            false
-          }
-        }
-        keepThis
-      }.getOrElse { false }
-
-      validTime && (!inactive)
-    }
-    .project('iindex)
-    .write(recommendItemsSink)
-
-  // filter and pre-process actions
-  val validu2i = u2i.joinWithSmaller('iid -> 'iidx, itemsIndex) // only select actions of these items
-
-  /* for training */
-  validu2i
-    .filter('action, 'v) { fields: (String, Option[String]) =>
-      val (action, v) = fields
-      isValidAction(action)
-    }
-    .map(('action, 'v, 't) -> ('rating, 'tLong)) { fields: (String, Option[String], String) =>
-      val (action, v, t) = fields
-
-      // convert actions into rating value based on "action" and "v" fields
-      val rating: Int = action match {
-        case ACTION_RATE => try {
-          v.get.toInt
-        } catch {
-          case e: Exception => {
-            assert(false, s"Failed to convert v field ${v} to integer for ${action} action. Exception:" + e)
-            1
-          }
-        }
-        case ACTION_LIKE => likeParamArg.getOrElse {
-          assert(false, "Action type " + action + " should have been filtered out!")
-          1
-        }
-        case ACTION_DISLIKE => dislikeParamArg.getOrElse {
-          assert(false, "Action type " + action + " should have been filtered out!")
-          1
-        }
-        case ACTION_VIEW => viewParamArg.getOrElse {
-          assert(false, "Action type " + action + " should have been filtered out!")
-          1
-        }
-        case ACTION_CONVERSION => conversionParamArg.getOrElse {
-          assert(false, "Action type " + action + " should have been filtered out!")
-          1
-        }
-        case _ => { // all other unsupported actions
-          assert(false, "Action type " + action + " should have been filtered out!")
-          1
-        }
-      }
-
-      (rating, t.toLong)
-    }
-    .then(resolveConflict('uid, 'iid, 'tLong, 'rating, conflictParamArg) _)
-    .joinWithSmaller('uid -> 'uidx, usersIndex)
-    .project('uindex, 'iindex, 'rating)
-    .write(ratingsSink) // write ratings to a file
-
-  /* generate seen file */
-  validu2i
-    .filter('action) { action: String =>
-      seenActionsArg.map { seenActions =>
-        unseenOnlyArg && seenActions.contains(action)
-      }.getOrElse {
-        // if seenAction is not defined, all actions used in treaining are considered as seen
-        unseenOnlyArg && isValidAction(action)
-      }
-    }
-    .groupBy('uid, 'iid) { _.take(1) } // don't care which action, just take one
-    .joinWithSmaller('uid -> 'uidx, usersIndex)
-    .project('uindex, 'iindex)
-    .write(seenSink)
-
-  /**
-   *
-   */
-  def isValidAction(action: String): Boolean = {
-    val keepThis: Boolean = action match {
-      case ACTION_RATE => true
-      case ACTION_LIKE => (likeParamArg != None)
-      case ACTION_DISLIKE => (dislikeParamArg != None)
-      case ACTION_VIEW => (viewParamArg != None)
-      case ACTION_CONVERSION => (conversionParamArg != None)
-      case _ => {
-        logger.debug(s"Found custom action ${action}")
-        false // all other unsupported actions
-      }
-    }
-    keepThis
-  }
-
-  /**
-   * function to resolve conflicting actions of same uid-iid pair.
-   */
-  def resolveConflict(uidField: Symbol, iidField: Symbol, tfield: Symbol, ratingField: Symbol, conflictSolution: String)(p: RichPipe): RichPipe = {
-
-    // NOTE: sortBy() sort from smallest to largest. use reverse to pick the largest one.
-    val dataPipe = conflictSolution match {
-      case CONFLICT_LATEST => p.groupBy(uidField, iidField) { _.sortBy(tfield).reverse.take(1) } // take latest one (largest t)
-      case CONFLICT_HIGHEST => p.groupBy(uidField, iidField) { _.sortBy(ratingField).reverse.take(1) } // take highest rating
-      case CONFLICT_LOWEST => p.groupBy(uidField, iidField) { _.sortBy(ratingField).take(1) } // take lowest rating
-    }
-
-    dataPipe
-  }
-
-}
diff --git a/process/engines/itemrec/algorithms/hadoop/scalding/mahout/src/main/scala/io/prediction/algorithms/scalding/mahout/itemrec/ModelConstructor.scala b/process/engines/itemrec/algorithms/hadoop/scalding/mahout/src/main/scala/io/prediction/algorithms/scalding/mahout/itemrec/ModelConstructor.scala
deleted file mode 100644
index 9391b19..0000000
--- a/process/engines/itemrec/algorithms/hadoop/scalding/mahout/src/main/scala/io/prediction/algorithms/scalding/mahout/itemrec/ModelConstructor.scala
+++ /dev/null
@@ -1,146 +0,0 @@
-package io.prediction.algorithms.scalding.mahout.itemrec
-
-import com.twitter.scalding._
-
-import io.prediction.commons.filepath.{ DataFile, AlgoFile }
-import io.prediction.commons.scalding.modeldata.ItemRecScores
-import cascading.pipe.joiner.LeftJoin
-
-/**
- * Source:
- *
- * Sink:
- *
- * Description:
- *
- * Required args:
- * --dbType: <string> modeldata DB type (eg. mongodb) (see --dbHost, --dbPort)
- * --dbName: <string> (eg. predictionio_modeldata)
- *
- * --hdfsRoot: <string>. Root directory of the HDFS
- *
- * --appid: <int>
- * --engineid: <int>
- * --algoid: <int>
- * --modelSet: <boolean> (true/false). flag to indicate which set
- *
- * --numRecommendations: <int>. number of recommendations to be generated
- *
- * Optionsl args:
- * --dbHost: <string> (eg. "127.0.0.1")
- * --dbPort: <int> (eg. 27017)
- *
- * --evalid: <int>. Offline Evaluation if evalid is specified
- * --debug: <String>. "test" - for testing purpose
- *
- * Example:
- *
- */
-class ModelConstructor(args: Args) extends Job(args) {
-
-  /**
-   * parse args
-   */
-  val dbTypeArg = args("dbType")
-  val dbNameArg = args("dbName")
-  val dbHostArg = args.list("dbHost")
-  val dbPortArg = args.list("dbPort") map (x => x.toInt)
-
-  val hdfsRootArg = args("hdfsRoot")
-
-  val appidArg = args("appid").toInt
-  val engineidArg = args("engineid").toInt
-  val algoidArg = args("algoid").toInt
-  val evalidArg = args.optional("evalid") map (x => x.toInt)
-  val OFFLINE_EVAL = (evalidArg != None) // offline eval mode
-
-  val debugArg = args.list("debug")
-  val DEBUG_TEST = debugArg.contains("test") // test mode
-
-  val modelSetArg = args("modelSet").toBoolean
-
-  val numRecommendationsArg = args("numRecommendations").toInt
-
-  /**
-   * source
-   */
-
-  val predicted = Tsv(AlgoFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "predicted.tsv"), ('uindex, 'predicted)).read
-
-  val itemsIndex = Tsv(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "itemsIndex.tsv")).read
-    .mapTo((0, 1, 2, 3, 4) -> ('iindexI, 'iidI, 'itypesI, 'starttimeI, 'endtimeI)) { fields: (String, String, String, Long, String) =>
-      val (iindex, iid, itypes, starttime, endtime) = fields // itypes are comma-separated String
-
-      val endtimeOpt: Option[Long] = endtime match {
-        case "PIO_NONE" => None
-        case x: String => {
-          try {
-            Some(x.toLong)
-          } catch {
-            case e: Exception => {
-              assert(false, s"Failed to convert ${x} to Long. Exception: " + e)
-              Some(0)
-            }
-          }
-        }
-      }
-
-      (iindex, iid, itypes.split(",").toList, starttime, endtimeOpt)
-    }
-
-  val usersIndex = Tsv(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "usersIndex.tsv")).read
-    .mapTo((0, 1) -> ('uindexU, 'uidU)) { fields: (String, String) =>
-
-      fields
-    }
-
-  /**
-   * sink
-   */
-
-  val itemRecScoresSink = ItemRecScores(dbType = dbTypeArg, dbName = dbNameArg, dbHost = dbHostArg, dbPort = dbPortArg, algoid = algoidArg, modelset = modelSetArg)
-
-  /**
-   * computation
-   */
-  // convert to (uindex, iindex, rating) format
-  val predictedRating = predicted.flatMap('predicted -> ('iindex, 'rating)) { data: String => parsePredictedData(data) }
-    .project('uindex, 'iindex, 'rating)
-
-  predictedRating
-    .joinWithSmaller('iindex -> 'iindexI, itemsIndex)
-    .joinWithSmaller('uindex -> 'uindexU, usersIndex)
-    .project('uidU, 'iidI, 'rating, 'itypesI)
-    .groupBy('uidU) { _.sortBy('rating).reverse.toList[(String, Double, List[String])](('iidI, 'rating, 'itypesI) -> 'iidsList) }
-    .mapTo(('uidU, 'iidsList) -> ('uidU, 'iidsList)) {
-      fields: (String, List[(String, Double, List[String])]) =>
-        val (uidU, iidsList) = fields
-        (uidU, iidsList.take(numRecommendationsArg))
-    }
-    .then(itemRecScoresSink.writeData('uidU, 'iidsList, algoidArg, modelSetArg) _)
-
-  /*
-  Mahout ItemRec output format
-  [24:3.2] => (24, 3.2)
-  [8:2.5,0:2.5]  => (8, 2.5), (0, 2.5)
-  [0:2.0]
-  [16:3.0]
-  */
-  def parsePredictedData(data: String): List[(String, Double)] = {
-    val dataLen = data.length
-    data.take(dataLen - 1).tail.split(",").toList.map { ratingData =>
-      val ratingDataArray = ratingData.split(":")
-      val item = ratingDataArray(0)
-      val rating: Double = try {
-        ratingDataArray(1).toDouble
-      } catch {
-        case e: Exception =>
-          {
-            assert(false, s"Cannot convert rating value of item ${item} to double: " + ratingDataArray + ". Exception: " + e)
-          }
-          0.0
-      }
-      (item, rating)
-    }
-  }
-}
diff --git a/process/engines/itemrec/algorithms/hadoop/scalding/mahout/src/main/scala/io/prediction/algorithms/scalding/mahout/itemrec/ParallelALSModelConstructor.scala b/process/engines/itemrec/algorithms/hadoop/scalding/mahout/src/main/scala/io/prediction/algorithms/scalding/mahout/itemrec/ParallelALSModelConstructor.scala
deleted file mode 100644
index ac10472..0000000
--- a/process/engines/itemrec/algorithms/hadoop/scalding/mahout/src/main/scala/io/prediction/algorithms/scalding/mahout/itemrec/ParallelALSModelConstructor.scala
+++ /dev/null
@@ -1,218 +0,0 @@
-package io.prediction.algorithms.scalding.mahout.itemrec
-
-import com.twitter.scalding._
-
-import io.prediction.commons.filepath.{ DataFile, AlgoFile }
-import io.prediction.commons.scalding.modeldata.ItemRecScores
-import cascading.pipe.joiner.LeftJoin
-
-/**
- * Source:
- *
- * Sink:
- *
- * Description:
- *
- * Required args:
- * --dbType: <string> modeldata DB type (eg. mongodb) (see --dbHost, --dbPort)
- * --dbName: <string> (eg. predictionio_modeldata)
- *
- * --hdfsRoot: <string>. Root directory of the HDFS
- *
- * --appid: <int>
- * --engineid: <int>
- * --algoid: <int>
- * --modelSet: <boolean> (true/false). flag to indicate which set
- *
- * --unseenOnly: <boolean> (true/false). only recommend unseen items if this is true.
- * --numRecommendations: <int>. number of recommendations to be generated
- * --recommendationTime: <long> (eg. 9876543210). recommend items with starttime <= recommendationTime and endtime > recommendationTime
- *
- * Optionsl args:
- * --dbHost: <string> (eg. "127.0.0.1")
- * --dbPort: <int> (eg. 27017)
- *
- * --evalid: <int>. Offline Evaluation if evalid is specified
- * --debug: <String>. "test" - for testing purpose
- *
- * --booleanData: <boolean>. Mahout item rec algo flag for implicit action data
- * --implicitFeedback: <boolean>. Mahout item rec algo flag for implicit action data
- *
- * Example:
- *
- */
-class ParallelALSModelConstructor(args: Args) extends Job(args) {
-
-  /**
-   * parse args
-   */
-  val dbTypeArg = args("dbType")
-  val dbNameArg = args("dbName")
-  val dbHostArg = args.list("dbHost")
-  val dbPortArg = args.list("dbPort") map (x => x.toInt)
-
-  val hdfsRootArg = args("hdfsRoot")
-
-  val appidArg = args("appid").toInt
-  val engineidArg = args("engineid").toInt
-  val algoidArg = args("algoid").toInt
-  val evalidArg = args.optional("evalid") map (x => x.toInt)
-  val OFFLINE_EVAL = (evalidArg != None) // offline eval mode
-
-  val debugArg = args.list("debug")
-  val DEBUG_TEST = debugArg.contains("test") // test mode
-
-  val modelSetArg = args("modelSet").toBoolean
-
-  val unseenOnlyArg = args("unseenOnly").toBoolean
-  val numRecommendationsArg = args("numRecommendations").toInt
-  val recommendationTimeArg = args("recommendationTime").toLong
-
-  val implicitFeedbackArg = args.optional("implicitFeedback").map(x => x.toBoolean).getOrElse(false)
-  // implicit preference flag.
-  val IMPLICIT_PREFERENCE = implicitFeedbackArg
-
-  /**
-   * source
-   */
-
-  val predicted = Tsv(AlgoFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "predicted.tsv"), ('uindex, 'predicted)).read
-
-  val ratingSource = Csv(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "ratings.csv"), ",", ('uindexR, 'iindexR, 'ratingR))
-
-  val seenSource = Csv(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "seen.csv"), ",", ('uindexS, 'iindexS))
-
-  val itemsIndex = Tsv(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "itemsIndex.tsv")).read
-    .mapTo((0, 1, 2, 3, 4, 5) -> ('iindexI, 'iidI, 'itypesI, 'starttimeI, 'endtimeI, 'inactive)) { fields: (String, String, String, Long, String, String) =>
-      val (iindex, iid, itypes, starttime, endtime, inactive) = fields // itypes are comma-separated String
-
-      val endtimeOpt: Option[Long] = endtime match {
-        case "PIO_NONE" => None
-        case x: String => {
-          try {
-            Some(x.toLong)
-          } catch {
-            case e: Exception => {
-              assert(false, s"Failed to convert ${x} to Long. Exception: " + e)
-              Some(0)
-            }
-          }
-        }
-      }
-
-      val inactiveB: Boolean = inactive match {
-        case "PIO_NONE" => false
-        case x: String => {
-          try {
-            x.toBoolean
-          } catch {
-            case e: Exception => {
-              assert(false, s"Failed to convert ${x} to Boolean. Exception: " + e)
-              false
-            }
-          }
-        }
-      }
-
-      (iindex, iid, itypes.split(",").toList, starttime, endtimeOpt, inactiveB)
-    }
-
-  val usersIndex = Tsv(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "usersIndex.tsv")).read
-    .mapTo((0, 1) -> ('uindexU, 'uidU)) { fields: (String, String) =>
-
-      fields
-    }
-
-  /**
-   * sink
-   */
-
-  val itemRecScoresSink = ItemRecScores(dbType = dbTypeArg, dbName = dbNameArg, dbHost = dbHostArg, dbPort = dbPortArg, algoid = algoidArg, modelset = modelSetArg)
-
-  /**
-   * computation
-   */
-
-  val seenRatings = ratingSource.read.mapTo(('uindexR, 'iindexR, 'ratingR) -> ('uindexR, 'iindexR, 'ratingR)) {
-    fields: (String, String, Double) => fields // convert score from String to Double
-  }
-
-  // convert to (uindex, iindex, rating) format
-  // and filter seen items from predicted
-  val predictedRating = predicted.flatMap('predicted -> ('iindex, 'rating)) { data: String => parsePredictedData(data) }
-    // mahout predicted output may contain items in rating file because it downsample
-    // we filter out known rating now because will merge with known rating later
-    .joinWithSmaller(('uindex, 'iindex) -> ('uindexR, 'iindexR), seenRatings, joiner = new LeftJoin)
-    .filter('ratingR) { r: Double => (r == 0) } // if ratingR == 0, means unseen rating
-    .project('uindex, 'iindex, 'rating)
-
-  val combinedRating = if (unseenOnlyArg) {
-
-    val seenActions = seenSource.read.mapTo(('uindexS, 'iindexS) -> ('uindexS, 'iindexS, 'actedS)) {
-      fields: (String, String) => (fields._1, fields._2, 1) // add dummy acted field for unseen filtering
-    }
-
-    predictedRating
-      .joinWithSmaller(('uindex, 'iindex) -> ('uindexS, 'iindexS), seenActions, joiner = new LeftJoin)
-      .filter('actedS) { a: Int => (a == 0) } // if actedS == 0, means unseen actions
-      .project('uindex, 'iindex, 'rating)
-
-  } else if (IMPLICIT_PREFERENCE) {
-    // NOTE: if IMPLICIT_PREFERENCE = true because
-    // can't simply merge the seen preference value with predicted preference value due to different meaning in value
-    // (depending on which distance function is used).
-    // TODO: need special way to handle this case
-    predictedRating
-  } else {
-    // rename for concatenation
-    val seenRatings2 = seenRatings.rename(('uindexR, 'iindexR, 'ratingR) -> ('uindex, 'iindex, 'rating))
-
-    predictedRating ++ seenRatings2
-  }
-
-  combinedRating
-    .joinWithSmaller('iindex -> 'iindexI, itemsIndex)
-    .filter('starttimeI, 'endtimeI, 'inactive) { fields: (Long, Option[Long], Boolean) =>
-      val (starttimeI, endtimeI, inactive) = fields
-
-      val keepThis: Boolean = (starttimeI, endtimeI) match {
-        case (start, None) => (recommendationTimeArg >= start)
-        case (start, Some(end)) => ((recommendationTimeArg >= start) && (recommendationTimeArg < end))
-        case _ => {
-          assert(false, s"Unexpected item starttime ${starttimeI} and endtime ${endtimeI}")
-          false
-        }
-      }
-      keepThis && (!inactive)
-    }
-    .groupBy('uindex) { _.sortBy('rating).reverse.take(numRecommendationsArg) }
-    .joinWithSmaller('uindex -> 'uindexU, usersIndex)
-    .project('uidU, 'iidI, 'rating, 'itypesI)
-    .groupBy('uidU) { _.sortBy('rating).reverse.toList[(String, Double, List[String])](('iidI, 'rating, 'itypesI) -> 'iidsList) }
-    .then(itemRecScoresSink.writeData('uidU, 'iidsList, algoidArg, modelSetArg) _)
-
-  /*
-  Mahout ItemRec output format
-  [24:3.2] => (24, 3.2)
-  [8:2.5,0:2.5]  => (8, 2.5), (0, 2.5)
-  [0:2.0]
-  [16:3.0]
-  */
-  def parsePredictedData(data: String): List[(String, Double)] = {
-    val dataLen = data.length
-    data.take(dataLen - 1).tail.split(",").toList.map { ratingData =>
-      val ratingDataArray = ratingData.split(":")
-      val item = ratingDataArray(0)
-      val rating: Double = try {
-        ratingDataArray(1).toDouble
-      } catch {
-        case e: Exception =>
-          {
-            assert(false, s"Cannot convert rating value of item ${item} to double: " + ratingDataArray + ". Exception: " + e)
-          }
-          0.0
-      }
-      (item, rating)
-    }
-  }
-}
diff --git a/process/engines/itemrec/algorithms/hadoop/scalding/mahout/src/test/scala/io/prediction/algorithms/scalding/mahout/itemrec/DataPreparatorTest.scala b/process/engines/itemrec/algorithms/hadoop/scalding/mahout/src/test/scala/io/prediction/algorithms/scalding/mahout/itemrec/DataPreparatorTest.scala
deleted file mode 100644
index 0ab3855..0000000
--- a/process/engines/itemrec/algorithms/hadoop/scalding/mahout/src/test/scala/io/prediction/algorithms/scalding/mahout/itemrec/DataPreparatorTest.scala
+++ /dev/null
@@ -1,671 +0,0 @@
-package io.prediction.algorithms.scalding.mahout.itemrec
-
-import org.specs2.mutable._
-
-import com.twitter.scalding._
-
-import io.prediction.commons.scalding.appdata.{ Users, Items, U2iActions }
-import io.prediction.commons.filepath.DataFile
-
-class DataPreparatorTest extends Specification with TupleConversions {
-
-  val Rate = "rate"
-  val Like = "like"
-  val Dislike = "dislike"
-  val View = "view"
-  //val ViewDetails = "viewDetails"
-  val Conversion = "conversion"
-
-  val appid = 2
-
-  def test(itypes: List[String], recommendationTime: Long, params: Map[String, String],
-    items: List[(String, String, String, String, String, String, String)], // id, itypes, appid, starttime, ct, endtime, inactive
-    users: List[Tuple1[String]],
-    u2iActions: List[(String, String, String, String, String)],
-    ratings: List[(String, String, String)],
-    selectedItems: List[(String, String, String, String, String)], // id, itypes, starttime, endtime, inactive
-    itemsIndexer: Map[String, String],
-    usersIndexer: Map[String, String],
-    recommendItems: Option[List[String]] = None,
-    unseenOnly: Boolean = false,
-    seenActions: List[String] = List(),
-    seen: List[(String, String)] = List()) = {
-
-    val userIds = users map (x => x._1)
-    val selectedItemsTextLine = selectedItems map { x => (itemsIndexer(x._1), x.productIterator.mkString("\t")) }
-    val usersTextLine = users map { x => (usersIndexer(x._1), x._1) }
-
-    val itemsIndex = selectedItems map { x => (itemsIndexer(x._1), x._1, x._2, x._3, x._4) }
-    val usersIndex = users map { x => (usersIndexer(x._1), x._1) }
-
-    val ratingsIndexed = ratings map { x => (usersIndexer(x._1), itemsIndexer(x._2), x._3) }
-
-    val recommendItemsIndexed = recommendItems.map { x => x.map(y => itemsIndexer(y)) }.getOrElse(List())
-
-    val seenIndexed: List[(String, String)] = if (unseenOnly) {
-      if (seenActions.isEmpty)
-        ratingsIndexed.map(y => (y._1, y._2))
-      else
-        seen.map(y => (usersIndexer(y._1), itemsIndexer(y._2)))
-    } else {
-      List()
-    }
-
-    val dbType = "file"
-    val dbName = "testpath/"
-    val dbHost = Seq()
-    val dbPort = Seq()
-    val hdfsRoot = "testroot/"
-
-    val engineid = 4
-    val algoid = 5
-    val evalid = None
-
-    JobTest("io.prediction.algorithms.scalding.mahout.itemrec.DataCopy")
-      .arg("dbType", dbType)
-      .arg("dbName", dbName)
-      .arg("hdfsRoot", hdfsRoot)
-      .arg("appid", appid.toString)
-      .arg("engineid", engineid.toString)
-      .arg("algoid", algoid.toString)
-      .arg("itypes", itypes)
-      .arg("viewParam", params("viewParam"))
-      .arg("likeParam", params("likeParam"))
-      .arg("dislikeParam", params("dislikeParam"))
-      .arg("conversionParam", params("conversionParam"))
-      .arg("conflictParam", params("conflictParam"))
-      .arg("recommendationTime", recommendationTime.toString)
-      .arg("unseenOnly", unseenOnly.toString)
-      .source(Items(appId = appid, itypes = Some(itypes), dbType = dbType, dbName = dbName, dbHost = dbHost, dbPort = dbPort).getSource, items)
-      .source(Users(appId = appid, dbType = dbType, dbName = dbName, dbHost = dbHost, dbPort = dbPort).getSource, users)
-      .sink[(String)](Tsv(DataFile(hdfsRoot, appid, engineid, algoid, evalid, "userIds.tsv"))) { outputBuffer =>
-        "correctly write userIds.tsv" in {
-          outputBuffer.toList must containTheSameElementsAs(userIds)
-        }
-      }
-      .sink[(String, String, String, String, String)](Tsv(DataFile(hdfsRoot, appid, engineid, algoid, evalid, "selectedItems.tsv"))) { outputBuffer =>
-        "correctly write selectedItems.tsv" in {
-          outputBuffer.toList must containTheSameElementsAs(selectedItems)
-        }
-      }
-      .run
-      .finish
-
-    JobTest("io.prediction.algorithms.scalding.mahout.itemrec.DataPreparator")
-      .arg("dbType", dbType)
-      .arg("dbName", dbName)
-      .arg("hdfsRoot", hdfsRoot)
-      .arg("appid", appid.toString)
-      .arg("engineid", engineid.toString)
-      .arg("algoid", algoid.toString)
-      .arg("itypes", itypes)
-      .arg("viewParam", params("viewParam"))
-      .arg("likeParam", params("likeParam"))
-      .arg("dislikeParam", params("dislikeParam"))
-      .arg("conversionParam", params("conversionParam"))
-      .arg("conflictParam", params("conflictParam"))
-      .arg("recommendationTime", recommendationTime.toString)
-      .arg("unseenOnly", unseenOnly.toString)
-      .arg("seenActions", seenActions)
-      .source(U2iActions(appId = appid, dbType = dbType, dbName = dbName, dbHost = dbHost, dbPort = dbPort).getSource, u2iActions)
-      .source(TextLine(DataFile(hdfsRoot, appid, engineid, algoid, evalid, "selectedItems.tsv")), selectedItemsTextLine)
-      .source(TextLine(DataFile(hdfsRoot, appid, engineid, algoid, evalid, "userIds.tsv")), usersTextLine)
-      .sink[(String, String, String, String, String)](Tsv(DataFile(hdfsRoot, appid, engineid, algoid, evalid, "itemsIndex.tsv"))) { outputBuffer =>
-        // index, iid, itypes
-        "correctly write itemsIndex.tsv" in {
-          outputBuffer.toList must containTheSameElementsAs(itemsIndex)
-        }
-      }
-      .sink[(String, String)](Tsv(DataFile(hdfsRoot, appid, engineid, algoid, evalid, "usersIndex.tsv"))) { outputBuffer =>
-        // index, uid
-        "correctly write usersIndex.tsv" in {
-          outputBuffer.toList must containTheSameElementsAs(usersIndex)
-        }
-      }
-      .sink[(String, String, String)](Csv(DataFile(hdfsRoot, appid, engineid, algoid, evalid, "ratings.csv"))) { outputBuffer =>
-        "correctly process and write data to ratings.csv" in {
-          outputBuffer.toList must containTheSameElementsAs(ratingsIndexed)
-        }
-      }
-      .sink[(String)](Csv(DataFile(hdfsRoot, appid, engineid, algoid, evalid, "recommendItems.csv"))) { outputBuffer =>
-        "correctly process and write data to recomomendItems.csv" in {
-          outputBuffer.toList must containTheSameElementsAs(recommendItemsIndexed)
-        }
-      }
-      .sink[(String, String)](Csv(DataFile(hdfsRoot, appid, engineid, algoid, evalid, "seen.csv"))) { outputBuffer =>
-        "correctly write data to seen.csv" in {
-          outputBuffer.toList must containTheSameElementsAs(seenIndexed)
-        }
-      }
-      .run
-      .finish
-  }
-
-  val noEndtime = "PIO_NONE"
-  val noInactive = "PIO_NONE"
-
-  /**
-   * Test 1. basic. Rate actions only without conflicts
-   */
-  val test1AllItypes = List("t1", "t2", "t3", "t4")
-  val test1ItemsMap = Map(
-    // id, itypes, appid, starttime, ct, endtime
-    "i0" -> ("i0", "t1,t2,t3", appid.toString, "12345", "12346", noEndtime,
-      noInactive),
-    "i1" -> ("i1", "t2,t3", appid.toString, "12347", "12348", noEndtime,
-      noInactive),
-    "i2" -> ("i2", "t4", appid.toString, "12349", "12350", noEndtime,
-      noInactive),
-    "i3" -> ("i3", "t3,t4", appid.toString, "12351", "12352", noEndtime,
-      noInactive))
-
-  val test1Items = List(
-    test1ItemsMap("i0"),
-    test1ItemsMap("i1"),
-    test1ItemsMap("i2"),
-    test1ItemsMap("i3"))
-
-  val test1RecommendItems = Some(List("i0", "i1", "i2", "i3"))
-
-  def genSelectedItems(items: List[(String, String, String, String, String, String, String)]) = {
-    items map { x =>
-      val (id, itypes, appid, starttime, ct, endtime, inactive) = x
-      (id, itypes, starttime, endtime, inactive)
-    }
-  }
-
-  val test1ItemsIndexer = Map("i0" -> "0", "i1" -> "4", "i2" -> "7", "i3" -> "8") // map iid to index
-
-  val test1Users = List(Tuple1("u0"), Tuple1("u1"), Tuple1("u2"), Tuple1("u3"))
-  val test1UsersIndexer = Map("u0" -> "0", "u1" -> "1", "u2" -> "2", "u3" -> "3") // map uid to index
-
-  val test1U2i = List(
-    (Rate, "u0", "i0", "123450", "3"),
-    (Rate, "u0", "i1", "123457", "1"),
-    (Rate, "u0", "i2", "123458", "4"),
-    (Rate, "u0", "i3", "123459", "2"),
-    (Rate, "u1", "i0", "123457", "5"),
-    (Rate, "u1", "i1", "123458", "2"))
-
-  val test1Ratings = List(
-    ("u0", "i0", "3"),
-    ("u0", "i1", "1"),
-    ("u0", "i2", "4"),
-    ("u0", "i3", "2"),
-    ("u1", "i0", "5"),
-    ("u1", "i1", "2"))
-
-  val test1Params: Map[String, String] = Map("viewParam" -> "3", "likeParam" -> "4", "dislikeParam" -> "1", "conversionParam" -> "5",
-    "conflictParam" -> "latest")
-
-  "DataPreparator with only rate actions, all itypes, no conflict" should {
-    test(test1AllItypes, 20000, test1Params, test1Items, test1Users, test1U2i, test1Ratings, genSelectedItems(test1Items), test1ItemsIndexer, test1UsersIndexer, test1RecommendItems)
-  }
-
-  "DataPreparator with only rate actions, no itypes specified, no conflict" should {
-    test(List(), 20000, test1Params, test1Items, test1Users, test1U2i, test1Ratings, genSelectedItems(test1Items), test1ItemsIndexer, test1UsersIndexer, test1RecommendItems)
-  }
-
-  /**
-   * Test 2. rate actions only with conflicts
-   */
-  val test2AllItypes = List("t1", "t2", "t3", "t4")
-  val test2ItemsMap = Map(
-    // id, itypes, appid, starttime, ct, endtime
-    "i0" -> ("i0", "t1,t2,t3", appid.toString, "12345", "12346", noEndtime,
-      noInactive),
-    "i1" -> ("i1", "t2,t3", appid.toString, "12347", "12348", noEndtime,
-      noInactive),
-    "i2" -> ("i2", "t4", appid.toString, "12349", "12350", noEndtime,
-      noInactive),
-    "i3" -> ("i3", "t3,t4", appid.toString, "12351", "12352", noEndtime,
-      noInactive))
-
-  val test2Items = List(
-    test2ItemsMap("i0"),
-    test2ItemsMap("i1"),
-    test2ItemsMap("i2"),
-    test2ItemsMap("i3"))
-
-  val test2RecommendItems = Some(List("i0", "i1", "i2", "i3"))
-
-  val test2ItemsIndexer = Map("i0" -> "0", "i1" -> "4", "i2" -> "7", "i3" -> "8") // map iid to index
-
-  val test2Users = List(Tuple1("u0"), Tuple1("u1"), Tuple1("u2"), Tuple1("u3"))
-  val test2UsersIndexer = Map("u0" -> "0", "u1" -> "1", "u2" -> "2", "u3" -> "3") // map uid to index
-
-  val test2U2i = List(
-    (Rate, "u0", "i0", "123448", "3"),
-    (Rate, "u0", "i0", "123449", "4"), // highest
-    (Rate, "u0", "i0", "123451", "2"), // latest
-    (Rate, "u0", "i0", "123450", "1"), // lowest
-
-    (Rate, "u0", "i1", "123456", "1"), // lowest
-    (Rate, "u0", "i1", "123457", "2"),
-    (Rate, "u0", "i1", "123458", "3"), // latest, highest
-
-    (Rate, "u0", "i2", "123461", "2"), // latest, lowest
-    (Rate, "u0", "i2", "123459", "3"),
-    (Rate, "u0", "i2", "123460", "5"), // highest
-
-    (Rate, "u0", "i3", "123459", "2"),
-    (Rate, "u1", "i0", "123457", "5"),
-
-    (Rate, "u1", "i1", "123458", "3"), // lowest
-    (Rate, "u1", "i1", "123459", "4"), // highest
-    (Rate, "u1", "i1", "123460", "3")) // latest, lowest
-
-  val test2RatingsLatest = List(
-    ("u0", "i0", "2"),
-    ("u0", "i1", "3"),
-    ("u0", "i2", "2"),
-    ("u0", "i3", "2"),
-    ("u1", "i0", "5"),
-    ("u1", "i1", "3"))
-
-  val test2RatingsHighest = List(
-    ("u0", "i0", "4"),
-    ("u0", "i1", "3"),
-    ("u0", "i2", "5"),
-    ("u0", "i3", "2"),
-    ("u1", "i0", "5"),
-    ("u1", "i1", "4"))
-
-  val test2RatingsLowest = List(
-    ("u0", "i0", "1"),
-    ("u0", "i1", "1"),
-    ("u0", "i2", "2"),
-    ("u0", "i3", "2"),
-    ("u1", "i0", "5"),
-    ("u1", "i1", "3"))
-
-  val test2Itypes_t1t4 = List("t1", "t4")
-  val test2Items_t1t4 = List(
-    test2ItemsMap("i0"),
-    test2ItemsMap("i2"),
-    test2ItemsMap("i3"))
-
-  val test2RecommendItems_t1t4 = Some(List("i0", "i2", "i3"))
-
-  val test2RatingsHighest_t1t4 = List(
-    ("u0", "i0", "4"),
-    ("u0", "i2", "5"),
-    ("u0", "i3", "2"),
-    ("u1", "i0", "5"))
-
-  val test2Params: Map[String, String] = Map("viewParam" -> "3", "likeParam" -> "4", "dislikeParam" -> "1", "conversionParam" -> "5",
-    "conflictParam" -> "latest")
-  val test2ParamsHighest = test2Params + ("conflictParam" -> "highest")
-  val test2ParamsLowest = test2Params + ("conflictParam" -> "lowest")
-
-  "DataPreparator with only rate actions, all itypes, conflict=latest" should {
-    test(test2AllItypes, 20000, test2Params, test2Items, test2Users, test2U2i, test2RatingsLatest, genSelectedItems(test2Items), test2ItemsIndexer, test2UsersIndexer, test2RecommendItems)
-  }
-
-  "DataPreparator with only rate actions, all itypes, conflict=highest" should {
-    test(test2AllItypes, 20000, test2ParamsHighest, test2Items, test2Users, test2U2i, test2RatingsHighest, genSelectedItems(test2Items), test2ItemsIndexer, test2UsersIndexer, test2RecommendItems)
-  }
-
-  "DataPreparator with only rate actions, all itypes, conflict=lowest" should {
-    test(test2AllItypes, 20000, test2ParamsLowest, test2Items, test2Users, test2U2i, test2RatingsLowest, genSelectedItems(test2Items), test2ItemsIndexer, test2UsersIndexer, test2RecommendItems)
-  }
-
-  "DataPreparator with only rate actions, some itypes, conflict=highest" should {
-    test(test2Itypes_t1t4, 20000, test2ParamsHighest, test2Items, test2Users, test2U2i, test2RatingsHighest_t1t4, genSelectedItems(test2Items_t1t4), test2ItemsIndexer, test2UsersIndexer, test2RecommendItems_t1t4)
-  }
-
-  /**
-   * Test 3. Different Actions without conflicts and endtime
-   */
-  val test3AllItypes = List("t1", "t2", "t3", "t4")
-  val test3ItemsMap = Map(
-    // id, itypes, appid, starttime, ct, endtime
-    "i0" -> ("i0", "t1,t2,t3", appid.toString, "12345", "12346", "56789",
-      noInactive),
-    "i1" -> ("i1", "t2,t3", appid.toString, "12347", "12348", noEndtime,
-      noInactive),
-    "i2" -> ("i2", "t4", appid.toString, "12349", "12350", "56790",
-      noInactive),
-    "i3" -> ("i3", "t3,t4", appid.toString, "12351", "12352", noEndtime,
-      noInactive))
-
-  val test3Items = List(
-    test3ItemsMap("i0"),
-    test3ItemsMap("i1"),
-    test3ItemsMap("i2"),
-    test3ItemsMap("i3"))
-
-  val test3RecommendItems = Some(List("i0", "i1", "i2", "i3"))
-
-  val test3ItemsIndexer = Map("i0" -> "0", "i1" -> "4", "i2" -> "7", "i3" -> "8") // map iid to index
-
-  val test3Users = List(Tuple1("u0"), Tuple1("u1"), Tuple1("u2"), Tuple1("u3"))
-  val test3UsersIndexer = Map("u0" -> "0", "u1" -> "1", "u2" -> "2", "u3" -> "3") // map uid to index
-
-  val test3U2i = List(
-    (Rate, "u0", "i0", "123450", "4"),
-    (Like, "u0", "i1", "123457", "PIO_NONE"),
-    (Dislike, "u0", "i2", "123458", "PIO_NONE"),
-    (View, "u0", "i3", "123459", "PIO_NONE"), // NOTE: assume v field won't be missing
-    (Rate, "u1", "i0", "123457", "2"),
-    (Conversion, "u1", "i1", "123458", "PIO_NONE"))
-
-  val test3Ratings = List(
-    ("u0", "i0", "4"),
-    ("u0", "i1", "4"),
-    ("u0", "i2", "2"),
-    ("u0", "i3", "1"),
-    ("u1", "i0", "2"),
-    ("u1", "i1", "5"))
-
-  val test3Params: Map[String, String] = Map("viewParam" -> "1", "likeParam" -> "4", "dislikeParam" -> "2", "conversionParam" -> "5",
-    "conflictParam" -> "latest")
-
-  "DataPreparator with only all actions, all itypes, no conflict" should {
-    test(test3AllItypes, 20000, test3Params, test3Items, test3Users, test3U2i, test3Ratings, genSelectedItems(test3Items), test3ItemsIndexer, test3UsersIndexer, test3RecommendItems)
-  }
-
-  /**
-   * test 4. Different Actions with conflicts and endtime and inactive
-   */
-  val test4Params: Map[String, String] = Map("viewParam" -> "2", "likeParam" -> "5", "dislikeParam" -> "1", "conversionParam" -> "4",
-    "conflictParam" -> "latest")
-
-  val test4AllItypes = List("t1", "t2", "t3", "t4")
-  val test4ItemsMap = Map(
-    // id, itypes, appid, starttime, ct, endtime
-    "i0" -> ("i0", "t1,t2,t3", appid.toString, "12345", "12346", "56789",
-      noInactive),
-    "i1" -> ("i1", "t2,t3", appid.toString, "12347", "12348", noEndtime,
-      "true"),
-    "i2" -> ("i2", "t4", appid.toString, "12349", "12350", "56790",
-      "true"),
-    "i3" -> ("i3", "t3,t4", appid.toString, "12351", "12352", noEndtime,
-      "false"))
-
-  val test4Items = List(
-    test4ItemsMap("i0"),
-    test4ItemsMap("i1"),
-    test4ItemsMap("i2"),
-    test4ItemsMap("i3"))
-
-  val test4RecommendItems = Some(List("i0", "i3"))
-
-  val test4ItemsIndexer = Map("i0" -> "0", "i1" -> "4", "i2" -> "7", "i3" -> "8") // map iid to index
-
-  val test4Users = List(Tuple1("u0"), Tuple1("u1"), Tuple1("u2"), Tuple1("u3"))
-  val test4UsersIndexer = Map("u0" -> "0", "u1" -> "1", "u2" -> "2", "u3" -> "3") // map uid to index
-
-  val test4U2i = List(
-    (Rate, "u0", "i0", "123448", "3"),
-    (View, "u0", "i0", "123449", "PIO_NONE"), // lowest (2)
-    (Like, "u0", "i0", "123451", "PIO_NONE"), // latest, highest (5)
-    (Conversion, "u0", "i0", "123450", "PIO_NONE"),
-
-    (Rate, "u0", "i1", "123456", "1"), // lowest
-    (Rate, "u0", "i1", "123457", "4"), // highest
-    (View, "u0", "i1", "123458", "PIO_NONE"), // latest (2)
-
-    (Conversion, "u0", "i2", "123461", "PIO_NONE"), // latest, highest  (4)
-    (Rate, "u0", "i2", "123459", "3"),
-    (View, "u0", "i2", "123460", "PIO_NONE"), // lowest
-
-    (Rate, "u0", "i3", "123459", "2"),
-    (View, "u1", "i0", "123457", "PIO_NONE"), // (2)
-
-    (Rate, "u1", "i1", "123458", "5"), // highest
-    (Conversion, "u1", "i1", "123459", "PIO_NONE"), // (4)
-    (Dislike, "u1", "i1", "123460", "PIO_NONE")) // latest, lowest (1)
-
-  val test4RatingsLatest = List(
-    ("u0", "i0", "5"),
-    ("u0", "i1", "2"),
-    ("u0", "i2", "4"),
-    ("u0", "i3", "2"),
-    ("u1", "i0", "2"),
-    ("u1", "i1", "1"))
-
-  "DataPreparator with all actions, all itypes, and conflicts=latest" should {
-    test(test4AllItypes, 20000, test4Params, test4Items, test4Users, test4U2i, test4RatingsLatest, genSelectedItems(test4Items), test4ItemsIndexer, test4UsersIndexer, test4RecommendItems)
-  }
-
-  val test4ParamsIgnoreView = test4Params + ("viewParam" -> "ignore")
-
-  val test4RatingsIgnoreViewLatest = List(
-    ("u0", "i0", "5"),
-    ("u0", "i1", "4"),
-    ("u0", "i2", "4"),
-    ("u0", "i3", "2"),
-    ("u1", "i1", "1"))
-
-  // seen won't be affacted by the ignore setting
-  val test4Seen = List(
-    ("u0", "i0"),
-    ("u0", "i1"),
-    ("u0", "i2"),
-    ("u0", "i3"),
-    ("u1", "i0"),
-    ("u1", "i1"))
-
-  "DataPreparator with all actions, all itypes, ignore View actions and conflicts=latest" should {
-    test(test4AllItypes, 20000, test4ParamsIgnoreView, test4Items, test4Users, test4U2i, test4RatingsIgnoreViewLatest, genSelectedItems(test4Items), test4ItemsIndexer, test4UsersIndexer, test4RecommendItems, seen = test4Seen)
-  }
-
-  // note: currently rate action can't be ignored
-  val test4ParamsIgnoreAllExceptView = test4Params + ("viewParam" -> "1", "likeParam" -> "ignore", "dislikeParam" -> "ignore", "conversionParam" -> "ignore")
-
-  val test4RatingsIgnoreAllExceptViewLatest = List(
-    ("u0", "i0", "1"),
-    ("u0", "i1", "1"),
-    ("u0", "i2", "1"),
-    ("u0", "i3", "2"),
-    ("u1", "i0", "1"),
-    ("u1", "i1", "5"))
-
-  "DataPreparator with all actions, all itypes, ignore all actions except View (and Rate) and conflicts=latest" should {
-    test(test4AllItypes, 20000, test4ParamsIgnoreAllExceptView, test4Items, test4Users, test4U2i, test4RatingsIgnoreAllExceptViewLatest, genSelectedItems(test4Items), test4ItemsIndexer, test4UsersIndexer, test4RecommendItems, seen = test4Seen)
-  }
-
-  // note: meaning rate action only
-  val test4ParamsIgnoreAll = test4Params + ("viewParam" -> "ignore", "likeParam" -> "ignore", "dislikeParam" -> "ignore", "conversionParam" -> "ignore")
-
-  val test4RatingsIgnoreAllLatest = List(
-    ("u0", "i0", "3"),
-    ("u0", "i1", "4"),
-    ("u0", "i2", "3"),
-    ("u0", "i3", "2"),
-    ("u1", "i1", "5"))
-
-  "DataPreparator with all actions, all itypes, ignore all actions (except Rate) and conflicts=latest" should {
-    test(test4AllItypes, 20000, test4ParamsIgnoreAll, test4Items, test4Users, test4U2i, test4RatingsIgnoreAllLatest, genSelectedItems(test4Items), test4ItemsIndexer, test4UsersIndexer, test4RecommendItems, seen = test4Seen)
-  }
-
-  val test4ParamsLowest: Map[String, String] = test4Params + ("conflictParam" -> "lowest")
-
-  val test4Itypes_t3 = List("t3")
-  val test4Items_t3 = List(
-    test4ItemsMap("i0"),
-    test4ItemsMap("i1"),
-    test4ItemsMap("i3"))
-
-  val test4RecommendItems_t3 = Some(List("i0", "i3"))
-
-  val test4RatingsLowest_t3 = List(
-    ("u0", "i0", "2"),
-    ("u0", "i1", "1"),
-    ("u0", "i3", "2"),
-    ("u1", "i0", "2"),
-    ("u1", "i1", "1"))
-
-  "DataPreparator with only all actions, some itypes, and conflicts=lowest" should {
-    test(test4Itypes_t3, 20000, test4ParamsLowest, test4Items, test4Users, test4U2i, test4RatingsLowest_t3, genSelectedItems(test4Items_t3), test4ItemsIndexer, test4UsersIndexer, test4RecommendItems_t3)
-  }
-
-  /* test5: test starttime and endtime */
-
-  // starttime, endtime
-  // i0  A |---------|
-  // i1    B |---------|E
-  // i2       C|---------|
-  // i3           |---------|
-  //               D        F G
-
-  val tA = 123122
-  val tB = 123123
-  val tC = 123457
-  val tD = 123679
-  val tE = 543322
-  val tF = 543654
-  val tG = 543655
-
-  val test5AllItypes = List("t1", "t2", "t3", "t4")
-  val test5ItemsMap = Map(
-    // id, itypes, appid, starttime, ct, endtime
-    "i0" -> ("i0", "t1,t2,t3", appid.toString, "123123", "12345", "543210",
-      noInactive),
-    "i1" -> ("i1", "t1,t2", appid.toString, "123456", "12345", "543321",
-      noInactive),
-    "i2" -> ("i2", "t2,t3", appid.toString, "123567", "12345", "543432",
-      noInactive),
-    "i3" -> ("i3", "t2", appid.toString, "123678", "12345", "543654",
-      noInactive)
-  )
-
-  val test5Items = List(
-    test5ItemsMap("i0"),
-    test5ItemsMap("i1"),
-    test5ItemsMap("i2"),
-    test5ItemsMap("i3"))
-
-  val test5ItemsIndexer = Map("i0" -> "0", "i1" -> "4", "i2" -> "7", "i3" -> "8") // map iid to index
-
-  val test5Users = List(Tuple1("u0"), Tuple1("u1"), Tuple1("u2"), Tuple1("u3"))
-  val test5UsersIndexer = Map("u0" -> "0", "u1" -> "1", "u2" -> "2", "u3" -> "3") // map uid to index
-
-  val test5U2i = List(
-    (Rate, "u0", "i0", "123450", "4"),
-    (Like, "u0", "i1", "123457", "PIO_NONE"),
-    (Dislike, "u0", "i2", "123458", "PIO_NONE"),
-    (View, "u0", "i3", "123459", "PIO_NONE"), // NOTE: assume v field won't be missing
-    (Rate, "u1", "i0", "123457", "2"),
-    (Conversion, "u1", "i1", "123458", "PIO_NONE"))
-
-  val test5Ratings = List(
-    ("u0", "i0", "4"),
-    ("u0", "i1", "4"),
-    ("u0", "i2", "2"),
-    ("u0", "i3", "1"),
-    ("u1", "i0", "2"),
-    ("u1", "i1", "5"))
-
-  val test5RecommendItems = Some(List("i0", "i1", "i2", "i3"))
-  val test5RecommendItemsEmpty = Some(List())
-  val test5RecommendItemsi0 = Some(List("i0"))
-  val test5RecommendItemsi0i1 = Some(List("i0", "i1"))
-  val test5RecommendItemsi2i3 = Some(List("i2", "i3"))
-
-  val test5Params: Map[String, String] = Map("viewParam" -> "1", "likeParam" -> "4", "dislikeParam" -> "2", "conversionParam" -> "5",
-    "conflictParam" -> "latest")
-
-  "recommendationTime < all item starttime" should {
-    test(test5AllItypes, tA, test5Params, test5Items, test5Users, test5U2i, test5Ratings, genSelectedItems(test5Items), test5ItemsIndexer, test5UsersIndexer, test5RecommendItemsEmpty)
-  }
-
-  "recommendationTime == earliest starttime" should {
-    test(test5AllItypes, tB, test5Params, test5Items, test5Users, test5U2i, test5Ratings, genSelectedItems(test5Items), test5ItemsIndexer, test5UsersIndexer, test5RecommendItemsi0)
-  }
-
-  "recommendationTime > some items starttime" should {
-    test(test5AllItypes, tC, test5Params, test5Items, test5Users, test5U2i, test5Ratings, genSelectedItems(test5Items), test5ItemsIndexer, test5UsersIndexer, test5RecommendItemsi0i1)
-  }
-
-  "recommendationTime > all item starttime and < all item endtime" should {
-    test(test5AllItypes, tD, test5Params, test5Items, test5Users, test5U2i, test5Ratings, genSelectedItems(test5Items), test5ItemsIndexer, test5UsersIndexer, test5RecommendItems)
-  }
-
-  "recommendationTime > some item endtime" should {
-    test(test5AllItypes, tE, test5Params, test5Items, test5Users, test5U2i, test5Ratings, genSelectedItems(test5Items), test5ItemsIndexer, test5UsersIndexer, test5RecommendItemsi2i3)
-  }
-
-  "recommendationTime == last item endtime" should {
-    test(test5AllItypes, tF, test5Params, test5Items, test5Users, test5U2i, test5Ratings, genSelectedItems(test5Items), test5ItemsIndexer, test5UsersIndexer, test5RecommendItemsEmpty)
-  }
-
-  "recommendationTime > last item endtime" should {
-    test(test5AllItypes, tG, test5Params, test5Items, test5Users, test5U2i, test5Ratings, genSelectedItems(test5Items), test5ItemsIndexer, test5UsersIndexer, test5RecommendItemsEmpty)
-  }
-
-  /* test6: seen action */
-  val test6AllItypes = List("t1", "t2", "t3", "t4")
-  val test6ItemsMap = Map(
-    // id, itypes, appid, starttime, ct, endtime
-    "i0" -> ("i0", "t1,t2,t3", appid.toString, "12345", "12346", "56789",
-      noInactive),
-    "i1" -> ("i1", "t2,t3", appid.toString, "12347", "12348", noEndtime,
-      noInactive),
-    "i2" -> ("i2", "t4", appid.toString, "12349", "12350", "56790",
-      noInactive),
-    "i3" -> ("i3", "t3,t4", appid.toString, "12351", "12352", noEndtime,
-      noInactive))
-
-  val test6Items = List(
-    test6ItemsMap("i0"),
-    test6ItemsMap("i1"),
-    test6ItemsMap("i2"),
-    test6ItemsMap("i3"))
-
-  val test6RecommendItems = Some(List("i0", "i1", "i2", "i3"))
-
-  val test6ItemsIndexer = Map("i0" -> "0", "i1" -> "4", "i2" -> "7", "i3" -> "8") // map iid to index
-
-  val test6Users = List(Tuple1("u0"), Tuple1("u1"), Tuple1("u2"), Tuple1("u3"))
-  val test6UsersIndexer = Map("u0" -> "0", "u1" -> "1", "u2" -> "2", "u3" -> "3") // map uid to index
-
-  val test6U2i = List(
-    (Rate, "u0", "i0", "123450", "4"),
-    (Like, "u0", "i1", "123457", "PIO_NONE"),
-    (Dislike, "u0", "i2", "123458", "PIO_NONE"),
-    (View, "u0", "i3", "123459", "PIO_NONE"), // NOTE: assume v field won't be missing
-    (Rate, "u1", "i0", "123457", "2"),
-    (Conversion, "u1", "i1", "123458", "PIO_NONE"),
-    ("action1", "u0", "i2", "123459", "PIO_NONE"),
-    ("action2", "u1", "i1", "123459", "PIO_NONE"),
-    ("action1", "u2", "i0", "123459", "PIO_NONE")) // custom action only
-
-  val test6Ratings = List(
-    ("u0", "i0", "4"),
-    ("u0", "i1", "4"),
-    ("u0", "i2", "2"),
-    ("u0", "i3", "1"),
-    ("u1", "i0", "2"),
-    ("u1", "i1", "5"))
-
-  val test6seenActions = List("action1", "action2")
-  val test6Seen = List(
-    ("u0", "i2"),
-    ("u1", "i1"),
-    ("u2", "i0"))
-  val test6SeenAll = List(
-    ("u0", "i0"),
-    ("u0", "i1"),
-    ("u0", "i2"),
-    ("u0", "i3"),
-    ("u1", "i0"),
-    ("u1", "i1"))
-
-  val test6Params: Map[String, String] = Map("viewParam" -> "1", "likeParam" -> "4", "dislikeParam" -> "2", "conversionParam" -> "5",
-    "conflictParam" -> "latest")
-
-  "DataPreparator with only all actions, all itypes, no conflict, unseenOnly=true and seenActions" should {
-    test(test6AllItypes, 20000, test6Params, test6Items, test6Users, test6U2i, test6Ratings, genSelectedItems(test6Items), test6ItemsIndexer, test6UsersIndexer, test6RecommendItems, true, test6seenActions, test6Seen)
-  }
-
-  "DataPreparator with only all actions, all itypes, no conflict, unseenOnly=true and without seenActions defined" should {
-    test(test6AllItypes, 20000, test6Params, test6Items, test6Users, test6U2i, test6Ratings, genSelectedItems(test6Items), test6ItemsIndexer, test6UsersIndexer, test6RecommendItems, true, List(), test6SeenAll)
-  }
-
-  "DataPreparator with only all actions, all itypes, no conflict, unseenOnly=false and seenActions defined" should {
-    test(test6AllItypes, 20000, test6Params, test6Items, test6Users, test6U2i, test6Ratings, genSelectedItems(test6Items), test6ItemsIndexer, test6UsersIndexer, test6RecommendItems, false, test6seenActions, List())
-  }
-
-}
diff --git a/process/engines/itemrec/algorithms/hadoop/scalding/mahout/src/test/scala/io/prediction/algorithms/scalding/mahout/itemrec/ModelConstructorTest.scala b/process/engines/itemrec/algorithms/hadoop/scalding/mahout/src/test/scala/io/prediction/algorithms/scalding/mahout/itemrec/ModelConstructorTest.scala
deleted file mode 100644
index 912e48e..0000000
--- a/process/engines/itemrec/algorithms/hadoop/scalding/mahout/src/test/scala/io/prediction/algorithms/scalding/mahout/itemrec/ModelConstructorTest.scala
+++ /dev/null
@@ -1,107 +0,0 @@
-package io.prediction.algorithms.scalding.mahout.itemrec
-
-import org.specs2.mutable._
-
-import com.twitter.scalding._
-
-import io.prediction.commons.filepath.{ AlgoFile, DataFile }
-import io.prediction.commons.scalding.modeldata.ItemRecScores
-import cascading.tuple.{ Tuple, TupleEntry, TupleEntryIterator, Fields }
-
-class ModelConstructorTest extends Specification with TupleConversions {
-
-  val appid = 3
-
-  def test(numRecommendations: Int,
-    //(iindex, iid, itypes, starttime, endtime)
-    items: List[(String, String, String, String, String)],
-    users: List[(String, String)],
-    predicted: List[(String, String)],
-    output: List[(String, String, String, String)]) = {
-
-    val engineid = 4
-    val algoid = 7
-    val evalid = None
-    val modelSet = true
-
-    val dbType = "file"
-    val dbName = "testpath/"
-    val dbHost = Seq()
-    val dbPort = Seq()
-    val hdfsRoot = "testroot/"
-
-    val itemRecScores = output map { case (uid, iid, score, itypes) => (uid, iid, score, itypes, algoid, modelSet) }
-
-    JobTest("io.prediction.algorithms.scalding.mahout.itemrec.ModelConstructor")
-      .arg("dbType", dbType)
-      .arg("dbName", dbName)
-      .arg("hdfsRoot", hdfsRoot)
-      .arg("appid", appid.toString)
-      .arg("engineid", engineid.toString)
-      .arg("algoid", algoid.toString)
-      .arg("modelSet", modelSet.toString)
-      .arg("numRecommendations", numRecommendations.toString)
-      .source(Tsv(AlgoFile(hdfsRoot, appid, engineid, algoid, evalid, "predicted.tsv"), new Fields("uindex", "predicted")), predicted)
-      .source(Tsv(DataFile(hdfsRoot, appid, engineid, algoid, evalid, "itemsIndex.tsv")), items)
-      .source(Tsv(DataFile(hdfsRoot, appid, engineid, algoid, evalid, "usersIndex.tsv")), users)
-      .sink[(String, String, String, String, Int, Boolean)](ItemRecScores(dbType = dbType, dbName = dbName, dbHost = dbHost, dbPort = dbPort, algoid = algoid, modelset = modelSet).getSource) { outputBuffer =>
-        "correctly write model data to a file" in {
-          outputBuffer.toList must containTheSameElementsAs(itemRecScores)
-        }
-      }
-      .run
-      .finish
-  }
-
-  val noEndtime = "PIO_NONE"
-
-  /* test 1*/
-  val test1Items = List(
-    ("0", "i0", "t1,t2,t3", "12346", noEndtime),
-    ("1", "i1", "t1,t2", "12347", noEndtime),
-    ("2", "i2", "t2,t3", "12348", noEndtime),
-    ("3", "i3", "t2", "12349", noEndtime),
-    ("4", "i4", "t1", "12349", noEndtime))
-
-  val test1Users = List(("0", "u0"), ("1", "u1"), ("2", "u2"), ("3", "u3"))
-
-  val test1Predicted = List(("0", "[1:0.123,2:0.456,4:1.2]"), ("1", "[0:1.2]"))
-
-  val test1Output = List(
-    ("u0", "i4,i2,i1", "1.2,0.456,0.123", "[t1],[t2,t3],[t1,t2]"),
-    ("u1", "i0", "1.2", "[t1,t2,t3]"))
-
-  // only output 2 recommendations
-  val test1Output2 = List(
-    ("u0", "i4,i2", "1.2,0.456", "[t1],[t2,t3]"),
-    ("u1", "i0", "1.2", "[t1,t2,t3]"))
-
-  "mahout.itemrec.itembased ModelConstructor with numRecommendations=100" should {
-    test(100, test1Items, test1Users, test1Predicted, test1Output)
-  }
-
-  "mahout.itemrec.itembased ModelConstructor with numRecommendations=2" should {
-    test(2, test1Items, test1Users, test1Predicted, test1Output2)
-  }
-
-  /* test 2: test double comparision */
-  val test2Items = List(
-    ("0", "i0", "t1,t2,t3", "12346", noEndtime),
-    ("1", "i1", "t1,t2", "12347", noEndtime),
-    ("2", "i2", "t2,t3", "12348", noEndtime),
-    ("3", "i3", "t2", "12349", noEndtime))
-
-  val test2Users = List(("0", "u0"), ("1", "u1"), ("2", "u2"), ("3", "u3"))
-
-  val test2Predicted = List(("0", "[0:2,1:123,2:9,3:88]"), ("1", "[0:1]"))
-
-  val test2Output = List(
-    ("u0", "i1,i3,i2,i0", "123.0,88.0,9.0,2.0", "[t1,t2],[t2],[t2,t3],[t1,t2,t3]"),
-    ("u1", "i0", "1.0", "[t1,t2,t3]"))
-
-  "mahout.itemrec.itembased ModelConstructor with numRecommendations=100 (score should not be compared as string)" should {
-
-    test(100, test2Items, test2Users, test2Predicted, test2Output)
-  }
-
-}
diff --git a/process/engines/itemrec/algorithms/hadoop/scalding/mahout/src/test/scala/io/prediction/algorithms/scalding/mahout/itemrec/ParallelALSModelConstructorTest.scala b/process/engines/itemrec/algorithms/hadoop/scalding/mahout/src/test/scala/io/prediction/algorithms/scalding/mahout/itemrec/ParallelALSModelConstructorTest.scala
deleted file mode 100644
index e9449b6..0000000
--- a/process/engines/itemrec/algorithms/hadoop/scalding/mahout/src/test/scala/io/prediction/algorithms/scalding/mahout/itemrec/ParallelALSModelConstructorTest.scala
+++ /dev/null
@@ -1,330 +0,0 @@
-package io.prediction.algorithms.scalding.mahout.itemrec
-
-import org.specs2.mutable._
-
-import com.twitter.scalding._
-
-import io.prediction.commons.filepath.{ AlgoFile, DataFile }
-import io.prediction.commons.scalding.modeldata.ItemRecScores
-import cascading.tuple.{ Tuple, TupleEntry, TupleEntryIterator, Fields }
-
-class ParallelALSModelConstructorTest extends Specification with TupleConversions {
-
-  val appid = 3
-
-  def test(unseenOnly: Boolean, numRecommendations: Int, recommendationTime: Long,
-    items: List[(String, String, String, String, String, String)], //(iindex, iid, itypes, starttime, endtime, inactive)
-    users: List[(String, String)],
-    predicted: List[(String, String)],
-    ratings: List[(String, String, String)],
-    seen: List[(String, String)],
-    output: List[(String, String, String, String)]) = {
-
-    val engineid = 4
-    val algoid = 7
-    val evalid = None
-    val modelSet = true
-
-    val dbType = "file"
-    val dbName = "testpath/"
-    val dbHost = Seq()
-    val dbPort = Seq()
-    val hdfsRoot = "testroot/"
-
-    val itemRecScores = output map { case (uid, iid, score, itypes) => (uid, iid, score, itypes, algoid, modelSet) }
-
-    JobTest("io.prediction.algorithms.scalding.mahout.itemrec.ParallelALSModelConstructor")
-      .arg("dbType", dbType)
-      .arg("dbName", dbName)
-      .arg("hdfsRoot", hdfsRoot)
-      .arg("appid", appid.toString)
-      .arg("engineid", engineid.toString)
-      .arg("algoid", algoid.toString)
-      .arg("modelSet", modelSet.toString)
-      .arg("unseenOnly", unseenOnly.toString)
-      .arg("numRecommendations", numRecommendations.toString)
-      .arg("recommendationTime", recommendationTime.toString)
-      .source(Tsv(AlgoFile(hdfsRoot, appid, engineid, algoid, evalid, "predicted.tsv"), new Fields("uindex", "predicted")), predicted)
-      .source(Csv(DataFile(hdfsRoot, appid, engineid, algoid, evalid, "ratings.csv"), ",", new Fields("uindexR", "iindexR", "ratingR")), ratings)
-      .source(Tsv(DataFile(hdfsRoot, appid, engineid, algoid, evalid, "itemsIndex.tsv")), items)
-      .source(Tsv(DataFile(hdfsRoot, appid, engineid, algoid, evalid, "usersIndex.tsv")), users)
-      .source(Csv(DataFile(hdfsRoot, appid, engineid, algoid, evalid, "seen.csv"), ",", new Fields("uindexS", "iindexS")), seen)
-      .sink[(String, String, String, String, Int, Boolean)](ItemRecScores(dbType = dbType, dbName = dbName, dbHost = dbHost, dbPort = dbPort, algoid = algoid, modelset = modelSet).getSource) { outputBuffer =>
-        "correctly write model data to a file" in {
-          outputBuffer.toList must containTheSameElementsAs(itemRecScores)
-        }
-      }
-      .run
-      .finish
-  }
-
-  def testWithImplicitFeedback(unseenOnly: Boolean, numRecommendations: Int, recommendationTime: Long,
-    items: List[(String, String, String, String, String, String)], //(iindex, iid, itypes, starttime, endtime, inactive)
-    users: List[(String, String)],
-    predicted: List[(String, String)],
-    ratings: List[(String, String, String)],
-    seen: List[(String, String)],
-    output: List[(String, String, String, String)],
-    implicitFeedback: Boolean) = {
-
-    val engineid = 4
-    val algoid = 7
-    val evalid = None
-    val modelSet = true
-
-    val dbType = "file"
-    val dbName = "testpath/"
-    val dbHost = Seq()
-    val dbPort = Seq()
-    val hdfsRoot = "testroot/"
-
-    val itemRecScores = output map { case (uid, iid, score, itypes) => (uid, iid, score, itypes, algoid, modelSet) }
-
-    JobTest("io.prediction.algorithms.scalding.mahout.itemrec.ParallelALSModelConstructor")
-      .arg("dbType", dbType)
-      .arg("dbName", dbName)
-      .arg("hdfsRoot", hdfsRoot)
-      .arg("appid", appid.toString)
-      .arg("engineid", engineid.toString)
-      .arg("algoid", algoid.toString)
-      .arg("modelSet", modelSet.toString)
-      .arg("unseenOnly", unseenOnly.toString)
-      .arg("numRecommendations", numRecommendations.toString)
-      .arg("recommendationTime", recommendationTime.toString)
-      .arg("implicitFeedback", implicitFeedback.toString)
-      .source(Tsv(AlgoFile(hdfsRoot, appid, engineid, algoid, evalid, "predicted.tsv"), new Fields("uindex", "predicted")), predicted)
-      .source(Csv(DataFile(hdfsRoot, appid, engineid, algoid, evalid, "ratings.csv"), ",", new Fields("uindexR", "iindexR", "ratingR")), ratings)
-      .source(Tsv(DataFile(hdfsRoot, appid, engineid, algoid, evalid, "itemsIndex.tsv")), items)
-      .source(Tsv(DataFile(hdfsRoot, appid, engineid, algoid, evalid, "usersIndex.tsv")), users)
-      .source(Csv(DataFile(hdfsRoot, appid, engineid, algoid, evalid, "seen.csv"), ",", new Fields("uindexS", "iindexS")), seen)
-      .sink[(String, String, String, String, Int, Boolean)](ItemRecScores(dbType = dbType, dbName = dbName, dbHost = dbHost, dbPort = dbPort, algoid = algoid, modelset = modelSet).getSource) { outputBuffer =>
-        "correctly write model data to a file" in {
-          outputBuffer.toList must containTheSameElementsAs(itemRecScores)
-        }
-      }
-      .run
-      .finish
-  }
-
-  val noEndtime = "PIO_NONE"
-  val noInactive = "PIO_NONE"
-
-  /* test 1*/
-  val test1Items = List(
-    ("0", "i0", "t1,t2,t3", "12346", noEndtime, noInactive),
-    ("1", "i1", "t1,t2", "12347", noEndtime, noInactive),
-    ("2", "i2", "t2,t3", "12348", noEndtime, noInactive),
-    ("3", "i3", "t2", "12349", noEndtime, noInactive),
-    ("4", "i4", "t1", "12349", noEndtime, noInactive))
-
-  val test1Users = List(("0", "u0"), ("1", "u1"), ("2", "u2"), ("3", "u3"))
-
-  val test1Predicted = List(("0", "[1:0.123,2:0.456,4:1.2]"), ("1", "[0:1.2]"))
-  val test1PredictedWithSeenItems = List(("0", "[1:0.123,2:0.456,0:4.321,3:1.234,4:1.2]"), ("1", "[0:1.2]"))
-
-  val test1Ratings = List(("0", "0", "2.3"), ("0", "3", "4.56"))
-
-  val test1Output = List(
-    ("u0", "i3,i0,i4,i2,i1", "4.56,2.3,1.2,0.456,0.123", "[t2],[t1,t2,t3],[t1],[t2,t3],[t1,t2]"),
-    ("u1", "i0", "1.2", "[t1,t2,t3]"))
-
-  val test1Seen = List(("0", "0"), ("0", "2"))
-  // only output 2 recommendations
-  val test1Output2 = List(
-    ("u0", "i3,i0", "4.56,2.3", "[t2],[t1,t2,t3]"),
-    ("u1", "i0", "1.2", "[t1,t2,t3]"))
-
-  val test1OutputUnseenOnly = List(
-    ("u0", "i4,i1", "1.2,0.123", "[t1],[t1,t2]"),
-    ("u1", "i0", "1.2", "[t1,t2,t3]"))
-
-  val test1OutputUnratedOnly = List(
-    ("u0", "i4,i2,i1", "1.2,0.456,0.123", "[t1],[t2,t3],[t1,t2]"),
-    ("u1", "i0", "1.2", "[t1,t2,t3]"))
-
-  // only output 1 recommendation
-  val test1OutputUnseenOnly1 = List(
-    ("u0", "i4", "1.2", "[t1]"),
-    ("u1", "i0", "1.2", "[t1,t2,t3]"))
-
-  val test1OutputUnratedOnly1 = List(
-    ("u0", "i4", "1.2", "[t1]"),
-    ("u1", "i0", "1.2", "[t1,t2,t3]"))
-
-  "ParallelALSModelConstructor with unseenOnly=false and numRecommendations=100" should {
-    test(false, 100, 1234567890, test1Items, test1Users, test1Predicted, test1Ratings, test1Seen, test1Output)
-  }
-
-  "ParallelALSModelConstructor with unseenOnly=false and numRecommendations=2" should {
-    test(false, 2, 1234567890, test1Items, test1Users, test1Predicted, test1Ratings, test1Seen, test1Output2)
-  }
-
-  "ParallelALSModelConstructor with unseenOnly=true and numRecommendations=100" should {
-    test(true, 100, 1234567890, test1Items, test1Users, test1Predicted, test1Ratings, test1Seen, test1OutputUnseenOnly)
-  }
-
-  "ParallelALSModelConstructor with unseenOnly=true and numRecommendations=1" should {
-    test(true, 1, 1234567890, test1Items, test1Users, test1Predicted, test1Ratings, test1Seen, test1OutputUnseenOnly1)
-  }
-
-  "ParallelALSModelConstructor with unseenOnly=false, numRecommendations=100 and seen items in predicted results" should {
-    test(false, 100, 1234567890, test1Items, test1Users, test1PredictedWithSeenItems, test1Ratings, test1Seen, test1Output)
-  }
-
-  "ParallelALSModelConstructor with unseenOnly=true, numRecommendations=100 and seen items in predicted results" should {
-    test(true, 100, 1234567890, test1Items, test1Users, test1PredictedWithSeenItems, test1Ratings, test1Seen, test1OutputUnseenOnly)
-  }
-
-  /* implicitFeedback */
-  "ParallelALSModelConstructor with unseenOnly=true and numRecommendations=100 and implicitFeedback=true" should {
-    testWithImplicitFeedback(true, 100, 1234567890, test1Items, test1Users, test1Predicted, test1Ratings, test1Seen, test1OutputUnseenOnly, true)
-  }
-
-  "ParallelALSModelConstructor with unseenOnly=true and numRecommendations=100 and implicitFeedback=false" should {
-    testWithImplicitFeedback(true, 100, 1234567890, test1Items, test1Users, test1Predicted, test1Ratings, test1Seen, test1OutputUnseenOnly, false)
-  }
-
-  "ParallelALSModelConstructor with unseenOnly=false and numRecommendations=100 and implicitFeedback=true" should {
-    // should only generate unseen data if testWithImplicitFeedback=true although unseenOnly=false
-    testWithImplicitFeedback(false, 100, 1234567890, test1Items, test1Users, test1Predicted, test1Ratings, test1Seen, test1OutputUnratedOnly, true)
-  }
-
-  "ParallelALSModelConstructor with unseenOnly=false and numRecommendations=100 and implicitFeedback=false" should {
-    testWithImplicitFeedback(false, 100, 1234567890, test1Items, test1Users, test1Predicted, test1Ratings, test1Seen, test1Output, false)
-  }
-
-  /* test 2: test double comparision */
-  val test2Items = List(
-    ("0", "i0", "t1,t2,t3", "12346", noEndtime, noInactive),
-    ("1", "i1", "t1,t2", "12347", noEndtime, noInactive),
-    ("2", "i2", "t2,t3", "12348", noEndtime, noInactive),
-    ("3", "i3", "t2", "12349", noEndtime, noInactive))
-
-  val test2Users = List(("0", "u0"), ("1", "u1"), ("2", "u2"), ("3", "u3"))
-
-  val test2Predicted = List(("0", "[1:123,2:9]"), ("1", "[0:1]"))
-
-  val test2Ratings = List(("0", "0", "2"), ("0", "3", "88"))
-
-  val test2Seen = List(("0", "0"), ("0", "3"))
-
-  val test2Output = List(
-    ("u0", "i1,i3,i2,i0", "123.0,88.0,9.0,2.0", "[t1,t2],[t2],[t2,t3],[t1,t2,t3]"),
-    ("u1", "i0", "1.0", "[t1,t2,t3]"))
-
-  "ParallelALSModelConstructor with unseenOnly=false and numRecommendations=100 (score should not be compared as string)" should {
-
-    test(false, 100, 1234567890, test2Items, test2Users, test2Predicted, test2Ratings, test2Seen, test2Output)
-
-  }
-
-  /* test3: test starttime and endtime */
-
-  // starttime, endtime
-  // i0  A |---------|
-  // i1    B |---------|E
-  // i2       C|---------|
-  // i3           |---------|
-  //               D        F G
-
-  val tA = 123122
-  val tB = 123123
-  val tC = 123457
-  val tD = 123679
-  val tE = 543322
-  val tF = 543654
-  val tG = 543655
-
-  val test3Items = List(
-    ("0", "i0", "t1,t2,t3", "123123", "543210", noInactive),
-    ("1", "i1", "t1,t2", "123456", "543321", noInactive),
-    ("2", "i2", "t2,t3", "123567", "543432", noInactive),
-    ("3", "i3", "t2", "123678", "543654", noInactive))
-
-  val test3ItemsInactive = List(
-    ("0", "i0", "t1,t2,t3", "123123", "543210", noInactive),
-    ("1", "i1", "t1,t2", "123456", "543321", "true"),
-    ("2", "i2", "t2,t3", "123567", "543432", "false"),
-    ("3", "i3", "t2", "123678", "543654", "true"))
-
-  val test3Users = List(("0", "u0"), ("1", "u1"), ("2", "u2"), ("3", "u3"))
-
-  val test3Predicted = List(("0", "[1:123,2:9]"), ("1", "[0:1]"))
-
-  val test3Ratings = List(
-    ("0", "0", "2"), ("0", "3", "88"),
-    ("1", "2", "3"),
-    ("2", "3", "4"))
-
-  val test3Seen = List(
-    ("0", "0"), ("0", "3"),
-    ("1", "2"),
-    ("2", "3"))
-
-  val test3Output = List(
-    ("u0", "i1,i3,i2,i0", "123.0,88.0,9.0,2.0",
-      "[t1,t2],[t2],[t2,t3],[t1,t2,t3]"),
-    ("u1", "i2,i0", "3.0,1.0", "[t2,t3],[t1,t2,t3]"),
-    ("u2", "i3", "4.0", "[t2]"))
-
-  val test3OutputInactive = List(
-    ("u0", "i2,i0", "9.0,2.0",
-      "[t2,t3],[t1,t2,t3]"),
-    ("u1", "i2,i0", "3.0,1.0", "[t2,t3],[t1,t2,t3]"))
-
-  val test3OutputEmpty = List()
-
-  val test3Outputi0 = List(
-    ("u0", "i0", "2.0", "[t1,t2,t3]"),
-    ("u1", "i0", "1.0", "[t1,t2,t3]"))
-
-  val test3Outputi0i1 = List(
-    ("u0", "i1,i0", "123.0,2.0", "[t1,t2],[t1,t2,t3]"),
-    ("u1", "i0", "1.0", "[t1,t2,t3]"))
-
-  val test3Outputi2i3 = List(
-    ("u0", "i3,i2", "88.0,9.0", "[t2],[t2,t3]"),
-    ("u1", "i2", "3.0", "[t2,t3]"),
-    ("u2", "i3", "4.0", "[t2]"))
-
-  val test3Outputi2i3Inactive = List(
-    ("u0", "i2", "9.0", "[t2,t3]"),
-    ("u1", "i2", "3.0", "[t2,t3]"))
-
-  "unseenOnly=false, numRecommendations=100 and recommendationTime < all item starttime" should {
-    test(false, 100, tA, test3Items, test3Users, test3Predicted, test3Ratings, test3Seen, test3OutputEmpty)
-  }
-
-  "unseenOnly=false, numRecommendations=100 and recommendationTime == earliest starttime" should {
-    test(false, 100, tB, test3Items, test3Users, test3Predicted, test3Ratings, test3Seen, test3Outputi0)
-  }
-
-  "unseenOnly=false, numRecommendations=100 and recommendationTime > some items starttime" should {
-    test(false, 100, tC, test3Items, test3Users, test3Predicted, test3Ratings, test3Seen, test3Outputi0i1)
-  }
-
-  "unseenOnly=false, numRecommendations=100 and recommendationTime > all item starttime and < all item endtime" should {
-    test(false, 100, tD, test3Items, test3Users, test3Predicted, test3Ratings, test3Seen, test3Output)
-  }
-
-  "unseenOnly=false, numRecommendations=100 and recommendationTime > all item starttime and < all item endtime with some inactive" should {
-    test(false, 100, tD, test3ItemsInactive, test3Users, test3Predicted, test3Ratings, test3Seen, test3OutputInactive)
-  }
-
-  "unseenOnly=false, numRecommendations=100 and recommendationTime > some item endtime" should {
-    test(false, 100, tE, test3Items, test3Users, test3Predicted, test3Ratings, test3Seen, test3Outputi2i3)
-  }
-
-  "unseenOnly=false, numRecommendations=100 and recommendationTime > some item endtime with some inactive" should {
-    test(false, 100, tE, test3ItemsInactive, test3Users, test3Predicted, test3Ratings, test3Seen, test3Outputi2i3Inactive)
-  }
-
-  "unseenOnly=false, numRecommendations=100 and recommendationTime == last item endtime" should {
-    test(false, 100, tF, test3Items, test3Users, test3Predicted, test3Ratings, test3Seen, test3OutputEmpty)
-  }
-
-  "unseenOnly=false, numRecommendations=100 and recommendationTime > last item endtime" should {
-    test(false, 100, tG, test3Items, test3Users, test3Predicted, test3Ratings, test3Seen, test3OutputEmpty)
-  }
-
-}
diff --git a/process/engines/itemrec/algorithms/hadoop/scalding/randomrank/src/main/scala/io/prediction/algorithms/scalding/itemrec/randomrank/RandomRank.scala b/process/engines/itemrec/algorithms/hadoop/scalding/randomrank/src/main/scala/io/prediction/algorithms/scalding/itemrec/randomrank/RandomRank.scala
deleted file mode 100644
index a99e182..0000000
--- a/process/engines/itemrec/algorithms/hadoop/scalding/randomrank/src/main/scala/io/prediction/algorithms/scalding/itemrec/randomrank/RandomRank.scala
+++ /dev/null
@@ -1,138 +0,0 @@
-package io.prediction.algorithms.scalding.itemrec.randomrank
-
-import com.twitter.scalding._
-
-import io.prediction.commons.scalding.appdata.{ Items, Users }
-import io.prediction.commons.scalding.modeldata.ItemRecScores
-import io.prediction.commons.filepath.{ AlgoFile }
-import io.prediction.commons.appdata.{ Item }
-
-/**
- * Source:
- *
- * Sink:
- *
- * Description:
- *
- * Args:
- * --training_dbType: <string> training_appdata DB type
- * --training_dbName: <string>
- * --training_dbHost: <string> optional
- * --training_dbPort: <int> optional
- *
- * --modeldata_dbType: <string> modeldata DB type
- * --modeldata_dbName: <string>
- * --modeldata_dbHost: <string> optional
- * --modeldata_dbPort <int> optional
- *
- * --hdfsRoot: <string>. Root directory of the HDFS
- *
- * --appid: <int>
- * --engineid: <int>
- * --algoid: <int>
- * --evalid: <int>. optional. Offline Evaluation if evalid is specified
- *
- * --itypes: <string separated by white space>. optional. eg "--itypes type1 type2". If no --itypes specified, then ALL itypes will be used.
- * --numRecommendations: <int>. number of recommendations to be generated
- * --modelSet: <boolean> (true/false). flag to indicate which set
- * --recommendationTime: <long> (eg. 9876543210). recommend items with starttime <= recommendationTime and endtime > recommendationTime
- *
- * Example:
- * hadoop jar PredictionIO-Process-Hadoop-Scala-assembly-0.1.jar io.prediction.algorithms.scalding.itemrec.randomrank.RandomRank --hdfs --training_dbType mongodb --training_dbName predictionio_appdata --training_dbHost localhost --training_dbPort 27017 --modeldata_dbType mongodb --modeldata_dbName predictionio_modeldata --modeldata_dbHost localhost --modeldata_dbPort 27017 --hdfsRoot predictionio/ --appid 1 --engineid 1 --algoid 18 --modelSet true
- */
-class RandomRank(args: Args) extends Job(args) {
-
-  /**
-   * parse args
-   */
-  val training_dbTypeArg = args("training_dbType")
-  val training_dbNameArg = args("training_dbName")
-  val training_dbHostArg = args.list("training_dbHost")
-  val training_dbPortArg = args.list("training_dbPort") map (x => x.toInt)
-
-  val modeldata_dbTypeArg = args("modeldata_dbType")
-  val modeldata_dbNameArg = args("modeldata_dbName")
-  val modeldata_dbHostArg = args.list("modeldata_dbHost")
-  val modeldata_dbPortArg = args.list("modeldata_dbPort") map (x => x.toInt)
-
-  val hdfsRootArg = args("hdfsRoot")
-
-  val appidArg = args("appid").toInt
-  val engineidArg = args("engineid").toInt
-  val algoidArg = args("algoid").toInt
-  val evalidArg = args.optional("evalid") map (x => x.toInt)
-  val OFFLINE_EVAL = (evalidArg != None) // offline eval mode
-
-  val preItypesArg = args.list("itypes")
-  val itypesArg: Option[List[String]] = if (preItypesArg.mkString(",").length == 0) None else Option(preItypesArg)
-
-  val numRecommendationsArg = args("numRecommendations").toInt
-
-  val modelSetArg = args("modelSet").toBoolean
-  val recommendationTimeArg = args("recommendationTime").toLong
-
-  /**
-   * source
-   */
-
-  // get appdata
-  // NOTE: if OFFLINE_EVAL, read from training set, and use evalid as appid when read Items and U2iActions
-  val trainingAppid = if (OFFLINE_EVAL) evalidArg.get else appidArg
-
-  // get items data
-  val items = Items(appId = trainingAppid, itypes = itypesArg,
-    dbType = training_dbTypeArg, dbName = training_dbNameArg, dbHost = training_dbHostArg, dbPort = training_dbPortArg).readObj('item)
-    .mapTo('item -> ('iidx, 'itypes, 'starttime, 'endtime, 'inactive)) {
-      item: Item =>
-        (item.id,
-          item.itypes,
-          item.starttime.map(_.getMillis()).get,
-          item.endtime.map(_.getMillis()),
-          item.inactive.getOrElse(false)
-        )
-    }
-
-  val users = Users(appId = trainingAppid,
-    dbType = training_dbTypeArg, dbName = training_dbNameArg, dbHost = training_dbHostArg, dbPort = training_dbPortArg).readData('uid)
-
-  // TODO: unseenOnly filtering (need u2iActions)
-
-  /**
-   * sink
-   */
-  val itemRecScores = ItemRecScores(dbType = modeldata_dbTypeArg, dbName = modeldata_dbNameArg, dbHost = modeldata_dbHostArg, dbPort = modeldata_dbPortArg, algoid = algoidArg, modelset = modelSetArg)
-
-  //val scoresFile = Tsv(AlgoFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "itemRecScores.tsv"))
-
-  /**
-   * computation
-   */
-  val itemsWithKey = items
-    .filter('starttime, 'endtime, 'inactive) { fields: (Long, Option[Long], Boolean) =>
-      // only keep items with valid starttime and endtime
-      val (starttimeI, endtimeI, inactive) = fields
-
-      val keepThis: Boolean = (starttimeI, endtimeI) match {
-        case (start, None) => (recommendationTimeArg >= start)
-        case (start, Some(end)) => ((recommendationTimeArg >= start) && (recommendationTimeArg < end))
-        case _ => {
-          assert(false, s"Unexpected item starttime ${starttimeI} and endtime ${endtimeI}")
-          false
-        }
-      }
-      keepThis && (!inactive)
-    }
-    .map(() -> 'itemKey) { u: Unit => 1 }
-
-  val usersWithKey = users.map(() -> 'userKey) { u: Unit => 1 }
-
-  val scores = usersWithKey.joinWithSmaller('userKey -> 'itemKey, itemsWithKey)
-    .map(() -> 'score) { u: Unit => scala.util.Random.nextDouble() }
-    .project('uid, 'iidx, 'score, 'itypes)
-    .groupBy('uid) { _.sortBy('score).reverse.take(numRecommendationsArg) }
-    // another way to is to do toList then take top n from List. But then it would create an unncessary long List
-    // for each group first. not sure which way is better.
-    .groupBy('uid) { _.sortBy('score).reverse.toList[(String, Double, List[String])](('iidx, 'score, 'itypes) -> 'iidsList) }
-    .then(itemRecScores.writeData('uid, 'iidsList, algoidArg, modelSetArg) _)
-
-}
diff --git a/process/engines/itemrec/algorithms/hadoop/scalding/randomrank/src/test/scala/io/prediction/algorithms/scalding/itemrec/randomrank/RandomRankTest.scala b/process/engines/itemrec/algorithms/hadoop/scalding/randomrank/src/test/scala/io/prediction/algorithms/scalding/itemrec/randomrank/RandomRankTest.scala
deleted file mode 100644
index 4796825..0000000
--- a/process/engines/itemrec/algorithms/hadoop/scalding/randomrank/src/test/scala/io/prediction/algorithms/scalding/itemrec/randomrank/RandomRankTest.scala
+++ /dev/null
@@ -1,306 +0,0 @@
-package io.prediction.algorithms.scalding.itemrec.randomrank
-
-import org.specs2.mutable._
-
-import com.twitter.scalding._
-
-import io.prediction.commons.scalding.appdata.{ Items, Users }
-import io.prediction.commons.scalding.modeldata.{ ItemRecScores }
-import io.prediction.commons.filepath.{ AlgoFile }
-
-class RandomRankTest extends Specification with TupleConversions {
-
-  def test(algoid: Int, modelSet: Boolean,
-    itypes: List[String],
-    numRecommendations: Int,
-    recommendationTime: Long,
-    items: List[(String, String, String, String, String, String, String)], // id, itypes, appid, starttime, ct, endtime, inactive
-    users: List[(String, String)],
-    itemRecScores: List[(String, String, String, String, Int, Boolean)]) = {
-
-    val training_dbType = "file"
-    val training_dbName = "testpath/"
-
-    val modeldata_dbType = "file"
-    val modeldata_dbName = "testpath/"
-
-    val hdfsRoot = "testpath/"
-
-    val appid = 7
-    val engineid = 10
-    val evalid = None
-
-    JobTest("io.prediction.algorithms.scalding.itemrec.randomrank.RandomRank")
-      .arg("training_dbType", training_dbType)
-      .arg("training_dbName", training_dbName)
-      .arg("modeldata_dbType", modeldata_dbType)
-      .arg("modeldata_dbName", modeldata_dbName)
-      .arg("hdfsRoot", hdfsRoot)
-      .arg("appid", appid.toString)
-      .arg("engineid", engineid.toString)
-      .arg("algoid", algoid.toString)
-      .arg("itypes", itypes)
-      .arg("numRecommendations", numRecommendations.toString)
-      .arg("modelSet", modelSet.toString)
-      .arg("recommendationTime", recommendationTime.toString)
-      .source(Items(appId = appid, itypes = Some(itypes),
-        dbType = training_dbType, dbName = training_dbName, dbHost = Seq(), dbPort = Seq()).getSource, items)
-      .source(Users(appId = appid,
-        dbType = training_dbType, dbName = training_dbName, dbHost = Seq(), dbPort = Seq()).getSource, users)
-      /*
-      .sink[(String, String)](Tsv(AlgoFile(hdfsRoot, appid, engineid, algoid, evalid, "itemRecScores.tsv"))) { outputBuffer =>
-
-        def takeOutScoresAndItypes(d: List[(String, String, Double, String, Int, Boolean)]) = {
-          d map {x => (x._1, x._2) }
-        }
-
-        "generate correct user and item pairs in AlgoFile" in {
-          val result = outputBuffer.toList
-          val expected = takeOutScoresAndItypes(itemRecScores)
-
-          result must containTheSameElementsAs(expected)
-        }
-
-      }*/
-      .sink[(String, String, String, String, Int, Boolean)](ItemRecScores(dbType = modeldata_dbType, dbName = modeldata_dbName, dbHost = Seq(), dbPort = Seq(), algoid = algoid, modelset = modelSet).getSource) { outputBuffer =>
-
-        def takeOutScores(d: List[(String, String, String, String, Int, Boolean)]) = {
-          // don't check score and itypes.
-          // for iids, don't check order. convert to set
-          d map { x => (x._1, x._2.split(",").toSet, x._5, x._6) }
-        }
-
-        def getScoresOnly(d: List[(String, String, String, String, Int, Boolean)]) = {
-          d flatMap { x => x._3.split(",").toList.map(_.toDouble) }
-        }
-
-        def getIids(d: List[(String, String, String, String, Int, Boolean)]) = {
-          // List(List("i0", "i1"), List("i1", "i0"), ...)
-
-          d map { x => x._2.split(",").toList }
-        }
-
-        def getItypes(d: List[(String, String, String, String, Int, Boolean)]) = {
-          //("u0", "i0,i1", "0.0,0.0", "[t1,t2,t3],[t2,t3]", algoid, modelSet),
-          // => List( List( (i0, List(t1,t2,t3)) , (i1, List(t2,t3)) )
-          d.map { x =>
-            val itypesList = x._4.split("],").toList.map(x => x.stripPrefix("[").stripSuffix("]").split(",").toList)
-            val iidList = x._2.split(",").toList
-
-            iidList zip itypesList
-          }
-        }
-
-        "generate correct user and item pairs in modeldata" in {
-
-          // don't check scores since they are random
-          val result = takeOutScores(outputBuffer.toList)
-          val expected = takeOutScores(itemRecScores)
-
-          result must containTheSameElementsAs(expected)
-
-        }
-
-        "generate different scores for each pair in modeldata" in {
-          // very simple way to check if the scores are random
-          // (just to check if they are different)
-
-          val scoresList: List[Double] = getScoresOnly(outputBuffer.toList)
-          val scoresSet = scoresList.toSet
-
-          scoresSet.size must be_==(scoresList.size)
-
-        }
-
-        if (getIids(itemRecScores).flatMap { x => x }.toSet.size > 3) {
-          // only check this if the iids in itemRecScores are more than 1
-          "not generate same order of iid for all uid group" in {
-            if (!(getIids(outputBuffer.toList).toSet.size > 1)) {
-              println(outputBuffer)
-              println(getIids(outputBuffer.toList).toSet)
-            }
-            getIids(outputBuffer.toList).toSet.size must be_>(1)
-
-          }
-        }
-
-        "itypes order match the iids order" in {
-
-          // extract (iid, itypes) from the output
-          val itypesList = getItypes(outputBuffer.toList)
-          val itemsMap = items.map(x =>
-            (x._1, x)).toMap
-
-          // use the iid only and contruct the (iid, itypes)
-          val expected = getIids(outputBuffer.toList).map(x =>
-            // x is List of iid
-            // create the List of item types using the iid
-            x.map(x => (x, itemsMap(x)._2.split(",").toList))
-          )
-
-          itypesList must be_==(expected)
-
-        }
-
-      }
-      .run
-      .finish
-  }
-
-  val largeNumber: Long = scala.Long.MaxValue // larger than any item starttime
-  val noEndtime = "PIO_NONE"
-  val noInactive = "PIO_NONE"
-
-  "randomrank.RandomRank with selected itypes" should {
-
-    val algoid = 12
-    val modelSet = false
-    val itypes = List("t1", "t2")
-    val items = List(
-      ("i0", "t1,t2,t3", "19", "123456", "345678", noEndtime, noInactive),
-      ("i1", "t2,t3", "19", "123457", "567890", noEndtime, noInactive),
-      ("i2", "t4", "19", "21", "88", noEndtime, noInactive),
-      ("i3", "t3,t4", "19", "9876543210", "67890", noEndtime, noInactive))
-
-    val users = List(("u0", "3"), ("u1", "3"), ("u2", "3"), ("u3", "3"))
-    val itemRecScores = List(
-      ("u0", "i0,i1", "0.0,0.0", "[t1,t2,t3],[t2,t3]", algoid, modelSet),
-      ("u1", "i0,i1", "0.0,0.0", "[t1,t2,t3],[t2,t3]", algoid, modelSet),
-      ("u2", "i0,i1", "0.0,0.0", "[t1,t2,t3],[t2,t3]", algoid, modelSet),
-      ("u3", "i0,i1", "0.0,0.0", "[t1,t2,t3],[t2,t3]", algoid, modelSet))
-
-    test(algoid, modelSet, itypes, 500, largeNumber, items, users, itemRecScores)
-
-  }
-
-  "randomrank.RandomRank with all itypes" should {
-
-    val algoid = 12
-    val modelSet = false
-    val itypes = List("")
-    val items = List(
-      ("i0", "t1,t2,t3", "19", "123456", "345678", noEndtime, noInactive),
-      ("i1", "t2,t3", "19", "123457", "567890", noEndtime, noInactive),
-      ("i2", "t4", "19", "21", "88", noEndtime, noInactive),
-      ("i3", "t3,t4", "19", "9876543210", "67890", noEndtime, noInactive))
-    val users = List(("u0", "3"), ("u1", "3"), ("u2", "3"), ("u3", "3"))
-    val itemRecScores = List(
-      ("u0", "i0,i1,i2,i3", "0.0,0.0,0.0,0.0", "[t1,t2,t3],[t2,t3],[t4],[t3,t4]", algoid, modelSet),
-      ("u1", "i0,i1,i2,i3", "0.0,0.0,0.0,0.0", "[t1,t2,t3],[t2,t3],[t4],[t3,t4]", algoid, modelSet),
-      ("u2", "i0,i1,i2,i3", "0.0,0.0,0.0,0.0", "[t1,t2,t3],[t2,t3],[t4],[t3,t4]", algoid, modelSet),
-      ("u3", "i0,i1,i2,i3", "0.0,0.0,0.0,0.0", "[t1,t2,t3],[t2,t3],[t4],[t3,t4]", algoid, modelSet))
-
-    test(algoid, modelSet, itypes, 500, largeNumber, items, users, itemRecScores)
-
-  }
-
-  "randomrank.RandomRank with all itypes and some inactive" should {
-
-    val algoid = 12
-    val modelSet = false
-    val itypes = List("")
-    val items = List(
-      ("i0", "t1,t2,t3", "19", "123456", "345678", noEndtime, noInactive),
-      ("i1", "t2,t3", "19", "123457", "567890", noEndtime, "true"),
-      ("i2", "t4", "19", "21", "88", noEndtime, "false"),
-      ("i3", "t3,t4", "19", "9876543210", "67890", noEndtime, noInactive))
-    val users = List(("u0", "3"), ("u1", "3"), ("u2", "3"), ("u3", "3"))
-    val itemRecScores = List(
-      ("u0", "i0,i2,i3", "0.0,0.0,0.0", "[t1,t2,t3],[t4],[t3,t4]",
-        algoid, modelSet),
-      ("u1", "i0,i2,i3", "0.0,0.0,0.0", "[t1,t2,t3],[t4],[t3,t4]",
-        algoid, modelSet),
-      ("u2", "i0,i2,i3", "0.0,0.0,0.0", "[t1,t2,t3],[t4],[t3,t4]",
-        algoid, modelSet),
-      ("u3", "i0,i2,i3", "0.0,0.0,0.0", "[t1,t2,t3],[t4],[t3,t4]",
-        algoid, modelSet))
-
-    test(algoid, modelSet, itypes, 500, largeNumber, items, users, itemRecScores)
-
-  }
-
-  // TODO: test with smaller number of numRecommendations (but can't know expected result beacause the score is random...)
-
-  /* test 2: test starttime and endtime */
-  // starttime, endtime
-  // i0  A |---------|
-  // i1    B |---------|E
-  // i2       C|---------|
-  // i3           |---------|
-  //               D        F G
-
-  val tA = 123122
-  val tB = 123123
-  val tC = 123457
-  val tD = 123679
-  val tE = 543322
-  val tF = 543654
-  val tG = 543655
-
-  val test2Algoid = 12
-  val test2ModelSet = false
-
-  val test2ItypesAll = List("t1", "t2", "t3", "t4")
-  val test2Items = List(
-    ("i0", "t1,t2,t3", "19", "123123", "4", "543210", noInactive),
-    ("i1", "t2,t3", "19", "123456", "5", "543321", noInactive),
-    ("i2", "t4", "19", "123567", "6", "543432", noInactive),
-    ("i3", "t3,t4", "19", "123678", "7", "543654", noInactive))
-
-  val test2Users = List(("u0", "3"), ("u1", "3"), ("u2", "3"), ("u3", "3"))
-
-  val test2ItemRecScoresAll = List(
-    ("u0", "i3,i2,i1,i0", "0.0,0.0,0.0,0.0", "[t3,t4],[t4],[t2,t3],[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("u1", "i3,i2,i1,i0", "0.0,0.0,0.0,0.0", "[t3,t4],[t4],[t2,t3],[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("u2", "i3,i2,i1,i0", "0.0,0.0,0.0,0.0", "[t3,t4],[t4],[t2,t3],[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("u3", "i3,i2,i1,i0", "0.0,0.0,0.0,0.0", "[t3,t4],[t4],[t2,t3],[t1,t2,t3]", test2Algoid, test2ModelSet))
-
-  val test2ItemRecScoresEmpty = List()
-
-  val test2ItemRecScoresi0 = List(
-    ("u0", "i0", "0.0", "[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("u1", "i0", "0.0", "[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("u2", "i0", "0.0", "[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("u3", "i0", "0.0", "[t1,t2,t3]", test2Algoid, test2ModelSet))
-
-  val test2ItemRecScoresi0i1 = List(
-    ("u0", "i1,i0", "0.0,0.0", "[t2,t3],[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("u1", "i1,i0", "0.0,0.0", "[t2,t3],[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("u2", "i1,i0", "0.0,0.0", "[t2,t3],[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("u3", "i1,i0", "0.0,0.0", "[t2,t3],[t1,t2,t3]", test2Algoid, test2ModelSet))
-
-  val test2ItemRecScoresi2i3 = List(
-    ("u0", "i3,i2", "0.0,0.0", "[t3,t4],[t4]", test2Algoid, test2ModelSet),
-    ("u1", "i3,i2", "0.0,0.0", "[t3,t4],[t4]", test2Algoid, test2ModelSet),
-    ("u2", "i3,i2", "0.0,0.0", "[t3,t4],[t4]", test2Algoid, test2ModelSet),
-    ("u3", "i3,i2", "0.0,0.0", "[t3,t4],[t4]", test2Algoid, test2ModelSet))
-
-  "recommendationTime < all item starttime" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tA, test2Items, test2Users, test2ItemRecScoresEmpty)
-  }
-
-  "recommendationTime == earliest starttime" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tB, test2Items, test2Users, test2ItemRecScoresi0)
-  }
-
-  "recommendationTime > some items starttime" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tC, test2Items, test2Users, test2ItemRecScoresi0i1)
-  }
-
-  "recommendationTime > all item starttime and < all item endtime" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tD, test2Items, test2Users, test2ItemRecScoresAll)
-  }
-
-  "recommendationTime > some item endtime" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tE, test2Items, test2Users, test2ItemRecScoresi2i3)
-  }
-
-  "recommendationTime == last item endtime" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tA, test2Items, test2Users, test2ItemRecScoresEmpty)
-  }
-
-  "recommendationTime > last item endtime" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tA, test2Items, test2Users, test2ItemRecScoresEmpty)
-  }
-
-}
diff --git a/process/engines/itemrec/algorithms/scala/featurebased/build.sbt b/process/engines/itemrec/algorithms/scala/featurebased/build.sbt
deleted file mode 100644
index 781bb9e..0000000
--- a/process/engines/itemrec/algorithms/scala/featurebased/build.sbt
+++ /dev/null
@@ -1,35 +0,0 @@
-import xerial.sbt.Pack._
-
-name := "predictionio-process-itemrec-algorithms-scala-featurebased"
-
-libraryDependencies ++= Seq(
-  "ch.qos.logback" % "logback-classic" % "1.1.1",
-  "com.twitter" %% "scalding-args" % "0.8.11",
-  "org.clapper" %% "grizzled-slf4j" % "1.0.1",
-  "commons-io" % "commons-io" % "2.4")
-
-packSettings
-
-packJarNameConvention := "full"
-
-packExpandedClasspath := true
-
-packGenerateWindowsBatFile := false
-
-packMain := Map(
-  "itemrec.featurebased.Batch" ->
-  "io.prediction.algorithms.itemrec.featurebased.UserProfileRecommendationBatch",
-  "itemrec.featurebased.Realtime" ->
-  "io.prediction.algorithms.itemrec.featurebased.UserProfileRecommendationRealtime"
-  )
-
-packJvmOpts := Map(
-  "itemrec.featurebased.Batch" -> Common.packCommonJvmOpts,
-  "itemrec.featurebased.Realtime" -> Common.packCommonJvmOpts
-  )
-
-
-testOptions in Test += Tests.Argument("failtrace")
-
-// Can exclude some paths
-// testOptions in Test += Tests.Argument("tracefilter", "/io.prediction.algorithms.itemrec.featurebased.CustomMatcher")
diff --git a/process/engines/itemrec/algorithms/scala/featurebased/src/main/resources/application.conf b/process/engines/itemrec/algorithms/scala/featurebased/src/main/resources/application.conf
deleted file mode 100644
index c85803b..0000000
--- a/process/engines/itemrec/algorithms/scala/featurebased/src/main/resources/application.conf
+++ /dev/null
@@ -1,30 +0,0 @@
-# Used by PredictionIO Commons
-io.prediction.base=.
-
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.host=localhost
-io.prediction.commons.appdata.db.port=27017
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.host=localhost
-io.prediction.commons.appdata.test.db.port=27017
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.host=localhost
-io.prediction.commons.appdata.training.db.port=27017
-
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.host=localhost
-io.prediction.commons.appdata.validation.db.port=27017
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.host=localhost
-io.prediction.commons.modeldata.db.port=27017
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.host=localhost
-io.prediction.commons.modeldata.training.db.port=27017
-
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.host=localhost
-io.prediction.commons.settings.db.port=27017
diff --git a/process/engines/itemrec/algorithms/scala/featurebased/src/main/scala/Batch.scala b/process/engines/itemrec/algorithms/scala/featurebased/src/main/scala/Batch.scala
deleted file mode 100644
index be71336..0000000
--- a/process/engines/itemrec/algorithms/scala/featurebased/src/main/scala/Batch.scala
+++ /dev/null
@@ -1,107 +0,0 @@
-package io.prediction.algorithms.itemrec.featurebased
-
-import grizzled.slf4j.Logger
-import io.prediction.commons.Config
-import com.twitter.scalding.Args
-import io.prediction.commons.appdata.U2IAction
-import io.prediction.commons.modeldata.ItemRecScore
-
-/*
- * - construct feature-list, Seq[String]
- * - construct user-feature-map : Map[User, Seq[Double]]
- * - recommend: Map[User, Seq[(Item, Double)]]
- * - modelCon: output ItemRec in datastore.
- */
-
-object UserProfileRecommendationBatch {
-  val logger = Logger(UserProfileRecommendationBatch.getClass)
-  val commonsConfig = new Config
-
-
-  def recommend(
-    userFeaturesMap: Map[String, Seq[Double]],
-    itemTypesMap: Map[String, Seq[String]],
-    allItypes: Seq[String],
-    invItypes: Map[String, Int],
-    users: Seq[String],
-    numRecommendations: Int
-  ) : Map[String, Seq[(String, Double)]] = {
-
-    users.map { uid => {
-      val userFeatures = userFeaturesMap(uid)
-      
-      val itemScoreMap = itemTypesMap.map{ case(iid, itypes) => {
-        val score = itypes
-        .map(itype => invItypes(itype))
-        .map(idx => userFeatures(idx))
-        .sum
-        // FIXME: not decided yet. if item has too many types, need to discount
-        // them
-        // / itypes.size  
-        (iid, score)
-      }}
-
-      val top = itemScoreMap.toList.sortBy(-_._2).take(numRecommendations)
-      (uid, top)
-    }}.toMap
-  }
-
-  def modelCon(appid: Int, algoid: Int, modelset: Boolean,
-    userRecommendationsMap: Map[String, Seq[(String, Double)]],
-    itemTypesMap: Map[String, Seq[String]]
-  ) = {
-    val modeldataDb = commonsConfig.getModeldataItemRecScores
-
-    userRecommendationsMap.foreach{ case(user, recommendations) => {
-      modeldataDb.insert(ItemRecScore(
-        uid = user,
-        iids = recommendations.map(_._1),
-        scores = recommendations.map(_._2),
-        itypes = recommendations.map{ e => itemTypesMap(e._1) },
-        appid = appid,
-        algoid = algoid,
-        modelset = modelset))
-    }}
-  }
-
-  def run(appid: Int, algoid: Int, modelset: Boolean,
-    numRecommendations: Int,
-    optFeatureItypesStr: Option[String],
-    whiteItypes: Seq[String]) = {
-    val (userFeaturesMap, featureItypes, itemItypesMap, whiteItems) = (
-      UserProfileRecommendation.constructUserFeaturesMapFromArg(
-        appid, optFeatureItypesStr, whiteItypes))
-
-    val userRecommendationsMap = UserProfileRecommendation.recommend(
-      userFeaturesMap,
-      featureItypes,
-      itemItypesMap,
-      whiteItems,
-      numRecommendations
-    )
-    
-    modelCon(appid, algoid, modelset, userRecommendationsMap, itemItypesMap)
-  }
-
-  def main(cmdArgs: Array[String]) = {
-    val args = Args(cmdArgs)
-
-    val appid = args("appid").toInt
-    val algoid = args("algoid").toInt
-    val modelset = args("modelSet").toBoolean
-    val numRecommendations = args.optional("numRecommendations")
-    .getOrElse("10").toInt
-    val optFeatureItypesStr = args.optional("featureItypes")
-    val whiteItypes = args.list("itypes")
-
-    run(appid, algoid, modelset, numRecommendations,
-      optFeatureItypesStr, whiteItypes)
-    /*
-    if (verbose) {
-      UserProfileRecommendation.printRecommendations(
-        userFeaturesMap, featureItypes,
-        userRecommendationsMap, itemItypesMap)
-    }
-    */
-  }
-}
diff --git a/process/engines/itemrec/algorithms/scala/featurebased/src/main/scala/Common.scala b/process/engines/itemrec/algorithms/scala/featurebased/src/main/scala/Common.scala
deleted file mode 100644
index 0a23b51..0000000
--- a/process/engines/itemrec/algorithms/scala/featurebased/src/main/scala/Common.scala
+++ /dev/null
@@ -1,199 +0,0 @@
-package io.prediction.algorithms.itemrec.featurebased
-
-import grizzled.slf4j.Logger
-import io.prediction.commons.Config
-import com.twitter.scalding.Args
-import io.prediction.commons.appdata.{ Item, User, U2IAction }
-import io.prediction.commons.modeldata.ItemRecScore
-
-class UserProfileRecommendationException(msg: String = null, cause: Throwable=null) 
-extends RuntimeException(msg, cause)
-
-
-// Only consider items rated >= 3
-object UserProfileRecommendation {
-  val logger = Logger(UserProfileRecommendation.getClass)
-  val commonsConfig = new Config
-
-  // Return itypes if whiteItypesStr is empty or opt is None
-  // If WhiteItypesStr is specify, return their intersection, using whiteItypes
-  // order.
-  def getFeatureItypes(itypes: Seq[String], optFeatureItypesStr: Option[String])
-  : Seq[String] = {
-    if (optFeatureItypesStr.isEmpty)
-      return itypes
-
-    val featureItypesStr = optFeatureItypesStr.get
-    if (featureItypesStr == "")
-      return itypes
-
-    val itypeSet = itypes.toSet
-    featureItypesStr.split(',').filter{
-      featureItype => itypeSet.contains(featureItype)
-    }
-  }
-
-  def getUsers(appid: Int): Seq[User] = {
-    val usersDb = commonsConfig.getAppdataUsers
-    usersDb.getByAppid(appid).toSeq
-  }
-
-  // distinct itypes
-  // iid -> itypes
-  // [white iid]
-  def getItems(appid: Int, whiteItypes: Seq[String] = Seq[String]()): (
-    Seq[String], Map[String, Seq[String]], Seq[String]) = {
-    val itemsDb = commonsConfig.getAppdataItems
-
-    val trainingItems = (if (whiteItypes.length == 0) itemsDb.getByAppid(appid)
-      else itemsDb.getByAppidAndItypes(appid, whiteItypes)).toSeq
-
-    val itemTypesMap = trainingItems.map(item => (item.id, item.itypes)).toMap
-
-    val itypes: Seq[String]  = itemTypesMap.values.toSeq.flatten.distinct
-
-    // create white item list, filter inactive items. Note that it is
-    // independent of the whiteItypes.
-    val whiteItems = itemsDb.getByAppid(appid)
-      .filter(!_.inactive.getOrElse(false)).map(_.id).toSeq
-    
-    return (itypes, itemTypesMap, whiteItems)
-  }
-
-  def getU2I(appid: Int): (Map[String, Seq[U2IAction]]) = {
-    val u2iDb = commonsConfig.getAppdataU2IActions
-    u2iDb.getAllByAppid(appid).toSeq.groupBy(_.uid)
-  }
-
-  // Only featureInvItypes is used.
-  def constructUserFeatureMap(
-    featureInvItypes: Map[String, Int],
-    itemTypesMap: Map[String, Seq[String]],
-    uidList: Seq[String],
-    userU2IsMap: Map[String, Seq[U2IAction]]) : Map[String, Seq[Double]] = {
-    val userFeatureMap = uidList.map{ user => {
-      val u2is = userU2IsMap.getOrElse(user, Seq[U2IAction]())
-
-      // TODO. Discount early actions
-      val userFeatureList = u2is
-      .filter(_.action == "rate")
-      .filter(_.v.getOrElse(0) > 3)
-      .filter(u2i => itemTypesMap.contains(u2i.iid))
-      .map{ u2i => {
-        // Only populate the featurelisted itypes
-        val feature = Array.fill[Int](featureInvItypes.size)(0)
-        itemTypesMap(u2i.iid)
-          .filter(featureInvItypes.contains)
-          .foreach(e => feature(featureInvItypes(e)) = 1)
-
-        feature
-      }}
-
-      val userFeature = (
-        if (userFeatureList.length > 0) {
-          val sumUserFeature = userFeatureList.transpose.map(_.sum).toList
-          if (sumUserFeature.sum == 0) {
-            // This happens when all items rated by the user have no interested
-            // itypes. In such case we have to fill null.
-            Seq.fill(featureInvItypes.size)(1)
-          } else {
-            sumUserFeature
-          }
-        } else {
-          // For user has no feature, assumes uniform.
-          Seq.fill(featureInvItypes.size)(1)
-        }
-      )
-      
-      val featureSum = userFeature.sum 
-      val normalizedUserFeature = userFeature.map(_.toDouble / featureSum)
-
-      (user, normalizedUserFeature.toList)
-    }}.toMap
-    userFeatureMap
-  }
-
-  // Notice that the third return value is item to *all* its itypes. It is
-  // important to pass non-feature itypes since we need these info in modeldata
-  // for other pruning.
-  def constructUserFeaturesMapFromArg(
-    appid: Int,
-    optFeatureItypesStr: Option[String] = None,
-    whiteItypes: Seq[String] = Seq[String]()) : (
-    Map[String, Seq[Double]],  // User -> Itype Scores
-    Seq[String],  // Itype Feature List
-    Map[String, Seq[String]],  // Item -> All Itypes
-    Seq[String]  // Whitelist of items can be passed to output
-  ) = { 
-    val (itypes, itemTypesMap, whiteItems) = getItems(appid, whiteItypes)
-    
-    val users = getUsers(appid).map(_.id)
-
-    val featureItypes = getFeatureItypes(itypes, optFeatureItypesStr)
-    if (featureItypes.length == 0) {
-      throw new UserProfileRecommendationException("No items has featurelisted types")
-    }
-
-    val featureInvItypes = (0 until featureItypes.length)
-      .map(i => (featureItypes(i), i)).toMap
-
-    val userU2IsMap = getU2I(appid)
-
-    val userFeaturesMap = constructUserFeatureMap(
-      featureInvItypes, itemTypesMap, users, userU2IsMap)
-     
-    return (userFeaturesMap, featureItypes, itemTypesMap, whiteItems)
-  }
-
-  def printFeature(feature: Seq[Double], itypes: Seq[String]): String = {
-    (feature.zip(itypes)).filter(_._1 > 0)
-    .map(e => f"${e._2}=${e._1}%.4f").reduce(_ + "," + _)
-  }
-
-  def recommend(
-    userFeaturesMap: Map[String, Seq[Double]],
-    featureItypes: Seq[String],
-    itemItypes: Map[String, Seq[String]],
-    whiteItems: Seq[String],
-    numRecommendations: Int
-  ) : Map[String, Seq[(String, Double)]] = {
-
-    val featureIdxMap = featureItypes.zip(0 until featureItypes.size).toMap
-
-    userFeaturesMap.map { case(uid, features) => {
-      val itemScoreMap = whiteItems
-      .filter(iid => itemItypes.contains(iid))  // model must have this data.
-      .map{ case(iid) => {
-        val itypes = itemItypes(iid)
-        val score = itypes
-          .filter(featureIdxMap.contains)
-          .map(itype => featureIdxMap(itype))
-          .map(idx => features(idx))
-          .sum
-        // FIXME: not decided yet. if item has too many types, need to discount
-        // them / itypes.size  
-        (iid, score) 
-      }}
-      
-      val top = itemScoreMap.toList.sortBy(-_._2).take(numRecommendations)
-      (uid, top)
-    }}.toMap
-  }
-
-  def printRecommendations(
-    userFeaturesMap: Map[String, Seq[Double]],
-    itypes: Seq[String],
-    userRecommendationsMap: Map[String, Seq[(String, Double)]],
-    itemTypesMap: Map[String, Seq[String]]) {
-    userRecommendationsMap.foreach{ case(user, recommendations) => {
-      println("User: " + user)
-      println(" Features: " + 
-        printFeature(userFeaturesMap(user), itypes))
-      recommendations.foreach{ case (iid, score) => {
-        println(" Item: " + iid + f" score: $score%4f F: " + itemTypesMap(iid))
-      }}
-      println
-    }}
-  }
-}
-
diff --git a/process/engines/itemrec/algorithms/scala/featurebased/src/main/scala/Realtime.scala b/process/engines/itemrec/algorithms/scala/featurebased/src/main/scala/Realtime.scala
deleted file mode 100644
index dd5230d..0000000
--- a/process/engines/itemrec/algorithms/scala/featurebased/src/main/scala/Realtime.scala
+++ /dev/null
@@ -1,64 +0,0 @@
-package io.prediction.algorithms.itemrec.featurebased
-
-import grizzled.slf4j.Logger
-import io.prediction.commons.Config
-import com.twitter.scalding.Args
-import io.prediction.commons.appdata.U2IAction
-import io.prediction.commons.modeldata.ItemRecScore
-import io.prediction.commons.modeldata.{ MetadataKeyvals, MetadataKeyval }
-
-/*
- * - construct feature-list, Seq[String]
- * - construct user-feature-map : Map[User, Seq[Double]]
- * - modelCon: output UserFeatureMap in datastore.
- */
-
-object UserProfileRecommendationRealtime {
-  val logger = Logger(UserProfileRecommendationRealtime.getClass)
-  val commonsConfig = new Config
-
-  def modelCon(appid: Int, algoid: Int, modelset: Boolean,
-    itypes: Seq[String],
-    userFeaturesMap: Map[String, Seq[Double]]) {
-    // Write to metadata-keyval
-    val keyvalDb = commonsConfig.getModeldataMetadataKeyvals
-    keyvalDb.upsert(algoid, modelset, "features", itypes.reduce(_ + "," + _))
-
-    val userFeaturesDb = commonsConfig.getModeldataItemRecScores
-    userFeaturesMap.foreach { case(user, features) => {
-      userFeaturesDb.insert(ItemRecScore(
-        uid = user,
-        iids = Seq[String](),
-        scores = features,
-        itypes = Seq[Seq[String]](),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelset))
-    }}
-  }
-
-  def run(appid: Int, algoid: Int, modelset: Boolean,
-    optFeatureItypesStr: Option[String],
-    whiteItypes: Seq[String]) = {
-    val (userFeaturesMap, featureItypes, itemTypesMap, whiteItems) = (
-      UserProfileRecommendation.constructUserFeaturesMapFromArg(
-        appid, optFeatureItypesStr, whiteItypes))
-
-    modelCon(appid, algoid, modelset, featureItypes, userFeaturesMap)
-  }
-  
-  def main(cmdArgs: Array[String]) = {
-    val args = Args(cmdArgs)
-
-    val appid = args("appid").toInt
-    val algoid = args("algoid").toInt
-    val modelset = args("modelSet").toBoolean
-
-    // FIXME. Take another itypes list (engine setting), filter items by that
-    // itypes list
-    val optFeatureItypesStr = args.optional("featureItypes")
-    val whiteItypes = args.list("itypes")
-
-    run(appid, algoid, modelset, optFeatureItypesStr, whiteItypes)
-  }
-}
diff --git a/process/engines/itemrec/algorithms/scala/featurebased/src/test/resources/application.conf b/process/engines/itemrec/algorithms/scala/featurebased/src/test/resources/application.conf
deleted file mode 100644
index c1b2f0f..0000000
--- a/process/engines/itemrec/algorithms/scala/featurebased/src/test/resources/application.conf
+++ /dev/null
@@ -1,37 +0,0 @@
-# Used by PredictionIO Commons
-io.prediction.base=.
-
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.host=localhost
-io.prediction.commons.appdata.db.port=27017
-io.prediction.commons.appdata.db.name=predictionio_appdata_scala_itemrec_featurebased_test
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.host=localhost
-io.prediction.commons.appdata.test.db.port=27017
-io.prediction.commons.appdata.test.db.name=predictionio_test_appdata_scala_itemrec_featurebased_test
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.host=localhost
-io.prediction.commons.appdata.training.db.port=27017
-io.prediction.commons.appdata.training.db.name=predictionio_trainig_appdata_scala_itemrec_featurebased_test
-
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.host=localhost
-io.prediction.commons.appdata.validation.db.port=27017
-io.prediction.commons.appdata.validation.db.name=predictionio_validation_appdata_scala_itemrec_featurebased_test
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.host=localhost
-io.prediction.commons.modeldata.db.port=27017
-io.prediction.commons.modeldata.db.name=predictionio_modeldata_scala_itemrec_featurebased_test
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.host=localhost
-io.prediction.commons.modeldata.training.db.port=27017
-io.prediction.commons.modeldata.training.db.name=predictionio_training_modeldata_scala_itemrec_featurebased_test
-
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.host=localhost
-io.prediction.commons.settings.db.port=27017
-io.prediction.commons.settings.db.name=predictionio_scala_itemrec_featurebased_test
diff --git a/process/engines/itemrec/algorithms/scala/featurebased/src/test/scala/FeatureBasedItemRecSpec.scala b/process/engines/itemrec/algorithms/scala/featurebased/src/test/scala/FeatureBasedItemRecSpec.scala
deleted file mode 100644
index 06dc5f6..0000000
--- a/process/engines/itemrec/algorithms/scala/featurebased/src/test/scala/FeatureBasedItemRecSpec.scala
+++ /dev/null
@@ -1,510 +0,0 @@
-package io.prediction.algorithms.itemrec.featurebased 
-
-import org.specs2.mutable._
-import org.specs2.specification.Step
-import org.specs2.matcher.{ Matcher, Expectable }
-
-import com.mongodb.casbah.Imports._
-import com.github.nscala_time.time.Imports._
-
-import io.prediction.commons.Config
-import com.mongodb.casbah.Imports._
-import io.prediction.commons.appdata.{ Item, User, U2IAction }
-import io.prediction.commons.settings.{ App, Algo }
-
-object CustomMatcher {
-  def matchSeqDouble(expected: Seq[Double], epsilon: Double = 0.0001):
-  Matcher[Seq[Double]] = new Matcher[Seq[Double]] {
-    def apply[S <: Seq[Double]](actual: Expectable[S]) = {
-      val equalLength = (actual.value.length == expected.length)
-      val elementEqual = actual.value.zip(expected)
-        .map(e => ((e._1 - e._2).abs <= epsilon))
-        .reduce(_ && _)
-
-      result(equalLength && elementEqual,
-        s"Two Seq[Double] are almost equal (epsilon = $epsilon)",
-        s"Two Seq[Double] not eq: Length: $equalLength element: $elementEqual. " + 
-        s"Expected: $expected; Actual: ${actual.value}",
-        actual)
-    }
-  }
-
-  // actual must be same as expected
-  def matchMapStringDouble(expected: Map[String, Double], 
-  epsilon: Double = 0.0001): Matcher[Map[String, Double]] =
-  new Matcher[Map[String, Double]] {
-
-    def apply[S <: Map[String, Double]](actual: Expectable[S]) = {
-      val equalLength = (actual.value.size == expected.size)
-    
-      val elementEqual = actual.value.map{ case(k, v) => {
-        // true only if two numbers can be found and are within epsilon
-        expected.get(k).map(e => (e - v).abs <= epsilon).getOrElse(false)
-      }}.reduce(_ && _)
-
-      result(equalLength && elementEqual,
-        s"Two Map[S, Double] are almost equal (epsilon = $epsilon)",
-        s"Two Map[S, Double] not eq: Length: $equalLength element: $elementEqual. " + 
-        s"Expected: $expected; Actual: ${actual.value}",
-        actual)
-    }
-  }
- 
-  // Actual must contain all pairs in expected
-  def containMapStringDouble(expected: Map[String, Double], 
-  epsilon: Double = 0.0001): Matcher[Map[String, Double]] =
-  new Matcher[Map[String, Double]] {
-
-    def apply[S <: Map[String, Double]](actual: Expectable[S]) = {
-      val containElement = expected.map{ case(k, v) => {
-        // true only if two numbers can be found and are within epsilon
-        actual.value.get(k).map(e => (e - v).abs <= epsilon).getOrElse(false)
-      }}.reduce(_ && _)
-
-      result(containElement,
-        s"Actual contains expected",
-        s"Actual doesn't contain expected" + 
-        s"Expected: $expected; Actual: ${actual.value}",
-        actual)
-    }
-  }
-}
-
-class CustomMatcherSpec extends Specification {
-  import io.prediction.algorithms.itemrec.featurebased.CustomMatcher._
-
-  "MatchSeqDouble" should {
-    "false unequal length" in {
-      (Seq(1.0, 2.0, 3.0, 4.0) must matchSeqDouble(Seq(1.00001, 2.0, 2.99999)) not)
-    }
-    "true within epsilon" in {
-      (Seq(1.0, 2.0, 3.0) must matchSeqDouble(Seq(1.00001, 2.0, 2.99999)))
-    }
-    "false outside epsilon" in {
-      (Seq(1.0, 2.0, 3.0) must
-        matchSeqDouble(
-          Seq(1.00001, 2.0, 2.99999), epsilon=0.000001) not)
-    }
-  }
-  
-  "MatchMapStringDouble" should {
-    "true within epsilon" in {
-      val actual = Map("a" -> 1.0, "b" -> 2.0, "c" -> 3.0)
-      val expected = Map("a" -> 0.999999, "b" -> 2.0, "c" -> 3.000001)
-      actual must matchMapStringDouble(expected)
-    }
-    
-    "false outside epsilon" in {
-      val actual = Map("a" -> 1.0, "b" -> 2.0, "c" -> 3.0)
-      val expected = Map("a" -> 0.999999, "b" -> 2.0, "c" -> 3.000001)
-      (actual must matchMapStringDouble(expected, epsilon=0.0000001) not)
-    }
-    
-    "false mismatched items" in {
-      val actual = Map("a" -> 1.0, "b" -> 2.0, "c" -> 3.0)
-      val expected = Map("a" -> 0.999999, "b" -> 2.0, "d" -> 3.0)
-      (actual must matchMapStringDouble(expected) not)
-    }
-  }
-
-  // FIXME(yipjustin): Add spec for ContainMap
-}
-
-
-class FeatureBasedItemRecSpec extends Specification {
-  import io.prediction.algorithms.itemrec.featurebased.CustomMatcher._
-
-  def cleanUp() = {
-    val connection = MongoConnection()
-    Seq(
-      "predictionio_appdata_scala_itemrec_featurebased_test",
-      "predictionio_modeldata_scala_itemrec_featurebased_test"
-      ).foreach( mongoDbName => connection(mongoDbName).dropDatabase() )
-  }
-
-  val commonConfig = new Config
-  val appdataUsers = commonConfig.getAppdataUsers
-  val appdataItems = commonConfig.getAppdataItems
-  val appdataU2IActions = commonConfig.getAppdataU2IActions
-
-  val appid = 42
-    
-  val anotherAppid = 9527
-
-  val rawItems = Map(
-    "i1" -> Seq("t1", "t2"),
-    "i2" -> Seq[String](), 
-    "i3" -> Seq("t1", "t3"),
-    "i4" -> Seq("t1", "t2", "t3"),
-    "i5" -> Seq("t4"),
-    "i6" -> Seq("t2", "t3"),
-    "i7" -> Seq("t2", "t4"))
-  val rawInactiveItems = Map(
-    "i8" -> Seq("t5"),
-    "i9" -> Seq("t5", "t3"))
-  val rawUsers = Seq("u1", "u2", "u3", "u4")
-  val rawU2Is = Map(
-    "u1" -> Seq(
-      ("i1", "rate", 4),
-      ("i1", "rate", 5),
-      ("i3", "rate", 4),
-      ("i5", "rate", 3)),
-    "u2" -> Seq(
-      ("i1", "view", 1),
-      ("i5", "rate", 4),
-      ("i0", "rate", 5)),  // non-exist item
-    "u3" -> Seq(
-      ("i2", "rate", 5),
-      ("i2", "rate", 3)),  // no itypes
-    "u0" -> Seq(
-      ("i1", "rate", 4),
-      ("i3", "rate", 5)))
-
-  rawUsers.foreach{ uid => appdataUsers.insert(User(
-    id = uid,
-    appid = appid,
-    ct = DateTime.now))}
-    
-  rawItems.foreach{ case(iid, itypes) => {
-    appdataItems.insert(Item(
-      id = iid,
-      appid = appid,
-      ct = DateTime.now,
-      itypes = itypes,
-      starttime = None,
-      endtime = None))
-  }}
-  
-  rawInactiveItems.foreach{ case(iid, itypes) => {
-    appdataItems.insert(Item(
-      id = iid,
-      appid = appid,
-      ct = DateTime.now,
-      itypes = itypes,
-      inactive = Some(true),
-      starttime = None,
-      endtime = None))
-  }}
-
-  rawU2Is.foreach{ case(uid, actions) => {
-    actions.foreach { action => appdataU2IActions.insert(U2IAction(
-      appid = appid,
-      action = action._2,
-      uid = uid,
-      iid = action._1,
-      t = DateTime.now,
-      v = Some(action._3))) }
-  }}
-    
-  def getApp(appid: Int) = App(
-    id = appid,
-    userid = 0,
-    appkey = "123",
-    display = "12345")
-
-  def getAlgo(algoid: Int, modelset: Boolean) = Algo(
-    id = algoid,
-    engineid = 1234,
-    name = "",
-    infoid = "abc",
-    command = "",
-    modelset = modelset,
-    createtime = DateTime.now,
-    updatetime = DateTime.now)
-
-
-  "Extract correct itypes"  should {
-    val input = Seq("a", "b", "c")
-    "No feature itypes" in {
-      val r = UserProfileRecommendation.getFeatureItypes(input, None)
-      input === r
-    }
-    "Empty feature itypes" in {
-      val r = UserProfileRecommendation.getFeatureItypes(input, Some(""))
-      input === r
-    }
-    "Support feature itypes, same as input feature sequence" in {
-      val r = UserProfileRecommendation.getFeatureItypes(input, Some("c,b,d"))
-      r === Seq("c", "b")
-    }
-  }
-
-  "Get items and itypes" should {
-    "Empty App" in {
-      val r = UserProfileRecommendation.getItems(1679)
-      r._1 must have size(0)
-      r._2 must have size(0)
-    }
-
-    "Default App" in {
-      val r = UserProfileRecommendation.getItems(appid, Seq[String]())
-      val itypes = r._1
-      itypes must containTheSameElementsAs(Seq("t4", "t3", "t2", "t1", "t5"))
-      val itemItypes = r._2
-      itemItypes.keys must containTheSameElementsAs(
-        rawItems.keys.toSeq ++ rawInactiveItems.keys.toSeq)
-      val whiteItems = r._3
-      whiteItems must containTheSameElementsAs(rawItems.keys.toSeq)
-    }
-    
-    "Default App with whitelisted itypes" in {
-      val r = UserProfileRecommendation.getItems(appid, Seq("t1", "t3"))
-      val itypes = r._1
-      itypes must containTheSameElementsAs(Seq("t3", "t2", "t5", "t1"))
-      // notice there is a difference between itemItypesMap and whiteItems,
-      // as whiteItems filters inactive items.
-      val itemItypesMap = r._2
-      itemItypesMap.keys must containTheSameElementsAs(
-        Seq("i1", "i3", "i4", "i6", "i9"))
-      val whiteItems = r._3
-      whiteItems must containTheSameElementsAs(rawItems.keys.toSeq)
-    }
-  }
-
-  "Construct user features map" should {
-    "Run with all itypes" in {
-      val (userFeaturesMap, featureItypes, itemTypesMap, whiteItems) = (
-        UserProfileRecommendation.constructUserFeaturesMapFromArg(
-          appid, Some("t4,t1,t2,t3")))
-
-      val expectedUserFeaturesMap = Map(
-        "u1" -> Seq(0.0, 0.5, 0.333333, 0.16666),
-        "u2" -> Seq(1.0, 0.0, 0.0, 0.0),
-        "u3" -> Seq(0.25, 0.25, 0.25, 0.25),
-        "u4" -> Seq(0.25, 0.25, 0.25, 0.25))
-
-      expectedUserFeaturesMap.map{ case(user, features) => {
-        userFeaturesMap(user) must CustomMatcher.matchSeqDouble(features)
-      }}.reduce(_ and _)
-
-      userFeaturesMap.keys must containTheSameElementsAs(
-        expectedUserFeaturesMap.keys.toSeq)
-    }
-    
-    "Run with feature itypes t1,t2" in {
-      val (userFeaturesMap, featureItypes, itemTypesMap, whiteItems) = (
-        UserProfileRecommendation.constructUserFeaturesMapFromArg(
-          appid, Some("t1,t2")))
-
-      val expectedUserFeaturesMap = Map(
-        "u1" -> Seq(0.6, 0.4),
-        "u2" -> Seq(0.5, 0.5),
-        "u3" -> Seq(0.5, 0.5),
-        "u4" -> Seq(0.5, 0.5))
-
-      expectedUserFeaturesMap.map{ case(user, features) => {
-        userFeaturesMap(user) must CustomMatcher.matchSeqDouble(features)
-      }}.reduce(_ and _)
-
-      userFeaturesMap.keys must containTheSameElementsAs(
-        expectedUserFeaturesMap.keys.toSeq)
-
-      featureItypes must containTheSameElementsAs(Seq("t1", "t2"))
-    }
-    
-    "Run failure with feature (but not exist) itypes t6,t7" in {
-      UserProfileRecommendation.constructUserFeaturesMapFromArg(
-          appid, Some("t6,t7")) must throwA[UserProfileRecommendationException]
-    }
-    
-    "Run failure with empty app" in {
-      UserProfileRecommendation.constructUserFeaturesMapFromArg(
-          anotherAppid, Some("")) must throwA[UserProfileRecommendationException]
-    }
-  }
-
-  "Construct batch recommendation" should {
-    "Run with all t1, t2, t3, t4" in {
-      val (userFeaturesMap, featureItypes, itemItypesMap, whiteItems) = (
-        UserProfileRecommendation.constructUserFeaturesMapFromArg(
-          appid, Some(""), Seq("t1", "t3", "t4", "t2")))
-      val userRecommendationMap = UserProfileRecommendation.recommend(
-        userFeaturesMap, featureItypes, itemItypesMap, whiteItems, 100)
-      
-      val expectedUserRecommendationMap = Map(
-        "u1" -> Map("i4" -> 1.0, "i1" -> 0.83333, "i3" -> 0.666666, "i6" -> 0.5,
-          "i7" -> 0.333333, "i5" -> 0.0),
-        "u2" -> Map("i5" -> 1.0, "i7" -> 1.0, "i4" -> 0.0, "i3" -> 0.0,
-          "i1" -> 0.0, "i6" -> 0.0),
-        "u3" -> Map("i4" -> 0.6, "i3" -> 0.4, "i1" -> 0.4, "i7" -> 0.4,
-          "i6" -> 0.4, "i5" -> 0.2),
-        "u4" -> Map("i4" -> 0.6, "i3" -> 0.4, "i1" -> 0.4, "i7" -> 0.4,
-          "i6" -> 0.4, "i5" -> 0.2))
-
-      userRecommendationMap.keys must containTheSameElementsAs(
-        expectedUserRecommendationMap.keys.toSeq)
-
-      expectedUserRecommendationMap.map{ case(user, expected) => {
-        val recommendation = userRecommendationMap(user)
-        val actual = recommendation.toMap
-        val valueMatched = actual must CustomMatcher.matchMapStringDouble(expected)
-        // Score must be inversely sorted
-        val sorted = recommendation.map(-_._2) must beSorted
-        (valueMatched and sorted)
-      }}.reduce(_ and _)
-    }
-    
-    "Run with all itypes and top 2" in {
-      val (userFeaturesMap, featureItypes, itemItypesMap, whiteItems) = (
-        UserProfileRecommendation.constructUserFeaturesMapFromArg(
-          appid, Some("")))
-      val userRecommendationMap = UserProfileRecommendation.recommend(
-        userFeaturesMap, featureItypes, itemItypesMap, whiteItems, 2)
-    
-      val expectedUserRecommendationMap = Map(
-        "u1" -> Map("i4" -> 1.0, "i1" -> 0.83333),
-        "u2" -> Map("i5" -> 1.0, "i7" -> 1.0),
-        "u3" -> Map("i4" -> 0.6),
-        "u4" -> Map("i4" -> 0.6))
-
-      userRecommendationMap.keys must containTheSameElementsAs(
-        expectedUserRecommendationMap.keys.toSeq)
-
-      expectedUserRecommendationMap.map{ case(user, expected) => {
-        val recommendation = userRecommendationMap(user)
-        val actual = recommendation.toMap
-        ((recommendation must have size(2)) and
-          (actual must CustomMatcher.containMapStringDouble(expected)) and
-          (recommendation.map(-_._2) must beSorted))
-      }}.reduce(_ and _)
-    }
-    
-    "Run with all itypes and top 2 and whiteItypes 't1', 't3'" in {
-      // Only items with t1, t3 will be used for training.
-      val (userFeaturesMap, featureItypes, itemItypesMap, whiteItems) = (
-        UserProfileRecommendation.constructUserFeaturesMapFromArg(
-          appid, Some(""), Seq("t1", "t3")))
-      val userRecommendationMap = UserProfileRecommendation.recommend(
-        userFeaturesMap, featureItypes, itemItypesMap, whiteItems, 2)
-     
-      /*
-      println("f")
-      println(featureItypes)
-      println("u->f")
-      userFeaturesMap.foreach{println}
-      println("u->i")
-      userRecommendationMap.foreach{println}
-      */
-      val expectedUserRecommendationMap = Map(
-        "u1" -> Map("i4" -> 1.0, "i1" -> 0.83333),
-        "u2" -> Map("i4" -> 0.75, "i3" -> 0.5),
-        "u3" -> Map("i4" -> 0.75, "i3" -> 0.5),
-        "u4" -> Map("i4" -> 0.75, "i3" -> 0.5))
-
-      userRecommendationMap.keys must containTheSameElementsAs(
-        expectedUserRecommendationMap.keys.toSeq)
-
-      expectedUserRecommendationMap.map{ case(user, expected) => {
-        val recommendation = userRecommendationMap(user)
-        val actual = recommendation.toMap
-        ((recommendation must have size(2)) and
-          (actual must CustomMatcher.containMapStringDouble(expected)) and
-          (recommendation.map(-_._2) must beSorted))
-      }}.reduce(_ and _)
-    }
-  }
-
-  "Realtime Run" should {
-    "Run with all itypes" in {
-      implicit val app = getApp(appid)
-      val algoid = 1
-      val modelset = true
-      implicit val algo = getAlgo(algoid, modelset)
-      val keyvalDb = commonConfig.getModeldataMetadataKeyvals
-      val itemRecScoreDb = commonConfig.getModeldataItemRecScores
-
-      UserProfileRecommendationRealtime.run(appid, algoid, modelset, None,
-        Seq[String]())
-
-      // must find meta
-      val featuresStr = keyvalDb.get(algoid, modelset, "features")
-      featuresStr.isEmpty must beFalse
-      featuresStr.get.split(',').toSeq must containTheSameElementsAs(
-        Seq("t1", "t2", "t3", "t4", "t5"))
-
-      // must see all users from modeldata
-      rawUsers.map { uid => {
-        itemRecScoreDb.getByUid(uid).isEmpty must beFalse
-      }}.reduce(_ and _)
-    }
-    
-    "Run with t1,t2" in {
-      implicit val app = getApp(appid)
-      val algoid = 2
-      val modelset = true
-      implicit val algo = getAlgo(algoid, modelset)
-      val keyvalDb = commonConfig.getModeldataMetadataKeyvals
-      val itemRecScoreDb = commonConfig.getModeldataItemRecScores
-
-      UserProfileRecommendationRealtime.run(appid, algoid, modelset,
-        Some("t1,t2"), Seq[String]())
-
-      // must find meta
-      val featuresStr = keyvalDb.get(algoid, modelset, "features")
-      featuresStr.isEmpty must beFalse
-      // Since we specify the whitelist, therefore the featureStr will be in the
-      // same order.
-      featuresStr.get must be_==("t1,t2")
-      
-      val expectedUserFeaturesMap = Map(
-        "u1" -> Seq(0.6, 0.4),
-        "u2" -> Seq(0.5, 0.5),
-        "u3" -> Seq(0.5, 0.5),
-        "u4" -> Seq(0.5, 0.5))
-
-      expectedUserFeaturesMap.map { case(user, features) => {
-        val optUserScore = itemRecScoreDb.getByUid(user)
-        optUserScore.isEmpty must beFalse
-        val userScore = optUserScore.get
-        userScore.scores must CustomMatcher.matchSeqDouble(features)
-      }}.reduce(_ and _)
-    }
-  }
-
-  "Batch Run" should {
-    "Run with white types t1, t2, t3, t4" in {
-      implicit val app = getApp(appid)
-      val algoid = 3
-      val modelset = true
-      val numRecommendations = 10
-      implicit val algo = getAlgo(algoid, modelset)
-      val keyvalDb = commonConfig.getModeldataMetadataKeyvals
-      val itemRecScoreDb = commonConfig.getModeldataItemRecScores
-
-      UserProfileRecommendationBatch.run(appid, algoid, modelset,
-        numRecommendations, None, Seq("t1", "t2", "t3", "t4"))
-
-      val expectedUserRecommendationMap = Map(
-        "u1" -> Map("i4" -> 1.0, "i1" -> 0.83333, "i3" -> 0.666666, "i6" -> 0.5,
-          "i7" -> 0.333333, "i5" -> 0.0),
-        "u2" -> Map("i5" -> 1.0, "i7" -> 1.0, "i4" -> 0.0, "i3" -> 0.0,
-          "i1" -> 0.0, "i6" -> 0.0),
-        "u3" -> Map("i4" -> 0.6, "i3" -> 0.4, "i1" -> 0.4, "i7" -> 0.4,
-          "i6" -> 0.4, "i5" -> 0.2),
-        "u4" -> Map("i4" -> 0.6, "i3" -> 0.4, "i1" -> 0.4, "i7" -> 0.4,
-          "i6" -> 0.4, "i5" -> 0.2))
-      
-      // must see all users from modeldata
-      rawUsers.map { uid => {
-        val optItemRecScore = itemRecScoreDb.getByUid(uid)
-        optItemRecScore.isEmpty must beFalse
-
-        val itemRecScore = optItemRecScore.get
-
-        // check if values match
-        val actual = itemRecScore.iids.zip(itemRecScore.scores).toMap
-        val expected = expectedUserRecommendationMap(uid)
-        actual must matchMapStringDouble(expected)
-
-        // check if the itypes all passed to modelset
-        val iidItypesMap = itemRecScore.iids.zip(itemRecScore.itypes).toMap
-        iidItypesMap.map{ case (iid, itypes) => {
-          val expectedItypes = rawItems(iid)
-          itypes must containTheSameElementsAs(expectedItypes)
-        }}.reduce(_ and _)
-      }}.reduce(_ and _)
-    }
-
-  }
-  step(cleanUp())
-}
diff --git a/process/engines/itemrec/algorithms/scala/generic/build.sbt b/process/engines/itemrec/algorithms/scala/generic/build.sbt
deleted file mode 100644
index 760810a..0000000
--- a/process/engines/itemrec/algorithms/scala/generic/build.sbt
+++ /dev/null
@@ -1,23 +0,0 @@
-import xerial.sbt.Pack._
-
-name := "predictionio-process-itemrec-algorithms-scala-generic"
-
-libraryDependencies ++= Seq(
-  "ch.qos.logback" % "logback-classic" % "1.1.1",
-  "com.twitter" %% "scalding-args" % "0.8.11",
-  "org.clapper" %% "grizzled-slf4j" % "1.0.1",
-  "commons-io" % "commons-io" % "2.4")
-
-packSettings
-
-packJarNameConvention := "full"
-
-packExpandedClasspath := true
-
-packGenerateWindowsBatFile := false
-
-packMain := Map(
-  "itemrec.generic.dataprep" -> "io.prediction.algorithms.generic.itemrec.GenericDataPreparator")
-
-packJvmOpts := Map(
-  "itemrec.generic.dataprep" -> Common.packCommonJvmOpts)
diff --git a/process/engines/itemrec/algorithms/scala/generic/src/main/resources/application.conf b/process/engines/itemrec/algorithms/scala/generic/src/main/resources/application.conf
deleted file mode 100644
index c85803b..0000000
--- a/process/engines/itemrec/algorithms/scala/generic/src/main/resources/application.conf
+++ /dev/null
@@ -1,30 +0,0 @@
-# Used by PredictionIO Commons
-io.prediction.base=.
-
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.host=localhost
-io.prediction.commons.appdata.db.port=27017
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.host=localhost
-io.prediction.commons.appdata.test.db.port=27017
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.host=localhost
-io.prediction.commons.appdata.training.db.port=27017
-
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.host=localhost
-io.prediction.commons.appdata.validation.db.port=27017
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.host=localhost
-io.prediction.commons.modeldata.db.port=27017
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.host=localhost
-io.prediction.commons.modeldata.training.db.port=27017
-
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.host=localhost
-io.prediction.commons.settings.db.port=27017
diff --git a/process/engines/itemrec/algorithms/scala/generic/src/main/resources/logback.xml b/process/engines/itemrec/algorithms/scala/generic/src/main/resources/logback.xml
deleted file mode 100644
index 1a2768e..0000000
--- a/process/engines/itemrec/algorithms/scala/generic/src/main/resources/logback.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<configuration>
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <encoder>
-      <pattern>%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>
-    </encoder>
-  </appender>
-  <root level="info">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
-
diff --git a/process/engines/itemrec/algorithms/scala/generic/src/main/scala/io/prediction/algorithms/itemrec/generic/GenericDataPreparator.scala b/process/engines/itemrec/algorithms/scala/generic/src/main/scala/io/prediction/algorithms/itemrec/generic/GenericDataPreparator.scala
deleted file mode 100644
index 8310a18..0000000
--- a/process/engines/itemrec/algorithms/scala/generic/src/main/scala/io/prediction/algorithms/itemrec/generic/GenericDataPreparator.scala
+++ /dev/null
@@ -1,366 +0,0 @@
-package io.prediction.algorithms.generic.itemrec
-
-import io.prediction.commons.Config
-import io.prediction.commons.appdata.{ Item, U2IAction, User }
-
-import com.github.nscala_time.time.Imports._
-import grizzled.slf4j.Logger
-import java.io.File
-import java.io.FileWriter
-import java.io.RandomAccessFile
-import java.io.BufferedWriter
-import scala.io.Source
-
-import com.twitter.scalding.Args
-
-/**
- * Generic single machine data preparator for ItemRec engine.
- * Read data from appdata and output the following files:
- * - usersIndex.tsv (uindex uid)
- * - itemsIndex.tsv (iindex iid itypes starttime): only contain valid items to be recommended
- * - ratings.mm (if --matrixMarket true ): matrix market format rating
- * - ratings.csv (if --matrixMarket false): comma separated rating file
- * - seen.csv (uindex, iindex) (if --seenActions is defined, only contain seen
- *  actions, else, same as ratings)
- *
- * Args:
- * --seenActions: <string separated by white space>. optional. generate seen file separately.
- */
-object GenericDataPreparator {
-
-  /* constants */
-  final val ACTION_RATE = "rate"
-  final val ACTION_LIKE = "like"
-  final val ACTION_DISLIKE = "dislike"
-  final val ACTION_VIEW = "view"
-  final val ACTION_CONVERSION = "conversion"
-
-  // When there are conflicting actions, e.g. a user gives an item a rating 5 but later dislikes it,
-  // determine which action will be considered as final preference.
-  final val CONFLICT_LATEST: String = "latest" // use latest action
-  final val CONFLICT_HIGHEST: String = "highest" // use the one with highest score
-  final val CONFLICT_LOWEST: String = "lowest" // use the one with lowest score
-
-  /* global */
-  val logger = Logger(GenericDataPreparator.getClass)
-
-  //println(logger.isInfoEnabled)
-
-  val commonsConfig = new Config
-
-  // argument of this job
-  case class JobArg(
-    val outputDir: String,
-    val appid: Int,
-    val evalid: Option[Int],
-    val itypes: Option[List[String]],
-    val viewParam: Option[Int],
-    val likeParam: Option[Int],
-    val dislikeParam: Option[Int],
-    val conversionParam: Option[Int],
-    val conflictParam: String,
-    val recommendationTime: Option[Long],
-    val seenActions: Option[List[String]],
-    val matrixMarket: Boolean)
-
-  def main(cmdArgs: Array[String]) {
-
-    logger.info("Running generic data preparator ...")
-    logger.info(cmdArgs.mkString(","))
-
-    /* get arg */
-    val args = Args(cmdArgs)
-
-    val outputDirArg = args("outputDir")
-    val appidArg = args("appid").toInt
-    val evalidArg = args.optional("evalid") map (x => x.toInt)
-    val OFFLINE_EVAL = (evalidArg != None) // offline eval mode
-
-    val preItypesArg = args.list("itypes")
-    val itypesArg: Option[List[String]] = if (preItypesArg.mkString(",").length == 0) None else Option(preItypesArg)
-
-    // determine how to map actions to rating values
-    def getActionParam(name: String): Option[Int] = {
-      val actionParam: Option[Int] = args(name) match {
-        case "ignore" => None
-        case x => Some(x.toInt)
-      }
-      actionParam
-    }
-
-    val viewParamArg: Option[Int] = getActionParam("viewParam")
-    val likeParamArg: Option[Int] = getActionParam("likeParam")
-    val dislikeParamArg: Option[Int] = getActionParam("dislikeParam")
-    val conversionParamArg: Option[Int] = getActionParam("conversionParam")
-
-    val conflictParamArg: String = args("conflictParam")
-
-    // check if the conflictParam is valid
-    require(List(CONFLICT_LATEST, CONFLICT_HIGHEST, CONFLICT_LOWEST).contains(conflictParamArg), "conflict param " + conflictParamArg + " is not valid.")
-
-    val recommendationTimeArg = args.optional("recommendationTime").map(_.toLong)
-
-    val preSeenActionsArg = args.list("seenActions")
-    val seenActionsArg: Option[List[String]] = if (preSeenActionsArg.mkString(",").length == 0) None else Option(preSeenActionsArg)
-
-    // write data in matrix market format
-    val matrixMarketArg: Boolean = args.optional("matrixMarket").map(x => x.toBoolean).getOrElse(true)
-
-    val arg = JobArg(
-      outputDir = outputDirArg,
-      appid = appidArg,
-      evalid = evalidArg,
-      itypes = itypesArg,
-      viewParam = viewParamArg,
-      likeParam = likeParamArg,
-      dislikeParam = dislikeParamArg,
-      conversionParam = conversionParamArg,
-      conflictParam = conflictParamArg,
-      recommendationTime = recommendationTimeArg,
-      seenActions = seenActionsArg,
-      matrixMarket = matrixMarketArg
-    )
-
-    /* run job */
-    dataPrep(arg)
-    cleanup(arg)
-
-  }
-
-  case class RatingData(
-    uid: Int,
-    iid: Int,
-    rating: Int,
-    t: Long)
-
-  def dataPrep(arg: JobArg) = {
-
-    // NOTE: if OFFLINE_EVAL, read from training set, and use evalid as appid when read Items and U2iActions
-    val OFFLINE_EVAL = (arg.evalid != None)
-
-    val usersDb = if (!OFFLINE_EVAL)
-      commonsConfig.getAppdataUsers
-    else
-      commonsConfig.getAppdataTrainingUsers
-
-    val itemsDb = if (!OFFLINE_EVAL)
-      commonsConfig.getAppdataItems
-    else
-      commonsConfig.getAppdataTrainingItems
-
-    val u2iDb = if (!OFFLINE_EVAL)
-      commonsConfig.getAppdataU2IActions
-    else
-      commonsConfig.getAppdataTrainingU2IActions
-
-    val appid = if (OFFLINE_EVAL) arg.evalid.get else arg.appid
-
-    // create outputDir if doesn't exist yet.
-    val outputDir = new File(arg.outputDir)
-    outputDir.mkdirs()
-
-    /* write user index */
-    // convert to Map for later lookup
-    // assuming number of users can be fit into memory.
-    val usersMap: Map[String, Int] = usersDb.getByAppid(appid).map(_.id).zipWithIndex
-      .map { case (uid, index) => (uid, index + 1) }.toMap // +1 to make it starting from 1
-
-    val usersIndexWriter = new BufferedWriter(new FileWriter(new File(arg.outputDir + "usersIndex.tsv")))
-    usersMap.foreach {
-      case (uid, uindex) =>
-        usersIndexWriter.write(s"${uindex}\t${uid}\n")
-    }
-    usersIndexWriter.close()
-
-    case class ItemData(
-      val iindex: Int,
-      val itypes: Seq[String],
-      val starttime: Option[Long],
-      val endtime: Option[Long],
-      val inactive: Boolean)
-
-    val itemsMap: Map[String, ItemData] = arg.itypes.map { itypes =>
-      itemsDb.getByAppidAndItypes(appid, itypes)
-    }.getOrElse {
-      itemsDb.getByAppid(appid)
-    }.zipWithIndex
-      .map {
-        case (item, index) =>
-          val itemData = ItemData(
-            iindex = index + 1, // +1 to make index starting from 1 (required by graphchi)
-            itypes = item.itypes,
-            starttime = item.starttime.map[Long](_.getMillis()),
-            endtime = item.endtime.map[Long](_.getMillis()),
-            inactive = item.inactive.getOrElse(false)
-          )
-          (item.id -> itemData)
-      }.toMap
-
-    //
-    /* write item index (iindex iid itypes) */
-    val itemsIndexWriter = new BufferedWriter(new FileWriter(new File(arg.outputDir + "itemsIndex.tsv")))
-
-    // NOTE: only write valid items (eg. valid starttime and endtime,
-    // inactive=false)
-    itemsMap.filter {
-      case (iid, itemData) =>
-        val validTime = itemTimeFilter(true, itemData.starttime,
-          itemData.endtime, arg.recommendationTime)
-
-        validTime && (!itemData.inactive)
-    }.foreach {
-      case (iid, itemData) =>
-        val itypes = itemData.itypes.mkString(",")
-        // write starttime for freshness
-        itemsIndexWriter.write(s"${itemData.iindex}\t${iid}\t${itypes}\t${itemData.starttime.getOrElse(arg.recommendationTime)}\n")
-    }
-    itemsIndexWriter.close()
-
-    /* write u2i ratings */
-
-    val u2iActions = u2iDb.getAllByAppid(appid).toSeq
-
-    val u2iRatings = u2iActions
-      .filter { u2i =>
-        val validAction = isValidAction(u2i, arg.likeParam, arg.dislikeParam, arg.viewParam, arg.conversionParam)
-        val validUser = usersMap.contains(u2i.uid)
-        val validItem = itemsMap.contains(u2i.iid)
-        (validAction && validUser && validItem)
-      }.map { u2i =>
-        val rating = convertToRating(u2i, arg.likeParam, arg.dislikeParam, arg.viewParam, arg.conversionParam)
-
-        RatingData(
-          uid = usersMap(u2i.uid),
-          iid = itemsMap(u2i.iid).iindex,
-          rating = rating,
-          t = u2i.t.getMillis
-        )
-      }
-
-    if (!u2iRatings.isEmpty) {
-
-      val ratingReduced = u2iRatings.groupBy(x => (x.iid, x.uid))
-        .mapValues { v =>
-          v.reduce { (a, b) =>
-            resolveConflict(a, b, arg.conflictParam)
-          }
-        }.values
-        .toSeq
-        .sortBy { x: RatingData =>
-          (x.iid, x.uid)
-        }
-
-      val fileName = if (arg.matrixMarket) "ratings.mm" else "ratings.csv"
-      val ratingsWriter = new BufferedWriter(new FileWriter(new File(arg.outputDir + fileName))) // intermediate file
-
-      if (arg.matrixMarket) {
-        ratingsWriter.write("%%MatrixMarket matrix coordinate real general\n")
-        ratingsWriter.write(s"${usersMap.size} ${itemsMap.size} ${ratingReduced.size}\n")
-      }
-
-      ratingReduced.foreach { r =>
-        if (arg.matrixMarket) {
-          ratingsWriter.write(s"${r.uid} ${r.iid} ${r.rating}\n")
-        } else {
-          ratingsWriter.write(s"${r.uid},${r.iid},${r.rating}\n")
-        }
-      }
-
-      ratingsWriter.close()
-    }
-
-    /* write u2i seen */
-    val u2iSeen = u2iActions
-      .filter { u2i =>
-        val validAction = arg.seenActions.map(seenActions =>
-          seenActions.contains(u2i.action)).getOrElse(
-          // same as training actions if seenActions is not defined
-          isValidAction(u2i, arg.likeParam, arg.dislikeParam,
-            arg.viewParam, arg.conversionParam)
-        )
-        val validUser = usersMap.contains(u2i.uid)
-        val validItem = itemsMap.contains(u2i.iid)
-        (validAction && validUser && validItem)
-      }
-      // convert to index
-      .map { u2i => (usersMap(u2i.uid), itemsMap(u2i.iid).iindex) }
-      .groupBy(x => x)
-      .mapValues { v => v(0) } // take 1
-      .values
-
-    val fileName = "seen.csv"
-    val seenWriter = new BufferedWriter(new FileWriter(new File(arg.outputDir + fileName)))
-
-    u2iSeen.foreach { s =>
-      seenWriter.write(s"${s._1},${s._2}\n")
-    }
-    seenWriter.close()
-
-  }
-
-  def itemTimeFilter(enable: Boolean, starttime: Option[Long], endtime: Option[Long], recommendationTime: Option[Long]): Boolean = {
-    if (enable) {
-      recommendationTime.map { recTime =>
-        (starttime, endtime) match {
-          case (Some(start), None) => (recTime >= start)
-          case (Some(start), Some(end)) => ((recTime >= start) && (recTime < end))
-          case (None, Some(end)) => (recTime < end)
-          case (None, None) => true
-        }
-      }.getOrElse(true)
-    } else true
-  }
-
-  def isValidAction(u2i: U2IAction, likeParam: Option[Int], dislikeParam: Option[Int],
-    viewParam: Option[Int], conversionParam: Option[Int]): Boolean = {
-    val keepThis: Boolean = u2i.action match {
-      case ACTION_RATE => true
-      case ACTION_LIKE => (likeParam != None)
-      case ACTION_DISLIKE => (dislikeParam != None)
-      case ACTION_VIEW => (viewParam != None)
-      case ACTION_CONVERSION => (conversionParam != None)
-      case _ => {
-        //assert(false, "Action type " + u2i.action + " in u2iActions appdata is not supported!")
-        false // all other unsupported actions
-      }
-    }
-    keepThis
-  }
-
-  def convertToRating(u2i: U2IAction, likeParam: Option[Int], dislikeParam: Option[Int],
-    viewParam: Option[Int], conversionParam: Option[Int]): Int = {
-    val rating: Int = u2i.action match {
-      case ACTION_RATE => u2i.v.get.toInt
-      case ACTION_LIKE => likeParam.getOrElse {
-        assert(false, "Action type " + u2i.action + " should have been filtered out!")
-        0
-      }
-      case ACTION_DISLIKE => dislikeParam.getOrElse {
-        assert(false, "Action type " + u2i.action + " should have been filtered out!")
-        0
-      }
-      case ACTION_VIEW => viewParam.getOrElse {
-        assert(false, "Action type " + u2i.action + " should have been filtered out!")
-        0
-      }
-      case ACTION_CONVERSION => conversionParam.getOrElse {
-        assert(false, "Action type " + u2i.action + " should have been filtered out!")
-        0
-      }
-    }
-    rating
-  }
-
-  def resolveConflict(a: RatingData, b: RatingData, conflictParam: String) = {
-    conflictParam match {
-      case CONFLICT_LATEST => if (a.t > b.t) a else b
-      case CONFLICT_HIGHEST => if (a.rating > b.rating) a else b
-      case CONFLICT_LOWEST => if (a.rating < b.rating) a else b
-    }
-  }
-
-  def cleanup(arg: JobArg) = {
-
-  }
-
-}
diff --git a/process/engines/itemrec/algorithms/scala/generic/src/test/resources/application.conf b/process/engines/itemrec/algorithms/scala/generic/src/test/resources/application.conf
deleted file mode 100644
index 9e296b6..0000000
--- a/process/engines/itemrec/algorithms/scala/generic/src/test/resources/application.conf
+++ /dev/null
@@ -1,37 +0,0 @@
-# Used by PredictionIO Commons
-io.prediction.base=.
-
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.host=localhost
-io.prediction.commons.appdata.db.port=27017
-io.prediction.commons.appdata.db.name=predictionio_appdata_generic_dataprep_test
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.host=localhost
-io.prediction.commons.appdata.test.db.port=27017
-io.prediction.commons.appdata.test.db.name=predictionio_test_appdata_generic_dataprep_test
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.host=localhost
-io.prediction.commons.appdata.training.db.port=27017
-io.prediction.commons.appdata.training.db.name=predictionio_trainig_appdata_generic_dataprep_test
-
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.host=localhost
-io.prediction.commons.appdata.validation.db.port=27017
-io.prediction.commons.appdata.validation.db.name=predictionio_validation_appdata_generic_dataprep_test
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.host=localhost
-io.prediction.commons.modeldata.db.port=27017
-io.prediction.commons.modeldata.db.name=predictionio_modeldata_generic_dataprep_test
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.host=localhost
-io.prediction.commons.modeldata.training.db.port=27017
-io.prediction.commons.modeldata.training.db.name=predictionio_training_modeldata_generic_dataprep_test
-
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.host=localhost
-io.prediction.commons.settings.db.port=27017
-io.prediction.commons.settings.db.name=predictionio_generic_dataprep_test
diff --git a/process/engines/itemrec/algorithms/scala/generic/src/test/resources/logback.xml b/process/engines/itemrec/algorithms/scala/generic/src/test/resources/logback.xml
deleted file mode 100644
index 1a2768e..0000000
--- a/process/engines/itemrec/algorithms/scala/generic/src/test/resources/logback.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<configuration>
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <encoder>
-      <pattern>%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>
-    </encoder>
-  </appender>
-  <root level="info">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
-
diff --git a/process/engines/itemrec/algorithms/scala/generic/src/test/scala/io/prediction/algorithms/itemrec/generic/GenericDataPreparatorSpec.scala b/process/engines/itemrec/algorithms/scala/generic/src/test/scala/io/prediction/algorithms/itemrec/generic/GenericDataPreparatorSpec.scala
deleted file mode 100644
index 6aedd75..0000000
--- a/process/engines/itemrec/algorithms/scala/generic/src/test/scala/io/prediction/algorithms/itemrec/generic/GenericDataPreparatorSpec.scala
+++ /dev/null
@@ -1,383 +0,0 @@
-package io.prediction.algorithms.generic.itemrec
-
-import io.prediction.commons.Config
-import io.prediction.commons.appdata.{ User, Item, U2IAction }
-
-import org.apache.commons.io.FileUtils
-import java.io.File
-import org.specs2.mutable._
-import com.github.nscala_time.time.Imports._
-import scala.io.Source
-import com.mongodb.casbah.Imports._
-
-class GenericDataPreparatorSpec extends Specification {
-
-  // note: should match the db name defined in the application.conf
-  val parentDir = "/tmp/pio_test/io.prediction.algorithms.generic.itemrec.GenericDataPreparatorSpec"
-
-  val mongoDbName = "predictionio_appdata_generic_dataprep_test"
-  def cleanUp() = {
-    // remove the test database
-    MongoConnection()(mongoDbName).dropDatabase()
-    FileUtils.deleteDirectory(new File(parentDir))
-  }
-
-  val commonConfig = new Config
-  val appdataUsers = commonConfig.getAppdataUsers
-  val appdataItems = commonConfig.getAppdataItems
-  val appdataU2IActions = commonConfig.getAppdataU2IActions
-
-  val appid = 23
-  // insert a few users into db
-  val user = User(
-    id = "u1",
-    appid = appid,
-    ct = DateTime.now,
-    latlng = None,
-    inactive = None,
-    attributes = None)
-
-  appdataUsers.insert(user.copy(id = "u1"))
-  appdataUsers.insert(user.copy(id = "u2"))
-  appdataUsers.insert(user.copy(id = "u3"))
-
-  // insert a few items into db
-  val itemStartTime = DateTime.now
-  val itemStartTimeMillis = itemStartTime.millis
-  val item = Item(
-    id = "i1",
-    appid = appid,
-    ct = DateTime.now,
-    itypes = List("t1", "t2"),
-    starttime = Some(itemStartTime),
-    endtime = None,
-    price = None,
-    profit = None,
-    latlng = None,
-    inactive = None,
-    attributes = None)
-
-  appdataItems.insert(item.copy(id = "i1", itypes = List("t1", "t2"),
-    inactive = Some(false)))
-  appdataItems.insert(item.copy(id = "i2", itypes = List("t1")))
-  appdataItems.insert(item.copy(id = "i3", itypes = List("t2", "t3"),
-    inactive = Some(true)))
-  appdataItems.insert(item.copy(id = "i4", itypes = List("t3")))
-  appdataItems.insert(item.copy(id = "i5", itypes = List("t1"),
-    inactive = Some(true)))
-  appdataItems.insert(item.copy(id = "i6", itypes = List("t3"),
-    inactive = Some(false)))
-
-  // insert a few u2i into db
-  val u2i = U2IAction(
-    appid = appid,
-    action = "rate",
-    uid = "u0",
-    iid = "i0",
-    t = DateTime.now,
-    latlng = None,
-    v = Some(3),
-    price = None)
-
-  // test mixed and conflict actions
-  appdataU2IActions.insert(u2i.copy(uid = "u1", iid = "i1", action = "view"))
-  appdataU2IActions.insert(u2i.copy(uid = "u1", iid = "i1", action = "rate", v = Some(3)))
-  appdataU2IActions.insert(u2i.copy(uid = "u1", iid = "i2", action = "rate", v = Some(4)))
-  appdataU2IActions.insert(u2i.copy(uid = "u1", iid = "i3", action = "rate", v = Some(1)))
-
-  appdataU2IActions.insert(u2i.copy(uid = "u2", iid = "i1", action = "view"))
-  appdataU2IActions.insert(u2i.copy(uid = "u2", iid = "i1", action = "rate", v = Some(2)))
-  appdataU2IActions.insert(u2i.copy(uid = "u2", iid = "i2", action = "view"))
-  appdataU2IActions.insert(u2i.copy(uid = "u2", iid = "i2", action = "rate", v = Some(5)))
-  appdataU2IActions.insert(u2i.copy(uid = "u2", iid = "i2", action = "rate", v = Some(1)))
-  appdataU2IActions.insert(u2i.copy(uid = "u2", iid = "i4", action = "dislike"))
-  appdataU2IActions.insert(u2i.copy(uid = "u2", iid = "i4", action = "rate", v = Some(3)))
-
-  appdataU2IActions.insert(u2i.copy(uid = "u3", iid = "i2", action = "like"))
-  appdataU2IActions.insert(u2i.copy(uid = "u3", iid = "i2", action = "rate", v = Some(5)))
-  appdataU2IActions.insert(u2i.copy(uid = "u3", iid = "i3", action = "view"))
-  appdataU2IActions.insert(u2i.copy(uid = "u3", iid = "i3", action = "view"))
-  appdataU2IActions.insert(u2i.copy(uid = "u3", iid = "i3", action = "rate", v = Some(1)))
-  appdataU2IActions.insert(u2i.copy(uid = "u3", iid = "i4", action = "view"))
-  appdataU2IActions.insert(u2i.copy(uid = "u3", iid = "i4", action = "rate", v = Some(4)))
-
-  // unknown user and item actions (not exist in user and items appdata)
-  appdataU2IActions.insert(u2i.copy(uid = "u3", iid = "unkowni5", action = "view"))
-  appdataU2IActions.insert(u2i.copy(uid = "u3", iid = "unkowni6", action = "rate", v = Some(4)))
-  appdataU2IActions.insert(u2i.copy(uid = "unkownu4", iid = "i2", action = "view"))
-  appdataU2IActions.insert(u2i.copy(uid = "unkownu4", iid = "i1", action = "rate", v = Some(3)))
-
-  "GenericDataPreparator with matrixMarket = true" should {
-
-    val outputDir = s"${parentDir}/mmtrue"
-    val args = Map(
-      "outputDir" -> outputDir,
-      "appid" -> appid,
-      "viewParam" -> 4,
-      "likeParam" -> 3,
-      "dislikeParam" -> 1,
-      "conversionParam" -> 2,
-      "conflictParam" -> "latest",
-      "matrixMarket" -> true
-    )
-
-    val argsArray = args.toArray.flatMap {
-      case (k, v) =>
-        Array(s"--${k}", v.toString)
-    }
-
-    GenericDataPreparator.main(argsArray)
-
-    "correctly generate usersIndex.tsv" in {
-      val usersIndex = Source.fromFile(s"${outputDir}usersIndex.tsv")
-        .getLines()
-        .toList
-
-      val expected = List(
-        "1\tu1",
-        "2\tu2",
-        "3\tu3")
-
-      usersIndex must containTheSameElementsAs(expected)
-    }
-
-    "correctly generate itemsIndex.tsv" in {
-      val itemsIndex = Source.fromFile(s"${outputDir}itemsIndex.tsv")
-        .getLines()
-        .toList
-
-      val expected = List(
-        s"1\ti1\tt1,t2\t${itemStartTimeMillis}",
-        s"2\ti2\tt1\t${itemStartTimeMillis}",
-        //s"3\ti3\tt2,t3\t${itemStartTimeMillis}", inactive
-        s"4\ti4\tt3\t${itemStartTimeMillis}",
-        s"6\ti6\tt3\t${itemStartTimeMillis}"
-      )
-      itemsIndex must containTheSameElementsAs(expected)
-    }
-
-    "correctly generate ratings.mm" in {
-      val ratingsLines = Source.fromFile(s"${outputDir}ratings.mm")
-        .getLines().toList
-
-      val headers = ratingsLines.take(2)
-
-      val ratings = ratingsLines.drop(2)
-
-      val expectedHeaders = List(
-        "%%MatrixMarket matrix coordinate real general",
-        "3 6 9"
-      )
-
-      val expected = List(
-        "1 1 3",
-        "1 2 4",
-        "1 3 1",
-        "2 1 2",
-        "2 2 1",
-        "2 4 3",
-        "3 2 5",
-        "3 3 1",
-        "3 4 4"
-      )
-      headers must be_==(expectedHeaders) and
-        (ratings must containTheSameElementsAs(expected))
-    }
-
-    "correctly write seen.csv" in {
-      val seen = Source.fromFile(s"${outputDir}seen.csv").getLines().toList
-      val expected = List(
-        "1,1",
-        "1,2",
-        "1,3",
-        "2,1",
-        "2,2",
-        "2,4",
-        "3,2",
-        "3,3",
-        "3,4"
-      )
-      seen must containTheSameElementsAs(expected)
-    }
-
-  }
-
-  "GenericDataPreparator with matrixMarket = false" should {
-
-    val outputDir = s"${parentDir}/mmfalse"
-    val args = Map(
-      "outputDir" -> outputDir,
-      "appid" -> appid,
-      "viewParam" -> 4,
-      "likeParam" -> 3,
-      "dislikeParam" -> 1,
-      "conversionParam" -> 2,
-      "conflictParam" -> "latest",
-      "matrixMarket" -> false
-    )
-
-    val argsArray = args.toArray.flatMap {
-      case (k, v) =>
-        Array(s"--${k}", v.toString)
-    }
-
-    GenericDataPreparator.main(argsArray)
-
-    "correctly generate usersIndex.tsv" in {
-      val usersIndex = Source.fromFile(s"${outputDir}usersIndex.tsv")
-        .getLines()
-        .toList
-
-      val expected = List(
-        "1\tu1",
-        "2\tu2",
-        "3\tu3")
-
-      usersIndex must containTheSameElementsAs(expected)
-    }
-
-    "correctly generate itemsIndex.tsv" in {
-      val itemsIndex = Source.fromFile(s"${outputDir}itemsIndex.tsv")
-        .getLines()
-        .toList
-
-      val expected = List(
-        s"1\ti1\tt1,t2\t${itemStartTimeMillis}",
-        s"2\ti2\tt1\t${itemStartTimeMillis}",
-        //s"3\ti3\tt2,t3\t${itemStartTimeMillis}", inactive
-        s"4\ti4\tt3\t${itemStartTimeMillis}",
-        s"6\ti6\tt3\t${itemStartTimeMillis}"
-      )
-      itemsIndex must containTheSameElementsAs(expected)
-    }
-
-    "correctly generate ratings.csv" in {
-      val ratings = Source.fromFile(s"${outputDir}ratings.csv")
-        .getLines().toList
-
-      val expected = List(
-        "1,1,3",
-        "1,2,4",
-        "1,3,1",
-        "2,1,2",
-        "2,2,1",
-        "2,4,3",
-        "3,2,5",
-        "3,3,1",
-        "3,4,4"
-      )
-
-      ratings must containTheSameElementsAs(expected)
-    }
-
-    "correctly write seen.csv" in {
-      val seen = Source.fromFile(s"${outputDir}seen.csv").getLines().toList
-      val expected = List(
-        "1,1",
-        "1,2",
-        "1,3",
-        "2,1",
-        "2,2",
-        "2,4",
-        "3,2",
-        "3,3",
-        "3,4"
-      )
-      seen must containTheSameElementsAs(expected)
-    }
-  }
-
-  "GenericDataPreparator with matrixMarket = false and seenAction" should {
-
-    val outputDir = s"${parentDir}/seenActions"
-    val args = Map(
-      "outputDir" -> outputDir,
-      "appid" -> appid,
-      "viewParam" -> 4,
-      "likeParam" -> 3,
-      "dislikeParam" -> 1,
-      "conversionParam" -> 2,
-      "conflictParam" -> "latest",
-      "seenActions" -> Array("view", "like"),
-      "matrixMarket" -> false
-    )
-
-    val argsArray = args.toArray.flatMap {
-      case (k, v) =>
-        v match {
-          case x: Array[String] => Array(s"--${k}") ++ x
-          case _ => Array(s"--${k}", v.toString)
-        }
-
-    }
-
-    GenericDataPreparator.main(argsArray)
-
-    "correctly generate usersIndex.tsv" in {
-      val usersIndex = Source.fromFile(s"${outputDir}usersIndex.tsv")
-        .getLines()
-        .toList
-
-      val expected = List(
-        "1\tu1",
-        "2\tu2",
-        "3\tu3")
-
-      usersIndex must containTheSameElementsAs(expected)
-    }
-
-    "correctly generate itemsIndex.tsv" in {
-      val itemsIndex = Source.fromFile(s"${outputDir}itemsIndex.tsv")
-        .getLines()
-        .toList
-
-      val expected = List(
-        s"1\ti1\tt1,t2\t${itemStartTimeMillis}",
-        s"2\ti2\tt1\t${itemStartTimeMillis}",
-        //s"3\ti3\tt2,t3\t${itemStartTimeMillis}", inactive
-        s"4\ti4\tt3\t${itemStartTimeMillis}",
-        s"6\ti6\tt3\t${itemStartTimeMillis}"
-      )
-      itemsIndex must containTheSameElementsAs(expected)
-    }
-
-    "correctly generate ratings.csv" in {
-      val ratings = Source.fromFile(s"${outputDir}ratings.csv")
-        .getLines().toList
-
-      val expected = List(
-        "1,1,3",
-        "1,2,4",
-        "1,3,1",
-        "2,1,2",
-        "2,2,1",
-        "2,4,3",
-        "3,2,5",
-        "3,3,1",
-        "3,4,4"
-      )
-
-      ratings must containTheSameElementsAs(expected)
-    }
-
-    "correctly write seen.csv" in {
-      val seen = Source.fromFile(s"${outputDir}seen.csv").getLines().toList
-      val expected = List(
-        "1,1",
-        "2,1",
-        "2,2",
-        "3,2",
-        "3,3",
-        "3,4"
-      )
-      seen must containTheSameElementsAs(expected)
-    }
-  }
-
-  // TODO: test start and end time
-
-  // TODO: test evalid != None
-
-  // clean up when finish test
-  step(cleanUp())
-}
diff --git a/process/engines/itemrec/algorithms/scala/graphchi/build.sbt b/process/engines/itemrec/algorithms/scala/graphchi/build.sbt
deleted file mode 100644
index 82d9699..0000000
--- a/process/engines/itemrec/algorithms/scala/graphchi/build.sbt
+++ /dev/null
@@ -1,23 +0,0 @@
-import xerial.sbt.Pack._
-
-name := "predictionio-process-itemrec-algorithms-scala-graphchi"
-
-libraryDependencies ++= Seq(
-  "ch.qos.logback" % "logback-classic" % "1.1.1",
-  "com.twitter" %% "scalding-args" % "0.8.11",
-  "org.clapper" %% "grizzled-slf4j" % "1.0.1",
-  "org.scalanlp" %% "breeze" % "0.7")
-
-packSettings
-
-packJarNameConvention := "full"
-
-packExpandedClasspath := true
-
-packGenerateWindowsBatFile := false
-
-packMain := Map(
-  "itemrec.graphchi.modelcon" -> "io.prediction.algorithms.graphchi.itemrec.GraphChiModelConstructor")
-
-packJvmOpts := Map(
-  "itemrec.graphchi.modelcon" -> Common.packCommonJvmOpts)
diff --git a/process/engines/itemrec/algorithms/scala/graphchi/src/main/resources/application.conf b/process/engines/itemrec/algorithms/scala/graphchi/src/main/resources/application.conf
deleted file mode 100644
index c85803b..0000000
--- a/process/engines/itemrec/algorithms/scala/graphchi/src/main/resources/application.conf
+++ /dev/null
@@ -1,30 +0,0 @@
-# Used by PredictionIO Commons
-io.prediction.base=.
-
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.host=localhost
-io.prediction.commons.appdata.db.port=27017
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.host=localhost
-io.prediction.commons.appdata.test.db.port=27017
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.host=localhost
-io.prediction.commons.appdata.training.db.port=27017
-
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.host=localhost
-io.prediction.commons.appdata.validation.db.port=27017
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.host=localhost
-io.prediction.commons.modeldata.db.port=27017
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.host=localhost
-io.prediction.commons.modeldata.training.db.port=27017
-
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.host=localhost
-io.prediction.commons.settings.db.port=27017
diff --git a/process/engines/itemrec/algorithms/scala/graphchi/src/main/resources/logback.xml b/process/engines/itemrec/algorithms/scala/graphchi/src/main/resources/logback.xml
deleted file mode 100644
index 1a2768e..0000000
--- a/process/engines/itemrec/algorithms/scala/graphchi/src/main/resources/logback.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<configuration>
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <encoder>
-      <pattern>%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>
-    </encoder>
-  </appender>
-  <root level="info">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
-
diff --git a/process/engines/itemrec/algorithms/scala/graphchi/src/main/scala/io/prediction/algorithms/graphchi/itemrec/GraphChiModelConstructor.scala b/process/engines/itemrec/algorithms/scala/graphchi/src/main/scala/io/prediction/algorithms/graphchi/itemrec/GraphChiModelConstructor.scala
deleted file mode 100644
index c0d9ec4..0000000
--- a/process/engines/itemrec/algorithms/scala/graphchi/src/main/scala/io/prediction/algorithms/graphchi/itemrec/GraphChiModelConstructor.scala
+++ /dev/null
@@ -1,221 +0,0 @@
-package io.prediction.algorithms.graphchi.itemrec
-
-import grizzled.slf4j.Logger
-import breeze.linalg._
-import com.twitter.scalding.Args
-import scala.io.Source
-import scala.collection.mutable.PriorityQueue
-
-import io.prediction.algorithms.graphchi.itemrec.MatrixMarketReader
-import io.prediction.commons.Config
-import io.prediction.commons.modeldata.{ ItemRecScore }
-
-/**
- * Input files:
- * - usersIndex.tsv (uindex uid)
- * - itemsIndex.tsv (iindex iid itypes) (only recommend items in this list)
- * - seen.csv (uindex, iindex) (For unseenOnly filtering)
- * - ratings.mm_U.mm User x feature matrix generated by GraphChi
- * - ratings.mm_V.mm Item x feature matrix generated by GraphChi
- *
- */
-object GraphChiModelConstructor {
-
-  /* global */
-  val logger = Logger(GraphChiModelConstructor.getClass)
-  //println(logger.isInfoEnabled)
-  val commonsConfig = new Config
-
-  // argument of this job
-  case class JobArg(
-    val inputDir: String,
-    val appid: Int,
-    val algoid: Int,
-    val evalid: Option[Int],
-    val modelSet: Boolean,
-    val unseenOnly: Boolean,
-    val numRecommendations: Int)
-
-  def main(cmdArgs: Array[String]) {
-    logger.info("Running model constructor for GraphChi ...")
-    logger.info(cmdArgs.mkString(","))
-
-    /* get arg */
-    val args = Args(cmdArgs)
-
-    val arg = JobArg(
-      inputDir = args("inputDir"),
-      appid = args("appid").toInt,
-      algoid = args("algoid").toInt,
-      evalid = args.optional("evalid") map (x => x.toInt),
-      modelSet = args("modelSet").toBoolean,
-      unseenOnly = args("unseenOnly").toBoolean,
-      numRecommendations = args("numRecommendations").toInt
-    )
-
-    /* run job */
-    modelCon(arg)
-    cleanUp(arg)
-  }
-
-  def modelCon(arg: JobArg) = {
-
-    // NOTE: if OFFLINE_EVAL, write to training modeldata and use evalid as appid
-    val OFFLINE_EVAL = (arg.evalid != None)
-
-    val modeldataDb = if (!OFFLINE_EVAL)
-      commonsConfig.getModeldataItemRecScores
-    else
-      commonsConfig.getModeldataTrainingItemRecScores
-
-    val appid = if (OFFLINE_EVAL) arg.evalid.get else arg.appid
-
-    // user index file
-    // uindex -> uid
-    val usersMap: Map[Int, String] = Source.fromFile(s"${arg.inputDir}usersIndex.tsv").getLines()
-      .map[(Int, String)] { line =>
-        val (uindex, uid) = try {
-          val data = line.split("\t")
-          (data(0).toInt, data(1))
-        } catch {
-          case e: Exception => {
-            throw new RuntimeException(s"Cannot get user index and uid in line: ${line}. ${e}")
-          }
-        }
-        (uindex, uid)
-      }.toMap
-
-    case class ItemData(
-      val iid: String,
-      val itypes: Seq[String])
-
-    // item index file (iindex iid itypes)
-    // iindex -> ItemData
-    val itemsMap: Map[Int, ItemData] = Source.fromFile(s"${arg.inputDir}itemsIndex.tsv")
-      .getLines()
-      .map[(Int, ItemData)] { line =>
-        val (iindex, item) = try {
-          val fields = line.split("\t")
-          val itemData = ItemData(
-            iid = fields(1),
-            itypes = fields(2).split(",").toList
-          )
-          (fields(0).toInt, itemData)
-        } catch {
-          case e: Exception => {
-            throw new RuntimeException(s"Cannot get item info in line: ${line}. ${e}")
-          }
-        }
-        (iindex, item)
-      }.toMap
-
-    // ratings file (for unseen filtering)
-    val seenSet: Map[Int, Set[Int]] = if (arg.unseenOnly) {
-      Source.fromFile(s"${arg.inputDir}seen.csv")
-        .getLines()
-        .map[(Int, Int)] { line =>
-          val (u, i) = try {
-            val fields = line.split(",")
-            // u, i
-            (fields(0).toInt, fields(1).toInt)
-          } catch {
-            case e: Exception => throw new RuntimeException(s"Cannot get user and item index from this line: ${line}. ${e}")
-          }
-          (u, i)
-        }.toSeq.groupBy(_._1)
-        .mapValues(_.map(_._2).toSet)
-    } else {
-      Map() // empty map
-    }
-
-    // feature x user matrix
-    val userMatrix = MatrixMarketReader.readDense(s"${arg.inputDir}ratings.mm_U.mm")
-
-    // feature x item matrix
-    val itemMatrix = MatrixMarketReader.readDense(s"${arg.inputDir}ratings.mm_V.mm")
-
-    val allUindex = for (uindex <- 1 to userMatrix.cols if usersMap.contains(uindex)) yield (uindex, userMatrix(::, uindex - 1), seenSet.getOrElse(uindex, Set()))
-
-    val validIindex = for (iindex <- 1 to itemMatrix.cols if validItemFilter(true, iindex, itemsMap)) yield (iindex)
-
-    val allScores = allUindex.par
-      .foreach { fields =>
-        val (uindex, userVector, seenItemSet) = fields
-        val q = new TopNQueue[(Int, Double)](arg.numRecommendations)(ScoreOrdering.reverse)
-        val candidateIindex = validIindex.toIterator
-          .filter(iindex => unseenItemFilter(arg.unseenOnly, iindex, seenItemSet))
-
-        while (candidateIindex.hasNext) {
-          val iindex = candidateIindex.next()
-          val score = userVector dot itemMatrix(::, iindex - 1)
-          q.add((iindex, score))
-        }
-
-        val topScores = q.toSeq
-
-        modeldataDb.insert(ItemRecScore(
-          uid = usersMap(uindex),
-          iids = topScores.map(x => itemsMap(x._1).iid),
-          scores = topScores.map(_._2),
-          itypes = topScores.map(x => itemsMap(x._1).itypes),
-          appid = appid,
-          algoid = arg.algoid,
-          modelset = arg.modelSet))
-      }
-  }
-
-  def unseenItemFilter(enable: Boolean, iindex: Int, seenSet: Set[Int]): Boolean = {
-    if (enable) (!seenSet(iindex)) else true
-  }
-
-  def validItemFilter(enable: Boolean, iindex: Int, validMap: Map[Int, Any]): Boolean = {
-    if (enable) validMap.contains(iindex) else true
-  }
-
-  def cleanUp(arg: JobArg) = {
-
-  }
-
-  object ScoreOrdering extends Ordering[(Int, Double)] {
-    override def compare(a: (Int, Double), b: (Int, Double)) = a._2 compare b._2
-  }
-
-  def getTopN[T](s: Seq[T], n: Int)(implicit ord: Ordering[T]): Seq[T] = {
-    val q = PriorityQueue()
-
-    for (x <- s) {
-      if (q.size < n)
-        q.enqueue(x)
-      else {
-        // q is full
-        if (ord.compare(x, q.head) < 0) {
-          q.dequeue()
-          q.enqueue(x)
-        }
-      }
-    }
-
-    q.dequeueAll.toSeq.reverse
-  }
-
-  class TopNQueue[T](val n: Int)(implicit ord: Ordering[T]) {
-    val q = PriorityQueue[T]()
-
-    def add(x: T) = {
-      if (q.size < n)
-        q.enqueue(x)
-      else {
-        // q is full
-        if (ord.compare(x, q.head) < 0) {
-          q.dequeue()
-          q.enqueue(x)
-        }
-      }
-    }
-
-    def toSeq[T] = {
-      q.dequeueAll.toSeq.reverse
-    }
-  }
-
-}
diff --git a/process/engines/itemrec/algorithms/scala/graphchi/src/main/scala/io/prediction/algorithms/graphchi/itemrec/MatrixMarketReader.scala b/process/engines/itemrec/algorithms/scala/graphchi/src/main/scala/io/prediction/algorithms/graphchi/itemrec/MatrixMarketReader.scala
deleted file mode 100644
index 851b48c..0000000
--- a/process/engines/itemrec/algorithms/scala/graphchi/src/main/scala/io/prediction/algorithms/graphchi/itemrec/MatrixMarketReader.scala
+++ /dev/null
@@ -1,80 +0,0 @@
-package io.prediction.algorithms.graphchi.itemrec
-
-import breeze.linalg._
-import grizzled.slf4j.Logger
-import scala.io.Source
-
-object MatrixMarketReader {
-
-  val logger = Logger(MatrixMarketReader.getClass)
-
-  /* read dense matrix market from file and return DenseMatrix object */
-  def readDense(path: String): DenseMatrix[Double] = {
-    val matrixFile = Source.fromFile(path)
-    // skip line starts with %
-    // skip empty line
-    val lines = matrixFile.getLines()
-      .filter(line => (line.length != 0) && (!line.startsWith("%")))
-
-    // first line is matrix size
-    if (lines.hasNext) {
-      val line = lines.next()
-      val size = line.split("""\s+""")
-
-      // matrix market dense format is column oriented
-      /* eg:
-       * 2 3
-       * 1
-       * 2
-       * 3
-       * 4
-       * 5
-       * 6
-       * becomes
-       * 1 4
-       * 2 5
-       * 3 6
-       */
-      val (colNum, rowNum): (Int, Int) = try {
-        (size(0).toInt, size(1).toInt)
-      } catch {
-        case e: Exception =>
-          throw new RuntimeException(s"Cannot extract matrix size from the line: ${line}. ${e}")
-      }
-
-      logger.debug(s"${rowNum}, ${colNum}")
-      val matrix = DenseMatrix.zeros[Double](rowNum, colNum)
-
-      var r = 0
-      var c = 0
-      lines.foreach { line =>
-        if (c >= colNum) {
-          throw new RuntimeException(s"Number of elements greater than the defined size: ${rowNum} ${colNum}")
-        } else {
-
-          logger.debug(s"${r}, ${c} = ${line}")
-          try {
-            matrix(r, c) = line.toDouble
-          } catch {
-            case e: Exception =>
-              throw new RuntimeException(s"Cannot convert line: ${line} to double. ${e}")
-          }
-          r += 1
-          if (r == rowNum) {
-            r = 0
-            c += 1
-          }
-        }
-      }
-      // c must == colNum when finish
-      if (c < colNum) {
-        throw new RuntimeException(s"Number of elements smaller than the defined size: ${rowNum} ${colNum}")
-      }
-      logger.debug(matrix)
-      matrix
-    } else {
-      DenseMatrix.zeros[Double](0, 0)
-    }
-  }
-
-}
\ No newline at end of file
diff --git a/process/engines/itemrec/algorithms/scala/graphchi/src/test/resources/application.conf b/process/engines/itemrec/algorithms/scala/graphchi/src/test/resources/application.conf
deleted file mode 100644
index 45b3078..0000000
--- a/process/engines/itemrec/algorithms/scala/graphchi/src/test/resources/application.conf
+++ /dev/null
@@ -1,37 +0,0 @@
-# Used by PredictionIO Commons
-io.prediction.base=.
-
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.host=localhost
-io.prediction.commons.appdata.db.port=27017
-io.prediction.commons.appdata.db.name=predictionio_appdata_graphchi_dataprep_test
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.host=localhost
-io.prediction.commons.appdata.test.db.port=27017
-io.prediction.commons.appdata.test.db.name=predictionio_test_appdata_graphchi_dataprep_test
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.host=localhost
-io.prediction.commons.appdata.training.db.port=27017
-io.prediction.commons.appdata.training.db.name=predictionio_trainig_appdata_graphchi_dataprep_test
-
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.host=localhost
-io.prediction.commons.appdata.validation.db.port=27017
-io.prediction.commons.appdata.validation.db.name=predictionio_validation_appdata_graphchi_dataprep_test
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.host=localhost
-io.prediction.commons.modeldata.db.port=27017
-io.prediction.commons.modeldata.db.name=predictionio_modeldata_graphchi_dataprep_test
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.host=localhost
-io.prediction.commons.modeldata.training.db.port=27017
-io.prediction.commons.modeldata.training.db.name=predictionio_training_modeldata_graphchi_dataprep_test
-
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.host=localhost
-io.prediction.commons.settings.db.port=27017
-io.prediction.commons.settings.db.name=predictionio_graphchi_dataprep_test
diff --git a/process/engines/itemrec/algorithms/scala/graphchi/src/test/resources/logback.xml b/process/engines/itemrec/algorithms/scala/graphchi/src/test/resources/logback.xml
deleted file mode 100644
index 1a2768e..0000000
--- a/process/engines/itemrec/algorithms/scala/graphchi/src/test/resources/logback.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<configuration>
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <encoder>
-      <pattern>%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>
-    </encoder>
-  </appender>
-  <root level="info">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
-
diff --git a/process/engines/itemrec/algorithms/scala/graphchi/src/test/scala/io/prediction/algorithms/graphchi/itemrec/GraphChiModelConstructorSpec.scala b/process/engines/itemrec/algorithms/scala/graphchi/src/test/scala/io/prediction/algorithms/graphchi/itemrec/GraphChiModelConstructorSpec.scala
deleted file mode 100644
index 867ef75..0000000
--- a/process/engines/itemrec/algorithms/scala/graphchi/src/test/scala/io/prediction/algorithms/graphchi/itemrec/GraphChiModelConstructorSpec.scala
+++ /dev/null
@@ -1,452 +0,0 @@
-package io.prediction.algorithms.graphchi.itemrec
-
-import io.prediction.commons.Config
-import io.prediction.commons.settings.{ App, Algo }
-import io.prediction.commons.modeldata.{ ItemRecScore }
-
-import org.specs2.mutable._
-import com.github.nscala_time.time.Imports._
-import scala.io.Source
-import java.io.File
-import java.io.FileWriter
-import java.io.BufferedWriter
-
-import com.mongodb.casbah.Imports._
-
-class GraphChiModelConstructorSpec extends Specification {
-
-  // note: should match the db name defined in the application.conf
-  val mongoDbName = "predictionio_modeldata_graphchi_dataprep_test"
-  def cleanUp() = {
-    // remove the test database
-    MongoConnection()(mongoDbName).dropDatabase()
-  }
-
-  val commonConfig = new Config
-  val modeldataItemRecScores = commonConfig.getModeldataItemRecScores
-
-  // NOTE: use HALF_UP mode to avoid error caused by rounding when compare data
-  // (eg. 3.5 vs 3.499999999999).
-  // (eg. 0.6666666666 vs 0.666666667)
-  def roundUpScores(irec: ItemRecScore): ItemRecScore = {
-    irec.copy(
-      scores = irec.scores.map { x =>
-        BigDecimal(x).setScale(9, BigDecimal.RoundingMode.HALF_UP).toDouble
-      }
-    )
-  }
-
-  def argMapToArray(args: Map[String, Any]): Array[String] = {
-    args.toArray.flatMap {
-      case (k, v) =>
-        Array(s"--${k}", v.toString)
-    }
-  }
-
-  "GraphChiModelConstructor" should {
-
-    val inputDir = "/tmp/pio_test/"
-
-    val inputDirFile = new File(inputDir)
-    inputDirFile.mkdirs()
-
-    val usersIndex = List(
-      "1\tu1",
-      "2\tu2",
-      "3\tu3")
-
-    val itemsIndex = List(
-      "1\ti1\tt1,t2",
-      "2\ti2\tt1",
-      "3\ti3\tt2,t3",
-      "4\ti4\tt3"
-    )
-
-    val seenCSV = List(
-      "1,1",
-      "1,2",
-      "1,3",
-      "2,1",
-      "2,4",
-      "3,2"
-    )
-
-    /*
-     * 1.2 2.4 1.1
-     * 4.3 1.1 2.4
-     */
-    val ratingsUMM = List(
-      "%%MatrixMarket matrix array real general",
-      "%This file contains ALS output matrix U. In each row D factors of a single user node.",
-      "3 2",
-      "1.2",
-      "4.3",
-      "2.4",
-      "1.1",
-      "1.1",
-      "2.4"
-    )
-
-    /*
-     * 2.1 3.1 2.6 1.9
-     * 1.5 1.2 1.3 2.0
-     */
-    val ratingsVMM = List(
-      "%%MatrixMarket matrix array real general",
-      "%This file contains ALS output matrix V. In each row D factors of a single item node.",
-      "4 2",
-      "2.1",
-      "1.5",
-      "3.1",
-      "1.2",
-      "2.6",
-      "1.3",
-      "1.9",
-      "2.0"
-    )
-
-    /* Ut V:
-     * 8.97 8.88  8.71  10.88
-     * 6.69 8.76  7.67  6.76
-     * 5.91 6.29  5.98  6.89
-     */
-
-    def writeToFile(lines: List[String], filePath: String) = {
-      val writer = new BufferedWriter(new FileWriter(new File(filePath)))
-      lines.foreach { line =>
-        writer.write(s"${line}\n")
-      }
-      writer.close()
-    }
-
-    writeToFile(usersIndex, s"${inputDir}usersIndex.tsv")
-    writeToFile(itemsIndex, s"${inputDir}itemsIndex.tsv")
-    writeToFile(seenCSV, s"${inputDir}seen.csv")
-    writeToFile(ratingsUMM, s"${inputDir}ratings.mm_U.mm")
-    writeToFile(ratingsVMM, s"${inputDir}ratings.mm_V.mm")
-
-    val appid = 24
-
-    implicit val app = App(
-      id = appid,
-      userid = 0,
-      appkey = "1234",
-      display = "12345",
-      url = None,
-      cat = None,
-      desc = None,
-      timezone = "UTC"
-    )
-
-    "correctly writes ItemRecScores with larger numRecommendations" in {
-
-      val algoid = 25
-      val modelSet = false
-
-      implicit val algo = Algo(
-        id = algoid,
-        engineid = 1234,
-        name = "",
-        infoid = "abc",
-        command = "",
-        params = Map(),
-        settings = Map(),
-        modelset = modelSet,
-        createtime = DateTime.now,
-        updatetime = DateTime.now,
-        status = "deployed",
-        offlineevalid = None,
-        offlinetuneid = None,
-        loop = None,
-        paramset = None
-      )
-
-      val args = Map(
-        "inputDir" -> inputDir,
-        "appid" -> appid,
-        "algoid" -> algoid,
-        "modelSet" -> modelSet,
-        "unseenOnly" -> false,
-        "numRecommendations" -> 5
-      )
-
-      val u1Expected = ItemRecScore(
-        uid = "u1",
-        iids = Seq("i4", "i1", "i2", "i3"),
-        scores = Seq(10.88, 8.97, 8.88, 8.71),
-        itypes = Seq(Seq("t3"), Seq("t1", "t2"), Seq("t1"), Seq("t2", "t3")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val u2Expected = ItemRecScore(
-        uid = "u2",
-        iids = Seq("i2", "i3", "i4", "i1"),
-        scores = Seq(8.76, 7.67, 6.76, 6.69),
-        itypes = Seq(Seq("t1"), Seq("t2", "t3"), Seq("t3"), Seq("t1", "t2")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val u3Expected = ItemRecScore(
-        uid = "u3",
-        iids = Seq("i4", "i2", "i3", "i1"),
-        scores = Seq(6.89, 6.29, 5.98, 5.91),
-        itypes = Seq(Seq("t3"), Seq("t1"), Seq("t2", "t3"), Seq("t1", "t2")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      GraphChiModelConstructor.main(argMapToArray(args))
-
-      val u1ItemRec = modeldataItemRecScores.getByUid("u1")
-      val u2ItemRec = modeldataItemRecScores.getByUid("u2")
-      val u3ItemRec = modeldataItemRecScores.getByUid("u3")
-
-      // don't check id
-      u1ItemRec.map(roundUpScores(_).copy(id = None)) must beSome(roundUpScores(u1Expected)) and
-        (u2ItemRec.map(roundUpScores(_).copy(id = None)) must beSome(roundUpScores(u2Expected))) and
-        (u3ItemRec.map(roundUpScores(_).copy(id = None)) must beSome(roundUpScores(u3Expected)))
-
-    }
-
-    "correctly writes ItemRecScores with smaller numRecommendations" in {
-
-      val algoid = 26
-      val modelSet = true
-
-      implicit val algo = Algo(
-        id = algoid,
-        engineid = 1234,
-        name = "",
-        infoid = "abc",
-        command = "",
-        params = Map(),
-        settings = Map(),
-        modelset = modelSet,
-        createtime = DateTime.now,
-        updatetime = DateTime.now,
-        status = "deployed",
-        offlineevalid = None,
-        offlinetuneid = None,
-        loop = None,
-        paramset = None
-      )
-
-      val args = Map(
-        "inputDir" -> inputDir,
-        "appid" -> appid,
-        "algoid" -> algoid,
-        "modelSet" -> modelSet,
-        "unseenOnly" -> false,
-        "numRecommendations" -> 2
-      )
-
-      val u1Expected = ItemRecScore(
-        uid = "u1",
-        iids = Seq("i4", "i1"),
-        scores = Seq(10.88, 8.97),
-        itypes = Seq(Seq("t3"), Seq("t1", "t2")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val u2Expected = ItemRecScore(
-        uid = "u2",
-        iids = Seq("i2", "i3"),
-        scores = Seq(8.76, 7.67),
-        itypes = Seq(Seq("t1"), Seq("t2", "t3")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val u3Expected = ItemRecScore(
-        uid = "u3",
-        iids = Seq("i4", "i2"),
-        scores = Seq(6.89, 6.29),
-        itypes = Seq(Seq("t3"), Seq("t1")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      GraphChiModelConstructor.main(argMapToArray(args))
-
-      val u1ItemRec = modeldataItemRecScores.getByUid("u1")
-      val u2ItemRec = modeldataItemRecScores.getByUid("u2")
-      val u3ItemRec = modeldataItemRecScores.getByUid("u3")
-
-      // don't check id
-      u1ItemRec.map(roundUpScores(_).copy(id = None)) must beSome(roundUpScores(u1Expected)) and
-        (u2ItemRec.map(roundUpScores(_).copy(id = None)) must beSome(roundUpScores(u2Expected))) and
-        (u3ItemRec.map(roundUpScores(_).copy(id = None)) must beSome(roundUpScores(u3Expected)))
-
-    }
-
-    "correctly writes ItemRecScores with subset itemsIndex.tsv" in {
-
-      val inputDir = "/tmp/pio_test/subset/"
-
-      val inputDirFile = new File(inputDir)
-      inputDirFile.mkdirs()
-
-      val itemsIndex = List(
-        "1\ti1\tt1,t2",
-        "3\ti3\tt2,t3",
-        "4\ti4\tt3"
-      )
-
-      writeToFile(usersIndex, s"${inputDir}usersIndex.tsv")
-      writeToFile(itemsIndex, s"${inputDir}itemsIndex.tsv")
-      writeToFile(seenCSV, s"${inputDir}seen.csv")
-      writeToFile(ratingsUMM, s"${inputDir}ratings.mm_U.mm")
-      writeToFile(ratingsVMM, s"${inputDir}ratings.mm_V.mm")
-
-      val algoid = 27
-      val modelSet = false
-
-      implicit val algo = Algo(
-        id = algoid,
-        engineid = 1234,
-        name = "",
-        infoid = "abc",
-        command = "",
-        params = Map(),
-        settings = Map(),
-        modelset = modelSet,
-        createtime = DateTime.now,
-        updatetime = DateTime.now,
-        status = "deployed",
-        offlineevalid = None,
-        offlinetuneid = None,
-        loop = None,
-        paramset = None
-      )
-
-      val args = Map(
-        "inputDir" -> inputDir,
-        "appid" -> appid,
-        "algoid" -> algoid,
-        "modelSet" -> modelSet,
-        "unseenOnly" -> false,
-        "numRecommendations" -> 5
-      )
-
-      val u1Expected = ItemRecScore(
-        uid = "u1",
-        iids = Seq("i4", "i1", "i3"),
-        scores = Seq(10.88, 8.97, 8.71),
-        itypes = Seq(Seq("t3"), Seq("t1", "t2"), Seq("t2", "t3")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val u2Expected = ItemRecScore(
-        uid = "u2",
-        iids = Seq("i3", "i4", "i1"),
-        scores = Seq(7.67, 6.76, 6.69),
-        itypes = Seq(Seq("t2", "t3"), Seq("t3"), Seq("t1", "t2")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val u3Expected = ItemRecScore(
-        uid = "u3",
-        iids = Seq("i4", "i3", "i1"),
-        scores = Seq(6.89, 5.98, 5.91),
-        itypes = Seq(Seq("t3"), Seq("t2", "t3"), Seq("t1", "t2")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      GraphChiModelConstructor.main(argMapToArray(args))
-
-      val u1ItemRec = modeldataItemRecScores.getByUid("u1")
-      val u2ItemRec = modeldataItemRecScores.getByUid("u2")
-      val u3ItemRec = modeldataItemRecScores.getByUid("u3")
-
-      // don't check id
-      u1ItemRec.map(roundUpScores(_).copy(id = None)) must beSome(roundUpScores(u1Expected)) and
-        (u2ItemRec.map(roundUpScores(_).copy(id = None)) must beSome(roundUpScores(u2Expected))) and
-        (u3ItemRec.map(roundUpScores(_).copy(id = None)) must beSome(roundUpScores(u3Expected)))
-
-    }
-
-    "correctly writes ItemRecScores with unseenOnly=true" in {
-
-      val algoid = 28
-      val modelSet = true
-
-      implicit val algo = Algo(
-        id = algoid,
-        engineid = 1234,
-        name = "",
-        infoid = "abc",
-        command = "",
-        params = Map(),
-        settings = Map(),
-        modelset = modelSet,
-        createtime = DateTime.now,
-        updatetime = DateTime.now,
-        status = "deployed",
-        offlineevalid = None,
-        offlinetuneid = None,
-        loop = None,
-        paramset = None
-      )
-
-      val args = Map(
-        "inputDir" -> inputDir,
-        "appid" -> appid,
-        "algoid" -> algoid,
-        "modelSet" -> modelSet,
-        "unseenOnly" -> true,
-        "numRecommendations" -> 4
-      )
-
-      val u1Expected = ItemRecScore(
-        uid = "u1",
-        iids = Seq("i4"),
-        scores = Seq(10.88),
-        itypes = Seq(Seq("t3")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val u2Expected = ItemRecScore(
-        uid = "u2",
-        iids = Seq("i2", "i3"),
-        scores = Seq(8.76, 7.67),
-        itypes = Seq(Seq("t1"), Seq("t2", "t3")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val u3Expected = ItemRecScore(
-        uid = "u3",
-        iids = Seq("i4", "i3", "i1"),
-        scores = Seq(6.89, 5.98, 5.91),
-        itypes = Seq(Seq("t3"), Seq("t2", "t3"), Seq("t1", "t2")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      GraphChiModelConstructor.main(argMapToArray(args))
-
-      val u1ItemRec = modeldataItemRecScores.getByUid("u1")
-      val u2ItemRec = modeldataItemRecScores.getByUid("u2")
-      val u3ItemRec = modeldataItemRecScores.getByUid("u3")
-
-      // don't check id
-      u1ItemRec.map(roundUpScores(_).copy(id = None)) must beSome(roundUpScores(u1Expected)) and
-        (u2ItemRec.map(roundUpScores(_).copy(id = None)) must beSome(roundUpScores(u2Expected))) and
-        (u3ItemRec.map(roundUpScores(_).copy(id = None)) must beSome(roundUpScores(u3Expected)))
-
-    }
-
-  }
-
-  // TODO: test evalid != None
-
-  // clean up when finish test
-  step(cleanUp())
-}
diff --git a/process/engines/itemrec/algorithms/scala/mahout/build.sbt b/process/engines/itemrec/algorithms/scala/mahout/build.sbt
deleted file mode 100644
index 52dc73c..0000000
--- a/process/engines/itemrec/algorithms/scala/mahout/build.sbt
+++ /dev/null
@@ -1,27 +0,0 @@
-import xerial.sbt.Pack._
-
-name := "predictionio-process-itemrec-algorithms-scala-mahout"
-
-libraryDependencies ++= Seq(
-  "org.apache.mahout" % "mahout-core" % "0.9",
-  "ch.qos.logback" % "logback-classic" % "1.1.1",
-  "com.twitter" %% "scalding-args" % "0.8.11",
-  "org.clapper" %% "grizzled-slf4j" % "1.0.1")
-
-parallelExecution in Test := false
-
-packSettings
-
-packJarNameConvention := "full"
-
-packExpandedClasspath := true
-
-packGenerateWindowsBatFile := false
-
-packMain := Map(
-  "itemrec.mahout.mahoutjob" -> "io.prediction.algorithms.mahout.itemrec.MahoutJob",
-  "itemrec.mahout.modelcon" -> "io.prediction.algorithms.mahout.itemrec.MahoutModelConstructor")
-
-packJvmOpts := Map(
-  "itemrec.mahout.mahoutjob" -> Common.packCommonJvmOpts,
-  "itemrec.mahout.modelcon" -> Common.packCommonJvmOpts)
diff --git a/process/engines/itemrec/algorithms/scala/mahout/src/main/resources/application.conf b/process/engines/itemrec/algorithms/scala/mahout/src/main/resources/application.conf
deleted file mode 100644
index 2a462df..0000000
--- a/process/engines/itemrec/algorithms/scala/mahout/src/main/resources/application.conf
+++ /dev/null
@@ -1,26 +0,0 @@
-# Used by PredictionIO Commons
-io.prediction.base=.
-
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.host=localhost
-io.prediction.commons.appdata.db.port=27017
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.host=localhost
-io.prediction.commons.appdata.test.db.port=27017
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.host=localhost
-io.prediction.commons.appdata.training.db.port=27017
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.host=localhost
-io.prediction.commons.modeldata.db.port=27017
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.host=localhost
-io.prediction.commons.modeldata.training.db.port=27017
-
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.host=localhost
-io.prediction.commons.settings.db.port=27017
diff --git a/process/engines/itemrec/algorithms/scala/mahout/src/main/resources/logback.xml b/process/engines/itemrec/algorithms/scala/mahout/src/main/resources/logback.xml
deleted file mode 100644
index 1a2768e..0000000
--- a/process/engines/itemrec/algorithms/scala/mahout/src/main/resources/logback.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<configuration>
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <encoder>
-      <pattern>%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>
-    </encoder>
-  </appender>
-  <root level="info">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
-
diff --git a/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/AllPreferredItemsNeighborhoodCandidateItemsStrategy.java b/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/AllPreferredItemsNeighborhoodCandidateItemsStrategy.java
deleted file mode 100644
index f59721a..0000000
--- a/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/AllPreferredItemsNeighborhoodCandidateItemsStrategy.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package io.prediction.algorithms.mahout.itemrec;
-
-import org.apache.mahout.cf.taste.impl.recommender.AbstractCandidateItemsStrategy;
-import org.apache.mahout.cf.taste.common.TasteException;
-import org.apache.mahout.cf.taste.impl.common.FastIDSet;
-import org.apache.mahout.cf.taste.model.DataModel;
-import org.apache.mahout.cf.taste.model.PreferenceArray;
-import org.apache.mahout.cf.taste.impl.common.FastByIDMap;
-import org.apache.mahout.cf.taste.impl.common.FastIDSet;
-import org.apache.mahout.cf.taste.impl.model.GenericBooleanPrefDataModel;
-
-/* modified based on PreferredItemsNeighborhoodCandidateItemsStrategy */
-
-public final class AllPreferredItemsNeighborhoodCandidateItemsStrategy extends AbstractCandidateItemsStrategy {
-
-  //private final DataModel seenDataModel;
-  private final FastByIDMap<FastIDSet> seenDataMap;
-  /*
-   * @param seenDataModel set this to null if don't exclude seen items
-   */
-  public AllPreferredItemsNeighborhoodCandidateItemsStrategy(
-    DataModel seenDataModel) throws TasteException {
-      super();
-      if (seenDataModel != null)
-        this.seenDataMap = GenericBooleanPrefDataModel.toDataMap(
-          seenDataModel);
-      else
-        this.seenDataMap = null;
-  }
-
-  public AllPreferredItemsNeighborhoodCandidateItemsStrategy()
-    throws TasteException {
-    this(null);
-  }
-
-  @Override
-  public FastIDSet getCandidateItems(long userID,
-    PreferenceArray preferencesFromUser, DataModel dataModel)
-    throws TasteException {
-      long[] seenItemIDs;
-      if (this.seenDataMap != null) {
-        FastIDSet ids = seenDataMap.get(userID);
-        if (ids != null) {
-          seenItemIDs = ids.toArray();
-        } else {
-          seenItemIDs = null;
-        }
-      } else {
-        seenItemIDs = null;
-      }
-    return doGetCandidateItems(preferencesFromUser.getIDs(),
-      dataModel, seenItemIDs);
-  }
-
-  /**
-   * returns all items that have not been rated by the user and that were preferred by another user
-   * that has preferred at least one item that the current user has preferred too.
-   * excluding seen items.
-   */
-  protected FastIDSet doGetCandidateItems(long[] preferredItemIDs,
-    DataModel dataModel, long[] seenItemIDs) throws TasteException {
-    FastIDSet possibleItemsIDs = new FastIDSet();
-    for (long itemID : preferredItemIDs) {
-      PreferenceArray itemPreferences = dataModel.getPreferencesForItem(itemID);
-      int numUsersPreferringItem = itemPreferences.length();
-      for (int index = 0; index < numUsersPreferringItem; index++) {
-        possibleItemsIDs.addAll(
-          dataModel.getItemIDsFromUser(itemPreferences.getUserID(index)));
-      }
-    }
-    if (seenItemIDs != null)
-      possibleItemsIDs.removeAll(seenItemIDs);
-    return possibleItemsIDs;
-  }
-
-  @Override
-  protected FastIDSet doGetCandidateItems(long[] preferredItemIDs,
-    DataModel dataModel) throws TasteException {
-      return doGetCandidateItems(preferredItemIDs, dataModel, null);
-  }
-
-}
diff --git a/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/AllValidItemsCandidateItemsStrategy.java b/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/AllValidItemsCandidateItemsStrategy.java
deleted file mode 100644
index 5867f75..0000000
--- a/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/AllValidItemsCandidateItemsStrategy.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package io.prediction.algorithms.mahout.itemrec;
-
-import org.apache.mahout.cf.taste.impl.recommender.AbstractCandidateItemsStrategy;
-import org.apache.mahout.cf.taste.common.TasteException;
-import org.apache.mahout.cf.taste.model.DataModel;
-import org.apache.mahout.cf.taste.impl.common.FastIDSet;
-import org.apache.mahout.cf.taste.impl.common.FastByIDMap;
-import org.apache.mahout.cf.taste.model.PreferenceArray;
-import org.apache.mahout.cf.taste.impl.model.GenericBooleanPrefDataModel;
-
-public final class AllValidItemsCandidateItemsStrategy extends AbstractCandidateItemsStrategy {
-
-  private final FastByIDMap<FastIDSet> seenDataMap;
-  private final long[] validItemIDs;
-  /*
-   * @param validItemIDs valid item IDs
-   * @param seenDataModel set this to null if don't exclude seen items
-   */
-  public AllValidItemsCandidateItemsStrategy(long[] validItemIDs,
-    DataModel seenDataModel) throws TasteException {
-      super();
-      if (seenDataModel != null)
-        this.seenDataMap = GenericBooleanPrefDataModel.toDataMap(
-          seenDataModel);
-      else
-        this.seenDataMap = null;
-
-      this.validItemIDs = validItemIDs;
-  }
-
-  // include seen items as candidate items
-  public AllValidItemsCandidateItemsStrategy(long[] validItemIDs)
-    throws TasteException {
-      this(validItemIDs, null);
-  }
-
-  @Override
-  public FastIDSet getCandidateItems(long userID,
-    PreferenceArray preferencesFromUser, DataModel dataModel)
-    throws TasteException {
-      long[] seenItemIDs;
-      if (this.seenDataMap != null) {
-        FastIDSet ids = seenDataMap.get(userID);
-        if (ids != null) {
-          seenItemIDs = ids.toArray();
-        } else {
-          // user doesn't have any seen action
-          seenItemIDs = null;
-        }
-      } else {
-        seenItemIDs = null;
-      }
-
-      return doGetCandidateItemsInternal(this.validItemIDs, seenItemIDs);
-  }
-
-  protected FastIDSet doGetCandidateItemsInternal(long[] validItemIDs,
-    long[] seenItemIDs) throws TasteException {
-      FastIDSet possibleItemsIDs = new FastIDSet();
-      possibleItemsIDs.addAll(this.validItemIDs);
-
-      if (seenItemIDs != null)
-        possibleItemsIDs.removeAll(seenItemIDs);
-
-      return possibleItemsIDs;
-  }
-
-  // override for AbstractCandidateItemsStrategy
-  @Override
-  protected FastIDSet doGetCandidateItems(long[] preferredItemIDs,
-    DataModel dataModel) throws TasteException {
-      return doGetCandidateItemsInternal(this.validItemIDs, null);
-  }
-
-}
diff --git a/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/BooleanPrefUserBasedRecommender.java b/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/BooleanPrefUserBasedRecommender.java
deleted file mode 100644
index dcd7d87..0000000
--- a/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/BooleanPrefUserBasedRecommender.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package io.prediction.algorithms.mahout.itemrec;
-
-import org.apache.mahout.cf.taste.common.TasteException;
-import org.apache.mahout.cf.taste.model.DataModel;
-import org.apache.mahout.cf.taste.impl.common.FastByIDMap;
-import org.apache.mahout.cf.taste.impl.common.FastIDSet;
-import org.apache.mahout.cf.taste.impl.model.GenericBooleanPrefDataModel;
-import org.apache.mahout.cf.taste.impl.recommender.GenericUserBasedRecommender;
-import org.apache.mahout.cf.taste.neighborhood.UserNeighborhood;
-import org.apache.mahout.cf.taste.similarity.UserSimilarity;
-
-/* based on Mahout GenericBooleanPrefUserBasedRecommender */
-public class BooleanPrefUserBasedRecommender extends GenericUserBasedRecommender {
-
-  private final FastByIDMap<FastIDSet> seenDataMap;
-  private final FastIDSet validItemIDSet;
-
-  public BooleanPrefUserBasedRecommender(DataModel dataModel,
-    UserNeighborhood neighborhood,
-    UserSimilarity similarity,
-    long[] validItemIDs,
-    DataModel seenDataModel)
-    throws TasteException {
-      super(dataModel, neighborhood, similarity);
-      if (seenDataModel != null)
-        this.seenDataMap = GenericBooleanPrefDataModel.toDataMap(
-          seenDataModel);
-      else
-        this.seenDataMap = null;
-
-      this.validItemIDSet = new FastIDSet(validItemIDs);
-  }
-
-  /**
-   * This computation is in a technical sense, wrong, since in the domain of "boolean preference users" where
-   * all preference values are 1, this method should only ever return 1.0 or NaN. This isn't terribly useful
-   * however since it means results can't be ranked by preference value (all are 1). So instead this returns a
-   * sum of similarities to any other user in the neighborhood who has also rated the item.
-   */
-  @Override
-  protected float doEstimatePreference(long theUserID, long[] theNeighborhood, long itemID) throws TasteException {
-    if (theNeighborhood.length == 0) {
-      return Float.NaN;
-    }
-    DataModel dataModel = getDataModel();
-    UserSimilarity similarity = getSimilarity();
-    float totalSimilarity = 0.0f;
-    boolean foundAPref = false;
-    for (long userID : theNeighborhood) {
-      // See GenericItemBasedRecommender.doEstimatePreference() too
-      if (userID != theUserID && dataModel.getPreferenceValue(userID, itemID) != null) {
-        foundAPref = true;
-        totalSimilarity += (float) similarity.userSimilarity(theUserID, userID);
-      }
-    }
-    return foundAPref ? totalSimilarity : Float.NaN;
-  }
-
-  @Override
-  protected FastIDSet getAllOtherItems(long[] theNeighborhood, long theUserID) throws TasteException {
-    DataModel dataModel = getDataModel();
-    FastIDSet possibleItemIDs = new FastIDSet();
-    for (long userID : theNeighborhood) {
-      possibleItemIDs.addAll(dataModel.getItemIDsFromUser(userID));
-    }
-
-    possibleItemIDs.retainAll(this.validItemIDSet);
-
-    // exclude seen items if seenDataMap != null
-    if (this.seenDataMap != null) {
-      FastIDSet ids = seenDataMap.get(theUserID);
-      if (ids != null) {
-        possibleItemIDs.removeAll(ids);
-      }
-    }
-
-    return possibleItemIDs;
-  }
-
-  @Override
-  public String toString() {
-    return "BooleanPrefUserBasedRecommender";
-  }
-
-}
diff --git a/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/MahoutCommons.scala b/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/MahoutCommons.scala
deleted file mode 100644
index 3f977c5..0000000
--- a/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/MahoutCommons.scala
+++ /dev/null
@@ -1,29 +0,0 @@
-package io.prediction.algorithms.mahout.itemrec
-
-import scala.io.Source
-
-object MahoutCommons {
-  case class ItemData(
-    val iid: String,
-    val itypes: Seq[String],
-    val starttime: Long)
-
-  // item index file (iindex iid itypes starttime)
-  // iindex -> ItemData
-  def itemsMap(input: String): Map[Long, ItemData] = Source.fromFile(input)
-    .getLines().map[(Long, ItemData)] { line =>
-      val (iindex, item) = try {
-        val fields = line.split("\t")
-        val itemData = ItemData(
-          iid = fields(1),
-          itypes = fields(2).split(",").toSeq,
-          starttime = fields(3).toLong)
-        (fields(0).toLong, itemData)
-      } catch {
-        case e: Exception =>
-          throw new RuntimeException(
-            s"Cannot get item info in line: ${line}. ${e}")
-      }
-      (iindex, item)
-    }.toMap
-}
diff --git a/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/MahoutJob.scala b/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/MahoutJob.scala
deleted file mode 100644
index bb5de5c..0000000
--- a/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/MahoutJob.scala
+++ /dev/null
@@ -1,210 +0,0 @@
-package io.prediction.algorithms.mahout.itemrec
-
-import java.io.File
-import java.io.FileWriter
-import java.io.BufferedWriter
-
-import scala.collection.JavaConversions._
-import scala.sys.process._
-
-import com.github.nscala_time.time.Imports._
-import grizzled.slf4j.Logger
-import org.apache.mahout.cf.taste.impl.model.file.FileDataModel
-import org.apache.mahout.cf.taste.model.DataModel
-import org.apache.mahout.cf.taste.recommender.{ IDRescorer, Recommender }
-
-/** main function to run non-distributed Mahout Job */
-object MahoutJob {
-
-  val logger = Logger(MahoutJob.getClass)
-
-  def main(args: Array[String]) {
-    if (args.size < 1) {
-      logger.error("Please specify Mahout job class name")
-      logger.error("Example. <job class name> --param1 1 --param2 2")
-      System.exit(1)
-    }
-
-    val jobName = args(0)
-
-    logger.info("Running Job %s...".format(jobName))
-
-    logger.info(args.mkString(" "))
-    val (argMap, lastkey) = args.drop(1).foldLeft((Map[String, String](), "")) {
-      (res, data) =>
-        val (argMap, lastkey) = res
-        val key: Option[String] = if (data.startsWith("--"))
-          Some(data.stripPrefix("--")) else None
-
-        key map { k =>
-          (argMap ++ Map(k -> ""), k)
-        } getOrElse {
-          val orgData = argMap(lastkey)
-          val newData = orgData match {
-            case "" => data
-            case _ => orgData + " " + data
-          }
-          (argMap ++ Map(lastkey -> newData), lastkey)
-        }
-    }
-    //println(argMap)
-
-    val job = Class.forName(jobName).
-      getConstructor().
-      newInstance().
-      asInstanceOf[MahoutJob]
-
-    val runArgs = job.prepare(argMap)
-
-    val finishArgs = job.run(runArgs)
-
-    val cleanupArgs = job.finish(finishArgs)
-
-    job.cleanup(cleanupArgs)
-
-  }
-
-}
-
-/** Wrapper job class for Mahout algo */
-abstract class MahoutJob {
-  /** Get required arg */
-  def getArg(args: Map[String, String], key: String): String = {
-    if (!args.contains(key)) sys.error("Please specify value for parameter --" + key)
-
-    args(key)
-  }
-
-  /** Get optional arg */
-  def getArgOpt(args: Map[String, String], key: String,
-    default: String): String = {
-    if (args.contains(key)) args(key) else default
-  }
-
-  def getArgOpt(args: Map[String, String], key: String): Option[String] = {
-    if (args.contains(key)) Some(args(key)) else None
-  }
-
-  /** Prepare stage for algo */
-  def prepare(args: Map[String, String]): Map[String, String] = {
-    // simply pass the args to next stage
-    args
-  }
-
-  /** create and return Mahout's Recommender object. */
-  def buildRecommender(dataModel: DataModel, seenDataModel: DataModel,
-    validItemIDs: Set[Long], args: Map[String, String]): Recommender
-
-  /**
-   * Run algo job.
-   * In default implementation, the prepare() function does nothing
-   * The run() function read and process this local file (defined by --input
-   * arg) file and generate the prediction output file (defined by --output arg)
-   * for each user. Then finish() does nothing
-   */
-  def run(args: Map[String, String]): Map[String, String] = {
-
-    val input = args("input")
-    val output = args("output")
-
-    val numRecommendations: Int = getArgOpt(args, "numRecommendations").
-      map(_.toInt).getOrElse(Int.MaxValue)
-    val recommendationTime: Long = getArg(args, "recommendationTime").toLong
-    val freshnessTimeUnit: Long = getArgOpt(args, "freshnessTimeUnit")
-      .map(_.toLong).getOrElse(1.hours.millis)
-
-    val itemsFile = getArg(args, "itemsFile")
-    /** use input ratng file as seen data if it's not defined */
-    val seenFileOpt = getArgOpt(args, "seenFile")
-    val freshnessOpt = getArgOpt(args, "freshness")
-
-    val dataModel: DataModel = new FileDataModel(new File(input))
-
-    val itemsMap: Map[Long, MahoutCommons.ItemData] =
-      MahoutCommons.itemsMap(itemsFile)
-
-    val validItemIDs: Set[Long] = itemsMap.keySet
-
-    val seenDataModel: DataModel = seenFileOpt.map { seenFileName =>
-      val seenFile = new File(seenFileName)
-      if (seenFile.exists())
-        if (seenFile.length() != 0) // if not empty
-          new FileDataModel(seenFile)
-        else
-          null // seen file exists but it's empty
-      else
-        dataModel // fall back to rating dataModel if no seenFile defined
-    }.getOrElse(dataModel)
-
-    val recommender: Recommender = buildRecommender(dataModel, seenDataModel,
-      validItemIDs, args)
-
-    val outputFile = new File(output)
-    // create dir if it doesn't exist yet.
-    outputFile.getParentFile().mkdirs()
-
-    // handle freshness rescoring
-    val freshnessRescorer = freshnessOpt map { f =>
-      new FreshnessRescorer(f.toInt, recommendationTime, freshnessTimeUnit,
-        itemsMap)
-    }
-
-    // generate prediction output file
-    val userRec = dataModel.getUserIDs.toSeq.par
-      .map { uid =>
-        val rec = freshnessRescorer map { r =>
-          recommender.recommend(uid, numRecommendations, r)
-        } getOrElse {
-          recommender.recommend(uid, numRecommendations)
-        }
-        if (rec.size != 0) {
-          val prediction = uid + "\t" + "[" + (rec map { x =>
-            x.getItemID + ":" + x.getValue
-          }).mkString(",") + "]"
-          Some(prediction)
-        } else {
-          None
-        }
-      }
-
-    val outputWriter = new BufferedWriter(new FileWriter(outputFile))
-    userRec.seq.foreach { line =>
-      line.map(v => outputWriter.write(v + "\n"))
-    }
-    outputWriter.close()
-
-    args
-  }
-
-  /** finish stage for algo */
-  def finish(args: Map[String, String]): Map[String, String] = {
-    // simply pass the args to next stage
-    args
-  }
-
-  /** Cleanup stage for algo */
-  def cleanup(args: Map[String, String]) = {
-    // simpley pass the args to next stage
-    args
-  }
-
-}
-
-class FreshnessRescorer(freshness: Int, recommendationTime: Long,
-    freshnessTimeUnit: Long,
-    itemsMap: Map[Long, MahoutCommons.ItemData]) extends IDRescorer {
-  def isFiltered(id: Long): Boolean = false
-
-  def rescore(id: Long, originalScore: Double): Double = {
-    if (freshness > 0) {
-      itemsMap.get(id) map { data =>
-        val timeDiff = (recommendationTime - data.starttime) / 1000 /
-          freshnessTimeUnit
-        if (timeDiff > 0)
-          originalScore * scala.math.exp(-timeDiff / (11 - freshness))
-        else
-          originalScore
-      } getOrElse originalScore
-    } else originalScore
-  }
-}
diff --git a/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/MahoutModelConstructor.scala b/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/MahoutModelConstructor.scala
deleted file mode 100644
index 63854d7..0000000
--- a/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/MahoutModelConstructor.scala
+++ /dev/null
@@ -1,220 +0,0 @@
-package io.prediction.algorithms.mahout.itemrec
-
-import grizzled.slf4j.Logger
-import com.twitter.scalding.Args
-import scala.io.Source
-
-import io.prediction.commons.Config
-import io.prediction.commons.modeldata.{ ItemRecScore }
-
-/**
- * Description:
- * Model constuctor for non-distributed (single machine) Mahout ItemRec algo
- *
- * Input files:
- * - predicted.tsv (uindex prediction-string) prediction output generated by MahoutJob
- * - ratings.csv (uindex iindex rating)
- * - itemsIndex.tsv (iindex iid itypes starttime endtime)
- * - usersIndex.tsv (uindex uid)
- *
- * Required args:
- * --appid: <int>
- * --algoid: <int>
- * --modelSet: <boolean> (true/false). flag to indicate which set
- *
- * --unseenOnly: <boolean> (true/false). only recommend unseen items if this is true.
- * --numRecommendations: <int>. number of recommendations to be generated
- *
- * Optionsl args:
- * --evalid: <int>. Offline Evaluation if evalid is specified
- * --debug: <String>. "test" - for testing purpose
- *
- * --booleanData: <boolean>. Mahout item rec algo flag for implicit action data
- * --implicitFeedback: <boolean>. Mahout item rec algo flag for implicit action data
- *
- */
-object MahoutModelConstructor {
-  /* global */
-  val logger = Logger(MahoutModelConstructor.getClass)
-  val commonsConfig = new Config
-
-  // argument of this job
-  case class JobArg(
-    val inputDir: String,
-    val appid: Int,
-    val algoid: Int,
-    val evalid: Option[Int],
-    val modelSet: Boolean,
-    val unseenOnly: Boolean,
-    val numRecommendations: Option[Int],
-    val booleanData: Boolean,
-    val implicitFeedback: Boolean)
-
-  def main(cmdArgs: Array[String]) {
-    logger.info("Running model constructor for Mahout ...")
-    logger.info(cmdArgs.mkString(","))
-
-    /* get arg */
-    val args = Args(cmdArgs)
-
-    val arg = JobArg(
-      inputDir = args("inputDir"),
-      appid = args("appid").toInt,
-      algoid = args("algoid").toInt,
-      evalid = args.optional("evalid") map (x => x.toInt),
-      modelSet = args("modelSet").toBoolean,
-      unseenOnly = args.optional("unseenOnly").map(_.toBoolean).getOrElse(false),
-      numRecommendations = args.optional("numRecommendations").map(x => x.toInt),
-      booleanData = args.optional("booleanData").map(x => x.toBoolean).getOrElse(false),
-      implicitFeedback = args.optional("implicitFeedback").map(x => x.toBoolean).getOrElse(false)
-    )
-
-    /* run job */
-    modelCon(arg)
-    cleanUp(arg)
-  }
-
-  def modelCon(arg: JobArg) = {
-    // implicit preference flag.
-    val IMPLICIT_PREFERENCE = arg.booleanData || arg.implicitFeedback
-
-    // NOTE: if OFFLINE_EVAL, write to training modeldata and use evalid as appid
-    val OFFLINE_EVAL = (arg.evalid != None)
-
-    val modeldataDb = if (!OFFLINE_EVAL)
-      commonsConfig.getModeldataItemRecScores
-    else
-      commonsConfig.getModeldataTrainingItemRecScores
-
-    val appid = if (OFFLINE_EVAL) arg.evalid.get else arg.appid
-
-    // user index file
-    // uindex -> uid
-    val usersMap: Map[Int, String] = Source.fromFile(s"${arg.inputDir}usersIndex.tsv").getLines()
-      .map[(Int, String)] { line =>
-        val (uindex, uid) = try {
-          val data = line.split("\t")
-          (data(0).toInt, data(1))
-        } catch {
-          case e: Exception => {
-            throw new RuntimeException(s"Cannot get user index and uid in line: ${line}. ${e}")
-          }
-        }
-        (uindex, uid)
-      }.toMap
-
-    val itemsMap = MahoutCommons.itemsMap(s"${arg.inputDir}itemsIndex.tsv")
-
-    // ratings file (for unseen filtering)
-    val seenMap: Map[(Int, Int), Double] = if (arg.unseenOnly) {
-      Source.fromFile(s"${arg.inputDir}ratings.csv")
-        .getLines()
-        .map { line =>
-          val (u, i, r) = try {
-            val fields = line.split(",")
-            // u, i, rating
-            (fields(0).toInt, fields(1).toInt, fields(2).toDouble)
-          } catch {
-            case e: Exception => throw new RuntimeException(s"Cannot get user and item index from this line: ${line}. ${e}")
-          }
-          ((u, i) -> r)
-        }.toMap
-    } else {
-      Map()
-    }
-
-    /* TODO: handling merging seen rating
-    // uindx -> Seq[(iindex, rating)]
-    val ratingsMap: Map[Int, Seq[(Int, Double)]] = seenMap.groupBy { case ((u, i), s) => u }
-      .mapValues { v =>
-        // v is Map[()]
-        v.toSeq.map { case ((u, i), s) => (i, s) }
-      }
-    */
-
-    // prediction
-    Source.fromFile(s"${arg.inputDir}predicted.tsv")
-      .getLines()
-      .foreach { line =>
-        val fields = line.split("\t")
-
-        val (uindex, predictedData) = try {
-          (fields(0).toInt, fields(1))
-        } catch {
-          case e: Exception => throw new RuntimeException(s"Cannot extract uindex and prediction output from this line: ${line}. ${e}")
-        }
-
-        val predicted: Seq[(Int, Double)] = parsePredictedData(predictedData)
-          .map { case (iindex, rating) => (iindex.toInt, rating) }
-
-        // TODO: handling merging seen rating
-        val combined = predicted
-        // if unseenOnly (or implicit preference), no merge with known rating
-        /*if (arg.unseenOnly || IMPLICIT_PREFERENCE) predicted
-        else (predicted ++ ratingsMap.getOrElse(uindex, Seq()))*/
-
-        val topScoresAll = combined
-          .filter {
-            case (iindex, rating) =>
-              unseenItemFilter(arg.unseenOnly, uindex, iindex, seenMap) &&
-                validItemFilter(true, iindex, itemsMap)
-          }.sortBy(_._2)(Ordering[Double].reverse)
-        val topScores = arg.numRecommendations.map(x => topScoresAll.take(x)).getOrElse(topScoresAll)
-
-        logger.debug(s"$topScores")
-
-        val uid = try {
-          usersMap(uindex)
-        } catch {
-          case e: Exception => throw new RuntimeException(s"Cannot get uid for this uindex: ${line}. ${e}")
-        }
-        modeldataDb.insert(ItemRecScore(
-          uid = usersMap(uindex),
-          iids = topScores.map(x => itemsMap(x._1).iid),
-          scores = topScores.map(_._2),
-          itypes = topScores.map(x => itemsMap(x._1).itypes),
-          appid = appid,
-          algoid = arg.algoid,
-          modelset = arg.modelSet))
-
-      }
-  }
-
-  def cleanUp(arg: JobArg) = {
-
-  }
-
-  /* TODO refactor this
-  Mahout ItemRec output format
-  [24:3.2] => (24, 3.2)
-  [8:2.5,0:2.5]  => (8, 2.5), (0, 2.5)
-  [0:2.0]
-  [16:3.0]
-  */
-  def parsePredictedData(data: String): List[(String, Double)] = {
-    val dataLen = data.length
-    data.take(dataLen - 1).tail.split(",").toList.map { ratingData =>
-      val ratingDataArray = ratingData.split(":")
-      val item = ratingDataArray(0)
-      val rating: Double = try {
-        ratingDataArray(1).toDouble
-      } catch {
-        case e: Exception =>
-          {
-            assert(false, s"Cannot convert rating value of item ${item} to double: " + ratingDataArray + ". Exception: " + e)
-          }
-          0.0
-      }
-      (item, rating)
-    }
-  }
-
-  def unseenItemFilter(enable: Boolean, uindex: Int, iindex: Int, seenMap: Map[(Int, Int), Any]): Boolean = {
-    if (enable) (!seenMap.contains((uindex, iindex))) else true
-  }
-
-  def validItemFilter(enable: Boolean, iindex: Int, validMap: Map[Long, Any]): Boolean = {
-    if (enable) validMap.contains(iindex) else true
-  }
-
-}
diff --git a/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/UserBasedRecommender.java b/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/UserBasedRecommender.java
deleted file mode 100644
index 6ed9be4..0000000
--- a/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/UserBasedRecommender.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package io.prediction.algorithms.mahout.itemrec;
-
-import org.apache.mahout.cf.taste.common.TasteException;
-import org.apache.mahout.cf.taste.model.DataModel;
-import org.apache.mahout.cf.taste.impl.common.FastByIDMap;
-import org.apache.mahout.cf.taste.impl.common.FastIDSet;
-import org.apache.mahout.cf.taste.impl.model.GenericBooleanPrefDataModel;
-import org.apache.mahout.cf.taste.impl.recommender.GenericUserBasedRecommender;
-import org.apache.mahout.cf.taste.neighborhood.UserNeighborhood;
-import org.apache.mahout.cf.taste.similarity.UserSimilarity;
-
-/* based on Mahout GenericUserBasedRecommender */
-public class UserBasedRecommender extends GenericUserBasedRecommender {
-
-  private final FastByIDMap<FastIDSet> seenDataMap;
-  private final FastIDSet validItemIDSet;
-
-  public UserBasedRecommender(DataModel dataModel,
-    UserNeighborhood neighborhood,
-    UserSimilarity similarity,
-    long[] validItemIDs,
-    DataModel seenDataModel)
-    throws TasteException {
-      super(dataModel, neighborhood, similarity);
-      if (seenDataModel != null)
-        this.seenDataMap = GenericBooleanPrefDataModel.toDataMap(
-          seenDataModel);
-      else
-        this.seenDataMap = null;
-
-      this.validItemIDSet = new FastIDSet(validItemIDs);
-  }
-
-
-  @Override
-  protected FastIDSet getAllOtherItems(long[] theNeighborhood, long theUserID) throws TasteException {
-    DataModel dataModel = getDataModel();
-    FastIDSet possibleItemIDs = new FastIDSet();
-    for (long userID : theNeighborhood) {
-      possibleItemIDs.addAll(dataModel.getItemIDsFromUser(userID));
-    }
-
-    possibleItemIDs.retainAll(this.validItemIDSet);
-
-    // exclude seen items if seenDataMap != null
-    if (this.seenDataMap != null) {
-      FastIDSet ids = seenDataMap.get(theUserID);
-      if (ids != null) {
-        possibleItemIDs.removeAll(ids);
-      }
-    }
-
-    return possibleItemIDs;
-  }
-
-  @Override
-  public String toString() {
-    return "UserBasedRecommender";
-  }
-
-}
diff --git a/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/alswr/ALSWRJob.scala b/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/alswr/ALSWRJob.scala
deleted file mode 100644
index d03d255..0000000
--- a/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/alswr/ALSWRJob.scala
+++ /dev/null
@@ -1,38 +0,0 @@
-package io.prediction.algorithms.mahout.itemrec.alswr
-
-import scala.collection.JavaConversions._
-
-import io.prediction.algorithms.mahout.itemrec.MahoutJob
-import io.prediction.algorithms.mahout.itemrec.AllValidItemsCandidateItemsStrategy
-
-import org.apache.mahout.cf.taste.model.DataModel
-import org.apache.mahout.cf.taste.recommender.Recommender
-import org.apache.mahout.cf.taste.impl.recommender.svd.SVDRecommender
-import org.apache.mahout.cf.taste.impl.recommender.svd.ALSWRFactorizer
-import org.apache.mahout.cf.taste.impl.recommender.svd.Factorizer
-
-class ALSWRJob extends MahoutJob {
-
-  override def buildRecommender(dataModel: DataModel, seenDataModel: DataModel,
-    validItemIDs: Set[Long], args: Map[String, String]): Recommender = {
-
-    val numFeatures: Int = getArg(args, "numFeatures").toInt
-    val lambda: Double = getArg(args, "lambda").toDouble
-    val numIterations: Int = getArg(args, "numIterations").toInt
-    val unseenOnly: Boolean = getArgOpt(args, "unseenOnly", "false").toBoolean
-
-    val factorizer: Factorizer = new ALSWRFactorizer(dataModel, numFeatures, lambda, numIterations)
-
-    val candidateItemsStrategy = if (unseenOnly)
-      new AllValidItemsCandidateItemsStrategy(validItemIDs.toArray,
-        seenDataModel)
-    else
-      new AllValidItemsCandidateItemsStrategy(validItemIDs.toArray)
-
-    // default stratagy is PreferredItemsNeighborhoodCandidateItemsStrategy();
-    val recommender: Recommender = new SVDRecommender(dataModel, factorizer, candidateItemsStrategy)
-
-    recommender
-  }
-
-}
diff --git a/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/knnitembased/KNNItemBasedJob.scala b/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/knnitembased/KNNItemBasedJob.scala
deleted file mode 100644
index 2bfa74a..0000000
--- a/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/knnitembased/KNNItemBasedJob.scala
+++ /dev/null
@@ -1,110 +0,0 @@
-package io.prediction.algorithms.mahout.itemrec.knnitembased
-
-import io.prediction.algorithms.mahout.itemrec.MahoutJob
-import io.prediction.algorithms.mahout.itemrec.AllValidItemsCandidateItemsStrategy
-
-import org.apache.mahout.cf.taste.model.DataModel
-import org.apache.mahout.cf.taste.common.Weighting
-import org.apache.mahout.cf.taste.recommender.Recommender
-import org.apache.mahout.cf.taste.similarity.ItemSimilarity
-import org.apache.mahout.cf.taste.impl.recommender.{ GenericItemBasedRecommender, GenericBooleanPrefItemBasedRecommender }
-import org.apache.mahout.cf.taste.impl.similarity.{
-  CityBlockSimilarity,
-  EuclideanDistanceSimilarity,
-  LogLikelihoodSimilarity,
-  PearsonCorrelationSimilarity,
-  TanimotoCoefficientSimilarity,
-  UncenteredCosineSimilarity
-}
-import org.apache.mahout.cf.taste.impl.similarity.file.FileItemSimilarity
-import org.apache.mahout.cf.taste.similarity.precompute.BatchItemSimilarities
-import org.apache.mahout.cf.taste.impl.similarity.precompute.MultithreadedBatchItemSimilarities
-import org.apache.mahout.cf.taste.impl.similarity.precompute.FileSimilarItemsWriter
-import org.apache.mahout.cf.taste.similarity.precompute.SimilarItems
-import org.apache.mahout.cf.taste.impl.recommender.PreferredItemsNeighborhoodCandidateItemsStrategy
-
-import scala.collection.JavaConversions._
-
-import java.io.File
-
-class KNNItemBasedJob extends MahoutJob {
-
-  val defaultItemSimilarity = "LogLikelihoodSimilarity"
-
-  override def buildRecommender(dataModel: DataModel, seenDataModel: DataModel,
-    validItemIDs: Set[Long], args: Map[String, String]): Recommender = {
-
-    val booleanData: Boolean = getArgOpt(args, "booleanData", "false").toBoolean
-    val itemSimilarity: String = getArgOpt(args, "itemSimilarity", defaultItemSimilarity)
-    val weighted: Boolean = getArgOpt(args, "weighted", "false").toBoolean
-    val threshold: Double = getArgOpt(args, "threshold").map(_.toDouble).getOrElse(Double.MinPositiveValue)
-    val nearestN: Int = getArgOpt(args, "nearestN", "10").toInt
-    val outputSim: String = getArg(args, "outputSim")
-    val unseenOnly: Boolean = getArgOpt(args, "unseenOnly", "false").toBoolean
-
-    val preComputeItemSim: Boolean = getArgOpt(args, "preComputeItemSim", "false").toBoolean
-    val similarItemsPerItem: Int = getArgOpt(args, "similarItemsPerItem", "100").toInt // number of similar items per item in pre-computation
-    // MultithreadedBatchItemSimilarities parameter
-    /*
-    val batchSize: Int = getArgOpt(args, "batchSize", "500").toInt
-    val degreeOfParallelism: Int = getArgOpt(args, "parallelism", "8").toInt
-    val maxDurationInHours: Int = getArgOpt(args, "maxHours", "6").toInt
-    */
-
-    val weightedParam: Weighting = if (weighted) Weighting.WEIGHTED else Weighting.UNWEIGHTED
-
-    val similarity: ItemSimilarity = itemSimilarity match {
-      case "CityBlockSimilarity" => new CityBlockSimilarity(dataModel)
-      case "EuclideanDistanceSimilarity" => new EuclideanDistanceSimilarity(dataModel, weightedParam)
-      case "LogLikelihoodSimilarity" => new LogLikelihoodSimilarity(dataModel)
-      case "PearsonCorrelationSimilarity" => new PearsonCorrelationSimilarity(dataModel, weightedParam)
-      case "TanimotoCoefficientSimilarity" => new TanimotoCoefficientSimilarity(dataModel)
-      case "UncenteredCosineSimilarity" => new UncenteredCosineSimilarity(dataModel, weightedParam)
-      case _ => throw new RuntimeException("Invalid ItemSimilarity: " + itemSimilarity)
-    }
-
-    if (preComputeItemSim) {
-      val outputSimFile = new File(outputSim)
-      outputSimFile.getParentFile().mkdirs()
-      // delete old file
-      if (outputSimFile.exists()) outputSimFile.delete()
-
-      /*
-      val genericRecommeder = new GenericItemBasedRecommender(dataModel, similarity)
-      val batch: BatchItemSimilarities = new MultithreadedBatchItemSimilarities(genericRecommeder, similarItemsPerItem, batchSize)
-      batch.computeItemSimilarities(degreeOfParallelism, maxDurationInHours, new FileSimilarItemsWriter(outputSimFile))
-      */
-
-      val genericRecommeder = new GenericItemBasedRecommender(dataModel, similarity)
-      val itemIds = dataModel.getItemIDs.toSeq
-
-      val simPar = itemIds.par.map { itemId =>
-        new SimilarItems(itemId, genericRecommeder.mostSimilarItems(itemId, similarItemsPerItem))
-      }
-
-      val writer = new FileSimilarItemsWriter(outputSimFile)
-      writer.open()
-      simPar.seq.foreach { s: SimilarItems =>
-        writer.add(s)
-      }
-      writer.close()
-    }
-
-    val recSimilarity = if (preComputeItemSim) {
-      new FileItemSimilarity(new File(outputSim))
-    } else similarity
-
-    val candidateItemsStrategy = if (unseenOnly)
-      new AllValidItemsCandidateItemsStrategy(validItemIDs.toArray,
-        seenDataModel)
-    else
-      new AllValidItemsCandidateItemsStrategy(validItemIDs.toArray)
-
-    val recommender: Recommender = new KNNItemBasedRecommender(dataModel, recSimilarity,
-      candidateItemsStrategy,
-      booleanData, nearestN, threshold)
-
-    recommender
-  }
-
-}
diff --git a/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/knnitembased/KNNItemBasedRecommender.scala b/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/knnitembased/KNNItemBasedRecommender.scala
deleted file mode 100644
index 25de98d..0000000
--- a/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/knnitembased/KNNItemBasedRecommender.scala
+++ /dev/null
@@ -1,109 +0,0 @@
-package io.prediction.algorithms.mahout.itemrec.knnitembased
-
-import org.apache.mahout.cf.taste.common.TasteException
-import org.apache.mahout.cf.taste.impl.recommender.GenericItemBasedRecommender
-import org.apache.mahout.cf.taste.impl.recommender.AbstractRecommender
-import org.apache.mahout.cf.taste.model.DataModel
-import org.apache.mahout.cf.taste.model.PreferenceArray;
-import org.apache.mahout.cf.taste.similarity.ItemSimilarity
-import org.apache.mahout.cf.taste.recommender.CandidateItemsStrategy
-import org.apache.mahout.cf.taste.recommender.MostSimilarItemsCandidateItemsStrategy
-import org.apache.mahout.cf.taste.impl.recommender.EstimatedPreferenceCapper
-
-import scala.collection.mutable.PriorityQueue
-import scala.collection.JavaConversions._
-
-import io.prediction.algorithms.mahout.itemrec.AllPreferredItemsNeighborhoodCandidateItemsStrategy
-
-/* Extension to Mahout's GenericItemBasedRecommender
- * with the additional settings: booleanData, neighbourSize, threshold.
- */
-class KNNItemBasedRecommender(dataModel: DataModel,
-  similarity: ItemSimilarity,
-  candidateItemsStrategy: CandidateItemsStrategy,
-  mostSimilarItemsCandidateItemsStrategy: MostSimilarItemsCandidateItemsStrategy,
-  booleanData: Boolean,
-  neighbourSize: Int,
-  threshold: Double) extends GenericItemBasedRecommender(dataModel, similarity, candidateItemsStrategy,
-  mostSimilarItemsCandidateItemsStrategy) {
-
-  val capper: Option[EstimatedPreferenceCapper] = if (getDataModel().getMinPreference().isNaN ||
-    getDataModel().getMaxPreference().isNaN)
-    None
-  else
-    Some(new EstimatedPreferenceCapper(getDataModel()))
-
-  def this(dataModel: DataModel, similarity: ItemSimilarity,
-    candidateItemsStrategy: CandidateItemsStrategy,
-    booleanData: Boolean, neighbourSize: Int, threshold: Double) =
-    this(dataModel, similarity, candidateItemsStrategy,
-      GenericItemBasedRecommender.getDefaultMostSimilarItemsCandidateItemsStrategy(),
-      booleanData, neighbourSize, threshold)
-
-  def this(dataModel: DataModel, similarity: ItemSimilarity, booleanData: Boolean, neighbourSize: Int, threshold: Double) =
-    this(dataModel, similarity, AbstractRecommender.getDefaultCandidateItemsStrategy(),
-      GenericItemBasedRecommender.getDefaultMostSimilarItemsCandidateItemsStrategy(), booleanData, neighbourSize, threshold)
-
-  @throws(classOf[TasteException])
-  override def doEstimatePreference(userID: Long, preferencesFromUser: PreferenceArray, itemID: Long): Float = {
-    val ratedIds = preferencesFromUser.getIDs()
-      .zipWithIndex // need index for accessing preferencesFromUser later
-      .map { case (id, index) => (id, similarity.itemSimilarity(itemID, id), index) } // (id, simiarity, index)
-      .filter { case (id, sim, index) => (!sim.isNaN()) && (sim >= threshold) }
-
-    val neighbourRatedIds = getTopN(ratedIds, neighbourSize)(RatedIdOdering.reverse)
-
-    val estimatedPreference: Float = if (booleanData) {
-      val totalSimilarity = neighbourRatedIds.foldLeft[Double](0) { (acc, x) =>
-        val (id, sim, index) = x
-        acc + sim
-      }
-      totalSimilarity.toFloat
-    } else {
-      val (totalPreference, totalSimilarity) = neighbourRatedIds.foldLeft[(Double, Double)]((0, 0)) { (acc, x) =>
-        val (accPreference, accSimilarity) = acc
-        val (id, sim, index) = x
-
-        val totalPreference = accPreference + (sim * preferencesFromUser.getValue(index))
-        val totalSimilarity = accSimilarity + sim
-        (totalPreference, totalSimilarity)
-      }
-      // if there is only 1 similar item, the estimate preference will be same as the preferewnce of that item
-      // regardless of similarity. so don't count it and return NaN instead.
-      if (neighbourRatedIds.size <= 1) {
-        Float.NaN
-      } else {
-        val estimate = (totalPreference / totalSimilarity).toFloat
-        val cappedEstimate = capper.map(c => c.capEstimate(estimate)).getOrElse(estimate)
-        cappedEstimate
-      }
-    }
-    estimatedPreference
-  }
-
-  object RatedIdOdering extends Ordering[(Long, Double, Int)] {
-    override def compare(a: (Long, Double, Int), b: (Long, Double, Int)) = a._2 compare b._2
-  }
-
-  def getTopN[T](s: Seq[T], n: Int)(implicit ord: Ordering[T]): Seq[T] = {
-    val q = PriorityQueue()
-
-    for (x <- s) {
-      if (q.size < n)
-        q.enqueue(x)
-      else {
-        // q is full
-        if (ord.compare(x, q.head) < 0) {
-          q.dequeue()
-          q.enqueue(x)
-        }
-      }
-    }
-
-    q.dequeueAll.toSeq.reverse
-  }
-
-  override def toString() = {
-    "KNNItemBasedRecommender"
-  }
-}
diff --git a/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/knnuserbased/KNNUserBasedJob.scala b/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/knnuserbased/KNNUserBasedJob.scala
deleted file mode 100644
index d6fe247..0000000
--- a/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/knnuserbased/KNNUserBasedJob.scala
+++ /dev/null
@@ -1,76 +0,0 @@
-package io.prediction.algorithms.mahout.itemrec.knnuserbased
-
-import scala.collection.JavaConversions._
-
-import io.prediction.algorithms.mahout.itemrec.MahoutJob
-import io.prediction.algorithms.mahout.itemrec.{ UserBasedRecommender, BooleanPrefUserBasedRecommender }
-
-import org.apache.mahout.cf.taste.model.DataModel
-import org.apache.mahout.cf.taste.recommender.Recommender
-import org.apache.mahout.cf.taste.recommender.RecommendedItem
-import org.apache.mahout.cf.taste.neighborhood.UserNeighborhood
-import org.apache.mahout.cf.taste.similarity.UserSimilarity
-import org.apache.mahout.cf.taste.common.Weighting
-import org.apache.mahout.cf.taste.impl.neighborhood.NearestNUserNeighborhood
-import org.apache.mahout.cf.taste.impl.similarity.{
-  CityBlockSimilarity,
-  EuclideanDistanceSimilarity,
-  LogLikelihoodSimilarity,
-  PearsonCorrelationSimilarity,
-  SpearmanCorrelationSimilarity,
-  TanimotoCoefficientSimilarity,
-  UncenteredCosineSimilarity
-}
-
-class KNNUserBasedJob extends MahoutJob {
-
-  val userSimilarityValues = Seq(
-    "CityBlockSimilarity",
-    "EuclideanDistanceSimilarity",
-    "LogLikelihoodSimilarity",
-    "PearsonCorrelationSimilarity",
-    "SpearmanCorrelationSimilarity",
-    "TanimotoCoefficientSimilarity",
-    "UncenteredCosineSimilarity")
-
-  val defaultUserSimilarity = "PearsonCorrelationSimilarity"
-
-  override def buildRecommender(dataModel: DataModel, seenDataModel: DataModel,
-    validItemIDs: Set[Long], args: Map[String, String]): Recommender = {
-
-    val booleanData: Boolean = getArgOpt(args, "booleanData", "false").toBoolean
-    val nearestN: Int = getArgOpt(args, "nearestN", "10").toInt
-    val userSimilarity: String = getArgOpt(args, "userSimilarity", defaultUserSimilarity)
-    val weighted: Boolean = getArgOpt(args, "weighted", "false").toBoolean
-    val minSimilarity: Double = getArgOpt(args, "minSimilarity").map(_.toDouble).getOrElse(Double.NegativeInfinity)
-    val samplingRate: Double = getArgOpt(args, "samplingRate", "1.0").toDouble
-    val unseenOnly: Boolean = getArgOpt(args, "unseenOnly", "false").toBoolean
-
-    val weightedParam: Weighting = if (weighted) Weighting.WEIGHTED else Weighting.UNWEIGHTED
-
-    val similarity: UserSimilarity = userSimilarity match {
-      case "CityBlockSimilarity" => new CityBlockSimilarity(dataModel)
-      case "EuclideanDistanceSimilarity" => new EuclideanDistanceSimilarity(dataModel, weightedParam)
-      case "LogLikelihoodSimilarity" => new LogLikelihoodSimilarity(dataModel)
-      case "PearsonCorrelationSimilarity" => new PearsonCorrelationSimilarity(dataModel, weightedParam)
-      case "SpearmanCorrelationSimilarity" => new SpearmanCorrelationSimilarity(dataModel)
-      case "TanimotoCoefficientSimilarity" => new TanimotoCoefficientSimilarity(dataModel)
-      case "UncenteredCosineSimilarity" => new UncenteredCosineSimilarity(dataModel, weightedParam)
-      case _ => throw new RuntimeException("Invalid UserSimilarity: " + userSimilarity)
-    }
-
-    val neighborhood: UserNeighborhood = new NearestNUserNeighborhood(nearestN, minSimilarity, similarity, dataModel, samplingRate)
-
-    val recSeenDataModel = if (unseenOnly) seenDataModel else null
-
-    val recommender: Recommender = if (booleanData) {
-      new BooleanPrefUserBasedRecommender(dataModel, neighborhood, similarity,
-        validItemIDs.toArray, recSeenDataModel)
-    } else {
-      new UserBasedRecommender(dataModel, neighborhood, similarity,
-        validItemIDs.toArray, recSeenDataModel)
-    }
-
-    recommender
-  }
-}
diff --git a/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/svdplusplus/SVDPlusPlusJob.scala b/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/svdplusplus/SVDPlusPlusJob.scala
deleted file mode 100644
index 213cbf3..0000000
--- a/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/svdplusplus/SVDPlusPlusJob.scala
+++ /dev/null
@@ -1,40 +0,0 @@
-package io.prediction.algorithms.mahout.itemrec.svdplusplus
-
-import scala.collection.JavaConversions._
-
-import io.prediction.algorithms.mahout.itemrec.MahoutJob
-import io.prediction.algorithms.mahout.itemrec.AllValidItemsCandidateItemsStrategy
-
-import org.apache.mahout.cf.taste.model.DataModel
-import org.apache.mahout.cf.taste.recommender.Recommender
-import org.apache.mahout.cf.taste.impl.recommender.svd.SVDRecommender
-import org.apache.mahout.cf.taste.impl.recommender.svd.SVDPlusPlusFactorizer
-import org.apache.mahout.cf.taste.impl.recommender.svd.Factorizer
-
-class SVDPlusPlusJob extends MahoutJob {
-
-  override def buildRecommender(dataModel: DataModel, seenDataModel: DataModel,
-    validItemIDs: Set[Long], args: Map[String, String]): Recommender = {
-
-    val numFeatures: Int = getArg(args, "numFeatures").toInt
-    val learningRate: Double = getArg(args, "learningRate").toDouble
-    val preventOverfitting: Double = getArg(args, "preventOverfitting").toDouble
-    val randomNoise: Double = getArg(args, "randomNoise").toDouble
-    val numIterations: Int = getArg(args, "numIterations").toInt
-    val learningRateDecay: Double = getArg(args, "learningRateDecay").toDouble
-    val unseenOnly: Boolean = getArgOpt(args, "unseenOnly", "false").toBoolean
-
-    val factorizer: Factorizer = new SVDPlusPlusFactorizer(dataModel, numFeatures, learningRate, preventOverfitting,
-      randomNoise, numIterations, learningRateDecay)
-
-    val candidateItemsStrategy = if (unseenOnly)
-      new AllValidItemsCandidateItemsStrategy(validItemIDs.toArray,
-        seenDataModel)
-    else
-      new AllValidItemsCandidateItemsStrategy(validItemIDs.toArray)
-
-    val recommender: Recommender = new SVDRecommender(dataModel, factorizer, candidateItemsStrategy)
-
-    recommender
-  }
-}
diff --git a/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/svdsgd/SVDSGDJob.scala b/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/svdsgd/SVDSGDJob.scala
deleted file mode 100644
index defd459..0000000
--- a/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/svdsgd/SVDSGDJob.scala
+++ /dev/null
@@ -1,40 +0,0 @@
-package io.prediction.algorithms.mahout.itemrec.svdsgd
-
-import scala.collection.JavaConversions._
-
-import io.prediction.algorithms.mahout.itemrec.MahoutJob
-import io.prediction.algorithms.mahout.itemrec.AllValidItemsCandidateItemsStrategy
-
-import org.apache.mahout.cf.taste.model.DataModel
-import org.apache.mahout.cf.taste.recommender.Recommender
-import org.apache.mahout.cf.taste.impl.recommender.svd.SVDRecommender
-import org.apache.mahout.cf.taste.impl.recommender.svd.RatingSGDFactorizer
-import org.apache.mahout.cf.taste.impl.recommender.svd.Factorizer
-
-class SVDSGDJob extends MahoutJob {
-
-  override def buildRecommender(dataModel: DataModel, seenDataModel: DataModel,
-    validItemIDs: Set[Long], args: Map[String, String]): Recommender = {
-
-    val numFeatures: Int = getArg(args, "numFeatures").toInt
-    val learningRate: Double = getArg(args, "learningRate").toDouble
-    val preventOverfitting: Double = getArg(args, "preventOverfitting").toDouble
-    val randomNoise: Double = getArg(args, "randomNoise").toDouble
-    val numIterations: Int = getArg(args, "numIterations").toInt
-    val learningRateDecay: Double = getArg(args, "learningRateDecay").toDouble
-    val unseenOnly: Boolean = getArgOpt(args, "unseenOnly", "false").toBoolean
-
-    val factorizer: Factorizer = new RatingSGDFactorizer(dataModel, numFeatures, learningRate, preventOverfitting,
-      randomNoise, numIterations, learningRateDecay)
-
-    val candidateItemsStrategy = if (unseenOnly)
-      new AllValidItemsCandidateItemsStrategy(validItemIDs.toArray,
-        seenDataModel)
-    else
-      new AllValidItemsCandidateItemsStrategy(validItemIDs.toArray)
-
-    val recommender: Recommender = new SVDRecommender(dataModel, factorizer, candidateItemsStrategy)
-
-    recommender
-  }
-}
diff --git a/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/thresholduserbased/ThresholdUserBasedJob.scala b/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/thresholduserbased/ThresholdUserBasedJob.scala
deleted file mode 100644
index 9f522b8..0000000
--- a/process/engines/itemrec/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemrec/thresholduserbased/ThresholdUserBasedJob.scala
+++ /dev/null
@@ -1,76 +0,0 @@
-package io.prediction.algorithms.mahout.itemrec.thresholduserbased
-
-import scala.collection.JavaConversions._
-
-import io.prediction.algorithms.mahout.itemrec.MahoutJob
-import io.prediction.algorithms.mahout.itemrec.{ UserBasedRecommender, BooleanPrefUserBasedRecommender }
-
-import org.apache.mahout.cf.taste.model.DataModel
-import org.apache.mahout.cf.taste.recommender.Recommender
-import org.apache.mahout.cf.taste.recommender.RecommendedItem
-import org.apache.mahout.cf.taste.neighborhood.UserNeighborhood
-import org.apache.mahout.cf.taste.similarity.UserSimilarity
-import org.apache.mahout.cf.taste.common.Weighting
-import org.apache.mahout.cf.taste.impl.neighborhood.ThresholdUserNeighborhood
-import org.apache.mahout.cf.taste.impl.similarity.{
-  CityBlockSimilarity,
-  EuclideanDistanceSimilarity,
-  LogLikelihoodSimilarity,
-  PearsonCorrelationSimilarity,
-  SpearmanCorrelationSimilarity,
-  TanimotoCoefficientSimilarity,
-  UncenteredCosineSimilarity
-}
-
-class ThresholdUserBasedJob extends MahoutJob {
-
-  val userSimilarityValues = Seq(
-    "CityBlockSimilarity",
-    "EuclideanDistanceSimilarity",
-    "LogLikelihoodSimilarity",
-    "PearsonCorrelationSimilarity",
-    "SpearmanCorrelationSimilarity",
-    "TanimotoCoefficientSimilarity",
-    "UncenteredCosineSimilarity")
-
-  val defaultUserSimilarity = "PearsonCorrelationSimilarity"
-
-  override def buildRecommender(dataModel: DataModel, seenDataModel: DataModel,
-    validItemIDs: Set[Long], args: Map[String, String]): Recommender = {
-
-    val booleanData: Boolean = getArgOpt(args, "booleanData", "false").toBoolean
-    val userSimilarity: String = getArgOpt(args, "userSimilarity", defaultUserSimilarity)
-    val weighted: Boolean = getArgOpt(args, "weighted", "false").toBoolean
-    val threshold: Double = getArgOpt(args, "threshold").map(_.toDouble).getOrElse(Double.MinPositiveValue)
-    val samplingRate: Double = getArgOpt(args, "samplingRate", "1.0").toDouble
-
-    val weightedParam: Weighting = if (weighted) Weighting.WEIGHTED else Weighting.UNWEIGHTED
-    val unseenOnly: Boolean = getArgOpt(args, "unseenOnly", "false").toBoolean
-
-    val similarity: UserSimilarity = userSimilarity match {
-      case "CityBlockSimilarity" => new CityBlockSimilarity(dataModel)
-      case "EuclideanDistanceSimilarity" => new EuclideanDistanceSimilarity(dataModel, weightedParam)
-      case "LogLikelihoodSimilarity" => new LogLikelihoodSimilarity(dataModel)
-      case "PearsonCorrelationSimilarity" => new PearsonCorrelationSimilarity(dataModel, weightedParam)
-      case "SpearmanCorrelationSimilarity" => new SpearmanCorrelationSimilarity(dataModel)
-      case "TanimotoCoefficientSimilarity" => new TanimotoCoefficientSimilarity(dataModel)
-      case "UncenteredCosineSimilarity" => new UncenteredCosineSimilarity(dataModel, weightedParam)
-      case _ => throw new RuntimeException("Invalid UserSimilarity: " + userSimilarity)
-    }
-
-    val neighborhood: UserNeighborhood = new ThresholdUserNeighborhood(threshold, similarity, dataModel, samplingRate)
-
-    val recSeenDataModel = if (unseenOnly) seenDataModel else null
-
-    val recommender: Recommender = if (booleanData) {
-      new BooleanPrefUserBasedRecommender(dataModel, neighborhood, similarity,
-        validItemIDs.toArray, recSeenDataModel)
-    } else {
-      new UserBasedRecommender(dataModel, neighborhood, similarity,
-        validItemIDs.toArray, recSeenDataModel)
-    }
-
-    recommender
-  }
-
-}
diff --git a/process/engines/itemrec/algorithms/scala/mahout/src/test/resources/application.conf b/process/engines/itemrec/algorithms/scala/mahout/src/test/resources/application.conf
deleted file mode 100644
index 28ac0ee..0000000
--- a/process/engines/itemrec/algorithms/scala/mahout/src/test/resources/application.conf
+++ /dev/null
@@ -1,37 +0,0 @@
-# Used by PredictionIO Commons
-io.prediction.base=.
-
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.host=localhost
-io.prediction.commons.appdata.db.port=27017
-io.prediction.commons.appdata.db.name=predictionio_appdata_mahout_dataprep_test
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.host=localhost
-io.prediction.commons.appdata.test.db.port=27017
-io.prediction.commons.appdata.test.db.name=predictionio_test_appdata_mahout_dataprep_test
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.host=localhost
-io.prediction.commons.appdata.training.db.port=27017
-io.prediction.commons.appdata.training.db.name=predictionio_trainig_appdata_mahout_dataprep_test
-
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.host=localhost
-io.prediction.commons.appdata.validation.db.port=27017
-io.prediction.commons.appdata.validation.db.name=predictionio_validation_appdata_mahout_dataprep_test
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.host=localhost
-io.prediction.commons.modeldata.db.port=27017
-io.prediction.commons.modeldata.db.name=predictionio_modeldata_mahout_dataprep_test
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.host=localhost
-io.prediction.commons.modeldata.training.db.port=27017
-io.prediction.commons.modeldata.training.db.name=predictionio_training_modeldata_mahout_dataprep_test
-
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.host=localhost
-io.prediction.commons.settings.db.port=27017
-io.prediction.commons.settings.db.name=predictionio_mahout_dataprep_test
diff --git a/process/engines/itemrec/algorithms/scala/mahout/src/test/resources/logback.xml b/process/engines/itemrec/algorithms/scala/mahout/src/test/resources/logback.xml
deleted file mode 100644
index 1a2768e..0000000
--- a/process/engines/itemrec/algorithms/scala/mahout/src/test/resources/logback.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<configuration>
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <encoder>
-      <pattern>%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>
-    </encoder>
-  </appender>
-  <root level="info">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
-
diff --git a/process/engines/itemrec/algorithms/scala/mahout/src/test/scala/io/prediction/algorithms/mahout/itemrec/MahoutModelConstructorSpec.scala b/process/engines/itemrec/algorithms/scala/mahout/src/test/scala/io/prediction/algorithms/mahout/itemrec/MahoutModelConstructorSpec.scala
deleted file mode 100644
index 2dd96e6..0000000
--- a/process/engines/itemrec/algorithms/scala/mahout/src/test/scala/io/prediction/algorithms/mahout/itemrec/MahoutModelConstructorSpec.scala
+++ /dev/null
@@ -1,401 +0,0 @@
-package io.prediction.algorithms.mahout.itemrec
-
-import io.prediction.commons.Config
-import io.prediction.commons.settings.{ App, Algo }
-import io.prediction.commons.modeldata.{ ItemRecScore }
-import io.prediction.algorithms.mahout.itemrec.TestUtils
-
-import org.specs2.mutable._
-import com.github.nscala_time.time.Imports._
-import scala.io.Source
-import java.io.File
-import java.io.FileWriter
-import java.io.BufferedWriter
-
-import com.mongodb.casbah.Imports._
-
-class MahoutModelConstructorSpec extends Specification {
-
-  // note: should match the db name defined in the application.conf
-  val mongoDbName = "predictionio_modeldata_mahout_dataprep_test"
-  def cleanUp() = {
-    // remove the test database
-    MongoConnection()(mongoDbName).dropDatabase()
-  }
-
-  val commonConfig = new Config
-  val modeldataItemRecScores = commonConfig.getModeldataItemRecScores
-
-  "MahoutModelConstructor" should {
-
-    val inputDir = "/tmp/pio_test/"
-
-    val inputDirFile = new File(inputDir)
-    inputDirFile.mkdirs()
-
-    val usersIndex = List(
-      "1\tu0",
-      "2\tu1",
-      "3\tu2")
-
-    val itemsIndex = List(
-      "1\ti0\tt1,t2\t0",
-      "2\ti1\tt1\t0",
-      "3\ti2\tt2,t3\t0",
-      "4\ti3\tt3\t0",
-      "5\ti4\tt2,t3\t0",
-      "6\ti5\tt1,t2\t0"
-    )
-
-    val ratingsCSV = List(
-      "1,1,3",
-      "1,2,4",
-      "1,3,1",
-      "2,1,2",
-      "2,2,1",
-      "3,2,5",
-      "3,4,4"
-    )
-
-    val predicted = List(
-      "1\t[4:0.6123,5:31.432,6:11.3,1:2.3]",
-      "2\t[3:1.2,4:11.4,5:3.0,6:2.55]",
-      "3\t[1:4.5,3:22.5,2:3.3,5:2.2]")
-
-    TestUtils.writeToFile(usersIndex, s"${inputDir}usersIndex.tsv")
-    TestUtils.writeToFile(itemsIndex, s"${inputDir}itemsIndex.tsv")
-    TestUtils.writeToFile(ratingsCSV, s"${inputDir}ratings.csv")
-    TestUtils.writeToFile(predicted, s"${inputDir}predicted.tsv")
-
-    val appid = 24
-
-    implicit val app = App(
-      id = appid,
-      userid = 0,
-      appkey = "1234",
-      display = "12345",
-      url = None,
-      cat = None,
-      desc = None,
-      timezone = "UTC"
-    )
-
-    "correctly writes ItemRecScores with larger numRecommendations" in {
-
-      val algoid = 25
-      val modelSet = false
-
-      implicit val algo = Algo(
-        id = algoid,
-        engineid = 1234,
-        name = "",
-        infoid = "abc",
-        command = "",
-        params = Map(),
-        settings = Map(),
-        modelset = modelSet,
-        createtime = DateTime.now,
-        updatetime = DateTime.now,
-        status = "deployed",
-        offlineevalid = None,
-        offlinetuneid = None,
-        loop = None,
-        paramset = None
-      )
-
-      val args = Map(
-        "inputDir" -> inputDir,
-        "appid" -> appid,
-        "algoid" -> algoid,
-        "modelSet" -> modelSet,
-        "unseenOnly" -> false,
-        "numRecommendations" -> 5,
-        "booleanData" -> false,
-        "implicitFeedback" -> false
-      )
-
-      val u0Expected = ItemRecScore(
-        uid = "u0",
-        iids = Seq("i4", "i5", "i0", "i3"),
-        scores = Seq(31.432, 11.3, 2.3, 0.6123),
-        itypes = Seq(Seq("t2", "t3"), Seq("t1", "t2"), Seq("t1", "t2"), Seq("t3")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val u1Expected = ItemRecScore(
-        uid = "u1",
-        iids = Seq("i3", "i4", "i5", "i2"),
-        scores = Seq(11.4, 3.0, 2.55, 1.2),
-        itypes = Seq(Seq("t3"), Seq("t2", "t3"), Seq("t1", "t2"), Seq("t2", "t3")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val u2Expected = ItemRecScore(
-        uid = "u2",
-        iids = Seq("i2", "i0", "i1", "i4"),
-        scores = Seq(22.5, 4.5, 3.3, 2.2),
-        itypes = Seq(Seq("t2", "t3"), Seq("t1", "t2"), Seq("t1"), Seq("t2", "t3")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      MahoutModelConstructor.main(TestUtils.argMapToArray(args))
-
-      val u0ItemRec = modeldataItemRecScores.getByUid("u0")
-      val u1ItemRec = modeldataItemRecScores.getByUid("u1")
-      val u2ItemRec = modeldataItemRecScores.getByUid("u2")
-
-      // don't check id
-      u0ItemRec.map(TestUtils.roundUpScores(_).copy(id = None)) must beSome(TestUtils.roundUpScores(u0Expected)) and
-        (u1ItemRec.map(TestUtils.roundUpScores(_).copy(id = None)) must beSome(TestUtils.roundUpScores(u1Expected))) and
-        (u2ItemRec.map(TestUtils.roundUpScores(_).copy(id = None)) must beSome(TestUtils.roundUpScores(u2Expected)))
-
-    }
-
-    "correctly writes ItemRecScores with smaller numRecommendations" in {
-
-      val algoid = 26
-      val modelSet = true
-
-      implicit val algo = Algo(
-        id = algoid,
-        engineid = 1234,
-        name = "",
-        infoid = "abc",
-        command = "",
-        params = Map(),
-        settings = Map(),
-        modelset = modelSet,
-        createtime = DateTime.now,
-        updatetime = DateTime.now,
-        status = "deployed",
-        offlineevalid = None,
-        offlinetuneid = None,
-        loop = None,
-        paramset = None
-      )
-
-      val args = Map(
-        "inputDir" -> inputDir,
-        "appid" -> appid,
-        "algoid" -> algoid,
-        "modelSet" -> modelSet,
-        "unseenOnly" -> false,
-        "numRecommendations" -> 2,
-        "booleanData" -> false,
-        "implicitFeedback" -> false
-      )
-
-      val u0Expected = ItemRecScore(
-        uid = "u0",
-        iids = Seq("i4", "i5"),
-        scores = Seq(31.432, 11.3),
-        itypes = Seq(Seq("t2", "t3"), Seq("t1", "t2")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val u1Expected = ItemRecScore(
-        uid = "u1",
-        iids = Seq("i3", "i4"),
-        scores = Seq(11.4, 3.0),
-        itypes = Seq(Seq("t3"), Seq("t2", "t3")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val u2Expected = ItemRecScore(
-        uid = "u2",
-        iids = Seq("i2", "i0"),
-        scores = Seq(22.5, 4.5),
-        itypes = Seq(Seq("t2", "t3"), Seq("t1", "t2")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      MahoutModelConstructor.main(TestUtils.argMapToArray(args))
-
-      val u0ItemRec = modeldataItemRecScores.getByUid("u0")
-      val u1ItemRec = modeldataItemRecScores.getByUid("u1")
-      val u2ItemRec = modeldataItemRecScores.getByUid("u2")
-
-      // don't check id
-      u0ItemRec.map(TestUtils.roundUpScores(_).copy(id = None)) must beSome(TestUtils.roundUpScores(u0Expected)) and
-        (u1ItemRec.map(TestUtils.roundUpScores(_).copy(id = None)) must beSome(TestUtils.roundUpScores(u1Expected))) and
-        (u2ItemRec.map(TestUtils.roundUpScores(_).copy(id = None)) must beSome(TestUtils.roundUpScores(u2Expected)))
-
-    }
-
-    "correctly writes ItemRecScores with subset itemsIndex.tsv" in {
-
-      val inputDir = "/tmp/pio_test/subset/"
-
-      val inputDirFile = new File(inputDir)
-      inputDirFile.mkdirs()
-
-      val itemsIndex = List(
-        "1\ti0\tt1,t2\t0",
-        "3\ti2\tt2,t3\t0",
-        "4\ti3\tt3\t0"
-      )
-
-      TestUtils.writeToFile(usersIndex, s"${inputDir}usersIndex.tsv")
-      TestUtils.writeToFile(itemsIndex, s"${inputDir}itemsIndex.tsv")
-      TestUtils.writeToFile(ratingsCSV, s"${inputDir}ratings.csv")
-      TestUtils.writeToFile(predicted, s"${inputDir}predicted.tsv")
-
-      val algoid = 27
-      val modelSet = false
-
-      implicit val algo = Algo(
-        id = algoid,
-        engineid = 1234,
-        name = "",
-        infoid = "abc",
-        command = "",
-        params = Map(),
-        settings = Map(),
-        modelset = modelSet,
-        createtime = DateTime.now,
-        updatetime = DateTime.now,
-        status = "deployed",
-        offlineevalid = None,
-        offlinetuneid = None,
-        loop = None,
-        paramset = None
-      )
-
-      val args = Map(
-        "inputDir" -> inputDir,
-        "appid" -> appid,
-        "algoid" -> algoid,
-        "modelSet" -> modelSet,
-        "unseenOnly" -> false,
-        "numRecommendations" -> 5,
-        "booleanData" -> false,
-        "implicitFeedback" -> false
-      )
-
-      val u0Expected = ItemRecScore(
-        uid = "u0",
-        iids = Seq("i0", "i3"),
-        scores = Seq(2.3, 0.6123),
-        itypes = Seq(Seq("t1", "t2"), Seq("t3")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val u1Expected = ItemRecScore(
-        uid = "u1",
-        iids = Seq("i3", "i2"),
-        scores = Seq(11.4, 1.2),
-        itypes = Seq(Seq("t3"), Seq("t2", "t3")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val u2Expected = ItemRecScore(
-        uid = "u2",
-        iids = Seq("i2", "i0"),
-        scores = Seq(22.5, 4.5),
-        itypes = Seq(Seq("t2", "t3"), Seq("t1", "t2")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      MahoutModelConstructor.main(TestUtils.argMapToArray(args))
-
-      val u0ItemRec = modeldataItemRecScores.getByUid("u0")
-      val u1ItemRec = modeldataItemRecScores.getByUid("u1")
-      val u2ItemRec = modeldataItemRecScores.getByUid("u2")
-
-      // don't check id
-      u0ItemRec.map(TestUtils.roundUpScores(_).copy(id = None)) must beSome(TestUtils.roundUpScores(u0Expected)) and
-        (u1ItemRec.map(TestUtils.roundUpScores(_).copy(id = None)) must beSome(TestUtils.roundUpScores(u1Expected))) and
-        (u2ItemRec.map(TestUtils.roundUpScores(_).copy(id = None)) must beSome(TestUtils.roundUpScores(u2Expected)))
-
-    }
-
-    "correctly writes ItemRecScores with unseenOnly=true" in {
-
-      val algoid = 28
-      val modelSet = true
-
-      implicit val algo = Algo(
-        id = algoid,
-        engineid = 1234,
-        name = "",
-        infoid = "abc",
-        command = "",
-        params = Map(),
-        settings = Map(),
-        modelset = modelSet,
-        createtime = DateTime.now,
-        updatetime = DateTime.now,
-        status = "deployed",
-        offlineevalid = None,
-        offlinetuneid = None,
-        loop = None,
-        paramset = None
-      )
-
-      val args = Map(
-        "inputDir" -> inputDir,
-        "appid" -> appid,
-        "algoid" -> algoid,
-        "modelSet" -> modelSet,
-        "unseenOnly" -> true,
-        "numRecommendations" -> 4,
-        "booleanData" -> false,
-        "implicitFeedback" -> false
-      )
-
-      val u0Expected = ItemRecScore(
-        uid = "u0",
-        iids = Seq("i4", "i5", "i3"),
-        scores = Seq(31.432, 11.3, 0.6123),
-        itypes = Seq(Seq("t2", "t3"), Seq("t1", "t2"), Seq("t3")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val u1Expected = ItemRecScore(
-        uid = "u1",
-        iids = Seq("i3", "i4", "i5", "i2"),
-        scores = Seq(11.4, 3.0, 2.55, 1.2),
-        itypes = Seq(Seq("t3"), Seq("t2", "t3"), Seq("t1", "t2"), Seq("t2", "t3")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val u2Expected = ItemRecScore(
-        uid = "u2",
-        iids = Seq("i2", "i0", "i4"),
-        scores = Seq(22.5, 4.5, 2.2),
-        itypes = Seq(Seq("t2", "t3"), Seq("t1", "t2"), Seq("t2", "t3")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      MahoutModelConstructor.main(TestUtils.argMapToArray(args))
-
-      val u0ItemRec = modeldataItemRecScores.getByUid("u0")
-      val u1ItemRec = modeldataItemRecScores.getByUid("u1")
-      val u2ItemRec = modeldataItemRecScores.getByUid("u2")
-
-      // don't check id
-      u0ItemRec.map(TestUtils.roundUpScores(_).copy(id = None)) must beSome(TestUtils.roundUpScores(u0Expected)) and
-        (u1ItemRec.map(TestUtils.roundUpScores(_).copy(id = None)) must beSome(TestUtils.roundUpScores(u1Expected))) and
-        (u2ItemRec.map(TestUtils.roundUpScores(_).copy(id = None)) must beSome(TestUtils.roundUpScores(u2Expected)))
-
-    }
-
-  }
-
-  // TODO: test evalid != None
-
-  // clean up when finish test
-  step(cleanUp())
-}
diff --git a/process/engines/itemrec/algorithms/scala/mahout/src/test/scala/io/prediction/algorithms/mahout/itemrec/TestUtils.scala b/process/engines/itemrec/algorithms/scala/mahout/src/test/scala/io/prediction/algorithms/mahout/itemrec/TestUtils.scala
deleted file mode 100644
index e5f3301..0000000
--- a/process/engines/itemrec/algorithms/scala/mahout/src/test/scala/io/prediction/algorithms/mahout/itemrec/TestUtils.scala
+++ /dev/null
@@ -1,36 +0,0 @@
-package io.prediction.algorithms.mahout.itemrec
-
-import io.prediction.commons.modeldata.{ ItemRecScore }
-import java.io.File
-import java.io.FileWriter
-import java.io.BufferedWriter
-
-object TestUtils {
-
-  // NOTE: use HALF_UP mode to avoid error caused by rounding when compare data
-  // (eg. 3.5 vs 3.499999999999).
-  // (eg. 0.6666666666 vs 0.666666667)
-  def roundUpScores(irec: ItemRecScore): ItemRecScore = {
-    irec.copy(
-      scores = irec.scores.map { x =>
-        BigDecimal(x).setScale(9, BigDecimal.RoundingMode.HALF_UP).toDouble
-      }
-    )
-  }
-
-  def argMapToArray(args: Map[String, Any]): Array[String] = {
-    args.toArray.flatMap {
-      case (k, v) =>
-        Array(s"--${k}", v.toString)
-    }
-  }
-
-  def writeToFile(lines: List[String], filePath: String) = {
-    val writer = new BufferedWriter(new FileWriter(new File(filePath)))
-    lines.foreach { line =>
-      writer.write(s"${line}\n")
-    }
-    writer.close()
-  }
-
-}
diff --git a/process/engines/itemrec/algorithms/scala/mahout/src/test/scala/io/prediction/algorithms/mahout/itemrec/knnitembased/KNNItemBasedJobSpec.scala b/process/engines/itemrec/algorithms/scala/mahout/src/test/scala/io/prediction/algorithms/mahout/itemrec/knnitembased/KNNItemBasedJobSpec.scala
deleted file mode 100644
index c40b091..0000000
--- a/process/engines/itemrec/algorithms/scala/mahout/src/test/scala/io/prediction/algorithms/mahout/itemrec/knnitembased/KNNItemBasedJobSpec.scala
+++ /dev/null
@@ -1,375 +0,0 @@
-package io.prediction.algorithms.mahout.itemrec.knnitembased
-
-import org.specs2.mutable._
-import com.github.nscala_time.time.Imports._
-import scala.io.Source
-import java.io.File
-import java.io.FileWriter
-import java.io.BufferedWriter
-
-import io.prediction.algorithms.mahout.itemrec.MahoutJob
-import io.prediction.algorithms.mahout.itemrec.TestUtils
-
-class KNNItemBasedJobSpec extends Specification {
-
-  val ratingsCSV = List(
-    "1,1,3",
-    "4,1,5",
-    "1,2,3",
-    "3,2,2",
-    "4,2,4",
-    "1,3,4",
-    "2,3,4",
-    "3,3,2",
-    "2,4,2",
-    "3,4,3",
-    "4,4,2"
-  )
-
-  val itemsIndexTSV = List(
-    s"1\ti1\tt1,t2\t12345000",
-    s"2\ti2\tt1\t12346000",
-    s"3\ti3\tt2,t3\t12346100",
-    s"4\ti4\tt3\t12347100"
-  )
-
-  val appid = 25
-  val engineid = 31
-  val algoid = 32
-
-  val jobName =
-    "io.prediction.algorithms.mahout.itemrec.knnitembased.KNNItemBasedJob"
-
-  "KNNItemBasedJob with unseenOnly=false" should {
-    val testDir = "/tmp/pio_test/KNNItemBasedJob/unseenOnlyfalse/"
-    val inputFile = s"${testDir}ratings.csv"
-    val itemsFile = s"${testDir}itemsIndex.tsv"
-    val outputFile = s"${testDir}predicted.tsv"
-    val outputSim = s"${testDir}sim.csv"
-
-    val testDirFile = new File(testDir)
-    testDirFile.mkdirs()
-
-    val jobArgs = Map(
-      "input" -> inputFile,
-      "itemsFile" -> itemsFile,
-      "output" -> outputFile,
-      "appid" -> appid,
-      "engineid" -> engineid,
-      "algoid" -> algoid,
-      "booleanData" -> false,
-      "numRecommendations" -> 5,
-      "itemSimilarity" -> "LogLikelihoodSimilarity",
-      "weighted" -> false,
-      "nearestN" -> 10,
-      "threshold" -> 4.9E-324,
-      "outputSim" -> outputSim,
-      "preComputeItemSim" -> false,
-      "unseenOnly" -> false,
-      "recommendationTime" -> DateTime.now.millis
-    )
-
-    TestUtils.writeToFile(ratingsCSV, inputFile)
-    TestUtils.writeToFile(itemsIndexTSV, itemsFile)
-
-    val predictedExpected = List(
-      "1\t[3:3.4408236,1:3.2995765,4:3.2805154,2:3.2180138]",
-      "2\t[3:3.338186,1:3.0,2:3.0,4:2.661814]",
-      "3\t[4:2.5027347,1:2.3333333,2:2.2486327,3:2.2486327]",
-      "4\t[2:3.905135,3:3.8779385,1:3.8016937,4:3.4595158]"
-    )
-
-    MahoutJob.main(Array(jobName) ++ TestUtils.argMapToArray(jobArgs))
-
-    "generate prediction output correctly" in {
-      val predicted = Source.fromFile(outputFile)
-        .getLines().toList
-
-      predicted must containTheSameElementsAs(predictedExpected)
-    }
-
-  }
-
-  "KNNItemBasedJob with unseenOnly=false and subset itemsIndex" should {
-    val testDir = "/tmp/pio_test/KNNItemBasedJob/unseenOnlyfalseSubSetItemsIndex/"
-    val inputFile = s"${testDir}ratings.csv"
-    val itemsFile = s"${testDir}itemsIndex.tsv"
-    val outputFile = s"${testDir}predicted.tsv"
-    val outputSim = s"${testDir}sim.csv"
-
-    val itemsIndexTSV = List(
-      s"2\ti2\tt1\t12346000",
-      s"4\ti4\tt3\t12347100"
-    )
-
-    val testDirFile = new File(testDir)
-    testDirFile.mkdirs()
-
-    val jobArgs = Map(
-      "input" -> inputFile,
-      "itemsFile" -> itemsFile,
-      "output" -> outputFile,
-      "appid" -> appid,
-      "engineid" -> engineid,
-      "algoid" -> algoid,
-      "booleanData" -> false,
-      "numRecommendations" -> 5,
-      "itemSimilarity" -> "LogLikelihoodSimilarity",
-      "weighted" -> false,
-      "nearestN" -> 10,
-      "threshold" -> 4.9E-324,
-      "outputSim" -> outputSim,
-      "preComputeItemSim" -> false,
-      "unseenOnly" -> false,
-      "recommendationTime" -> DateTime.now.millis
-    )
-
-    TestUtils.writeToFile(ratingsCSV, inputFile)
-    TestUtils.writeToFile(itemsIndexTSV, itemsFile)
-
-    val predictedExpected = List(
-      "1\t[4:3.2805154,2:3.2180138]",
-      "2\t[2:3.0,4:2.661814]",
-      "3\t[4:2.5027347,2:2.2486327]",
-      "4\t[2:3.905135,4:3.4595158]"
-    )
-
-    MahoutJob.main(Array(jobName) ++ TestUtils.argMapToArray(jobArgs))
-
-    "generate prediction output correctly" in {
-      val predicted = Source.fromFile(outputFile)
-        .getLines().toList
-
-      predicted must containTheSameElementsAs(predictedExpected)
-    }
-
-  }
-
-  "KNNItemBasedJob with unseenOnly=true" should {
-    val testDir = "/tmp/pio_test/KNNItemBasedJob/unseenOnlytrue/"
-    val inputFile = s"${testDir}ratings.csv"
-    val itemsFile = s"${testDir}itemsIndex.tsv"
-    val outputFile = s"${testDir}predicted.tsv"
-    val outputSim = s"${testDir}sim.csv"
-
-    val testDirFile = new File(testDir)
-    testDirFile.mkdirs()
-
-    val jobArgs = Map(
-      "input" -> inputFile,
-      "itemsFile" -> itemsFile,
-      "output" -> outputFile,
-      "appid" -> appid,
-      "engineid" -> engineid,
-      "algoid" -> algoid,
-      "booleanData" -> false,
-      "numRecommendations" -> 5,
-      "itemSimilarity" -> "LogLikelihoodSimilarity",
-      "weighted" -> false,
-      "nearestN" -> 10,
-      "threshold" -> 4.9E-324,
-      "outputSim" -> outputSim,
-      "preComputeItemSim" -> false,
-      "unseenOnly" -> true,
-      "recommendationTime" -> DateTime.now.millis
-    )
-
-    TestUtils.writeToFile(ratingsCSV, inputFile)
-    TestUtils.writeToFile(itemsIndexTSV, itemsFile)
-
-    val predictedExpected = List(
-      "1\t[4:3.2805154]",
-      "2\t[1:3.0,2:3.0]",
-      "3\t[1:2.3333333]",
-      "4\t[3:3.8779385]"
-    )
-
-    MahoutJob.main(Array(jobName) ++ TestUtils.argMapToArray(jobArgs))
-
-    "generate prediction output correctly" in {
-      val predicted = Source.fromFile(outputFile)
-        .getLines().toList
-
-      predicted must containTheSameElementsAs(predictedExpected)
-    }
-  }
-
-  "KNNItemBasedJob with unseenOnly=true and seenFile" should {
-    val testDir = "/tmp/pio_test/KNNItemBasedJob/unseenOnlytrueSeenFile/"
-    val inputFile = s"${testDir}ratings.csv"
-    val itemsFile = s"${testDir}itemsIndex.tsv"
-    val outputFile = s"${testDir}predicted.tsv"
-    val outputSim = s"${testDir}sim.csv"
-    val seenFile = s"${testDir}seen.csv"
-
-    val testDirFile = new File(testDir)
-    testDirFile.mkdirs()
-
-    val seenCSV = List(
-      "1,1",
-      "4,1",
-      "1,2"
-    )
-
-    val jobArgs = Map(
-      "input" -> inputFile,
-      "itemsFile" -> itemsFile,
-      "output" -> outputFile,
-      "appid" -> appid,
-      "engineid" -> engineid,
-      "algoid" -> algoid,
-      "booleanData" -> false,
-      "numRecommendations" -> 5,
-      "itemSimilarity" -> "LogLikelihoodSimilarity",
-      "weighted" -> false,
-      "nearestN" -> 10,
-      "threshold" -> 4.9E-324,
-      "outputSim" -> outputSim,
-      "preComputeItemSim" -> false,
-      "unseenOnly" -> true,
-      "seenFile" -> seenFile,
-      "recommendationTime" -> DateTime.now.millis
-    )
-
-    TestUtils.writeToFile(ratingsCSV, inputFile)
-    TestUtils.writeToFile(itemsIndexTSV, itemsFile)
-    TestUtils.writeToFile(seenCSV, seenFile)
-
-    val predictedExpected = List(
-      "1\t[3:3.4408236,4:3.2805154]",
-      "2\t[3:3.338186,1:3.0,2:3.0,4:2.661814]",
-      "3\t[4:2.5027347,1:2.3333333,2:2.2486327,3:2.2486327]",
-      "4\t[2:3.905135,3:3.8779385,4:3.4595158]"
-    )
-
-    MahoutJob.main(Array(jobName) ++ TestUtils.argMapToArray(jobArgs))
-
-    "generate prediction output correctly" in {
-      val predicted = Source.fromFile(outputFile)
-        .getLines().toList
-
-      predicted must containTheSameElementsAs(predictedExpected)
-    }
-  }
-
-  "KNNItemBasedJob with unseenOnly=true and seenFile and subset itemsIndex" should {
-    val testDir = "/tmp/pio_test/KNNItemBasedJob/unseenOnlytrueSeenFileSubSetItemsIndex/"
-    val inputFile = s"${testDir}ratings.csv"
-    val itemsFile = s"${testDir}itemsIndex.tsv"
-    val outputFile = s"${testDir}predicted.tsv"
-    val outputSim = s"${testDir}sim.csv"
-    val seenFile = s"${testDir}seen.csv"
-
-    val testDirFile = new File(testDir)
-    testDirFile.mkdirs()
-
-    val itemsIndexTSV = List(
-      s"1\ti1\tt1,t2\t12345000",
-      s"2\ti2\tt1\t12346000",
-      s"4\ti4\tt3\t12347100"
-    )
-
-    val seenCSV = List(
-      "1,1",
-      "4,1",
-      "1,2"
-    )
-
-    val jobArgs = Map(
-      "input" -> inputFile,
-      "itemsFile" -> itemsFile,
-      "output" -> outputFile,
-      "appid" -> appid,
-      "engineid" -> engineid,
-      "algoid" -> algoid,
-      "booleanData" -> false,
-      "numRecommendations" -> 5,
-      "itemSimilarity" -> "LogLikelihoodSimilarity",
-      "weighted" -> false,
-      "nearestN" -> 10,
-      "threshold" -> 4.9E-324,
-      "outputSim" -> outputSim,
-      "preComputeItemSim" -> false,
-      "unseenOnly" -> true,
-      "seenFile" -> seenFile,
-      "recommendationTime" -> DateTime.now.millis
-    )
-
-    TestUtils.writeToFile(ratingsCSV, inputFile)
-    TestUtils.writeToFile(itemsIndexTSV, itemsFile)
-    TestUtils.writeToFile(seenCSV, seenFile)
-
-    val predictedExpected = List(
-      "1\t[4:3.2805154]",
-      "2\t[2:3.0,1:3.0,4:2.661814]",
-      "3\t[4:2.5027347,1:2.3333333,2:2.2486327]",
-      "4\t[2:3.905135,4:3.4595158]"
-    )
-
-    MahoutJob.main(Array(jobName) ++ TestUtils.argMapToArray(jobArgs))
-
-    "generate prediction output correctly" in {
-      val predicted = Source.fromFile(outputFile)
-        .getLines().toList
-
-      predicted must containTheSameElementsAs(predictedExpected)
-    }
-  }
-
-  "KNNItemBasedJob with unseenOnly=true and empty seenFile" should {
-    val testDir = "/tmp/pio_test/KNNItemBasedJob/unseenOnlytrueEmptySeenFile/"
-    val inputFile = s"${testDir}ratings.csv"
-    val itemsFile = s"${testDir}itemsIndex.tsv"
-    val outputFile = s"${testDir}predicted.tsv"
-    val outputSim = s"${testDir}sim.csv"
-    val seenFile = s"${testDir}seen.csv"
-
-    val testDirFile = new File(testDir)
-    testDirFile.mkdirs()
-
-    val seenCSV = List()
-
-    val jobArgs = Map(
-      "input" -> inputFile,
-      "itemsFile" -> itemsFile,
-      "output" -> outputFile,
-      "appid" -> appid,
-      "engineid" -> engineid,
-      "algoid" -> algoid,
-      "booleanData" -> false,
-      "numRecommendations" -> 5,
-      "itemSimilarity" -> "LogLikelihoodSimilarity",
-      "weighted" -> false,
-      "nearestN" -> 10,
-      "threshold" -> 4.9E-324,
-      "outputSim" -> outputSim,
-      "preComputeItemSim" -> false,
-      "unseenOnly" -> true,
-      "seenFile" -> seenFile,
-      "recommendationTime" -> DateTime.now.millis
-    )
-
-    TestUtils.writeToFile(ratingsCSV, inputFile)
-    TestUtils.writeToFile(itemsIndexTSV, itemsFile)
-    TestUtils.writeToFile(seenCSV, seenFile)
-
-    val predictedExpected = List(
-      "1\t[3:3.4408236,1:3.2995765,4:3.2805154,2:3.2180138]",
-      "2\t[3:3.338186,1:3.0,2:3.0,4:2.661814]",
-      "3\t[4:2.5027347,1:2.3333333,2:2.2486327,3:2.2486327]",
-      "4\t[2:3.905135,3:3.8779385,1:3.8016937,4:3.4595158]"
-    )
-
-    MahoutJob.main(Array(jobName) ++ TestUtils.argMapToArray(jobArgs))
-
-    "generate prediction output correctly" in {
-      val predicted = Source.fromFile(outputFile)
-        .getLines().toList
-
-      predicted must containTheSameElementsAs(predictedExpected)
-    }
-  }
-
-  // TODO: add more tests...
-
-}
diff --git a/process/engines/itemrec/algorithms/scala/mahout/src/test/scala/io/prediction/algorithms/mahout/itemrec/knnuserbased/KNNUserBasedJobSpec.scala b/process/engines/itemrec/algorithms/scala/mahout/src/test/scala/io/prediction/algorithms/mahout/itemrec/knnuserbased/KNNUserBasedJobSpec.scala
deleted file mode 100644
index a0b259c..0000000
--- a/process/engines/itemrec/algorithms/scala/mahout/src/test/scala/io/prediction/algorithms/mahout/itemrec/knnuserbased/KNNUserBasedJobSpec.scala
+++ /dev/null
@@ -1,365 +0,0 @@
-package io.prediction.algorithms.mahout.itemrec.knnuserbased
-
-import org.specs2.mutable._
-import com.github.nscala_time.time.Imports._
-import scala.io.Source
-import java.io.File
-import java.io.FileWriter
-import java.io.BufferedWriter
-
-import io.prediction.algorithms.mahout.itemrec.MahoutJob
-import io.prediction.algorithms.mahout.itemrec.TestUtils
-
-class KNNUserBasedJobSpec extends Specification {
-
-  val ratingsCSV = List(
-    "1,1,3",
-    "4,1,5",
-    "1,2,3",
-    "3,2,2",
-    "4,2,4",
-    "1,3,5",
-    "2,3,1",
-    "3,3,2",
-    "2,4,2",
-    "3,4,3",
-    "4,4,2"
-  )
-
-  val itemsIndexTSV = List(
-    s"1\ti1\tt1,t2\t12345000",
-    s"2\ti2\tt1\t12346000",
-    s"3\ti3\tt2,t3\t12346100",
-    s"4\ti4\tt3\t12347100"
-  )
-
-  val appid = 25
-  val engineid = 31
-  val algoid = 32
-
-  val jobName =
-    "io.prediction.algorithms.mahout.itemrec.knnuserbased.KNNUserBasedJob"
-
-  "KNNUserBasedJob with unseenOnly=false" should {
-    val testDir = "/tmp/pio_test/KNNUserBasedJob/unseenOnlyfalse/"
-    val inputFile = s"${testDir}ratings.csv"
-    val itemsFile = s"${testDir}itemsIndex.tsv"
-    val outputFile = s"${testDir}predicted.tsv"
-
-    val testDirFile = new File(testDir)
-    testDirFile.mkdirs()
-
-    val jobArgs = Map(
-      "input" -> inputFile,
-      "itemsFile" -> itemsFile,
-      "output" -> outputFile,
-      "appid" -> appid,
-      "engineid" -> engineid,
-      "algoid" -> algoid,
-      "booleanData" -> false,
-      "numRecommendations" -> 5,
-      "nearestN" -> 10,
-      "userSimilarity" -> "LogLikelihoodSimilarity",
-      "weighted" -> false,
-      "minSimilarity" -> 5e-324,
-      "samplingRate" -> 1,
-      "unseenOnly" -> false,
-      "recommendationTime" -> 0
-    )
-
-    TestUtils.writeToFile(ratingsCSV, inputFile)
-    TestUtils.writeToFile(itemsIndexTSV, itemsFile)
-
-    val predictedExpected = List(
-      "1\t[2:3.0,4:2.2805154,3:1.3898838]",
-      "2\t[1:4.0,3:3.5,2:3.0,4:2.5]",
-      "3\t[1:4.0,2:3.5,3:2.559535,4:2.0]",
-      "4\t[2:2.5,3:2.402577,4:2.3898838]"
-    )
-
-    MahoutJob.main(Array(jobName) ++ TestUtils.argMapToArray(jobArgs))
-
-    "generate prediction output correctly" in {
-      val predicted = Source.fromFile(outputFile)
-        .getLines().toList
-
-      predicted must containTheSameElementsAs(predictedExpected)
-    }
-
-  }
-
-  "KNNUserBasedJob with unseenOnly=false and subset itemsIndex" should {
-    val testDir = "/tmp/pio_test/KNNUserBasedJob/unseenOnlyfalseSubSetItemsIndex/"
-    val inputFile = s"${testDir}ratings.csv"
-    val itemsFile = s"${testDir}itemsIndex.tsv"
-    val outputFile = s"${testDir}predicted.tsv"
-
-    val itemsIndexTSV = List(
-      s"2\ti2\tt1\t12346000",
-      s"4\ti4\tt3\t12347100"
-    )
-
-    val testDirFile = new File(testDir)
-    testDirFile.mkdirs()
-
-    val jobArgs = Map(
-      "input" -> inputFile,
-      "itemsFile" -> itemsFile,
-      "output" -> outputFile,
-      "appid" -> appid,
-      "engineid" -> engineid,
-      "algoid" -> algoid,
-      "booleanData" -> false,
-      "numRecommendations" -> 5,
-      "nearestN" -> 10,
-      "userSimilarity" -> "LogLikelihoodSimilarity",
-      "weighted" -> false,
-      "minSimilarity" -> 5e-324,
-      "samplingRate" -> 1,
-      "unseenOnly" -> false,
-      "recommendationTime" -> 0
-    )
-
-    TestUtils.writeToFile(ratingsCSV, inputFile)
-    TestUtils.writeToFile(itemsIndexTSV, itemsFile)
-
-    val predictedExpected = List(
-      "1\t[2:3.0,4:2.2805154]",
-      "2\t[2:3.0,4:2.5]",
-      "3\t[2:3.5,4:2.0]",
-      "4\t[2:2.5,4:2.3898838]"
-    )
-
-    MahoutJob.main(Array(jobName) ++ TestUtils.argMapToArray(jobArgs))
-
-    "generate prediction output correctly" in {
-      val predicted = Source.fromFile(outputFile)
-        .getLines().toList
-
-      predicted must containTheSameElementsAs(predictedExpected)
-    }
-
-  }
-
-  "KNNUserBasedJob with unseenOnly=true" should {
-    val testDir = "/tmp/pio_test/KNNUserBasedJob/unseenOnlytrue/"
-    val inputFile = s"${testDir}ratings.csv"
-    val itemsFile = s"${testDir}itemsIndex.tsv"
-    val outputFile = s"${testDir}predicted.tsv"
-
-    val testDirFile = new File(testDir)
-    testDirFile.mkdirs()
-
-    val jobArgs = Map(
-      "input" -> inputFile,
-      "itemsFile" -> itemsFile,
-      "output" -> outputFile,
-      "appid" -> appid,
-      "engineid" -> engineid,
-      "algoid" -> algoid,
-      "booleanData" -> false,
-      "numRecommendations" -> 5,
-      "nearestN" -> 10,
-      "userSimilarity" -> "LogLikelihoodSimilarity",
-      "weighted" -> false,
-      "minSimilarity" -> 5e-324,
-      "samplingRate" -> 1,
-      "unseenOnly" -> true,
-      "recommendationTime" -> 0
-    )
-
-    TestUtils.writeToFile(ratingsCSV, inputFile)
-    TestUtils.writeToFile(itemsIndexTSV, itemsFile)
-
-    val predictedExpected = List(
-      "1\t[4:2.2805154]",
-      "2\t[1:4.0,2:3.0]",
-      "3\t[1:4.0]",
-      "4\t[3:2.402577]"
-    )
-
-    MahoutJob.main(Array(jobName) ++ TestUtils.argMapToArray(jobArgs))
-
-    "generate prediction output correctly" in {
-      val predicted = Source.fromFile(outputFile)
-        .getLines().toList
-
-      predicted must containTheSameElementsAs(predictedExpected)
-    }
-  }
-
-  "KNNUserBasedJob with unseenOnly=true and seenFile" should {
-    val testDir = "/tmp/pio_test/KNNUserBasedJob/unseenOnlytrueSeenFile/"
-    val inputFile = s"${testDir}ratings.csv"
-    val itemsFile = s"${testDir}itemsIndex.tsv"
-    val outputFile = s"${testDir}predicted.tsv"
-    val seenFile = s"${testDir}seen.csv"
-
-    val testDirFile = new File(testDir)
-    testDirFile.mkdirs()
-
-    val seenCSV = List(
-      "1,1",
-      "4,1",
-      "1,2",
-      "2,1",
-      "3,1"
-    )
-
-    val jobArgs = Map(
-      "input" -> inputFile,
-      "itemsFile" -> itemsFile,
-      "output" -> outputFile,
-      "appid" -> appid,
-      "engineid" -> engineid,
-      "algoid" -> algoid,
-      "booleanData" -> false,
-      "numRecommendations" -> 5,
-      "nearestN" -> 10,
-      "userSimilarity" -> "LogLikelihoodSimilarity",
-      "weighted" -> false,
-      "minSimilarity" -> 5e-324,
-      "samplingRate" -> 1,
-      "unseenOnly" -> true,
-      "seenFile" -> seenFile,
-      "recommendationTime" -> 0
-    )
-
-    TestUtils.writeToFile(ratingsCSV, inputFile)
-    TestUtils.writeToFile(itemsIndexTSV, itemsFile)
-    TestUtils.writeToFile(seenCSV, seenFile)
-
-    val predictedExpected = List(
-      "1\t[4:2.2805154,3:1.3898838]",
-      "2\t[3:3.5,2:3.0,4:2.5]",
-      "3\t[2:3.5,3:2.559535,4:2.0]",
-      "4\t[2:2.5,3:2.402577,4:2.3898838]"
-    )
-
-    MahoutJob.main(Array(jobName) ++ TestUtils.argMapToArray(jobArgs))
-
-    "generate prediction output correctly" in {
-      val predicted = Source.fromFile(outputFile)
-        .getLines().toList
-
-      predicted must containTheSameElementsAs(predictedExpected)
-    }
-  }
-
-  "KNNUserBasedJob with unseenOnly=true and seenFile and subset itemsIndex" should {
-    val testDir = "/tmp/pio_test/KNNUserBasedJob/unseenOnlytrueSeenFileSubSetItemsIndex/"
-    val inputFile = s"${testDir}ratings.csv"
-    val itemsFile = s"${testDir}itemsIndex.tsv"
-    val outputFile = s"${testDir}predicted.tsv"
-    val seenFile = s"${testDir}seen.csv"
-
-    val testDirFile = new File(testDir)
-    testDirFile.mkdirs()
-
-    val itemsIndexTSV = List(
-      s"1\ti1\tt1,t2\t12345000",
-      s"2\ti2\tt1\t12346000",
-      s"4\ti4\tt3\t12347100"
-    )
-
-    val seenCSV = List(
-      "1,1",
-      "4,1",
-      "1,2",
-      "2,1",
-      "3,1"
-    )
-
-    val jobArgs = Map(
-      "input" -> inputFile,
-      "itemsFile" -> itemsFile,
-      "output" -> outputFile,
-      "appid" -> appid,
-      "engineid" -> engineid,
-      "algoid" -> algoid,
-      "booleanData" -> false,
-      "numRecommendations" -> 5,
-      "nearestN" -> 10,
-      "userSimilarity" -> "LogLikelihoodSimilarity",
-      "weighted" -> false,
-      "minSimilarity" -> 5e-324,
-      "samplingRate" -> 1,
-      "unseenOnly" -> true,
-      "seenFile" -> seenFile,
-      "recommendationTime" -> 0
-    )
-
-    TestUtils.writeToFile(ratingsCSV, inputFile)
-    TestUtils.writeToFile(itemsIndexTSV, itemsFile)
-    TestUtils.writeToFile(seenCSV, seenFile)
-
-    val predictedExpected = List(
-      "1\t[4:2.2805154]",
-      "2\t[2:3.0,4:2.5]",
-      "3\t[2:3.5,4:2.0]",
-      "4\t[2:2.5,4:2.3898838]"
-    )
-
-    MahoutJob.main(Array(jobName) ++ TestUtils.argMapToArray(jobArgs))
-
-    "generate prediction output correctly" in {
-      val predicted = Source.fromFile(outputFile)
-        .getLines().toList
-
-      predicted must containTheSameElementsAs(predictedExpected)
-    }
-  }
-
-  "KNNUserBasedJob with unseenOnly=true and empty seenFile" should {
-    val testDir = "/tmp/pio_test/KNNUserBasedJob/unseenOnlytrueEmptySeenFile/"
-    val inputFile = s"${testDir}ratings.csv"
-    val itemsFile = s"${testDir}itemsIndex.tsv"
-    val outputFile = s"${testDir}predicted.tsv"
-    val seenFile = s"${testDir}seen.csv"
-
-    val testDirFile = new File(testDir)
-    testDirFile.mkdirs()
-
-    val seenCSV = List()
-
-    val jobArgs = Map(
-      "input" -> inputFile,
-      "itemsFile" -> itemsFile,
-      "output" -> outputFile,
-      "appid" -> appid,
-      "engineid" -> engineid,
-      "algoid" -> algoid,
-      "booleanData" -> false,
-      "numRecommendations" -> 5,
-      "nearestN" -> 10,
-      "userSimilarity" -> "LogLikelihoodSimilarity",
-      "weighted" -> false,
-      "minSimilarity" -> 5e-324,
-      "samplingRate" -> 1,
-      "unseenOnly" -> true,
-      "seenFile" -> seenFile,
-      "recommendationTime" -> 0
-    )
-
-    TestUtils.writeToFile(ratingsCSV, inputFile)
-    TestUtils.writeToFile(itemsIndexTSV, itemsFile)
-    TestUtils.writeToFile(seenCSV, seenFile)
-
-    val predictedExpected = List(
-      "1\t[2:3.0,4:2.2805154,3:1.3898838]",
-      "2\t[1:4.0,3:3.5,2:3.0,4:2.5]",
-      "3\t[1:4.0,2:3.5,3:2.559535,4:2.0]",
-      "4\t[2:2.5,3:2.402577,4:2.3898838]"
-    )
-
-    MahoutJob.main(Array(jobName) ++ TestUtils.argMapToArray(jobArgs))
-
-    "generate prediction output correctly" in {
-      val predicted = Source.fromFile(outputFile)
-        .getLines().toList
-
-      predicted must containTheSameElementsAs(predictedExpected)
-    }
-  }
-
-}
diff --git a/process/engines/itemrec/algorithms/scala/mahout/src/test/scala/io/prediction/algorithms/mahout/itemrec/svdplusplus/SVDPlusPlusJobSpec.scala b/process/engines/itemrec/algorithms/scala/mahout/src/test/scala/io/prediction/algorithms/mahout/itemrec/svdplusplus/SVDPlusPlusJobSpec.scala
deleted file mode 100644
index a0962d2..0000000
--- a/process/engines/itemrec/algorithms/scala/mahout/src/test/scala/io/prediction/algorithms/mahout/itemrec/svdplusplus/SVDPlusPlusJobSpec.scala
+++ /dev/null
@@ -1,324 +0,0 @@
-package io.prediction.algorithms.mahout.itemrec.svdplusplus
-
-import org.specs2.mutable._
-import com.github.nscala_time.time.Imports._
-import scala.io.Source
-import java.io.File
-import java.io.FileWriter
-import java.io.BufferedWriter
-
-import io.prediction.algorithms.mahout.itemrec.MahoutJob
-import io.prediction.algorithms.mahout.itemrec.TestUtils
-
-class SVDPlusPlusJobSpec extends Specification {
-  val ratingsCSV = List(
-    "1,1,3",
-    "4,1,5",
-    "1,2,3",
-    "3,2,2",
-    "4,2,4",
-    "1,3,4",
-    "2,3,4",
-    "3,3,2",
-    "2,4,2",
-    "3,4,3",
-    "4,4,2"
-  )
-
-  val itemsIndexTSV = List(
-    s"1\ti1\tt1,t2\t12345000",
-    s"2\ti2\tt1\t12346000",
-    s"3\ti3\tt2,t3\t12346100",
-    s"4\ti4\tt3\t12347100"
-  )
-
-  val appid = 25
-  val engineid = 31
-  val algoid = 32
-
-  val jobName =
-    "io.prediction.algorithms.mahout.itemrec.svdplusplus.SVDPlusPlusJob"
-
-  def convertToIDSet(rec: String): (String, Set[String]) = {
-    val field = rec.split("\t")
-    val uid = field(0)
-    val data = field(1)
-    val dataLen = data.length
-    val iids = data.take(dataLen - 1).tail.split(",").toList
-      .map { ratingData =>
-        val ratingDataArray = ratingData.split(":")
-        ratingDataArray(0)
-      }.toSet
-    (uid, iids)
-  }
-
-  "SVDPlusPlusJob with unseenOnly=false" should {
-    val testDir = "/tmp/pio_test/SVDPlusPlusJob/unseenOnlyfalse/"
-    val inputFile = s"${testDir}ratings.csv"
-    val itemsFile = s"${testDir}itemsIndex.tsv"
-    val outputFile = s"${testDir}predicted.tsv"
-
-    val testDirFile = new File(testDir)
-    testDirFile.mkdirs()
-
-    val jobArgs = Map(
-      "input" -> inputFile,
-      "itemsFile" -> itemsFile,
-      "output" -> outputFile,
-      "appid" -> appid,
-      "engineid" -> engineid,
-      "algoid" -> algoid,
-      "numRecommendations" -> 5,
-      "numFeatures" -> 3,
-      "learningRate" -> 0.01,
-      "preventOverfitting" -> 0.1,
-      "randomNoise" -> 0.01,
-      "numIterations" -> 3,
-      "learningRateDecay" -> 1,
-      "unseenOnly" -> false,
-      "recommendationTime" -> DateTime.now.millis
-    )
-
-    TestUtils.writeToFile(ratingsCSV, inputFile)
-    TestUtils.writeToFile(itemsIndexTSV, itemsFile)
-
-    MahoutJob.main(Array(jobName) ++ TestUtils.argMapToArray(jobArgs))
-
-    // NOTE: don't check predicted score
-    val predictedExp = List(
-      ("1", Set("1", "2", "3", "4")),
-      ("2", Set("1", "2", "3", "4")),
-      ("3", Set("1", "2", "3", "4")),
-      ("4", Set("1", "2", "3", "4"))
-    )
-
-    "generate prediction output correctly" in {
-      val predicted = Source.fromFile(outputFile).getLines().toList
-      predicted.map(convertToIDSet(_)) must
-        containTheSameElementsAs(predictedExp)
-    }
-  }
-
-  "SVDPlusPlusJob with unseenOnly=false and subset itemsIndex" should {
-    val testDir = "/tmp/pio_test/SVDPlusPlusJob/unseenOnlyfalseSubSetItemsIndex/"
-    val inputFile = s"${testDir}ratings.csv"
-    val itemsFile = s"${testDir}itemsIndex.tsv"
-    val outputFile = s"${testDir}predicted.tsv"
-
-    val itemsIndexTSV = List(
-      s"2\ti2\tt1\t12346000",
-      s"4\ti4\tt3\t12347100"
-    )
-
-    val testDirFile = new File(testDir)
-    testDirFile.mkdirs()
-
-    val jobArgs = Map(
-      "input" -> inputFile,
-      "itemsFile" -> itemsFile,
-      "output" -> outputFile,
-      "appid" -> appid,
-      "engineid" -> engineid,
-      "algoid" -> algoid,
-      "numRecommendations" -> 5,
-      "numFeatures" -> 3,
-      "learningRate" -> 0.01,
-      "preventOverfitting" -> 0.1,
-      "randomNoise" -> 0.01,
-      "numIterations" -> 3,
-      "learningRateDecay" -> 1,
-      "unseenOnly" -> false,
-      "recommendationTime" -> DateTime.now.millis
-    )
-
-    TestUtils.writeToFile(ratingsCSV, inputFile)
-    TestUtils.writeToFile(itemsIndexTSV, itemsFile)
-
-    MahoutJob.main(Array(jobName) ++ TestUtils.argMapToArray(jobArgs))
-
-    // NOTE: don't check predicted score
-    val predictedExp = List(
-      ("1", Set("2", "4")),
-      ("2", Set("2", "4")),
-      ("3", Set("2", "4")),
-      ("4", Set("2", "4"))
-    )
-
-    "generate prediction output correctly" in {
-      val predicted = Source.fromFile(outputFile).getLines().toList
-      predicted.map(convertToIDSet(_)) must
-        containTheSameElementsAs(predictedExp)
-    }
-  }
-
-  "SVDPlusPlusJob with unseenOnly=true" should {
-    val testDir = "/tmp/pio_test/SVDPlusPlusJob/unseenOnlytrue/"
-    val inputFile = s"${testDir}ratings.csv"
-    val itemsFile = s"${testDir}itemsIndex.tsv"
-    val outputFile = s"${testDir}predicted.tsv"
-
-    val testDirFile = new File(testDir)
-    testDirFile.mkdirs()
-
-    val jobArgs = Map(
-      "input" -> inputFile,
-      "itemsFile" -> itemsFile,
-      "output" -> outputFile,
-      "appid" -> appid,
-      "engineid" -> engineid,
-      "algoid" -> algoid,
-      "numRecommendations" -> 5,
-      "numFeatures" -> 3,
-      "learningRate" -> 0.01,
-      "preventOverfitting" -> 0.1,
-      "randomNoise" -> 0.01,
-      "numIterations" -> 3,
-      "learningRateDecay" -> 1,
-      "unseenOnly" -> true,
-      "recommendationTime" -> DateTime.now.millis
-    )
-
-    TestUtils.writeToFile(ratingsCSV, inputFile)
-    TestUtils.writeToFile(itemsIndexTSV, itemsFile)
-
-    MahoutJob.main(Array(jobName) ++ TestUtils.argMapToArray(jobArgs))
-
-    // NOTE: don't check predicted score
-    val predictedExp = List(
-      ("1", Set("4")),
-      ("2", Set("1", "2")),
-      ("3", Set("1")),
-      ("4", Set("3"))
-    )
-
-    "generate prediction output correctly" in {
-      val predicted = Source.fromFile(outputFile).getLines().toList
-      predicted.map(convertToIDSet(_)) must
-        containTheSameElementsAs(predictedExp)
-    }
-
-  }
-
-  "SVDPlusPlusJob with unseenOnly=true and seenFile" should {
-    val testDir = "/tmp/pio_test/SVDPlusPlusJob/unseenOnlytrueSeenFile/"
-    val inputFile = s"${testDir}ratings.csv"
-    val itemsFile = s"${testDir}itemsIndex.tsv"
-    val outputFile = s"${testDir}predicted.tsv"
-    val seenFile = s"${testDir}seen.csv"
-
-    val testDirFile = new File(testDir)
-    testDirFile.mkdirs()
-
-    val seenCSV = List(
-      "1,1",
-      "4,1",
-      "1,2"
-    )
-
-    val jobArgs = Map(
-      "input" -> inputFile,
-      "itemsFile" -> itemsFile,
-      "output" -> outputFile,
-      "appid" -> appid,
-      "engineid" -> engineid,
-      "algoid" -> algoid,
-      "numRecommendations" -> 5,
-      "numFeatures" -> 3,
-      "learningRate" -> 0.01,
-      "preventOverfitting" -> 0.1,
-      "randomNoise" -> 0.01,
-      "numIterations" -> 3,
-      "learningRateDecay" -> 1,
-      "unseenOnly" -> true,
-      "seenFile" -> seenFile,
-      "recommendationTime" -> DateTime.now.millis
-    )
-
-    TestUtils.writeToFile(ratingsCSV, inputFile)
-    TestUtils.writeToFile(itemsIndexTSV, itemsFile)
-    TestUtils.writeToFile(seenCSV, seenFile)
-
-    MahoutJob.main(Array(jobName) ++ TestUtils.argMapToArray(jobArgs))
-
-    // NOTE: don't check predicted score
-    val predictedExp = List(
-      ("1", Set("3", "4")),
-      ("2", Set("1", "2", "3", "4")),
-      ("3", Set("1", "2", "3", "4")),
-      ("4", Set("2", "3", "4"))
-    )
-
-    "generate prediction output correctly" in {
-      val predicted = Source.fromFile(outputFile).getLines().toList
-      predicted.map(convertToIDSet(_)) must
-        containTheSameElementsAs(predictedExp)
-    }
-
-  }
-
-  "SVDPlusPlusJob with unseenOnly=true and seenFile and subset itemdIndex" should {
-    val testDir = "/tmp/pio_test/SVDPlusPlusJob/unseenOnlytrueSeenFileSubSetItemsIndex/"
-    val inputFile = s"${testDir}ratings.csv"
-    val itemsFile = s"${testDir}itemsIndex.tsv"
-    val outputFile = s"${testDir}predicted.tsv"
-    val seenFile = s"${testDir}seen.csv"
-
-    val testDirFile = new File(testDir)
-    testDirFile.mkdirs()
-
-    val seenCSV = List(
-      "1,1",
-      "4,1",
-      "1,2"
-    )
-
-    val itemsIndexTSV = List(
-      s"1\ti1\tt1,t2\t12345000",
-      s"2\ti2\tt1\t12346000",
-      s"4\ti4\tt3\t12347100"
-    )
-
-    val jobArgs = Map(
-      "input" -> inputFile,
-      "itemsFile" -> itemsFile,
-      "output" -> outputFile,
-      "appid" -> appid,
-      "engineid" -> engineid,
-      "algoid" -> algoid,
-      "numRecommendations" -> 5,
-      "numFeatures" -> 3,
-      "learningRate" -> 0.01,
-      "preventOverfitting" -> 0.1,
-      "randomNoise" -> 0.01,
-      "numIterations" -> 3,
-      "learningRateDecay" -> 1,
-      "unseenOnly" -> true,
-      "seenFile" -> seenFile,
-      "recommendationTime" -> DateTime.now.millis
-    )
-
-    TestUtils.writeToFile(ratingsCSV, inputFile)
-    TestUtils.writeToFile(itemsIndexTSV, itemsFile)
-    TestUtils.writeToFile(seenCSV, seenFile)
-
-    MahoutJob.main(Array(jobName) ++ TestUtils.argMapToArray(jobArgs))
-
-    // NOTE: don't check predicted score
-    val predictedExp = List(
-      ("1", Set("4")),
-      ("2", Set("1", "2", "4")),
-      ("3", Set("1", "2", "4")),
-      ("4", Set("2", "4"))
-    )
-
-    "generate prediction output correctly" in {
-      val predicted = Source.fromFile(outputFile).getLines().toList
-      predicted.map(convertToIDSet(_)) must
-        containTheSameElementsAs(predictedExp)
-    }
-
-  }
-
-  // TODO: add more tests...
-
-}
diff --git a/process/engines/itemrec/evaluations/hadoop/scalding/build.sbt b/process/engines/itemrec/evaluations/hadoop/scalding/build.sbt
deleted file mode 100644
index 8ab4fb5..0000000
--- a/process/engines/itemrec/evaluations/hadoop/scalding/build.sbt
+++ /dev/null
@@ -1,38 +0,0 @@
-import AssemblyKeys._
-
-name := "predictionio-process-itemrec-evaluations-hadoop-scalding"
-
-packageOptions += Package.ManifestAttributes(java.util.jar.Attributes.Name.MAIN_CLASS -> "com.twitter.scalding.Tool")
-
-parallelExecution in Test := false
-
-resolvers ++= Seq("Concurrent Maven Repo" at "http://conjars.org/repo")
-
-assemblySettings
-
-test in assembly := {}
-
-assembleArtifact in packageScala := true
-
-excludedJars in assembly <<= (fullClasspath in assembly) map { cp =>
-  val excludes = Set(
-    "jsp-api-2.1-6.1.14.jar",
-    "jsp-2.1-6.1.14.jar",
-    "jasper-compiler-5.5.12.jar",
-    "janino-2.5.16.jar",
-    "minlog-1.2.jar",
-    "hadoop-core-1.0.4.jar")
-  cp filter { jar => excludes(jar.data.getName)}
-}
-
-// Some of these files have duplicates, let's ignore:
-mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) =>
-  {
-    case s if s.endsWith(".class") => MergeStrategy.last
-    case s if s.endsWith("project.clj") => MergeStrategy.concat
-    case s if s.endsWith(".html") => MergeStrategy.last
-    case s if s.endsWith(".properties") => MergeStrategy.last
-    case s if s.endsWith(".xml") => MergeStrategy.last
-    case x => old(x)
-  }
-}
diff --git a/process/engines/itemrec/evaluations/hadoop/scalding/metrics/map/src/main/scala/io/prediction/metrics/scalding/itemrec/map/MAPAtK.scala b/process/engines/itemrec/evaluations/hadoop/scalding/metrics/map/src/main/scala/io/prediction/metrics/scalding/itemrec/map/MAPAtK.scala
deleted file mode 100644
index 6dd9414..0000000
--- a/process/engines/itemrec/evaluations/hadoop/scalding/metrics/map/src/main/scala/io/prediction/metrics/scalding/itemrec/map/MAPAtK.scala
+++ /dev/null
@@ -1,207 +0,0 @@
-package io.prediction.metrics.scalding.itemrec.map
-
-import com.twitter.scalding._
-
-import cascading.pipe.joiner.LeftJoin
-import cascading.pipe.joiner.RightJoin
-
-import io.prediction.commons.filepath.OfflineMetricFile
-import io.prediction.commons.scalding.settings.OfflineEvalResults
-
-/**
- * Source:
- *   relevantItems.tsv eg  u0   i0,i1,i2
- *   topKItems.tsv  eg.  u0  i1,i4,i5
- *
- * Sink:
- *   offlineEvalResults DB
- *   averagePrecision.tsv  eg.  u0  0.03
- *
- *
- * Description:
- *   Calculate Mean Average Precision @ k score
- *
- * Required args:
- * --dbType: <string> The OfflineEvalResults DB Type (eg. mongodb) (see --dbHost, --dbPort)
- * --dbName: <string>
- *
- * --hdfsRoot: <string>. Root directory of the HDFS
- *
- * --appid: <int>
- * --engineid: <int>
- * --evalid: <int>
- * --metricid: <int>
- * --algoid: <int>
- * --iteration: <int>
- * --splitset: <string>
- *
- * --kParam: <int>
- *
- * Optional args:
- * --dbHost: <string> (eg. "127.0.0.1")
- * --dbPort: <int> (eg. 27017)
- *
- * --debug: <String>. "test" - for testing purpose
- *
- * Example:
- * scald.rb --hdfs-local io.prediction.metrics.scalding.itemrec.map.MAPAtK --dbType mongodb --dbName predictionio --dbHost 127.0.0.1 --dbPort 27017 --hdfsRoot hdfs/predictionio/ --appid 34 --engineid 3 --evalid 15 --metricid 10 --algoid 9 --kParam 30
- */
-class MAPAtK(args: Args) extends Job(args) {
-
-  /**
-   * parse args
-   */
-  val dbTypeArg = args("dbType")
-  val dbNameArg = args("dbName")
-  val dbHostArg = args.list("dbHost")
-  val dbPortArg = args.list("dbPort") map (x => x.toInt)
-
-  val hdfsRootArg = args("hdfsRoot")
-
-  val appidArg = args("appid").toInt
-  val engineidArg = args("engineid").toInt
-  val evalidArg = args("evalid").toInt
-  val metricidArg = args("metricid").toInt
-  val algoidArg = args("algoid").toInt
-  //val iterationArg = args("iteration").toInt
-  val iterationArg = args.getOrElse("iteration", "1").toInt
-  val splitsetArg = args.getOrElse("splitset", "")
-
-  val kParamArg = args("kParam").toInt
-
-  val debugArg = args.list("debug")
-  val DEBUG_TEST = debugArg.contains("test") // test mode
-
-  /**
-   * get Sources
-   */
-  val relevantItems = Tsv(OfflineMetricFile(hdfsRootArg, appidArg, engineidArg, evalidArg, metricidArg, algoidArg, "relevantItems.tsv")).read
-    .mapTo((0, 1) -> ('uidTest, 'relevantList)) { fields: (String, String) =>
-      val (uidTest, relevantList) = fields
-
-      (uidTest, relevantList.split(",").toList)
-    }
-
-  val topKItems = Tsv(OfflineMetricFile(hdfsRootArg, appidArg, engineidArg, evalidArg, metricidArg, algoidArg, "topKItems.tsv")).read
-    .mapTo((0, 1) -> ('uid, 'topList)) { fields: (String, String) =>
-      val (uid, topList) = fields
-      (uid, topList.split(",").toList)
-    }
-
-  /**
-   * sink
-   */
-
-  val averagePrecisionSink = Tsv(OfflineMetricFile(hdfsRootArg, appidArg, engineidArg, evalidArg, metricidArg, algoidArg, "averagePrecision.tsv"))
-
-  val offlineEvalResultsSink = OfflineEvalResults(dbType = dbTypeArg, dbName = dbNameArg, dbHost = dbHostArg, dbPort = dbPortArg)
-
-  /**
-   * computation
-   */
-
-  // for each user, calculate the AP based on relvantList and topList
-
-  // use RightJoin, so that if there is no topList but there is relevantList, set AP to 0.
-  // if the user has no relevantList in relevantItems, ignore this user.
-  val averagePrecision = topKItems.joinWithSmaller('uid -> 'uidTest, relevantItems, joiner = new RightJoin)
-    .rename(('uid, 'topList) -> ('uidX, 'topListX))
-    .map(('uidX, 'topListX, 'uidTest) -> ('uid, 'topList)) { fields: (String, List[String], String) =>
-      val (uidX, topListX, uidTest) = fields
-
-      if (uidX == null)
-        (uidTest, List(""))
-      else
-        (uidX, topListX)
-    }
-    .map(('topList, 'relevantList) -> ('avgPreAtK, 'key, 'zeroAP, 'numOfHits)) { fields: (List[String], List[String]) =>
-      val (topList, relevantList) = fields
-
-      val (ap, numOfHits) = averagePrecisionAtK(kParamArg, topList, relevantList)
-      val zeroAP = if (ap == 0) 1 else 0
-
-      (ap, 1, zeroAP, numOfHits)
-    }
-
-  averagePrecision
-    .mapTo(('uid, 'topList, 'relevantList, 'avgPreAtK, 'numOfHits) -> ('uid, 'topList, 'relevantList, 'avgPreAtK, 'numOfHits)) {
-      fields: (String, List[String], List[String], Double, Int) =>
-        val (uid, topList, relevantList, avgPreAtK, numOfHits) = fields
-
-        (uid, topList.mkString(","), relevantList.mkString(","), avgPreAtK, numOfHits)
-    }
-
-  averagePrecision.project('uid, 'avgPreAtK, 'numOfHits)
-    .write(averagePrecisionSink)
-
-  val results = averagePrecision.groupBy('key) {
-    _
-      .size('num) // how many users in total
-      .sum('avgPreAtK -> 'avgPreAtKSum)
-      .sum('zeroAP -> 'numOfZeroAP)
-  }
-    .mapTo(('num, 'avgPreAtKSum, 'numOfZeroAP) -> ('evalid, 'metricid, 'algoid, 'score, 'iteration, 'splitset, 'num, 'numOfZeroAP)) { fields: (Int, Double, Int) =>
-
-      val (num, avgPreAtKSum, numOfZeroAP) = fields
-
-      val meanAveragePrecision = avgPreAtKSum / num
-
-      (evalidArg, metricidArg, algoidArg, meanAveragePrecision, iterationArg, splitsetArg, num, numOfZeroAP)
-    }
-
-  results.then(offlineEvalResultsSink.writeData('evalid, 'metricid, 'algoid, 'score, 'iteration, 'splitset) _)
-
-  /**
-   * Calculate the average precision @ k
-   *
-   * ap@k = sum(P(i)/min(m, k)) wher i=1 to k
-   * k is number of prediction to be retrieved.
-   * P(i) is the precision at position i of the top-K list
-   *    if the item at position i is relevant, then P(i) = (the number of releavent items up to that position in the top-k list / position)
-   *    if the item at position i is not relevant, then P(i)=0
-   * m is the number of relevant items for this user.
-   *
-   * return:
-   *   averagePrecision (Double)
-   *   numOfHits (Int)
-   */
-  def averagePrecisionAtK(k: Int, predictedItems: List[String], relevantItems: List[String]): (Double, Int) = {
-
-    // supposedly the predictedItems.size should match k
-    // NOTE: what if predictedItems is less than k? use the avaiable items as k.
-    require((predictedItems.size <= k), "The size of predicted Items list should be <= k.")
-    val n = scala.math.min(predictedItems.size, k)
-
-    // find if each element in the predictedItems is one of the relevant items
-    // if so, map to 1. else map to 0
-    // (0, 1, 0, 1, 1, 0, 0)
-    val relevantBinary: List[Int] = predictedItems.map { x => if (relevantItems.contains(x)) 1 else 0 }
-    val numOfHits: Int = relevantBinary.sum
-
-    // prepare the data for AP calculation.
-    // take the relevantBinary List and map each element to tuple (num, index)
-    // where num is number of 1s up to that position if the element is 1 and 0 if the elemtn is 0.
-    // index is the position index of the element starting from 1.
-    def prepareAPData(org: List[Int], accum: Int, index: Int): List[(Int, Int)] = {
-      if (org.isEmpty)
-        List()
-      else {
-        val newAccum = accum + org.head
-        val num = if (org.head == 1) newAccum else 0
-        val element = (num -> index)
-        List(element) ++ prepareAPData(org.tail, newAccum, index + 1)
-      }
-    }
-
-    val averagePrecisionData = prepareAPData(relevantBinary, 0, 1)
-
-    val apDenom = scala.math.min(n, relevantItems.size)
-
-    // NOTE: if relevantItems.size is 0, the averagePrecision is 0
-    val averagePrecision = if (apDenom == 0) 0 else
-      ((averagePrecisionData.map { x => if (x._1 != 0) (x._1.toDouble / x._2) else 0 }.sum) / apDenom)
-
-    (averagePrecision, numOfHits)
-  }
-
-}
diff --git a/process/engines/itemrec/evaluations/hadoop/scalding/metrics/map/src/main/scala/io/prediction/metrics/scalding/itemrec/map/MAPAtKDataPreparator.scala b/process/engines/itemrec/evaluations/hadoop/scalding/metrics/map/src/main/scala/io/prediction/metrics/scalding/itemrec/map/MAPAtKDataPreparator.scala
deleted file mode 100644
index 3683e2c..0000000
--- a/process/engines/itemrec/evaluations/hadoop/scalding/metrics/map/src/main/scala/io/prediction/metrics/scalding/itemrec/map/MAPAtKDataPreparator.scala
+++ /dev/null
@@ -1,169 +0,0 @@
-package io.prediction.metrics.scalding.itemrec.map
-
-import com.twitter.scalding._
-
-import io.prediction.commons.filepath.OfflineMetricFile
-import io.prediction.commons.scalding.appdata.U2iActions
-//import io.prediction.commons.scalding.modeldata.ItemRecScores
-
-/**
- * Source:
- *   Test set u2iActions.
- *
- * Sink:
- *   relevantItems.tsv eg  u0   i0,i1,i2
- *
- * Description:
- *   Generate relevantItems for MAP@k
- *
- * Required args:
- * --test_dbType: <string> test_appdata DB type (eg. mongodb)
- * --test_dbName: <string>
- *
- * --training_dbType: <string> training_appdata DB type
- * --training_dbName: <string>
- *
- * --modeldata_dbType: <string> modeldata DB type
- * --modeldata_dbName: <string>
- *
- * --hdfsRoot: <string>. Root directory of the HDFS
- *
- * --appid: <int>
- * --engineid: <int>
- * --evalid: <int>
- * --metricid: <int>
- * --algoid: <int>
- *
- * --kParam: <int>
- * --goalParam: <string> ("view", "conversion", "like", "rate3", "rate4", "rate5)
- *
- * Optional args:
- * --test_dbHost: <string> (eg. "127.0.0.1")
- * --test_dbPort: <int> (eg. 27017)
- *
- * --training_dbHost: <string>
- * --training_dbPort: <int>
- *
- * --modeldata_dbHost: <string>
- * --modeldata_dbPort <int>
- *
- * --debug: <String>. "test" - for testing purpose
- *
- * Example:
- * scald.rb --hdfs-local io.prediction.metrics.scalding.itemrec.map.MAPAtKDataPreparator --test_dbType mongodb --test_dbName test_appdata --test_dbHost 127.0.0.1 --test_dbPort 27017 --training_dbType mongodb --training_dbName training_appdata --training_dbHost 127.0.0.1 --training_dbPort 27017 --modeldata_dbType file --modeldata_dbName modeldata_path/ --hdfsRoot hdfs/predictionio/ --appid 34 --engineid 3 --evalid 15 --metricid 10 --algoid 9 --kParam 30 --goalParam rate3
- *
- */
-class MAPAtKDataPreparator(args: Args) extends Job(args) {
-
-  /**
-   * parse arguments
-   */
-  val test_dbTypeArg = args("test_dbType")
-  val test_dbNameArg = args("test_dbName")
-  val test_dbHostArg = args.list("test_dbHost")
-  val test_dbPortArg = args.list("test_dbPort") map (x => x.toInt)
-
-  val training_dbTypeArg = args("training_dbType")
-  val training_dbNameArg = args("training_dbName")
-  val training_dbHostArg = args.list("training_dbHost")
-  val training_dbPortArg = args.list("training_dbPort") map (x => x.toInt)
-
-  val modeldata_dbTypeArg = args("modeldata_dbType")
-  val modeldata_dbNameArg = args("modeldata_dbName")
-  val modeldata_dbHostArg = args.list("modeldata_dbHost")
-  val modeldata_dbPortArg = args.list("modeldata_dbPort") map (x => x.toInt)
-
-  val hdfsRootArg = args("hdfsRoot")
-
-  val appidArg = args("appid").toInt
-  val engineidArg = args("engineid").toInt
-  val evalidArg = args("evalid").toInt
-  val metricidArg = args("metricid").toInt
-  val algoidArg = args("algoid").toInt
-
-  val GOAL_VIEW: String = "view"
-  val GOAL_CONVERSION: String = "conversion"
-  val GOAL_LIKE: String = "like"
-  val GOAL_RATE3: String = "rate3"
-  val GOAL_RATE4: String = "rate4"
-  val GOAL_RATE5: String = "rate5"
-  val GOAL_ARG_LIST: List[String] = List(GOAL_VIEW, GOAL_CONVERSION, GOAL_LIKE, GOAL_RATE3, GOAL_RATE4, GOAL_RATE5)
-
-  val goalParamArg = args("goalParam")
-
-  require(GOAL_ARG_LIST.contains(goalParamArg), "goalParam " + goalParamArg + " is not valid.")
-
-  val kParamArg = args("kParam").toInt
-
-  /**
-   * constants
-   */
-  final val ACTION_RATE = "rate"
-  final val ACTION_LIKE = "like"
-  final val ACTION_DISLIKE = "dislike"
-  final val ACTION_VIEW = "view"
-  //final val ACTION_VIEWDETAILS = "viewDetails"
-  final val ACTION_CONVERSION = "conversion"
-
-  /**
-   * source
-   */
-  /*val trainingU2i = U2iActions(appId=evalidArg,
-      dbType=training_dbTypeArg, dbName=training_dbNameArg, dbHost=training_dbHostArg, dbPort=training_dbPortArg).readData('actionTrain, 'uidTrain, 'iidTrain, 'tTrain, 'vTrain)*/
-
-  val testU2i = U2iActions(appId = evalidArg,
-    dbType = test_dbTypeArg, dbName = test_dbNameArg, dbHost = test_dbHostArg, dbPort = test_dbPortArg).readData('actionTest, 'uidTest, 'iidTest, 'tTest, 'vTest)
-
-  /**
-   * computation
-   */
-  // for each user, get a list of items which match the goalParam
-  // TODO: filter out items appeared in trainingU2i?
-  val testSetRelevant = testU2i
-    .filter('actionTest, 'vTest) { fields: (String, Option[String]) =>
-      val (action, v) = fields
-
-      val cond: Boolean = goalParamArg match {
-        case GOAL_VIEW => (action == ACTION_VIEW)
-        case GOAL_CONVERSION => (action == ACTION_CONVERSION)
-        case GOAL_LIKE => (action == ACTION_LIKE)
-        case GOAL_RATE3 => try {
-          (action == ACTION_RATE) && (v.get.toInt >= 3)
-        } catch {
-          case e: Exception => {
-            assert(false, s"Failed to convert v field ${v} to int. Exception:" + e)
-            false
-          }
-        }
-        case GOAL_RATE4 => try {
-          (action == ACTION_RATE) && (v.get.toInt >= 4)
-        } catch {
-          case e: Exception => {
-            assert(false, s"Failed to convert v field ${v} to int. Exception:" + e)
-            false
-          }
-        }
-        case GOAL_RATE5 => try {
-          (action == ACTION_RATE) && (v.get.toInt >= 5)
-        } catch {
-          case e: Exception => {
-            assert(false, s"Failed to convert v field ${v} to int. Exception:" + e)
-            false
-          }
-        }
-        case _ => {
-          assert(false, "Invalid goalParam " + goalParamArg + ".")
-          false
-        }
-      }
-      cond
-    }
-    .groupBy('uidTest) { _.toList[String]('iidTest -> 'relevantList) }
-    .mapTo(('uidTest, 'relevantList) -> ('uidTest, 'relevantList)) { fields: (String, List[String]) =>
-      val (uidTest, relevantList) = fields
-
-      (uidTest, relevantList.mkString(","))
-    }
-    .write(Tsv(OfflineMetricFile(hdfsRootArg, appidArg, engineidArg, evalidArg, metricidArg, algoidArg, "relevantItems.tsv")))
-
-}
diff --git a/process/engines/itemrec/evaluations/hadoop/scalding/metrics/map/src/test/scala/io/prediction/metrics/scalding/itemrec/map/MAPAtKDataPreparatorTest.scala b/process/engines/itemrec/evaluations/hadoop/scalding/metrics/map/src/test/scala/io/prediction/metrics/scalding/itemrec/map/MAPAtKDataPreparatorTest.scala
deleted file mode 100644
index 923b3d1..0000000
--- a/process/engines/itemrec/evaluations/hadoop/scalding/metrics/map/src/test/scala/io/prediction/metrics/scalding/itemrec/map/MAPAtKDataPreparatorTest.scala
+++ /dev/null
@@ -1,154 +0,0 @@
-package io.prediction.metrics.scalding.itemrec.map
-
-import org.specs2.mutable._
-
-import com.twitter.scalding._
-
-import io.prediction.commons.filepath.OfflineMetricFile
-import io.prediction.commons.scalding.appdata.U2iActions
-
-class MAPAtKDataPreparatorTest extends Specification with TupleConversions {
-
-  val Rate = "rate"
-  val Like = "like"
-  val Dislike = "dislike"
-  val View = "view"
-  //val ViewDetails = "viewDetails"
-  val Conversion = "conversion"
-
-  def test(params: Map[String, String],
-    testU2i: List[(String, String, String, String, String)],
-    relevantItems: List[(String, String)] // List(("u0", "i0,i1,i2"), ("u1", "i0,i1,i2"))
-    ) = {
-
-    val test_dbType = "file"
-    val test_dbName = "testsetpath/"
-    val test_dbHost = Seq()
-    val test_dbPort = Seq()
-
-    val training_dbType = "file"
-    val training_dbName = "trainingsetpath/"
-    val training_dbHost = Seq()
-    val training_dbPort = Seq()
-
-    val modeldata_dbType = "file"
-    val modeldata_dbName = "modeldatapath/"
-    val modeldata_dbHost = Seq()
-    val modeldata_dbPort = Seq()
-
-    val hdfsRoot = "testroot/"
-
-    JobTest("io.prediction.metrics.scalding.itemrec.map.MAPAtKDataPreparator")
-      .arg("test_dbType", test_dbType)
-      .arg("test_dbName", test_dbName)
-      .arg("training_dbType", training_dbType)
-      .arg("training_dbName", training_dbName)
-      .arg("modeldata_dbType", modeldata_dbType)
-      .arg("modeldata_dbName", modeldata_dbName)
-      .arg("hdfsRoot", hdfsRoot)
-      .arg("appid", "2")
-      .arg("engineid", "4")
-      .arg("evalid", "5")
-      .arg("metricid", "6")
-      .arg("algoid", "8")
-      .arg("goalParam", params("goalParam"))
-      .arg("kParam", params("kParam"))
-      .source(U2iActions(appId = 5, dbType = test_dbType, dbName = test_dbName, dbHost = test_dbHost, dbPort = test_dbPort).getSource, testU2i)
-      .sink[(String, String)](Tsv(OfflineMetricFile(hdfsRoot, 2, 4, 5, 6, 8, "relevantItems.tsv"))) { outputBuffer =>
-
-        def sortItems(t: List[(String, String)]): List[(String, List[String])] = {
-          t map (x => (x._1, x._2.split(",").toList.sorted))
-        }
-
-        "correctly generates relevantItems for each user" in {
-          // since DataPrepator may generate relevantItems list in any order
-          // and the order is not important,
-          // sort the list first so we can compare it with expected result.
-          val output = sortItems(outputBuffer.toList)
-          val expected = sortItems(relevantItems)
-
-          println(outputBuffer.toList)
-          //println(output)
-          println(expected)
-
-          output must containTheSameElementsAs(expected)
-
-        }
-      }
-      .run
-      .finish
-  }
-
-  val testU2i = List(
-    // u0
-    (Rate, "u0", "i0", "123450", "4"),
-    (View, "u0", "i1", "123457", "PIO_NONE"),
-    (Dislike, "u0", "i2", "123458", "PIO_NONE"),
-    (View, "u0", "i3", "123459", "PIO_NONE"),
-    (View, "u0", "i7", "123460", "PIO_NONE"),
-    (Rate, "u0", "i8", "123450", "5"),
-
-    // u1
-    (View, "u1", "i0", "123457", "PIO_NONE"),
-    (Conversion, "u1", "i1", "123458", "PIO_NONE"),
-    (Conversion, "u1", "i4", "123457", "PIO_NONE"),
-    (Conversion, "u1", "i5", "123456", "PIO_NONE"),
-    (Rate, "u1", "i7", "123456", "3"),
-    (Rate, "u1", "i8", "123454", "3"),
-    (Rate, "u1", "i9", "123453", "4"),
-
-    // u2
-    (View, "u2", "i3", "123458", "PIO_NONE"),
-    (Conversion, "u2", "i4", "123451", "PIO_NONE"),
-    (Conversion, "u2", "i5", "123452", "PIO_NONE"),
-    (Rate, "u2", "i6", "123452", "5"))
-
-  "itemrec.map MAPAtKDataPreparator with goal = view" should {
-    val params = Map("goalParam" -> "view", "kParam" -> "4")
-    val relevantItems = List(
-      ("u0", "i1,i3,i7"),
-      ("u1", "i0"),
-      ("u2", "i3"))
-
-    test(params, testU2i, relevantItems)
-  }
-
-  "itemrec.map MAPAtKDataPreparator with goal = conversion" should {
-    val params = Map("goalParam" -> "conversion", "kParam" -> "8")
-    val relevantItems = List(
-      ("u1", "i1,i4,i5"),
-      ("u2", "i4,i5"))
-
-    test(params, testU2i, relevantItems)
-  }
-
-  "itemrec.map MAPAtKDataPreparator with goal = rate >= 3" should {
-    val params = Map("goalParam" -> "rate3", "kParam" -> "8")
-    val relevantItems = List(
-      ("u0", "i0,i8"),
-      ("u1", "i7,i8,i9"),
-      ("u2", "i6"))
-
-    test(params, testU2i, relevantItems)
-  }
-
-  "itemrec.map MAPAtKDataPreparator with goal = rate >= 4" should {
-    val params = Map("goalParam" -> "rate4", "kParam" -> "8")
-    val relevantItems = List(
-      ("u0", "i0,i8"),
-      ("u1", "i9"),
-      ("u2", "i6"))
-
-    test(params, testU2i, relevantItems)
-  }
-
-  "itemrec.map MAPAtKDataPreparator with goal = rate >= 5" should {
-    val params = Map("goalParam" -> "rate5", "kParam" -> "8")
-    val relevantItems = List(
-      ("u0", "i8"),
-      ("u2", "i6"))
-
-    test(params, testU2i, relevantItems)
-  }
-
-}
diff --git a/process/engines/itemrec/evaluations/hadoop/scalding/metrics/map/src/test/scala/io/prediction/metrics/scalding/itemrec/map/MAPAtKTest.scala b/process/engines/itemrec/evaluations/hadoop/scalding/metrics/map/src/test/scala/io/prediction/metrics/scalding/itemrec/map/MAPAtKTest.scala
deleted file mode 100644
index 4772b13..0000000
--- a/process/engines/itemrec/evaluations/hadoop/scalding/metrics/map/src/test/scala/io/prediction/metrics/scalding/itemrec/map/MAPAtKTest.scala
+++ /dev/null
@@ -1,101 +0,0 @@
-package io.prediction.metrics.scalding.itemrec.map
-
-import org.specs2.mutable._
-
-import com.twitter.scalding._
-
-import io.prediction.commons.filepath.{ OfflineMetricFile }
-import io.prediction.commons.scalding.settings.OfflineEvalResults
-
-class MAPAtKTest extends Specification with TupleConversions {
-
-  def test(
-    evalid: Int, metricid: Int, algoid: Int, iteration: Int, splitset: String,
-    params: Map[String, String],
-    relevantItems: List[(String, String)],
-    topKItems: List[(String, String)],
-    averagePrecision: List[(String, Double)],
-    meanAveragePrecision: Double) = {
-
-    val dbType = "file"
-    val dbName = "testpath/"
-    val dbHost = Seq()
-    val dbPort = Seq()
-    val hdfsRoot = "testroot/"
-
-    val appid = 20
-    val engineid = 1
-
-    val offlineEvalResults = List((evalid, metricid, algoid, meanAveragePrecision, iteration, splitset))
-
-    JobTest("io.prediction.metrics.scalding.itemrec.map.MAPAtK")
-      .arg("dbType", dbType)
-      .arg("dbName", dbName)
-      .arg("hdfsRoot", hdfsRoot)
-      .arg("appid", appid.toString)
-      .arg("engineid", engineid.toString)
-      .arg("evalid", evalid.toString)
-      .arg("metricid", metricid.toString)
-      .arg("algoid", algoid.toString)
-      .arg("iteration", iteration.toString)
-      .arg("splitset", splitset)
-      .arg("kParam", params("kParam"))
-      .source(Tsv(OfflineMetricFile(hdfsRoot, appid, engineid, evalid, metricid, algoid, "relevantItems.tsv")), relevantItems)
-      .source(Tsv(OfflineMetricFile(hdfsRoot, appid, engineid, evalid, metricid, algoid, "topKItems.tsv")), topKItems)
-      .sink[(String, Double)](Tsv(OfflineMetricFile(hdfsRoot, appid, engineid, evalid, metricid, algoid, "averagePrecision.tsv"))) { outputBuffer =>
-        // only compare double up to 6 decimal places
-        def roundingData(orgList: List[(String, Double)]) = {
-          orgList map { x =>
-            val (t1, t2) = x
-            // NOTE: use HALF_UP mode to avoid error caused by rounding when compare data
-            // (eg. 3.5 vs 3.499999999999, 0.6666666666 vs 0.666666667)
-            (t1, BigDecimal(t2).setScale(6, BigDecimal.RoundingMode.HALF_UP).toDouble)
-          }
-        }
-
-        "correctly calculate Average Precision for each user" in {
-          roundingData(outputBuffer.toList) must containTheSameElementsAs(roundingData(averagePrecision))
-        }
-      }
-      .sink[(Int, Int, Int, Double, Int, String)](OfflineEvalResults(dbType = dbType, dbName = dbName, dbHost = dbHost, dbPort = dbPort).getSource) { outputBuffer =>
-        def roundingData(orgList: List[(Int, Int, Int, Double, Int, String)]) = {
-          orgList map { x =>
-            val (t1, t2, t3, t4, t5, t6) = x
-            // NOTE: use HALF_UP mode to avoid error caused by rounding when compare data
-            // (eg. 3.5 vs 3.499999999999, 0.6666666666 vs 0.666666667)
-            (t1, t2, t3, BigDecimal(t4).setScale(6, BigDecimal.RoundingMode.HALF_UP).toDouble, t5, t6)
-          }
-        }
-        "correctly write MAP@k score into a file" in {
-          roundingData(outputBuffer.toList) must containTheSameElementsAs(roundingData(offlineEvalResults))
-        }
-      }
-      .run
-      .finish
-  }
-
-  "itemrec.map" should {
-    val relevantItems = List(("u0", "i3,i4,i5"), ("u1", "i0,i1"), ("u3", "i0"))
-    val topKItems = List(("u0", "i6,i4,i3,i5,i0"), ("u1", "i1,i4,i5,i0"))
-    val averagePrecision = List(("u0", 0.638888888), ("u1", 0.75), ("u3", 0.0))
-    val meanAveragePrecision = 0.4629629333333
-
-    val params = Map("kParam" -> "5")
-
-    test(2, 3, 4, 11, "",
-      params, relevantItems, topKItems, averagePrecision, meanAveragePrecision)
-  }
-
-  "itemrec.map with different ids" should {
-    val relevantItems = List(("u0", "i3,i4,i5"), ("u1", "i0,i1"), ("u3", "i0"))
-    val topKItems = List(("u0", "i6,i4,i3,i5,i0"), ("u1", "i1,i4,i5,i0"))
-    val averagePrecision = List(("u0", 0.638888888), ("u1", 0.75), ("u3", 0.0))
-    val meanAveragePrecision = 0.4629629333333
-
-    val params = Map("kParam" -> "5")
-
-    test(12, 2, 54, 9, "validation",
-      params, relevantItems, topKItems, averagePrecision, meanAveragePrecision)
-  }
-
-}
diff --git a/process/engines/itemsim/algorithms/hadoop/scalding/build.sbt b/process/engines/itemsim/algorithms/hadoop/scalding/build.sbt
deleted file mode 100644
index c336f82..0000000
--- a/process/engines/itemsim/algorithms/hadoop/scalding/build.sbt
+++ /dev/null
@@ -1,42 +0,0 @@
-import AssemblyKeys._
-
-name := "predictionio-process-itemsim-algorithms-hadoop-scalding"
-
-packageOptions += Package.ManifestAttributes(java.util.jar.Attributes.Name.MAIN_CLASS -> "com.twitter.scalding.Tool")
-
-parallelExecution in Test := false
-
-libraryDependencies ++= Seq(
-  "org.apache.hadoop" % "hadoop-core" % "1.0.4",
-  "com.twitter" %% "scalding-core" % "0.8.6")
-
-resolvers ++= Seq("Concurrent Maven Repo" at "http://conjars.org/repo")
-
-assemblySettings
-
-test in assembly := {}
-
-assembleArtifact in packageScala := true
-
-excludedJars in assembly <<= (fullClasspath in assembly) map { cp =>
-  val excludes = Set(
-    "jsp-api-2.1-6.1.14.jar",
-    "jsp-2.1-6.1.14.jar",
-    "jasper-compiler-5.5.12.jar",
-    "janino-2.5.16.jar",
-    "minlog-1.2.jar",
-    "hadoop-core-1.0.4.jar")
-  cp filter { jar => excludes(jar.data.getName)}
-}
-
-// Some of these files have duplicates, let's ignore:
-mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) =>
-  {
-    case s if s.endsWith(".class") => MergeStrategy.last
-    case s if s.endsWith("project.clj") => MergeStrategy.concat
-    case s if s.endsWith(".html") => MergeStrategy.last
-    case s if s.endsWith(".properties") => MergeStrategy.last
-    case s if s.endsWith(".xml") => MergeStrategy.last
-    case x => old(x)
-  }
-}
diff --git a/process/engines/itemsim/algorithms/hadoop/scalding/itemsimcf/src/main/scala/io/prediction/algorithms/scalding/itemsim/itemsimcf/DataPreparator.scala b/process/engines/itemsim/algorithms/hadoop/scalding/itemsimcf/src/main/scala/io/prediction/algorithms/scalding/itemsim/itemsimcf/DataPreparator.scala
deleted file mode 100644
index e7cc6f2..0000000
--- a/process/engines/itemsim/algorithms/hadoop/scalding/itemsimcf/src/main/scala/io/prediction/algorithms/scalding/itemsim/itemsimcf/DataPreparator.scala
+++ /dev/null
@@ -1,216 +0,0 @@
-package io.prediction.algorithms.scalding.itemsim.itemsimcf
-
-import com.twitter.scalding._
-
-import io.prediction.commons.scalding.appdata.{ Items, U2iActions }
-import io.prediction.commons.filepath.DataFile
-
-/**
- * Source: appdata DB (items, u2iActions)
- * Sink: selectedItems.tsv, ratings.tsv
- * Descripton:
- *   Prepare data for itemsim.itemsimcf algo. Read from appdata DB and store selected items
- *   and ratings into a file.
- *   (appdata store -> DataPreparator -> HDFS)
- *
- * Required args:
- * --dbType: <string> (eg. mongodb) (see --dbHost, --dbPort)
- * --dbName: <string> appdata database name. (eg predictionio_appdata, or predictionio_training_appdata)
- *
- * --hdfsRoot: <string>. Root directory of the HDFS
- *
- * --appid: <int>
- * --engineid: <int>
- * --algoid: <int>
- *
- * --viewParam: <string>. (number 1 to 5, or "ignore")
- * --likeParam: <string>
- * --dislikeParam: <string>
- * --conversionParam: <string>
- * --conflictParam: <string>. (latest/highest/lowest)
- *
- * Optional args:
- * --dbHost: <string> (eg. "127.0.0.1")
- * --dbPort: <int> (eg. 27017)
- *
- * --itypes: <string separated by white space>. eg "--itypes type1 type2". If no --itypes specified, then ALL itypes will be used.
- * --evalid: <int>. Offline Evaluation if evalid is specified
- * --debug: <String>. "test" - for testing purpose
- *
- * Example:
- * Batch:
- * scald.rb --hdfs-local io.prediction.algorithms.scalding.itemsim.itemsimcf.DataPreparator --dbType mongodb --dbName appdata --dbHost 127.0.0.1 --dbPort 27017 --hdfsRoot hdfs/predictionio/ --appid 34 --engineid 3 --algoid 9 --itypes t2 --viewParam 2 --likeParam 5 --dislikeParam 1 --conversionParam 4 --conflictParam latest
- *
- * Offline Eval:
- * scald.rb --hdfs-local io.prediction.algorithms.scalding.itemsim.itemsimcf.DataPreparator --dbType mongodb --dbName training_appdata --dbHost 127.0.0.1 --dbPort 27017 --hdfsRoot hdfs/predictionio/ --appid 34 --engineid 3 --algoid 9 --itypes t2 --viewParam 2 --likeParam 5 --dislikeParam 1 --conversionParam 4 --conflictParam latest --evalid 15
- *
- */
-class DataPreparator(args: Args) extends Job(args) {
-
-  /**
-   * parse arguments
-   */
-  val dbTypeArg = args("dbType")
-  val dbNameArg = args("dbName")
-  val dbHostArg = args.list("dbHost")
-  val dbPortArg = args.list("dbPort") map (x => x.toInt) // becomes Option[Int]
-
-  val hdfsRootArg = args("hdfsRoot")
-
-  val appidArg = args("appid").toInt
-  val engineidArg = args("engineid").toInt
-  val algoidArg = args("algoid").toInt
-  val evalidArg = args.optional("evalid") map (x => x.toInt)
-  val OFFLINE_EVAL = (evalidArg != None) // offline eval mode
-
-  val preItypesArg = args.list("itypes")
-  val itypesArg: Option[List[String]] = if (preItypesArg.mkString(",").length == 0) None else Option(preItypesArg)
-
-  // determine how to map actions to rating values
-  def getActionParam(name: String): Option[Int] = {
-    val actionParam: Option[Int] = args(name) match {
-      case "ignore" => None
-      case x => Some(x.toInt)
-    }
-    actionParam
-  }
-
-  val viewParamArg: Option[Int] = getActionParam("viewParam")
-  val likeParamArg: Option[Int] = getActionParam("likeParam")
-  val dislikeParamArg: Option[Int] = getActionParam("dislikeParam")
-  val conversionParamArg: Option[Int] = getActionParam("conversionParam")
-
-  // When there are conflicting actions, e.g. a user gives an item a rating 5 but later dislikes it,
-  // determine which action will be considered as final preference.
-  final val CONFLICT_LATEST: String = "latest" // use latest action
-  final val CONFLICT_HIGHEST: String = "highest" // use the one with highest score
-  final val CONFLICT_LOWEST: String = "lowest" // use the one with lowest score
-
-  val conflictParamArg: String = args("conflictParam")
-
-  // check if the conflictParam is valid
-  require(List(CONFLICT_LATEST, CONFLICT_HIGHEST, CONFLICT_LOWEST).contains(conflictParamArg), "conflict param " + conflictParamArg + " is not valid.")
-
-  val debugArg = args.list("debug")
-  val DEBUG_TEST = debugArg.contains("test") // test mode
-
-  /**
-   * constants
-   */
-
-  final val ACTION_RATE = "rate"
-  final val ACTION_LIKE = "like"
-  final val ACTION_DISLIKE = "dislike"
-  final val ACTION_VIEW = "view"
-  //final val ACTION_VIEWDETAILS = "viewDetails"
-  final val ACTION_CONVERSION = "conversion"
-
-  /**
-   * source
-   */
-  // get appdata
-  // NOTE: if OFFLINE_EVAL, read from training set, and use evalid as appid when read Items and U2iActions
-  val trainingAppid = if (OFFLINE_EVAL) evalidArg.get else appidArg
-
-  // get items data
-  val items = Items(appId = trainingAppid, itypes = itypesArg,
-    dbType = dbTypeArg, dbName = dbNameArg, dbHost = dbHostArg, dbPort = dbPortArg).readStartEndtime('iidx, 'itypes, 'starttime, 'endtime)
-
-  val u2i = U2iActions(appId = trainingAppid,
-    dbType = dbTypeArg, dbName = dbNameArg, dbHost = dbHostArg, dbPort = dbPortArg).readData('action, 'uid, 'iid, 't, 'v)
-
-  /**
-   * sink
-   */
-
-  // write ratings to a file
-  val ratingsSink = Tsv(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "ratings.tsv"))
-
-  val selectedItemsSink = Tsv(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "selectedItems.tsv"))
-
-  /**
-   * computation
-   */
-  u2i.joinWithSmaller('iid -> 'iidx, items) // only select actions of these items
-    .filter('action, 'v) { fields: (String, Option[String]) =>
-      val (action, v) = fields
-
-      val keepThis: Boolean = action match {
-        case ACTION_RATE => true
-        case ACTION_LIKE => (likeParamArg != None)
-        case ACTION_DISLIKE => (dislikeParamArg != None)
-        case ACTION_VIEW => (viewParamArg != None)
-        case ACTION_CONVERSION => (conversionParamArg != None)
-        case _ => {
-          assert(false, "Action type " + action + " in u2iActions appdata is not supported!")
-          false // all other unsupported actions
-        }
-      }
-      keepThis
-    }
-    .map(('action, 'v, 't) -> ('rating, 'tLong)) { fields: (String, Option[String], String) =>
-      val (action, v, t) = fields
-
-      // convert actions into rating value based on "action" and "v" fields
-      val rating: Int = action match {
-        case ACTION_RATE => try {
-          v.get.toInt
-        } catch {
-          case e: Exception => {
-            assert(false, s"Failed to convert v field ${v} to integer for ${action} action. Exception:" + e)
-            1
-          }
-        }
-        case ACTION_LIKE => likeParamArg.getOrElse {
-          assert(false, "Action type " + action + " should have been filtered out!")
-          1
-        }
-        case ACTION_DISLIKE => dislikeParamArg.getOrElse {
-          assert(false, "Action type " + action + " should have been filtered out!")
-          1
-        }
-        case ACTION_VIEW => viewParamArg.getOrElse {
-          assert(false, "Action type " + action + " should have been filtered out!")
-          1
-        }
-        case ACTION_CONVERSION => conversionParamArg.getOrElse {
-          assert(false, "Action type " + action + " should have been filtered out!")
-          1
-        }
-        case _ => { // all other unsupported actions
-          assert(false, "Action type " + action + " in u2iActions appdata is not supported!")
-          1
-        }
-      }
-
-      (rating, t.toLong)
-    }
-    .then(resolveConflict('uid, 'iid, 'tLong, 'rating, conflictParamArg) _)
-    .project('uid, 'iid, 'rating)
-    .write(ratingsSink)
-
-  // Also store the selected items into DataFile for later model construction usage.
-  items.mapTo(('iidx, 'itypes, 'starttime, 'endtime) -> ('iidx, 'itypes, 'starttime, 'endtime)) { fields: (String, List[String], Long, Option[Long]) =>
-    val (iidx, itypes, starttime, endtime) = fields
-
-    // NOTE: convert List[String] into comma-separated String
-    // NOTE: endtime is optional
-    (iidx, itypes.mkString(","), starttime, endtime.map(_.toString).getOrElse("PIO_NONE"))
-  }.write(selectedItemsSink)
-
-  /**
-   * function to resolve conflicting actions of same uid-iid pair.
-   */
-  def resolveConflict(uidField: Symbol, iidField: Symbol, tfield: Symbol, ratingField: Symbol, conflictSolution: String)(p: RichPipe): RichPipe = {
-
-    // NOTE: sortBy() sort from smallest to largest. use reverse to pick the largest one.
-    val dataPipe = conflictSolution match {
-      case CONFLICT_LATEST => p.groupBy(uidField, iidField) { _.sortBy(tfield).reverse.take(1) } // take latest one (largest t)
-      case CONFLICT_HIGHEST => p.groupBy(uidField, iidField) { _.sortBy(ratingField).reverse.take(1) } // take highest rating
-      case CONFLICT_LOWEST => p.groupBy(uidField, iidField) { _.sortBy(ratingField).take(1) } // take lowest rating
-    }
-
-    dataPipe
-  }
-
-}
diff --git a/process/engines/itemsim/algorithms/hadoop/scalding/itemsimcf/src/main/scala/io/prediction/algorithms/scalding/itemsim/itemsimcf/ItemSimilarity.scala b/process/engines/itemsim/algorithms/hadoop/scalding/itemsimcf/src/main/scala/io/prediction/algorithms/scalding/itemsim/itemsimcf/ItemSimilarity.scala
deleted file mode 100644
index cf549c0..0000000
--- a/process/engines/itemsim/algorithms/hadoop/scalding/itemsimcf/src/main/scala/io/prediction/algorithms/scalding/itemsim/itemsimcf/ItemSimilarity.scala
+++ /dev/null
@@ -1,79 +0,0 @@
-package io.prediction.algorithms.scalding.itemsim.itemsimcf
-
-import com.twitter.scalding._
-
-import cascading.pipe.Pipe
-
-import io.prediction.commons.filepath.{ DataFile, AlgoFile }
-
-/**
- * Source: ratings.tsv
- * Sink: itemSimScores.tsv
- * Descripton:
- *   Compute item similarity score.
- *
- * Required args:
- * --hdfsRoot: <string>. Root directory of the HDFS
- *
- * --appid: <int>
- * --engineid: <int>
- * --algoid: <int>
- *
- * --measureParam: <string>. distance measurement function. select one of "correl", "cosine", "jaccard"
- * --priorCountParam: <int>. for regularization. number of virtual pairs
- * --priorCorrelParam: <double>. for regularization. correlation of these virtual pairs
- * --minNumRatersParam: <int>. min number of raters of the item
- * --maxNumRatersParam: <int> max number of raters of the item
- * --minIntersectionParam: <int>. min number of co-rater users between 2 simliar items
- * --numSimilarItems: <int>. number of similar items to be generated
- *
- * Optional args:
- * --evalid: <int>. Offline Evaluation if evalid is specified
- *
- * Example:
- * scald.rb --hdfs-local io.prediction.algorithms.scalding.itemsim.itemsimcf.ItemSimilarity --hdfsRoot hdfs/predictionio/ --appid 34 --engineid 2 --algoid 8 --measureParam correl --priorCountParam 20 --priorCorrelParam 0.05
- */
-class ItemSimilarity(args: Args) extends VectorSimilarities(args) {
-
-  // args
-  val hdfsRootArg = args("hdfsRoot")
-
-  val appidArg = args("appid").toInt
-  val engineidArg = args("engineid").toInt
-  val algoidArg = args("algoid").toInt
-  val evalidArg = args.optional("evalid") map (x => x.toInt)
-
-  val measureParamArg = args("measureParam")
-  val priorCountParamArg = args("priorCountParam").toInt
-  val priorCorrelParamArg = args("priorCorrelParam").toDouble
-
-  val minNumRatersParamArg = args("minNumRatersParam").toInt
-  val maxNumRatersParamArg = args("maxNumRatersParam").toInt
-  val minIntersectionParamArg = args("minIntersectionParam").toInt
-  val numSimilarItemsArg = args("numSimilarItems").toInt
-
-  // override VectorSimilarities param
-  override val MEASURE: String = measureParamArg
-
-  override val PRIOR_COUNT: Int = priorCountParamArg
-
-  override val PRIOR_CORRELATION: Double = priorCorrelParamArg
-
-  override val MIN_NUM_RATERS: Int = minNumRatersParamArg
-
-  override val MAX_NUM_RATERS: Int = maxNumRatersParamArg
-
-  override val MIN_INTERSECTION: Int = minIntersectionParamArg
-
-  override def input(userField: Symbol, itemField: Symbol, ratingField: Symbol): Pipe = {
-    Tsv(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "ratings.tsv")).read
-      .mapTo((0, 1, 2) -> (userField, itemField, ratingField)) { fields: (String, String, Double) => fields }
-
-  }
-
-  // start computation
-  vectorSimilaritiesAlgo('iid, 'simiid, 'score)
-    .groupBy('iid) { _.sortBy('score).reverse.take(numSimilarItemsArg) }
-    .write(Tsv(AlgoFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "itemSimScores.tsv")))
-
-}
diff --git a/process/engines/itemsim/algorithms/hadoop/scalding/itemsimcf/src/main/scala/io/prediction/algorithms/scalding/itemsim/itemsimcf/ModelConstructor.scala b/process/engines/itemsim/algorithms/hadoop/scalding/itemsimcf/src/main/scala/io/prediction/algorithms/scalding/itemsim/itemsimcf/ModelConstructor.scala
deleted file mode 100644
index 31bec37..0000000
--- a/process/engines/itemsim/algorithms/hadoop/scalding/itemsimcf/src/main/scala/io/prediction/algorithms/scalding/itemsim/itemsimcf/ModelConstructor.scala
+++ /dev/null
@@ -1,115 +0,0 @@
-package io.prediction.algorithms.scalding.itemsim.itemsimcf
-
-import com.twitter.scalding._
-
-import io.prediction.commons.filepath.{ DataFile, AlgoFile }
-import io.prediction.commons.scalding.modeldata.ItemSimScores
-
-/**
- * Source:
- *   selectedItems.tsv
- *   itemSimScores.tsv
- * Sink:
- *   itemSimScores DB
- * Description:
- *   Read the itemSimScores.tsv and get additional attributes from selectedItems.tsv for each similiar items.
- *   Then write the result to model DB.
- *
- * Required args:
- * --dbType: <string> modeldata DB type (eg. mongodb) (see --dbHost, --dbPort)
- * --dbName: <string> (eg. predictionio_modeldata)
- *
- * --hdfsRoot: <string>. Root directory of the HDFS
- *
- * --appid: <int>
- * --engineid: <int>
- * --algoid: <int>
- * --modelSet: <boolean> (true/false). flag to indicate which set
- * --recommendationTime: <long> (eg. 9876543210). recommend items with starttime <= recommendationTime and endtime > recommendationTime
- *
- * Optionsl args:
- * --dbHost: <string> (eg. "127.0.0.1")
- * --dbPort: <int> (eg. 27017)
- *
- * --evalid: <int>. Offline Evaluation if evalid is specified
- * --debug: <String>. "test" - for testing purpose
- *
- * Example:
- * scald.rb --hdfs-local io.prediction.algorithms.scalding.itemsim.itemsimcf.ModelConstructor --dbType mongodb --dbName modeldata --dbHost 127.0.0.1 --dbPort 27017 --hdfsRoot hdfs/predictionio/ --appid 34 --engineid 2 --algoid 8 --modelSet false
- */
-class ModelConstructor(args: Args) extends Job(args) {
-
-  /**
-   * parse args
-   */
-  val dbTypeArg = args("dbType")
-  val dbNameArg = args("dbName")
-  val dbHostArg = args.list("dbHost")
-  val dbPortArg = args.list("dbPort") map (x => x.toInt)
-
-  val hdfsRootArg = args("hdfsRoot")
-
-  val appidArg = args("appid").toInt
-  val engineidArg = args("engineid").toInt
-  val algoidArg = args("algoid").toInt
-  val evalidArg = args.optional("evalid") map (x => x.toInt)
-  val OFFLINE_EVAL = (evalidArg != None) // offline eval mode
-
-  val debugArg = args.list("debug")
-  val DEBUG_TEST = debugArg.contains("test") // test mode
-
-  val modelSetArg = args("modelSet").toBoolean
-  val recommendationTimeArg = args("recommendationTime").toLong
-
-  /**
-   * input
-   */
-  val score = Tsv(AlgoFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "itemSimScores.tsv")).read
-    .mapTo((0, 1, 2) -> ('iid, 'simiid, 'score)) { fields: (String, String, Double) => fields }
-
-  val items = Tsv(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "selectedItems.tsv")).read
-    .mapTo((0, 1, 2, 3) -> ('iidx, 'itypes, 'starttime, 'endtime)) { fields: (String, String, Long, String) =>
-      val (iidx, itypes, starttime, endtime) = fields // itypes are comma-separated String
-
-      val endtimeOpt: Option[Long] = endtime match {
-        case "PIO_NONE" => None
-        case x: String => {
-          try {
-            Some(x.toLong)
-          } catch {
-            case e: Exception => {
-              assert(false, s"Failed to convert ${x} to Long. Exception: " + e)
-              Some(0)
-            }
-          }
-        }
-      }
-
-      (iidx, itypes.split(",").toList, starttime, endtimeOpt)
-    }
-
-  /**
-   * process & output
-   */
-  val p = score.joinWithSmaller('simiid -> 'iidx, items) // get items info for each simiid
-    .filter('starttime, 'endtime) { fields: (Long, Option[Long]) =>
-      val (starttimeI, endtimeI) = fields
-
-      val keepThis: Boolean = (starttimeI, endtimeI) match {
-        case (start, None) => (recommendationTimeArg >= start)
-        case (start, Some(end)) => ((recommendationTimeArg >= start) && (recommendationTimeArg < end))
-        case _ => {
-          assert(false, s"Unexpected item starttime ${starttimeI} and endtime ${endtimeI}")
-          false
-        }
-      }
-      keepThis
-    }
-    .project('iid, 'simiid, 'score, 'itypes)
-    .groupBy('iid) { _.sortBy('score).reverse.toList[(String, Double, List[String])](('simiid, 'score, 'itypes) -> 'simiidsList) }
-
-  val src = ItemSimScores(dbType = dbTypeArg, dbName = dbNameArg, dbHost = dbHostArg, dbPort = dbPortArg, algoid = algoidArg, modelset = modelSetArg)
-
-  p.then(src.writeData('iid, 'simiidsList, algoidArg, modelSetArg) _)
-
-}
diff --git a/process/engines/itemsim/algorithms/hadoop/scalding/itemsimcf/src/main/scala/io/prediction/algorithms/scalding/itemsim/itemsimcf/VectorSimilarities.scala b/process/engines/itemsim/algorithms/hadoop/scalding/itemsimcf/src/main/scala/io/prediction/algorithms/scalding/itemsim/itemsimcf/VectorSimilarities.scala
deleted file mode 100644
index cf19bef..0000000
--- a/process/engines/itemsim/algorithms/hadoop/scalding/itemsimcf/src/main/scala/io/prediction/algorithms/scalding/itemsim/itemsimcf/VectorSimilarities.scala
+++ /dev/null
@@ -1,222 +0,0 @@
-package io.prediction.algorithms.scalding.itemsim.itemsimcf
-
-/**
- * CREDIT: this file is based on Edwin Chen's VectorSimliarities.scala
- * with minor modifications. Thanks Edwin Chen for posting this awesome code!
- * https://github.com/echen/scaldingale
- */
-
-import com.twitter.scalding._
-
-import cascading.pipe.Pipe
-
-/**
- * Given a dataset of ratings, how can we compute the similarity
- * between pairs of items?
- *
- * This class defines an abstract ratings input format. Subclasses
- * that provide a concrete implementation of the input (in the form of
- * a tuple stream containing: a user, the item being rated, and the numeric
- * rating of the item by the user) will automatically calculate
- * similarities of items.
- *
- * In more detail, each item is represented as a (sparse) vector of all
- * its ratings. Similarity measures (such as correlation, cosine similarity,
- * and Jaccard similarity) are then applied to these vectors.
- *
- * @author Edwin Chen
- *
- * modified by Tappingstone
- */
-abstract class VectorSimilarities(args: Args) extends Job(args) {
-
-  // parameter to configure simliarity measurement functions
-  final val CORREL_MEASURE: String = "correl" // this is Pearson
-  final val COSINE_MEASURE: String = "cosine"
-  final val JACCARD_MEASURE: String = "jaccard"
-
-  // subclass should override this to change measurement function
-  val MEASURE: String = CORREL_MEASURE //default measure
-
-  /**
-   * Parameters to regularize correlation.
-   */
-  val PRIOR_COUNT: Int = 10 // default
-  val PRIOR_CORRELATION: Double = 0
-
-  /**
-   * Filters to speed up computation and reduce noise.
-   * Subclasses should probably override these, based on the actual data.
-   */
-  val MIN_NUM_RATERS: Int = 3
-  val MAX_NUM_RATERS: Int = 10000
-  val MIN_INTERSECTION: Int = 1
-
-  /**
-   * Subclasses should override this to define their own input.
-   * This method should return a Pipe using the Symbols in parameters
-   */
-  def input(userField: Symbol, itemField: Symbol, ratingField: Symbol): Pipe
-
-  // *************************
-  // * STEPS OF THE COMPUTATION
-  // *************************  
-
-  def vectorSimilaritiesAlgo(itemField: Symbol, simItemField: Symbol, scoreField: Symbol): Pipe = {
-    /**
-     * Read in the input and give each field a type and name.
-     */
-    val ratings = input('user, 'item, 'rating)
-
-    /**
-     * Also keep track of the total number of people who rated an item.
-     */
-    val ratingsWithSize =
-      ratings
-        // Put the size of each group in a field called "numRaters".  
-        .groupBy('item) { _.size('numRaters) }
-        // Rename, since Scalding currently requires both sides of a join to have distinctly named fields.
-        .rename('item -> 'itemX)
-        .joinWithLarger('itemX -> 'item, ratings).discard('itemX)
-        .filter('numRaters) { numRaters: Long => numRaters >= MIN_NUM_RATERS && numRaters <= MAX_NUM_RATERS }
-
-    /**
-     * Make a dummy copy of the ratings, so we can do a self-join.
-     */
-    val ratings2 =
-      ratingsWithSize
-        .rename(('user, 'item, 'rating, 'numRaters) -> ('user2, 'item2, 'rating2, 'numRaters2))
-
-    /**
-     * Join the two rating streams on their user fields,
-     * in order to find all pairs of items that a user has rated.
-     */
-    val ratingPairs =
-      ratingsWithSize
-        .joinWithSmaller('user -> 'user2, ratings2)
-        // De-dupe so that we don't calculate similarity of both (A, B) and (B, A).
-        .filter('item, 'item2) { items: (String, String) => items._1 < items._2 }
-        .project('item, 'rating, 'numRaters, 'item2, 'rating2, 'numRaters2)
-
-    /**
-     * Compute dot products, norms, sums, and sizes of the rating vectors.
-     */
-    val vectorCalcs =
-      ratingPairs
-        // Compute (x*y, x^2, y^2), which we need for dot products and norms.
-        .map(('rating, 'rating2) -> ('ratingProd, 'ratingSq, 'rating2Sq)) {
-          ratings: (Double, Double) =>
-            (ratings._1 * ratings._2, scala.math.pow(ratings._1, 2), scala.math.pow(ratings._2, 2))
-        }
-        .groupBy('item, 'item2) {
-          _
-            .size
-            .sum('ratingProd -> 'dotProduct)
-            .sum('rating -> 'ratingSum)
-            .sum('rating2 -> 'rating2Sum)
-            .sum('ratingSq -> 'ratingNormSq)
-            .sum('rating2Sq -> 'rating2NormSq)
-            .max('numRaters) // Simply an easy way to make sure the numRaters field stays.
-            .max('numRaters2)
-        }
-        .filter('size) { size: Long => size >= MIN_INTERSECTION }
-
-    /**
-     * Calculate similarity between rating vectors using similarity measures
-     * like correlation, cosine similarity, and Jaccard similarity.
-     */
-    val similaritiesScore =
-      vectorCalcs
-        .map(('size, 'dotProduct, 'ratingSum, 'rating2Sum, 'ratingNormSq, 'rating2NormSq, 'numRaters, 'numRaters2) ->
-          'score) {
-
-          fields: (Double, Double, Double, Double, Double, Double, Double, Double) =>
-
-            val (size, dotProduct, ratingSum, rating2Sum, ratingNormSq, rating2NormSq, numRaters, numRaters2) = fields
-
-            val score = MEASURE match {
-              case CORREL_MEASURE => correlation(size, dotProduct, ratingSum, rating2Sum, ratingNormSq, rating2NormSq)
-              case COSINE_MEASURE => cosineSimilarity(dotProduct, scala.math.sqrt(ratingNormSq), scala.math.sqrt(rating2NormSq))
-              case JACCARD_MEASURE => jaccardSimilarity(size, numRaters, numRaters2)
-              case _ => 0.0 // all other invalid cases
-
-            }
-
-            // regularization
-            // TODO: different measurement may have different way to do regularization
-            val regScore = regularized(size, score, PRIOR_COUNT, PRIOR_CORRELATION)
-
-            regScore
-        }
-
-    // return score for each pair.
-    val simScore1 = similaritiesScore
-      .mapTo(('item, 'item2, 'score) -> (itemField, simItemField, scoreField)) { fields: (String, String, Double) => fields }
-
-    val simScore2 = similaritiesScore
-      .mapTo(('item2, 'item, 'score) -> (itemField, simItemField, scoreField)) { fields: (String, String, Double) => fields }
-
-    // concatenate 2 simScore
-    val simScoreCat = simScore1 ++ simScore2
-
-    simScoreCat
-
-  }
-  // *************************
-  // * SIMILARITY MEASURES
-  // *************************
-
-  /**
-   * The correlation between two vectors A, B is
-   *   cov(A, B) / (stdDev(A) * stdDev(B))
-   *
-   * This is equivalent to
-   *   [n * dotProduct(A, B) - sum(A) * sum(B)] /
-   *     sqrt{ [n * norm(A)^2 - sum(A)^2] [n * norm(B)^2 - sum(B)^2] }
-   */
-  def correlation(size: Double, dotProduct: Double, ratingSum: Double,
-    rating2Sum: Double, ratingNormSq: Double, rating2NormSq: Double) = {
-
-    val numerator = size * dotProduct - ratingSum * rating2Sum
-    val denominator = scala.math.sqrt(size * ratingNormSq - ratingSum * ratingSum) * scala.math.sqrt(size * rating2NormSq - rating2Sum * rating2Sum)
-
-    // NOTE: check if denominator == 0
-    if (denominator == 0)
-      0.0
-    else
-      numerator / denominator
-  }
-
-  /**
-   * Regularize correlation by adding virtual pseudocounts over a prior:
-   *   RegularizedCorrelation = w * ActualCorrelation + (1 - w) * PriorCorrelation
-   * where w = # actualPairs / (# actualPairs + # virtualPairs).
-   */
-  def regularized(size: Double, score: Double, virtualCount: Double, priorCorrelation: Double): Double = {
-    if (virtualCount != 0) {
-      val w = size / (size + virtualCount)
-
-      w * score + (1 - w) * priorCorrelation
-    } else {
-
-      score
-    }
-  }
-
-  /**
-   * The cosine similarity between two vectors A, B is
-   *   dotProduct(A, B) / (norm(A) * norm(B))
-   */
-  def cosineSimilarity(dotProduct: Double, ratingNorm: Double, rating2Norm: Double) = {
-    dotProduct / (ratingNorm * rating2Norm)
-  }
-
-  /**
-   * The Jaccard Similarity between two sets A, B is
-   *   |Intersection(A, B)| / |Union(A, B)|
-   */
-  def jaccardSimilarity(usersInCommon: Double, totalUsers1: Double, totalUsers2: Double) = {
-    val union = totalUsers1 + totalUsers2 - usersInCommon
-    usersInCommon / union
-  }
-}
diff --git a/process/engines/itemsim/algorithms/hadoop/scalding/itemsimcf/src/test/scala/io/prediction/algorithms/scalding/itemsim/itemsimcf/DataPreparatorTest.scala b/process/engines/itemsim/algorithms/hadoop/scalding/itemsimcf/src/test/scala/io/prediction/algorithms/scalding/itemsim/itemsimcf/DataPreparatorTest.scala
deleted file mode 100644
index d12dcdf..0000000
--- a/process/engines/itemsim/algorithms/hadoop/scalding/itemsimcf/src/test/scala/io/prediction/algorithms/scalding/itemsim/itemsimcf/DataPreparatorTest.scala
+++ /dev/null
@@ -1,414 +0,0 @@
-package io.prediction.algorithms.scalding.itemsim.itemsimcf
-
-import org.specs2.mutable._
-
-import com.twitter.scalding._
-
-import io.prediction.commons.scalding.appdata.{ Items, U2iActions }
-import io.prediction.commons.filepath.DataFile
-
-class DataPreparatorTest extends Specification with TupleConversions {
-
-  val Rate = "rate"
-  val Like = "like"
-  val Dislike = "dislike"
-  val View = "view"
-  //val ViewDetails = "viewDetails"
-  val Conversion = "conversion"
-
-  val appid = 2
-
-  def test(itypes: List[String], params: Map[String, String],
-    items: List[(String, String, String, String, String, String)], // id, itypes, appid, starttime, ct, endtime
-    u2iActions: List[(String, String, String, String, String)],
-    ratings: List[(String, String, Int)],
-    selectedItems: List[(String, String, String, String)] // id, itypes, starttime, endtime
-    ) = {
-
-    val dbType = "file"
-    val dbName = "testpath/"
-    val dbHost = Seq() //Option("testhost")
-    val dbPort = Seq() //Option(27017)
-    val hdfsRoot = "testroot/"
-
-    JobTest("io.prediction.algorithms.scalding.itemsim.itemsimcf.DataPreparator")
-      .arg("dbType", dbType)
-      .arg("dbName", dbName)
-      //.arg("dbHost", dbHost.get)
-      //.arg("dbPort", dbPort.get.toString)
-      .arg("hdfsRoot", hdfsRoot)
-      .arg("appid", appid.toString)
-      .arg("engineid", "4")
-      .arg("algoid", "5")
-      .arg("itypes", itypes)
-      .arg("viewParam", params("viewParam"))
-      .arg("likeParam", params("likeParam"))
-      .arg("dislikeParam", params("dislikeParam"))
-      .arg("conversionParam", params("conversionParam"))
-      .arg("conflictParam", params("conflictParam"))
-      //.arg("debug", List("test")) // NOTE: test mode
-      .source(Items(appId = appid, itypes = Some(itypes), dbType = dbType, dbName = dbName, dbHost = dbHost, dbPort = dbPort).getSource, items)
-      .source(U2iActions(appId = appid, dbType = dbType, dbName = dbName, dbHost = dbHost, dbPort = dbPort).getSource, u2iActions)
-      .sink[(String, String, Int)](Tsv(DataFile(hdfsRoot, 2, 4, 5, None, "ratings.tsv"))) { outputBuffer =>
-        "correctly process and write data to ratings.tsv" in {
-          outputBuffer.toList must containTheSameElementsAs(ratings)
-        }
-      }
-      .sink[(String, String, String, String)](Tsv(DataFile(hdfsRoot, 2, 4, 5, None, "selectedItems.tsv"))) { outputBuffer =>
-        "correctly write selectedItems.tsv" in {
-          outputBuffer.toList must containTheSameElementsAs(selectedItems)
-        }
-      }
-      .run
-      .finish
-
-  }
-
-  /** no itypes specified */
-  def testWithoutItypes(params: Map[String, String],
-    items: List[(String, String, String, String, String, String)], // id, itypes, appid, starttime, ct, endtime
-    u2iActions: List[(String, String, String, String, String)],
-    ratings: List[(String, String, Int)],
-    selectedItems: List[(String, String, String, String)] // id, itypes, starttime, endtime
-    ) = {
-
-    val dbType = "file"
-    val dbName = "testpath/"
-    val dbHost = Seq() //Option("testhost")
-    val dbPort = Seq() //Option(27017)
-    val hdfsRoot = "testroot/"
-
-    JobTest("io.prediction.algorithms.scalding.itemsim.itemsimcf.DataPreparator")
-      .arg("dbType", dbType)
-      .arg("dbName", dbName)
-      //.arg("dbHost", dbHost.get)
-      //.arg("dbPort", dbPort.get.toString)
-      .arg("hdfsRoot", hdfsRoot)
-      .arg("appid", appid.toString)
-      .arg("engineid", "4")
-      .arg("algoid", "5")
-      //.arg("itypes", itypes) // NOTE: no itypes args!
-      .arg("viewParam", params("viewParam"))
-      .arg("likeParam", params("likeParam"))
-      .arg("dislikeParam", params("dislikeParam"))
-      .arg("conversionParam", params("conversionParam"))
-      .arg("conflictParam", params("conflictParam"))
-      //.arg("debug", List("test")) // NOTE: test mode
-      .source(Items(appId = appid, itypes = None, dbType = dbType, dbName = dbName, dbHost = dbHost, dbPort = dbPort).getSource, items)
-      .source(U2iActions(appId = appid, dbType = dbType, dbName = dbName, dbHost = dbHost, dbPort = dbPort).getSource, u2iActions)
-      .sink[(String, String, Int)](Tsv(DataFile(hdfsRoot, 2, 4, 5, None, "ratings.tsv"))) { outputBuffer =>
-        "correctly process and write data to ratings.tsv" in {
-          outputBuffer.toList must containTheSameElementsAs(ratings)
-        }
-      }
-      .sink[(String, String, String, String)](Tsv(DataFile(hdfsRoot, 2, 4, 5, None, "selectedItems.tsv"))) { outputBuffer =>
-        "correctly write selectedItems.tsv" in {
-          outputBuffer.toList must containTheSameElementsAs(selectedItems)
-        }
-      }
-      .run
-      .finish
-
-  }
-
-  val noEndtime = "PIO_NONE"
-  /**
-   * Test 1. basic. Rate actions only without conflicts
-   */
-  val test1AllItypes = List("t1", "t2", "t3", "t4")
-  val test1ItemsMap = Map(
-    // id, itypes, appid, starttime, ct, endtime
-    "i0" -> ("i0", "t1,t2,t3", appid.toString, "12345", "12346", noEndtime),
-    "i1" -> ("i1", "t2,t3", appid.toString, "12347", "12348", noEndtime),
-    "i2" -> ("i2", "t4", appid.toString, "12349", "12350", noEndtime),
-    "i3" -> ("i3", "t3,t4", appid.toString, "12351", "12352", noEndtime))
-
-  val test1Items = List(
-    test1ItemsMap("i0"),
-    test1ItemsMap("i1"),
-    test1ItemsMap("i2"),
-    test1ItemsMap("i3"))
-
-  def genSelectedItems(items: List[(String, String, String, String, String, String)]) = {
-    items map { x =>
-      val (id, itypes, appid, starttime, ct, endtime) = x
-      (id, itypes, starttime, endtime)
-    }
-  }
-
-  val test1U2i = List(
-    (Rate, "u0", "i0", "123450", "3"),
-    (Rate, "u0", "i1", "123457", "1"),
-    (Rate, "u0", "i2", "123458", "4"),
-    (Rate, "u0", "i3", "123459", "2"),
-    (Rate, "u1", "i0", "123457", "5"),
-    (Rate, "u1", "i1", "123458", "2"))
-
-  val test1Ratings = List(
-    ("u0", "i0", 3),
-    ("u0", "i1", 1),
-    ("u0", "i2", 4),
-    ("u0", "i3", 2),
-    ("u1", "i0", 5),
-    ("u1", "i1", 2))
-
-  val test1Params: Map[String, String] = Map("viewParam" -> "3", "likeParam" -> "4", "dislikeParam" -> "1", "conversionParam" -> "5",
-    "conflictParam" -> "latest")
-
-  "itemsim.itemsimcf DataPreparator with only rate actions, all itypes, no conflict" should {
-    test(test1AllItypes, test1Params, test1Items, test1U2i, test1Ratings, genSelectedItems(test1Items))
-  }
-
-  "itemsim.itemsimcf DataPreparator with only rate actions, no itypes specified, no conflict" should {
-    testWithoutItypes(test1Params, test1Items, test1U2i, test1Ratings, genSelectedItems(test1Items))
-  }
-
-  /**
-   * Test 2. rate actions only with conflicts
-   */
-  val test2AllItypes = List("t1", "t2", "t3", "t4")
-  val test2ItemsMap = Map(
-    // id, itypes, appid, starttime, ct, endtime
-    "i0" -> ("i0", "t1,t2,t3", appid.toString, "12345", "12346", noEndtime),
-    "i1" -> ("i1", "t2,t3", appid.toString, "12347", "12348", noEndtime),
-    "i2" -> ("i2", "t4", appid.toString, "12349", "12350", noEndtime),
-    "i3" -> ("i3", "t3,t4", appid.toString, "12351", "12352", noEndtime))
-
-  val test2Items = List(
-    test2ItemsMap("i0"),
-    test2ItemsMap("i1"),
-    test2ItemsMap("i2"),
-    test2ItemsMap("i3"))
-
-  val test2U2i = List(
-    (Rate, "u0", "i0", "123448", "3"),
-    (Rate, "u0", "i0", "123449", "4"), // highest
-    (Rate, "u0", "i0", "123451", "2"), // latest
-    (Rate, "u0", "i0", "123450", "1"), // lowest
-
-    (Rate, "u0", "i1", "123456", "1"), // lowest
-    (Rate, "u0", "i1", "123457", "2"),
-    (Rate, "u0", "i1", "123458", "3"), // latest, highest
-
-    (Rate, "u0", "i2", "123461", "2"), // latest, lowest
-    (Rate, "u0", "i2", "123459", "3"),
-    (Rate, "u0", "i2", "123460", "5"), // highest
-
-    (Rate, "u0", "i3", "123459", "2"),
-    (Rate, "u1", "i0", "123457", "5"),
-
-    (Rate, "u1", "i1", "123458", "3"), // lowest
-    (Rate, "u1", "i1", "123459", "4"), // highest
-    (Rate, "u1", "i1", "123460", "3")) // latest, lowest
-
-  val test2RatingsLatest = List(
-    ("u0", "i0", 2),
-    ("u0", "i1", 3),
-    ("u0", "i2", 2),
-    ("u0", "i3", 2),
-    ("u1", "i0", 5),
-    ("u1", "i1", 3))
-
-  val test2RatingsHighest = List(
-    ("u0", "i0", 4),
-    ("u0", "i1", 3),
-    ("u0", "i2", 5),
-    ("u0", "i3", 2),
-    ("u1", "i0", 5),
-    ("u1", "i1", 4))
-
-  val test2RatingsLowest = List(
-    ("u0", "i0", 1),
-    ("u0", "i1", 1),
-    ("u0", "i2", 2),
-    ("u0", "i3", 2),
-    ("u1", "i0", 5),
-    ("u1", "i1", 3))
-
-  val test2Itypes_t1t4 = List("t1", "t4")
-  val test2Items_t1t4 = List(
-    test2ItemsMap("i0"),
-    test2ItemsMap("i2"),
-    test2ItemsMap("i3"))
-  val test2RatingsHighest_t1t4 = List(
-    ("u0", "i0", 4),
-    ("u0", "i2", 5),
-    ("u0", "i3", 2),
-    ("u1", "i0", 5))
-
-  val test2Params: Map[String, String] = Map("viewParam" -> "3", "likeParam" -> "4", "dislikeParam" -> "1", "conversionParam" -> "5",
-    "conflictParam" -> "latest")
-  val test2ParamsHighest = test2Params + ("conflictParam" -> "highest")
-  val test2ParamsLowest = test2Params + ("conflictParam" -> "lowest")
-
-  "itemsim.itemsimcf DataPreparator with only rate actions, all itypes, conflict=latest" should {
-    test(test2AllItypes, test2Params, test2Items, test2U2i, test2RatingsLatest, genSelectedItems(test2Items))
-  }
-
-  "itemsim.itemsimcf DataPreparator with only rate actions, all itypes, conflict=highest" should {
-    test(test2AllItypes, test2ParamsHighest, test2Items, test2U2i, test2RatingsHighest, genSelectedItems(test2Items))
-  }
-
-  "itemsim.itemsimcf DataPreparator with only rate actions, all itypes, conflict=lowest" should {
-    test(test2AllItypes, test2ParamsLowest, test2Items, test2U2i, test2RatingsLowest, genSelectedItems(test2Items))
-  }
-
-  "itemsim.itemsimcf DataPreparator with only rate actions, some itypes, conflict=highest" should {
-    test(test2Itypes_t1t4, test2ParamsHighest, test2Items, test2U2i, test2RatingsHighest_t1t4, genSelectedItems(test2Items_t1t4))
-  }
-
-  /**
-   * Test 3. Different Actions without conflicts
-   */
-  val test3AllItypes = List("t1", "t2", "t3", "t4")
-  val test3ItemsMap = Map(
-    // id, itypes, appid, starttime, ct, endtime
-    "i0" -> ("i0", "t1,t2,t3", appid.toString, "12345", "12346", "56789"),
-    "i1" -> ("i1", "t2,t3", appid.toString, "12347", "12348", noEndtime),
-    "i2" -> ("i2", "t4", appid.toString, "12349", "12350", "56790"),
-    "i3" -> ("i3", "t3,t4", appid.toString, "12351", "12352", noEndtime))
-
-  val test3Items = List(
-    test3ItemsMap("i0"),
-    test3ItemsMap("i1"),
-    test3ItemsMap("i2"),
-    test3ItemsMap("i3"))
-
-  val test3U2i = List(
-    (Rate, "u0", "i0", "123450", "4"),
-    (Like, "u0", "i1", "123457", "PIO_NONE"),
-    (Dislike, "u0", "i2", "123458", "PIO_NONE"),
-    (View, "u0", "i3", "123459", "PIO_NONE"), // NOTE: assume v field won't be missing
-    (Rate, "u1", "i0", "123457", "2"),
-    (Conversion, "u1", "i1", "123458", "PIO_NONE"))
-
-  val test3Ratings = List(
-    ("u0", "i0", 4),
-    ("u0", "i1", 4),
-    ("u0", "i2", 2),
-    ("u0", "i3", 1),
-    ("u1", "i0", 2),
-    ("u1", "i1", 5))
-
-  val test3Params: Map[String, String] = Map("viewParam" -> "1", "likeParam" -> "4", "dislikeParam" -> "2", "conversionParam" -> "5",
-    "conflictParam" -> "latest")
-
-  "itemsim.itemsimcf DataPreparator with only all actions, all itypes, no conflict" should {
-    test(test3AllItypes, test3Params, test3Items, test3U2i, test3Ratings, genSelectedItems(test3Items))
-  }
-
-  /**
-   * test 4. Different Actions with conflicts
-   */
-  val test4Params: Map[String, String] = Map("viewParam" -> "2", "likeParam" -> "5", "dislikeParam" -> "1", "conversionParam" -> "4",
-    "conflictParam" -> "latest")
-
-  val test4AllItypes = List("t1", "t2", "t3", "t4")
-  val test4ItemsMap = Map(
-    // id, itypes, appid, starttime, ct, endtime
-    "i0" -> ("i0", "t1,t2,t3", appid.toString, "12345", "12346", "56789"),
-    "i1" -> ("i1", "t2,t3", appid.toString, "12347", "12348", noEndtime),
-    "i2" -> ("i2", "t4", appid.toString, "12349", "12350", "56790"),
-    "i3" -> ("i3", "t3,t4", appid.toString, "12351", "12352", noEndtime))
-
-  val test4Items = List(
-    test4ItemsMap("i0"),
-    test4ItemsMap("i1"),
-    test4ItemsMap("i2"),
-    test4ItemsMap("i3"))
-
-  val test4U2i = List(
-    (Rate, "u0", "i0", "123448", "3"),
-    (View, "u0", "i0", "123449", "PIO_NONE"), // lowest (2)
-    (Like, "u0", "i0", "123451", "PIO_NONE"), // latest, highest (5)
-    (Conversion, "u0", "i0", "123450", "PIO_NONE"),
-
-    (Rate, "u0", "i1", "123456", "1"), // lowest
-    (Rate, "u0", "i1", "123457", "4"), // highest
-    (View, "u0", "i1", "123458", "PIO_NONE"), // latest (2)
-
-    (Conversion, "u0", "i2", "123461", "PIO_NONE"), // latest, highest  (4)
-    (Rate, "u0", "i2", "123459", "3"),
-    (View, "u0", "i2", "123460", "PIO_NONE"), // lowest
-
-    (Rate, "u0", "i3", "123459", "2"),
-    (View, "u1", "i0", "123457", "PIO_NONE"), // (2)
-
-    (Rate, "u1", "i1", "123458", "5"), // highest
-    (Conversion, "u1", "i1", "123459", "PIO_NONE"), // (4)
-    (Dislike, "u1", "i1", "123460", "PIO_NONE")) // latest, lowest (1)
-
-  val test4RatingsLatest = List(
-    ("u0", "i0", 5),
-    ("u0", "i1", 2),
-    ("u0", "i2", 4),
-    ("u0", "i3", 2),
-    ("u1", "i0", 2),
-    ("u1", "i1", 1))
-
-  "itemsim.itemsimcf DataPreparator with all actions, all itypes, and conflicts=latest" should {
-    test(test4AllItypes, test4Params, test4Items, test4U2i, test4RatingsLatest, genSelectedItems(test4Items))
-  }
-
-  val test4ParamsIgnoreView = test4Params + ("viewParam" -> "ignore")
-
-  val test4RatingsIgnoreViewLatest = List(
-    ("u0", "i0", 5),
-    ("u0", "i1", 4),
-    ("u0", "i2", 4),
-    ("u0", "i3", 2),
-    ("u1", "i1", 1))
-
-  "itemsim.itemsimcf DataPreparator with all actions, all itypes, ignore View actions and conflicts=latest" should {
-    test(test4AllItypes, test4ParamsIgnoreView, test4Items, test4U2i, test4RatingsIgnoreViewLatest, genSelectedItems(test4Items))
-  }
-
-  // note: currently rate action can't be ignored
-  val test4ParamsIgnoreAllExceptView = test4Params + ("viewParam" -> "1", "likeParam" -> "ignore", "dislikeParam" -> "ignore", "conversionParam" -> "ignore")
-
-  val test4RatingsIgnoreAllExceptViewLatest = List(
-    ("u0", "i0", 1),
-    ("u0", "i1", 1),
-    ("u0", "i2", 1),
-    ("u0", "i3", 2),
-    ("u1", "i0", 1),
-    ("u1", "i1", 5))
-
-  "itemsim.itemsimcf DataPreparator with all actions, all itypes, ignore all actions except View (and Rate) and conflicts=latest" should {
-    test(test4AllItypes, test4ParamsIgnoreAllExceptView, test4Items, test4U2i, test4RatingsIgnoreAllExceptViewLatest, genSelectedItems(test4Items))
-  }
-
-  // note: meaning rate action only
-  val test4ParamsIgnoreAll = test4Params + ("viewParam" -> "ignore", "likeParam" -> "ignore", "dislikeParam" -> "ignore", "conversionParam" -> "ignore")
-
-  val test4RatingsIgnoreAllLatest = List(
-    ("u0", "i0", 3),
-    ("u0", "i1", 4),
-    ("u0", "i2", 3),
-    ("u0", "i3", 2),
-    ("u1", "i1", 5))
-
-  "itemsim.itemsimcf DataPreparator with all actions, all itypes, ignore all actions (except Rate) and conflicts=latest" should {
-    test(test4AllItypes, test4ParamsIgnoreAll, test4Items, test4U2i, test4RatingsIgnoreAllLatest, genSelectedItems(test4Items))
-  }
-
-  val test4ParamsLowest: Map[String, String] = test4Params + ("conflictParam" -> "lowest")
-
-  val test4Itypes_t3 = List("t3")
-  val test4Items_t3 = List(
-    test4ItemsMap("i0"),
-    test4ItemsMap("i1"),
-    test4ItemsMap("i3"))
-
-  val test4RatingsLowest_t3 = List(
-    ("u0", "i0", 2),
-    ("u0", "i1", 1),
-    ("u0", "i3", 2),
-    ("u1", "i0", 2),
-    ("u1", "i1", 1))
-
-  "itemsim.itemsimcf DataPreparator with all actions, some itypes, and conflicts=lowest" should {
-    test(test4Itypes_t3, test4ParamsLowest, test4Items, test4U2i, test4RatingsLowest_t3, genSelectedItems(test4Items_t3))
-  }
-
-}
diff --git a/process/engines/itemsim/algorithms/hadoop/scalding/itemsimcf/src/test/scala/io/prediction/algorithms/scalding/itemsim/itemsimcf/ItemSimilarityTest.scala b/process/engines/itemsim/algorithms/hadoop/scalding/itemsimcf/src/test/scala/io/prediction/algorithms/scalding/itemsim/itemsimcf/ItemSimilarityTest.scala
deleted file mode 100644
index 500106c..0000000
--- a/process/engines/itemsim/algorithms/hadoop/scalding/itemsimcf/src/test/scala/io/prediction/algorithms/scalding/itemsim/itemsimcf/ItemSimilarityTest.scala
+++ /dev/null
@@ -1,215 +0,0 @@
-package io.prediction.algorithms.scalding.itemsim.itemsimcf
-
-import org.specs2.mutable._
-
-import com.twitter.scalding._
-
-import io.prediction.commons.filepath.{ DataFile, AlgoFile }
-
-class ItemSimilarityTest extends Specification with TupleConversions {
-
-  // helper function
-  // only compare double up to 9 decimal places
-  def roundingData(orgList: List[(String, String, Double)]) = {
-    orgList map { x =>
-      val (t1, t2, t3) = x
-
-      // NOTE: use HALF_UP mode to avoid error caused by rounding when compare data
-      // (eg. 3.5 vs 3.499999999999).
-      // (eg. 0.6666666666 vs 0.666666667)
-
-      (t1, t2, BigDecimal(t3).setScale(9, BigDecimal.RoundingMode.HALF_UP).toDouble)
-    }
-  }
-
-  def test(testArgs: Map[String, String],
-    testInput: List[(String, String, Int)],
-    testOutput: List[(String, String, Double)]) = {
-
-    val hdfsRoot = "testroot/"
-
-    JobTest("io.prediction.algorithms.scalding.itemsim.itemsimcf.ItemSimilarity").
-      arg("hdfsRoot", hdfsRoot).
-      arg("appid", "8").
-      arg("engineid", "2").
-      arg("algoid", "3").
-      arg("measureParam", testArgs("measureParam")).
-      arg("priorCountParam", testArgs("priorCountParam")).
-      arg("priorCorrelParam", testArgs("priorCorrelParam")).
-      arg("minNumRatersParam", testArgs("minNumRatersParam")).
-      arg("maxNumRatersParam", testArgs("maxNumRatersParam")).
-      arg("minIntersectionParam", testArgs("minIntersectionParam")).
-      arg("numSimilarItems", testArgs("numSimilarItems")).
-      source(Tsv(DataFile(hdfsRoot, 8, 2, 3, None, "ratings.tsv")), testInput).
-      sink[(String, String, Double)](Tsv(AlgoFile(hdfsRoot, 8, 2, 3, None, "itemSimScores.tsv"))) { outputBuffer =>
-        "correctly calculate similarity score" in {
-          roundingData(outputBuffer.toList) must containTheSameElementsAs(roundingData(testOutput))
-        }
-      }
-      .run
-      .finish
-  }
-
-  // simple test1
-  val test1args = Map[String, String]("measureParam" -> "correl",
-    "priorCountParam" -> "10",
-    "priorCorrelParam" -> "0",
-    "minNumRatersParam" -> "1",
-    "maxNumRatersParam" -> "10000",
-    "minIntersectionParam" -> "1",
-    "numSimilarItems" -> "500"
-  )
-
-  val test1Input = List(
-    ("u0", "i0", 1),
-    ("u0", "i1", 2),
-    ("u0", "i2", 3),
-    ("u1", "i1", 4),
-    ("u1", "i2", 4),
-    ("u1", "i3", 2),
-    ("u2", "i0", 3),
-    ("u2", "i1", 2),
-    ("u2", "i3", 1),
-    ("u3", "i0", 2),
-    ("u3", "i2", 1),
-    ("u3", "i3", 5))
-
-  val test1Output = List(
-    ("i0", "i1", 0.0),
-    ("i1", "i0", 0.0),
-    ("i0", "i2", -0.16666666666666666),
-    ("i2", "i0", -0.16666666666666666),
-    ("i0", "i3", -0.16666666666666666),
-    ("i3", "i0", -0.16666666666666666),
-    ("i1", "i2", 0.16666666666666666),
-    ("i2", "i1", 0.16666666666666666),
-    ("i1", "i3", 0.16666666666666666),
-    ("i3", "i1", 0.16666666666666666),
-    ("i2", "i3", -0.16666666666666666),
-    ("i3", "i2", -0.16666666666666666))
-
-  val hdfsRoot = "testroot/"
-
-  "ItemSimilarity Correlation" should {
-    test(test1args, test1Input, test1Output)
-  }
-
-  // simple test2
-  val test2args = Map[String, String]("measureParam" -> "correl",
-    "priorCountParam" -> "20",
-    "priorCorrelParam" -> "0.5",
-    "minNumRatersParam" -> "1",
-    "maxNumRatersParam" -> "10000",
-    "minIntersectionParam" -> "1",
-    "numSimilarItems" -> "500"
-  )
-
-  val test2Input = List(
-    ("u0", "i0", 1),
-    ("u0", "i1", 2),
-    ("u0", "i2", 3),
-    ("u1", "i1", 4),
-    ("u1", "i2", 4),
-    ("u1", "i3", 2),
-    ("u2", "i0", 3),
-    ("u2", "i1", 2),
-    ("u2", "i3", 1),
-    ("u3", "i0", 2),
-    ("u3", "i2", 1),
-    ("u3", "i3", 5))
-
-  val test2Output = List(
-    ("i0", "i1", 0.454545454545454),
-    ("i1", "i0", 0.454545454545454),
-    ("i0", "i2", 0.363636363636364),
-    ("i2", "i0", 0.363636363636364),
-    ("i0", "i3", 0.363636363636364),
-    ("i3", "i0", 0.363636363636364),
-    ("i1", "i2", 0.545454545454545),
-    ("i2", "i1", 0.545454545454545),
-    ("i1", "i3", 0.545454545454545),
-    ("i3", "i1", 0.545454545454545),
-    ("i2", "i3", 0.363636363636364),
-    ("i3", "i2", 0.363636363636364))
-
-  "ItemSimilarity Correlation with different regularization" should {
-    test(test2args, test2Input, test2Output)
-  }
-
-  // simple test3
-  val test3args = Map[String, String]("measureParam" -> "cosine",
-    "priorCountParam" -> "0",
-    "priorCorrelParam" -> "0",
-    "minNumRatersParam" -> "1",
-    "maxNumRatersParam" -> "10000",
-    "minIntersectionParam" -> "1",
-    "numSimilarItems" -> "500"
-  )
-
-  val test3Input = List(
-    ("u0", "i0", 1),
-    ("u0", "i1", 2),
-    ("u0", "i2", 3),
-    ("u1", "i1", 4),
-    ("u1", "i2", 4),
-    ("u1", "i3", 2),
-    ("u2", "i0", 3),
-    ("u2", "i1", 2),
-    ("u2", "i3", 1),
-    ("u3", "i0", 2),
-    ("u3", "i2", 1),
-    ("u3", "i3", 5))
-
-  val test3Output = List[(String, String, Double)](
-    ("i0", "i1", 0.894427190999916),
-    ("i1", "i0", 0.894427190999916),
-    ("i0", "i2", 0.707106781186548),
-    ("i2", "i0", 0.707106781186548),
-    ("i0", "i3", 0.707106781186548),
-    ("i3", "i0", 0.707106781186548),
-    ("i1", "i2", 0.983869910099907),
-    ("i2", "i1", 0.983869910099907),
-    ("i1", "i3", 1.0), // NOTE: (use HALF_UP to work around 1.0 vs 0.999999999)
-    ("i3", "i1", 1.0),
-    ("i2", "i3", 0.585490553844358),
-    ("i3", "i2", 0.585490553844358))
-
-  "ItemSimilarity Cosine" should {
-    test(test3args, test3Input, test3Output)
-  }
-
-  // test4 - test numSimilarItems smaller than existing
-  val test4args = Map[String, String]("measureParam" -> "cosine",
-    "priorCountParam" -> "0",
-    "priorCorrelParam" -> "0",
-    "minNumRatersParam" -> "1",
-    "maxNumRatersParam" -> "10000",
-    "minIntersectionParam" -> "1",
-    "numSimilarItems" -> "1"
-  )
-
-  val test4Input = List(
-    ("u0", "i0", 1),
-    ("u0", "i1", 2),
-    ("u0", "i2", 3),
-    ("u1", "i1", 4),
-    ("u1", "i2", 4),
-    ("u1", "i3", 2),
-    ("u2", "i0", 3),
-    ("u2", "i1", 2),
-    ("u2", "i3", 1),
-    ("u3", "i0", 2),
-    ("u3", "i2", 1),
-    ("u3", "i3", 5))
-
-  val test4Output = List[(String, String, Double)](
-    ("i0", "i1", 0.894427190999916),
-    ("i2", "i1", 0.983869910099907),
-    ("i1", "i3", 1.0), // NOTE: (use HALF_UP to work around 1.0 vs 0.999999999)
-    ("i3", "i1", 1.0))
-
-  "ItemSimilarity Cosine with smaller numSimilarItems" should {
-    test(test4args, test4Input, test4Output)
-  }
-
-}
\ No newline at end of file
diff --git a/process/engines/itemsim/algorithms/hadoop/scalding/itemsimcf/src/test/scala/io/prediction/algorithms/scalding/itemsim/itemsimcf/ModelConstructorTest.scala b/process/engines/itemsim/algorithms/hadoop/scalding/itemsimcf/src/test/scala/io/prediction/algorithms/scalding/itemsim/itemsimcf/ModelConstructorTest.scala
deleted file mode 100644
index 03e941f..0000000
--- a/process/engines/itemsim/algorithms/hadoop/scalding/itemsimcf/src/test/scala/io/prediction/algorithms/scalding/itemsim/itemsimcf/ModelConstructorTest.scala
+++ /dev/null
@@ -1,142 +0,0 @@
-package io.prediction.algorithms.scalding.itemsim.itemsimcf
-
-import org.specs2.mutable._
-
-import com.twitter.scalding._
-
-import io.prediction.commons.filepath.{ AlgoFile, DataFile }
-import io.prediction.commons.scalding.modeldata.ItemSimScores
-
-class ModelConstructorTest extends Specification with TupleConversions {
-
-  def test(recommendationTime: Long,
-    items: List[(String, String, String, String)], //iid, itypes, starttime, endtime
-    itemSimScores: List[(String, String, String)],
-    output: List[(String, String, String, String)]) = {
-
-    val appid = 3
-    val engineid = 4
-    val algoid = 7
-    val modelSet = true
-
-    val dbType = "file"
-    val dbName = "testpath/"
-    val dbHost = Seq()
-    val dbPort = Seq()
-    val hdfsRoot = "testroot/"
-
-    val outputItemSimScores = output map { case (uid, iid, score, itypes) => (uid, iid, score, itypes, algoid, modelSet) }
-
-    JobTest("io.prediction.algorithms.scalding.itemsim.itemsimcf.ModelConstructor")
-      .arg("dbType", dbType)
-      .arg("dbName", dbName)
-      .arg("hdfsRoot", hdfsRoot)
-      .arg("appid", appid.toString)
-      .arg("engineid", engineid.toString)
-      .arg("algoid", algoid.toString)
-      .arg("modelSet", modelSet.toString)
-      .arg("recommendationTime", recommendationTime.toString)
-      //.arg("debug", "test") // NOTE: test mode
-      .source(Tsv(AlgoFile(hdfsRoot, appid, engineid, algoid, None, "itemSimScores.tsv")), itemSimScores)
-      .source(Tsv(DataFile(hdfsRoot, appid, engineid, algoid, None, "selectedItems.tsv")), items)
-      .sink[(String, String, String, String, Int, Boolean)](ItemSimScores(dbType = dbType, dbName = dbName, dbHost = dbHost, dbPort = dbPort, algoid = algoid, modelset = modelSet).getSource) { outputBuffer =>
-        "correctly write model data to a file" in {
-          outputBuffer.toList must containTheSameElementsAs(outputItemSimScores)
-        }
-      }
-      .run
-      .finish
-  }
-
-  val largeNumber = 1234567890 // larger than any item starttime
-  val noEndtime = "PIO_NONE"
-
-  /* test 1 */
-  val test1ItemSimScores = List(("i0", "i1", "0.123"), ("i0", "i2", "0.456"), ("i1", "i0", "1.23"))
-  val test1Items = List(
-    ("i0", "t1,t2,t3", "12346", noEndtime),
-    ("i1", "t1,t2", "12347", noEndtime),
-    ("i2", "t2,t3", "12348", noEndtime))
-  val test1Output = List(
-    ("i0", "i2,i1", "0.456,0.123", "[t2,t3],[t1,t2]"),
-    ("i1", "i0", "1.23", "[t1,t2,t3]"))
-
-  "ItemSim ModelConstructor in test mode" should {
-    test(largeNumber, test1Items, test1ItemSimScores, test1Output)
-  }
-
-  /* test 2: test starttime and endtime */
-  // starttime, endtime
-  // i0  A |---------|
-  // i1    B |---------|E
-  // i2       C|---------|
-  // i3           |---------|
-  //               D        F G
-
-  val tA = 123122
-  val tB = 123123
-  val tC = 123457
-  val tD = 123679
-  val tE = 543322
-  val tF = 543654
-  val tG = 543655
-
-  val test2ItemSimScores = List(
-    ("i0", "i1", "0.123"),
-    ("i0", "i2", "0.456"),
-    ("i0", "i3", "0.2"),
-    ("i1", "i0", "12"),
-    ("i1", "i2", "2"))
-
-  val test2Items = List(
-    ("i0", "t1,t2,t3", "123123", "543210"),
-    ("i1", "t1,t2", "123456", "543321"),
-    ("i2", "t2,t3", "123567", "543432"),
-    ("i3", "t2", "123678", "543654"))
-
-  val test2Output = List(
-    ("i0", "i2,i3,i1", "0.456,0.2,0.123", "[t2,t3],[t2],[t1,t2]"),
-    ("i1", "i0,i2", "12.0,2.0", "[t1,t2,t3],[t2,t3]"))
-
-  val test2OutputEmpty = List()
-
-  val test2Outputi0 = List(
-    ("i1", "i0", "12.0", "[t1,t2,t3]"))
-
-  val test2Outputi0i1 = List(
-    ("i0", "i1", "0.123", "[t1,t2]"),
-    ("i1", "i0", "12.0", "[t1,t2,t3]"))
-
-  val test2Outputi2i3 = List(
-    ("i0", "i2,i3", "0.456,0.2", "[t2,t3],[t2]"),
-    ("i1", "i2", "2.0", "[t2,t3]"))
-
-  "recommendationTime < all item starttime" should {
-    test(tA, test2Items, test2ItemSimScores, test2OutputEmpty)
-  }
-
-  "recommendationTime == earliest starttime" should {
-    test(tB, test2Items, test2ItemSimScores, test2Outputi0)
-  }
-
-  "recommendationTime > some items starttime" should {
-    test(tC, test2Items, test2ItemSimScores, test2Outputi0i1)
-  }
-
-  "recommendationTime > all item starttime and < all item endtime" should {
-    test(tD, test2Items, test2ItemSimScores, test2Output)
-  }
-
-  "recommendationTime > some item endtime" should {
-    test(tE, test2Items, test2ItemSimScores, test2Outputi2i3)
-  }
-
-  "recommendationTime == last item endtime" should {
-    test(tF, test2Items, test2ItemSimScores, test2OutputEmpty)
-  }
-
-  "recommendationTime > last item endtime" should {
-    test(tG, test2Items, test2ItemSimScores, test2OutputEmpty)
-  }
-
-}
diff --git a/process/engines/itemsim/algorithms/hadoop/scalding/latestrank/src/main/scala/io/prediction/algorithms/scalding/itemsim/latestrank/LatestRank.scala b/process/engines/itemsim/algorithms/hadoop/scalding/latestrank/src/main/scala/io/prediction/algorithms/scalding/itemsim/latestrank/LatestRank.scala
deleted file mode 100644
index bb6e3b9..0000000
--- a/process/engines/itemsim/algorithms/hadoop/scalding/latestrank/src/main/scala/io/prediction/algorithms/scalding/itemsim/latestrank/LatestRank.scala
+++ /dev/null
@@ -1,146 +0,0 @@
-package io.prediction.algorithms.scalding.itemsim.latestrank
-
-import com.twitter.scalding._
-
-import io.prediction.commons.scalding.appdata.{ Items, Users }
-import io.prediction.commons.scalding.modeldata.ItemSimScores
-import io.prediction.commons.filepath.{ AlgoFile }
-import io.prediction.commons.appdata.{ Item }
-
-/**
- * Source:
- *
- * Sink:
- *
- * Description:
- *
- * Args:
- * --training_dbType: <string> training_appdata DB type
- * --training_dbName: <string>
- * --training_dbHost: <string> optional
- * --training_dbPort: <int> optional
- *
- * --modeldata_dbType: <string> modeldata DB type
- * --modeldata_dbName: <string>
- * --modeldata_dbHost: <string> optional
- * --modeldata_dbPort <int> optional
- *
- * --hdfsRoot: <string>. Root directory of the HDFS
- *
- * --appid: <int>
- * --engineid: <int>
- * --algoid: <int>
- * --evalid: <int>. optional. Offline Evaluation if evalid is specified
- *
- * --itypes: <string separated by white space>. optional. eg "--itypes type1 type2". If no --itypes specified, then ALL itypes will be used.
- * --numSimilarItems: <int>. number of similar items to be generated
- *
- * --modelSet: <boolean> (true/false). flag to indicate which set
- * --recommendationTime: <long> (eg. 9876543210). recommend items with starttime <= recommendationTime and endtime > recommendationTime
- *
- * Example:
- * hadoop jar PredictionIO-Process-Hadoop-Scala-assembly-0.1.jar io.prediction.algorithms.scalding.itemsim.latestrank.LatestRank --hdfs --training_dbType mongodb --training_dbName predictionio_appdata --training_dbHost localhost --training_dbPort 27017 --modeldata_dbType mongodb --modeldata_dbName predictionio_modeldata --modeldata_dbHost localhost --modeldata_dbPort 27017 --hdfsRoot predictionio/ --appid 1 --engineid 1 --algoid 18 --modelSet true
- */
-class LatestRank(args: Args) extends Job(args) {
-
-  /**
-   * parse args
-   */
-  val training_dbTypeArg = args("training_dbType")
-  val training_dbNameArg = args("training_dbName")
-  val training_dbHostArg = args.list("training_dbHost")
-  val training_dbPortArg = args.list("training_dbPort") map (x => x.toInt)
-
-  val modeldata_dbTypeArg = args("modeldata_dbType")
-  val modeldata_dbNameArg = args("modeldata_dbName")
-  val modeldata_dbHostArg = args.list("modeldata_dbHost")
-  val modeldata_dbPortArg = args.list("modeldata_dbPort") map (x => x.toInt)
-
-  val hdfsRootArg = args("hdfsRoot")
-
-  val appidArg = args("appid").toInt
-  val engineidArg = args("engineid").toInt
-  val algoidArg = args("algoid").toInt
-  val evalidArg = args.optional("evalid") map (x => x.toInt)
-  val OFFLINE_EVAL = (evalidArg != None) // offline eval mode
-
-  val preItypesArg = args.list("itypes")
-  val itypesArg: Option[List[String]] = if (preItypesArg.mkString(",").length == 0) None else Option(preItypesArg)
-
-  val numSimilarItemsArg = args("numSimilarItems").toInt
-
-  val modelSetArg = args("modelSet").toBoolean
-  val recommendationTimeArg = args("recommendationTime").toLong
-
-  /**
-   * source
-   */
-
-  // get appdata
-  // NOTE: if OFFLINE_EVAL, read from training set, and use evalid as appid when read Items and U2iActions
-  val trainingAppid = if (OFFLINE_EVAL) evalidArg.get else appidArg
-
-  // get items data
-  val latestItems = Items(
-    appId = trainingAppid,
-    itypes = itypesArg,
-    dbType = training_dbTypeArg,
-    dbName = training_dbNameArg,
-    dbHost = training_dbHostArg,
-    dbPort = training_dbPortArg)
-    .readObj('item)
-    .mapTo('item -> ('iidx, 'itypes, 'starttime, 'endtime, 'inactive)) {
-      item: Item =>
-        (item.id,
-          item.itypes,
-          item.starttime.map(_.getMillis()).get,
-          item.endtime.map(_.getMillis()),
-          item.inactive.getOrElse(false)
-        )
-    }
-    .filter('starttime, 'endtime, 'inactive) { fields: (Long, Option[Long], Boolean) =>
-      // only keep items with valid starttime and endtime
-      val (starttimeI, endtimeI, inactive) = fields
-
-      val keepThis: Boolean = (starttimeI, endtimeI) match {
-        case (start, None) => (recommendationTimeArg >= start)
-        case (start, Some(end)) => ((recommendationTimeArg >= start) && (recommendationTimeArg < end))
-        case _ => {
-          assert(false, s"Unexpected item starttime ${starttimeI} and endtime ${endtimeI}")
-          false
-        }
-      }
-      keepThis && (!inactive)
-    }
-    .map('starttime -> 'score) { t: Long => t.toDouble }
-    .groupBy('iidx) { _.sortBy('score).reverse.take(numSimilarItemsArg + 1) }
-
-  val items = Items(
-    appId = trainingAppid,
-    itypes = None,
-    dbType = training_dbTypeArg,
-    dbName = training_dbNameArg,
-    dbHost = training_dbHostArg,
-    dbPort = training_dbPortArg)
-    .readData('iid, 'itypesx)
-
-  /**
-   * sink
-   */
-  val itemSimScores = ItemSimScores(
-    dbType = modeldata_dbTypeArg,
-    dbName = modeldata_dbNameArg,
-    dbHost = modeldata_dbHostArg,
-    dbPort = modeldata_dbPortArg,
-    algoid = algoidArg,
-    modelset = modelSetArg)
-
-  /**
-   * computation
-   */
-  val scores = items.crossWithTiny(latestItems)
-    .filter('iid, 'iidx) { fields: (String, String) => fields._1 != fields._2 }
-    .groupBy('iid) { _.sortBy('score).reverse.take(numSimilarItemsArg) }
-    .groupBy('iid) { _.sortBy('score).reverse.toList[(String, Double, List[String])](('iidx, 'score, 'itypes) -> 'simiidsList) }
-    .then(itemSimScores.writeData('iid, 'simiidsList, algoidArg, modelSetArg) _)
-}
diff --git a/process/engines/itemsim/algorithms/hadoop/scalding/latestrank/src/test/scala/io/prediction/algorithms/scalding/itemsim/latestrank/LatestRankTest.scala b/process/engines/itemsim/algorithms/hadoop/scalding/latestrank/src/test/scala/io/prediction/algorithms/scalding/itemsim/latestrank/LatestRankTest.scala
deleted file mode 100644
index 9b4d9a1..0000000
--- a/process/engines/itemsim/algorithms/hadoop/scalding/latestrank/src/test/scala/io/prediction/algorithms/scalding/itemsim/latestrank/LatestRankTest.scala
+++ /dev/null
@@ -1,215 +0,0 @@
-package io.prediction.algorithms.scalding.itemsim.latestrank
-
-import org.specs2.mutable._
-
-import com.twitter.scalding._
-
-import io.prediction.commons.scalding.appdata.Items
-import io.prediction.commons.scalding.modeldata.{ ItemSimScores }
-import io.prediction.commons.filepath.{ AlgoFile }
-
-class LatestRankTest extends Specification with TupleConversions {
-  def test(
-    algoid: Int,
-    modelSet: Boolean,
-    itypes: List[String],
-    numSimilarItems: Int,
-    recommendationTime: Long,
-    items: List[(String, String, String, String, String, String, String)], // id, itypes, appid, starttime, ct, endtime, inactive
-    itemSimScores: List[(String, String, String, String, Int, Boolean)]) = {
-    val training_dbType = "file"
-    val training_dbName = "testpath/"
-
-    val modeldata_dbType = "file"
-    val modeldata_dbName = "testpath/"
-
-    val hdfsRoot = "testpath/"
-
-    val appid = 7
-    val engineid = 10
-    val evalid = None
-
-    JobTest("io.prediction.algorithms.scalding.itemsim.latestrank.LatestRank")
-      .arg("training_dbType", training_dbType)
-      .arg("training_dbName", training_dbName)
-      .arg("modeldata_dbType", modeldata_dbType)
-      .arg("modeldata_dbName", modeldata_dbName)
-      .arg("hdfsRoot", hdfsRoot)
-      .arg("appid", appid.toString)
-      .arg("engineid", engineid.toString)
-      .arg("algoid", algoid.toString)
-      .arg("itypes", itypes)
-      .arg("numSimilarItems", numSimilarItems.toString)
-      .arg("modelSet", modelSet.toString)
-      .arg("recommendationTime", recommendationTime.toString)
-      .source(Items(appId = appid, itypes = Some(itypes), dbType = training_dbType, dbName = training_dbName, dbHost = Seq(), dbPort = Seq()).getSource, items)
-      .sink[(String, String, String, String, Int, Boolean)](ItemSimScores(dbType = modeldata_dbType, dbName = modeldata_dbName, dbHost = Seq(), dbPort = Seq(), algoid = algoid, modelset = modelSet).getSource) { outputBuffer =>
-        "correctly write ItemSimScores" in {
-          val outputList = outputBuffer.toList
-
-          // convert score to double and compare
-          // because double have different string representation
-          // eg 9.87654321E9 vs 9876543210.0
-          val outputListDouble = outputList.map { x => (x._1, x._2, x._3.split(",").toList.map(_.toDouble), x._4, x._5, x._6) }
-          val expectedDouble = itemSimScores.map { x => (x._1, x._2, x._3.split(",").toList.map(_.toDouble), x._4, x._5, x._6) }
-
-          outputListDouble must containTheSameElementsAs(expectedDouble)
-        }
-      }
-      .run
-      .finish
-  }
-
-  val largeNumber: Long = scala.Long.MaxValue // larger than any item starttime
-  val noEndtime = "PIO_NONE"
-  val noInactive = "PIO_NONE"
-
-  /* test 1 */
-  val algoid = 12
-  val modelSet = false
-  val itypesT1T2 = List("t1", "t2")
-  val itypesAll = List("t1", "t2", "t3", "t4")
-  val items = List(
-    ("i0", "t1,t2,t3", "19", "123456", "345678", noEndtime, noInactive),
-    ("i1", "t2,t3", "19", "123457", "567890", noEndtime, noInactive),
-    ("i2", "t4", "19", "21", "88", noEndtime, noInactive),
-    ("i3", "t3,t4", "19", "9876543210", "67890", noEndtime, noInactive))
-  val itemSimScoresT1T2 = List(
-    ("i3", "i1,i0", "123457.0,123456.0", "[t2,t3],[t1,t2,t3]", algoid, modelSet),
-    ("i2", "i1,i0", "123457.0,123456.0", "[t2,t3],[t1,t2,t3]", algoid, modelSet),
-    ("i1", "i0", "123456.0", "[t1,t2,t3]", algoid, modelSet),
-    ("i0", "i1", "123457.0", "[t2,t3]", algoid, modelSet))
-
-  val itemSimScoresAll = List(
-    ("i3", "i1,i0,i2", "123457.0,123456.0,21.0", "[t2,t3],[t1,t2,t3],[t4]", algoid, modelSet),
-    ("i2", "i3,i1,i0", "9876543210.0,123457.0,123456.0", "[t3,t4],[t2,t3],[t1,t2,t3]", algoid, modelSet),
-    ("i1", "i3,i0,i2", "9876543210.0,123456.0,21.0", "[t3,t4],[t1,t2,t3],[t4]", algoid, modelSet),
-    ("i0", "i3,i1,i2", "9876543210.0,123457.0,21.0", "[t3,t4],[t2,t3],[t4]", algoid, modelSet))
-
-  val itemSimScoresAllTop2 = List(
-    ("i3", "i1,i0", "123457.0,123456.0", "[t2,t3],[t1,t2,t3]", algoid, modelSet),
-    ("i2", "i3,i1", "9876543210.0,123457.0", "[t3,t4],[t2,t3]", algoid, modelSet),
-    ("i1", "i3,i0", "9876543210.0,123456.0", "[t3,t4],[t1,t2,t3]", algoid, modelSet),
-    ("i0", "i3,i1", "9876543210.0,123457.0", "[t3,t4],[t2,t3]", algoid, modelSet))
-
-  "latestrank.LatestRank with some itypes and numSimilarItems larger than number of items" should {
-    test(algoid, modelSet, itypesT1T2, 500, largeNumber, items, itemSimScoresT1T2)
-  }
-
-  "latestrank.LatestRank with all itypes and numSimilarItems larger than number of items" should {
-    test(algoid, modelSet, itypesAll, 500, largeNumber, items, itemSimScoresAll)
-  }
-
-  "latestrank.LatestRank with all itypes numSimilarItems smaller than number of items" should {
-    test(algoid, modelSet, itypesAll, 2, largeNumber, items, itemSimScoresAllTop2)
-  }
-
-  /* test 2: test starttime and endtime */
-  // starttime, endtime
-  // i0  A |---------|
-  // i1    B |---------|E
-  // i2       C|---------|
-  // i3           |---------|
-  //               D        F G
-
-  val tA = 123122
-  val tB = 123123
-  val tC = 123457
-  val tD = 123679
-  val tE = 543322
-  val tF = 543654
-  val tG = 543655
-
-  val test2Algoid = 12
-  val test2ModelSet = false
-
-  val test2ItypesAll = List("t1", "t2", "t3", "t4")
-  val test2Items = List(
-    ("i0", "t1,t2,t3", "19", "123123", "4", "543210", noInactive),
-    ("i1", "t2,t3", "19", "123456", "5", "543321", noInactive),
-    ("i2", "t4", "19", "123567", "6", "543432", noInactive),
-    ("i3", "t3,t4", "19", "123678", "7", "543654", noInactive))
-
-  val test2ItemsInactive = List(
-    ("i0", "t1,t2,t3", "19", "123123", "4", "543210", "false"),
-    ("i1", "t2,t3", "19", "123456", "5", "543321", "true"),
-    ("i2", "t4", "19", "123567", "6", "543432", "true"),
-    ("i3", "t3,t4", "19", "123678", "7", "543654", noInactive))
-
-  val test2Users = List(("u0", "3"), ("u1", "3"), ("u2", "3"), ("u3", "3"))
-
-  val test2ItemSimScoresAll = List(
-    ("i0", "i3,i2,i1", "123678.0,123567.0,123456.0", "[t3,t4],[t4],[t2,t3]", test2Algoid, test2ModelSet),
-    ("i1", "i3,i2,i0", "123678.0,123567.0,123123.0", "[t3,t4],[t4],[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("i2", "i3,i1,i0", "123678.0,123456.0,123123.0", "[t3,t4],[t2,t3],[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("i3", "i2,i1,i0", "123567.0,123456.0,123123.0", "[t4],[t2,t3],[t1,t2,t3]", test2Algoid, test2ModelSet))
-
-  val test2ItemSimScoresAllInactive = List(
-    ("i0", "i3", "123678.0", "[t3,t4]", test2Algoid, test2ModelSet),
-    ("i1", "i3,i0", "123678.0,123123.0", "[t3,t4],[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("i2", "i3,i0", "123678.0,123123.0", "[t3,t4],[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("i3", "i0", "123123.0", "[t1,t2,t3]", test2Algoid, test2ModelSet))
-
-  val test2ItemSimScoresEmpty = List()
-
-  val test2ItemSimScoresi0 = List(
-    ("i1", "i0", "123123.0", "[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("i2", "i0", "123123.0", "[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("i3", "i0", "123123.0", "[t1,t2,t3]", test2Algoid, test2ModelSet))
-
-  val test2ItemSimScoresi0i1 = List(
-    ("i0", "i1", "123456.0", "[t2,t3]", test2Algoid, test2ModelSet),
-    ("i1", "i0", "123123.0", "[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("i2", "i1,i0", "123456.0,123123.0", "[t2,t3],[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("i3", "i1,i0", "123456.0,123123.0", "[t2,t3],[t1,t2,t3]", test2Algoid, test2ModelSet))
-
-  val test2ItemSimScoresi0i1Inactive = List(
-    ("i1", "i0", "123123.0", "[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("i2", "i0", "123123.0", "[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("i3", "i0", "123123.0", "[t1,t2,t3]", test2Algoid, test2ModelSet))
-
-  val test2ItemSimScoresi2i3 = List(
-    ("i0", "i3,i2", "123678.0,123567.0", "[t3,t4],[t4]", test2Algoid, test2ModelSet),
-    ("i1", "i3,i2", "123678.0,123567.0", "[t3,t4],[t4]", test2Algoid, test2ModelSet),
-    ("i2", "i3", "123678.0", "[t3,t4]", test2Algoid, test2ModelSet),
-    ("i3", "i2", "123567.0", "[t4]", test2Algoid, test2ModelSet))
-
-  "recommendationTime < all item starttime" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tA, test2Items, test2ItemSimScoresEmpty)
-  }
-
-  "recommendationTime == earliest starttime" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tB, test2Items, test2ItemSimScoresi0)
-  }
-
-  "recommendationTime > some items starttime" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tC, test2Items, test2ItemSimScoresi0i1)
-  }
-
-  "recommendationTime > some items starttime with some inactive" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tC,
-      test2ItemsInactive, test2ItemSimScoresi0i1Inactive)
-  }
-
-  "recommendationTime > all item starttime and < all item endtime" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tD, test2Items, test2ItemSimScoresAll)
-  }
-
-  "recommendationTime > all item starttime and < all item endtime with some inactive" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tD,
-      test2ItemsInactive, test2ItemSimScoresAllInactive)
-  }
-
-  "recommendationTime > some item endtime" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tE, test2Items, test2ItemSimScoresi2i3)
-  }
-
-  "recommendationTime == last item endtime" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tA, test2Items, test2ItemSimScoresEmpty)
-  }
-
-  "recommendationTime > last item endtime" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tA, test2Items, test2ItemSimScoresEmpty)
-  }
-
-}
diff --git a/process/engines/itemsim/algorithms/hadoop/scalding/mahout/src/main/scala/io/prediction/algorithms/scalding/mahout/itemsim/DataPreparator.scala b/process/engines/itemsim/algorithms/hadoop/scalding/mahout/src/main/scala/io/prediction/algorithms/scalding/mahout/itemsim/DataPreparator.scala
deleted file mode 100644
index 641de3b..0000000
--- a/process/engines/itemsim/algorithms/hadoop/scalding/mahout/src/main/scala/io/prediction/algorithms/scalding/mahout/itemsim/DataPreparator.scala
+++ /dev/null
@@ -1,272 +0,0 @@
-package io.prediction.algorithms.scalding.mahout.itemsim
-
-import com.twitter.scalding._
-
-import io.prediction.commons.scalding.appdata.{ Users, Items, U2iActions }
-import io.prediction.commons.filepath.DataFile
-import io.prediction.commons.appdata.{ Item }
-import org.slf4j.{ Logger, LoggerFactory }
-
-/**
- * Source:
- *
- * Sink:
- *
- * Descripton:
- *   Prepare data for Mahout Item Similarity algo
- *
- * Required args:
- * --dbType: <string> (eg. mongodb) (see --dbHost, --dbPort)
- * --dbName: <string> appdata database name. (eg predictionio_appdata, or predictionio_training_appdata)
- *
- * --hdfsRoot: <string>. Root directory of the HDFS
- *
- * --appid: <int>
- * --engineid: <int>
- * --algoid: <int>
- *
- * --viewParam: <string>. (number 1 to 5, or "ignore")
- * --likeParam: <string>
- * --dislikeParam: <string>
- * --conversionParam: <string>
- * --conflictParam: <string>. (latest/highest/lowest)
- *
- * Optional args:
- * --dbHost: <string> (eg. "127.0.0.1")
- * --dbPort: <int> (eg. 27017)
- *
- * --itypes: <string separated by white space>. eg "--itypes type1 type2". If no --itypes specified, then ALL itypes will be used.
- * --evalid: <int>. Offline Evaluation if evalid is specified
- * --debug: <String>. "test" - for testing purpose
- *
- * Example:
- *
- */
-class DataPreparatorCommon(args: Args) extends Job(args) {
-  /**
-   * parse arguments
-   */
-  val dbTypeArg = args("dbType")
-  val dbNameArg = args("dbName")
-  val dbHostArg = args.list("dbHost")
-  val dbPortArg = args.list("dbPort") map (x => x.toInt) // becomes Option[Int]
-
-  val hdfsRootArg = args("hdfsRoot")
-
-  val appidArg = args("appid").toInt
-  val engineidArg = args("engineid").toInt
-  val algoidArg = args("algoid").toInt
-  val evalidArg = args.optional("evalid") map (x => x.toInt)
-  val OFFLINE_EVAL = (evalidArg != None) // offline eval mode
-
-  val preItypesArg = args.list("itypes")
-  val itypesArg: Option[List[String]] = if (preItypesArg.mkString(",").length == 0) None else Option(preItypesArg)
-
-  // determine how to map actions to rating values
-  def getActionParam(name: String): Option[Int] = {
-    val actionParam: Option[Int] = args(name) match {
-      case "ignore" => None
-      case x => Some(x.toInt)
-    }
-    actionParam
-  }
-
-  val viewParamArg: Option[Int] = getActionParam("viewParam")
-  val likeParamArg: Option[Int] = getActionParam("likeParam")
-  val dislikeParamArg: Option[Int] = getActionParam("dislikeParam")
-  val conversionParamArg: Option[Int] = getActionParam("conversionParam")
-
-  // When there are conflicting actions, e.g. a user gives an item a rating 5 but later dislikes it,
-  // determine which action will be considered as final preference.
-  final val CONFLICT_LATEST: String = "latest" // use latest action
-  final val CONFLICT_HIGHEST: String = "highest" // use the one with highest score
-  final val CONFLICT_LOWEST: String = "lowest" // use the one with lowest score
-
-  val conflictParamArg: String = args("conflictParam")
-
-  // check if the conflictParam is valid
-  require(List(CONFLICT_LATEST, CONFLICT_HIGHEST, CONFLICT_LOWEST).contains(conflictParamArg), "conflict param " + conflictParamArg + " is not valid.")
-
-  val debugArg = args.list("debug")
-  val DEBUG_TEST = debugArg.contains("test") // test mode
-
-  // NOTE: if OFFLINE_EVAL, read from training set, and use evalid as appid when read Items and U2iActions
-  val trainingAppid = if (OFFLINE_EVAL) evalidArg.get else appidArg
-
-  lazy val logger: Logger = LoggerFactory.getLogger(this.getClass)
-}
-
-class DataCopy(args: Args) extends DataPreparatorCommon(args) {
-
-  /**
-   * source
-   */
-
-  val items = Items(appId = trainingAppid, itypes = itypesArg,
-    dbType = dbTypeArg, dbName = dbNameArg, dbHost = dbHostArg, dbPort = dbPortArg).readObj('item)
-
-  val users = Users(appId = trainingAppid,
-    dbType = dbTypeArg, dbName = dbNameArg, dbHost = dbHostArg, dbPort = dbPortArg).readData('uid)
-
-  /**
-   * sink
-   */
-  val userIdSink = Tsv(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "userIds.tsv"))
-
-  val selectedItemSink = Tsv(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "selectedItems.tsv"))
-
-  /**
-   * computation
-   */
-
-  users.write(userIdSink)
-
-  items.mapTo('item -> ('iidx, 'itypes, 'starttime, 'endtime, 'inactive)) {
-    item: Item =>
-
-      // NOTE: convert List[String] into comma-separated String
-      // NOTE: endtime is optional
-      (item.id,
-        item.itypes.mkString(","),
-        item.starttime.map(_.getMillis().toString).getOrElse("PIO_NONE"),
-        item.endtime.map(_.getMillis().toString).getOrElse("PIO_NONE"),
-        item.inactive.map(_.toString).getOrElse("PIO_NONE"))
-  }.write(selectedItemSink)
-
-}
-
-class DataPreparator(args: Args) extends DataPreparatorCommon(args) {
-
-  /**
-   * constants
-   */
-  final val ACTION_RATE = "rate"
-  final val ACTION_LIKE = "like"
-  final val ACTION_DISLIKE = "dislike"
-  final val ACTION_VIEW = "view"
-  //final val ACTION_VIEWDETAILS = "viewDetails"
-  final val ACTION_CONVERSION = "conversion"
-
-  /**
-   * source
-   */
-
-  val u2i = U2iActions(appId = trainingAppid,
-    dbType = dbTypeArg, dbName = dbNameArg, dbHost = dbHostArg, dbPort = dbPortArg).readData('action, 'uid, 'iid, 't, 'v)
-
-  // use byte offset as index for Mahout algo
-  val itemsIndex = TextLine(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "selectedItems.tsv")).read
-    .mapTo(('offset, 'line) -> ('iindex, 'iidx, 'itypes, 'starttime, 'endtime, 'inactive)) { fields: (String, String) =>
-      val (offset, line) = fields
-
-      val lineArray = line.split("\t")
-
-      val (iidx, itypes, starttime, endtime, inactive) = try {
-        (lineArray(0), lineArray(1), lineArray(2), lineArray(3), lineArray(4))
-      } catch {
-        case e: Exception => {
-          assert(false, "Failed to extract iidx and itypes from the line: " + line + ". Exception: " + e)
-          (0, "dummy", "dummy", "dummy")
-        }
-      }
-
-      (offset, iidx, itypes, starttime, endtime, inactive)
-    }
-
-  val usersIndex = TextLine(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "userIds.tsv")).read
-    .rename(('offset, 'line) -> ('uindex, 'uidx))
-
-  /**
-   * sink
-   */
-
-  val itemsIndexSink = Tsv(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "itemsIndex.tsv"))
-
-  val usersIndexSink = Tsv(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "usersIndex.tsv"))
-
-  val ratingsSink = Csv(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "ratings.csv"))
-
-  /**
-   * computation
-   */
-
-  itemsIndex.write(itemsIndexSink)
-
-  usersIndex.write(usersIndexSink)
-
-  // filter and pre-process actions
-  u2i.joinWithSmaller('iid -> 'iidx, itemsIndex) // only select actions of these items
-    .filter('action, 'v) { fields: (String, Option[String]) =>
-      val (action, v) = fields
-
-      val keepThis: Boolean = action match {
-        case ACTION_RATE => true
-        case ACTION_LIKE => (likeParamArg != None)
-        case ACTION_DISLIKE => (dislikeParamArg != None)
-        case ACTION_VIEW => (viewParamArg != None)
-        case ACTION_CONVERSION => (conversionParamArg != None)
-        case _ => {
-          logger.debug(s"Found custom action ${action}")
-          false // all other unsupported actions
-        }
-      }
-      keepThis
-    }
-    .map(('action, 'v, 't) -> ('rating, 'tLong)) { fields: (String, Option[String], String) =>
-      val (action, v, t) = fields
-
-      // convert actions into rating value based on "action" and "v" fields
-      val rating: Int = action match {
-        case ACTION_RATE => try {
-          v.get.toInt
-        } catch {
-          case e: Exception => {
-            assert(false, s"Failed to convert v field ${v} to integer for ${action} action. Exception:" + e)
-            1
-          }
-        }
-        case ACTION_LIKE => likeParamArg.getOrElse {
-          assert(false, "Action type " + action + " should have been filtered out!")
-          1
-        }
-        case ACTION_DISLIKE => dislikeParamArg.getOrElse {
-          assert(false, "Action type " + action + " should have been filtered out!")
-          1
-        }
-        case ACTION_VIEW => viewParamArg.getOrElse {
-          assert(false, "Action type " + action + " should have been filtered out!")
-          1
-        }
-        case ACTION_CONVERSION => conversionParamArg.getOrElse {
-          assert(false, "Action type " + action + " should have been filtered out!")
-          1
-        }
-        case _ => { // all other unsupported actions
-          assert(false, "Action type " + action + " in u2iActions appdata is not supported!")
-          1
-        }
-      }
-
-      (rating, t.toLong)
-    }
-    .then(resolveConflict('uid, 'iid, 'tLong, 'rating, conflictParamArg) _)
-    .joinWithSmaller('uid -> 'uidx, usersIndex)
-    .project('uindex, 'iindex, 'rating)
-    .write(ratingsSink) // write ratings to a file
-
-  /**
-   * function to resolve conflicting actions of same uid-iid pair.
-   */
-  def resolveConflict(uidField: Symbol, iidField: Symbol, tfield: Symbol, ratingField: Symbol, conflictSolution: String)(p: RichPipe): RichPipe = {
-
-    // NOTE: sortBy() sort from smallest to largest. use reverse to pick the largest one.
-    val dataPipe = conflictSolution match {
-      case CONFLICT_LATEST => p.groupBy(uidField, iidField) { _.sortBy(tfield).reverse.take(1) } // take latest one (largest t)
-      case CONFLICT_HIGHEST => p.groupBy(uidField, iidField) { _.sortBy(ratingField).reverse.take(1) } // take highest rating
-      case CONFLICT_LOWEST => p.groupBy(uidField, iidField) { _.sortBy(ratingField).take(1) } // take lowest rating
-    }
-
-    dataPipe
-  }
-
-}
diff --git a/process/engines/itemsim/algorithms/hadoop/scalding/mahout/src/main/scala/io/prediction/algorithms/scalding/mahout/itemsim/ModelConstructor.scala b/process/engines/itemsim/algorithms/hadoop/scalding/mahout/src/main/scala/io/prediction/algorithms/scalding/mahout/itemsim/ModelConstructor.scala
deleted file mode 100644
index f894e57..0000000
--- a/process/engines/itemsim/algorithms/hadoop/scalding/mahout/src/main/scala/io/prediction/algorithms/scalding/mahout/itemsim/ModelConstructor.scala
+++ /dev/null
@@ -1,153 +0,0 @@
-package io.prediction.algorithms.scalding.mahout.itemsim
-
-import com.twitter.scalding._
-
-import io.prediction.commons.filepath.{ DataFile, AlgoFile }
-import io.prediction.commons.scalding.modeldata.ItemSimScores
-
-/**
- * Source:
- *
- * Sink:
- *
- * Description:
- *
- * Required args:
- * --dbType: <string> modeldata DB type (eg. mongodb) (see --dbHost, --dbPort)
- * --dbName: <string> (eg. predictionio_modeldata)
- *
- * --hdfsRoot: <string>. Root directory of the HDFS
- *
- * --appid: <int>
- * --engineid: <int>
- * --algoid: <int>
- * --modelSet: <boolean> (true/false). flag to indicate which set
- *
- * --numSimilarItems: <int>. number of similar items to be generated
- * --recommendationTime: <long> (eg. 9876543210). recommend items with starttime <= recommendationTime and endtime > recommendationTime
- *
- * Optionsl args:
- * --dbHost: <string> (eg. "127.0.0.1")
- * --dbPort: <int> (eg. 27017)
- *
- * --evalid: <int>. Offline Evaluation if evalid is specified
- * --debug: <String>. "test" - for testing purpose
- *
- * Example:
- *
- */
-class ModelConstructor(args: Args) extends Job(args) {
-
-  /**
-   * parse args
-   */
-  val dbTypeArg = args("dbType")
-  val dbNameArg = args("dbName")
-  val dbHostArg = args.list("dbHost")
-  val dbPortArg = args.list("dbPort") map (x => x.toInt)
-
-  val hdfsRootArg = args("hdfsRoot")
-
-  val appidArg = args("appid").toInt
-  val engineidArg = args("engineid").toInt
-  val algoidArg = args("algoid").toInt
-  val evalidArg = args.optional("evalid") map (x => x.toInt)
-  val OFFLINE_EVAL = (evalidArg != None) // offline eval mode
-
-  val debugArg = args.list("debug")
-  val DEBUG_TEST = debugArg.contains("test") // test mode
-
-  val modelSetArg = args("modelSet").toBoolean
-
-  val numSimilarItems = args("numSimilarItems").toInt
-  val recommendationTimeArg = args("recommendationTime").toLong
-
-  /**
-   * source
-   */
-  val similarities = Tsv(AlgoFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "similarities.tsv"), ('iindex, 'simiindex, 'score)).read
-    .mapTo(('iindex, 'simiindex, 'score) -> ('iindex, 'simiindex, 'score)) {
-      fields: (String, String, Double) => fields // convert score from String to Double
-    }
-
-  val itemsIndex = Tsv(DataFile(hdfsRootArg, appidArg, engineidArg, algoidArg, evalidArg, "itemsIndex.tsv")).read
-    .mapTo((0, 1, 2, 3, 4, 5) -> ('iindexI, 'iidI, 'itypesI, 'starttimeI, 'endtimeI, 'inactiveI)) { fields: (String, String, String, Long, String, String) =>
-      val (iindex, iid, itypes, starttime, endtime, inactive) = fields // itypes are comma-separated String
-
-      val endtimeOpt: Option[Long] = endtime match {
-        case "PIO_NONE" => None
-        case x: String => {
-          try {
-            Some(x.toLong)
-          } catch {
-            case e: Exception => {
-              assert(false, s"Failed to convert ${x} to Long. Exception: " + e)
-              Some(0)
-            }
-          }
-        }
-      }
-
-      val inactiveB: Boolean = inactive match {
-        case "PIO_NONE" => false
-        case x: String => {
-          try {
-            x.toBoolean
-          } catch {
-            case e: Exception => {
-              assert(false, s"Failed to convert ${x} to Boolean. Exception: " + e)
-              false
-            }
-          }
-        }
-      }
-
-      (iindex, iid, itypes.split(",").toList, starttime, endtimeOpt, inactiveB)
-    }
-
-  /**
-   * sink
-   */
-
-  val ItemSimScoresSink = ItemSimScores(dbType = dbTypeArg, dbName = dbNameArg, dbHost = dbHostArg, dbPort = dbPortArg, algoid = algoidArg, modelset = modelSetArg)
-
-  /**
-   * computation
-   */
-  val sim = similarities.joinWithSmaller('iindex -> 'iindexI, itemsIndex)
-    .discard('iindex, 'iindexI)
-    .rename(('iidI, 'itypesI, 'starttimeI, 'endtimeI, 'inactiveI) -> ('iid, 'itypes, 'starttime, 'endtime, 'inactive))
-    .joinWithSmaller('simiindex -> 'iindexI, itemsIndex)
-
-  // NOTE: use simiid's starttime and endtime. not iid's.
-  val sim1 = sim.project('iid, 'iidI, 'itypesI, 'score, 'starttimeI, 'endtimeI, 'inactiveI)
-  // NOTE: mahout only calculate half of the sim matrix, reverse the fields to get the other half
-  val sim2 = sim.mapTo(('iidI, 'iid, 'itypes, 'score, 'starttime, 'endtime, 'inactive) -> ('iid, 'iidI, 'itypesI, 'score, 'starttimeI, 'endtimeI, 'inactiveI)) {
-    fields: (String, String, List[String], Double, Long, Option[Long], Boolean) => fields
-  }
-
-  val combinedSimilarities = sim1 ++ sim2
-
-  combinedSimilarities
-    .filter('starttimeI, 'endtimeI, 'inactiveI) { fields: (Long, Option[Long], Boolean) =>
-      val (starttimeI, endtimeI, inactiveI) = fields
-
-      val keepThis: Boolean = (starttimeI, endtimeI) match {
-        case (start, None) => (recommendationTimeArg >= start)
-        case (start, Some(end)) => ((recommendationTimeArg >= start) && (recommendationTimeArg < end))
-        case _ => {
-          assert(false, s"Unexpected item starttime ${starttimeI} and endtime ${endtimeI}")
-          false
-        }
-      }
-      keepThis && (!inactiveI)
-    }
-    .groupBy('iid) { _.sortBy('score).reverse.toList[(String, Double, List[String])](('iidI, 'score, 'itypesI) -> 'simiidsList) }
-    .mapTo(('iid, 'simiidsList) -> ('iid, 'simiidsList)) { fields: (String, List[(String, Double, List[String])]) =>
-      val (iid, simiidsList) = fields
-
-      (iid, simiidsList.take(numSimilarItems))
-    }
-    .then(ItemSimScoresSink.writeData('iid, 'simiidsList, algoidArg, modelSetArg) _)
-
-}
diff --git a/process/engines/itemsim/algorithms/hadoop/scalding/mahout/src/test/scala/io/prediction/algorithms/scalding/mahout/itemsim/DataPreparatorTest.scala b/process/engines/itemsim/algorithms/hadoop/scalding/mahout/src/test/scala/io/prediction/algorithms/scalding/mahout/itemsim/DataPreparatorTest.scala
deleted file mode 100644
index cb18d17..0000000
--- a/process/engines/itemsim/algorithms/hadoop/scalding/mahout/src/test/scala/io/prediction/algorithms/scalding/mahout/itemsim/DataPreparatorTest.scala
+++ /dev/null
@@ -1,454 +0,0 @@
-package io.prediction.algorithms.scalding.mahout.itemsim
-
-import org.specs2.mutable._
-
-import com.twitter.scalding._
-
-import io.prediction.commons.scalding.appdata.{ Users, Items, U2iActions }
-import io.prediction.commons.filepath.DataFile
-
-class DataPreparatorTest extends Specification with TupleConversions {
-
-  val Rate = "rate"
-  val Like = "like"
-  val Dislike = "dislike"
-  val View = "view"
-  //val ViewDetails = "viewDetails"
-  val Conversion = "conversion"
-
-  val appid = 2
-
-  def test(itypes: List[String], params: Map[String, String],
-    items: List[(String, String, String, String, String, String, String)], // id, itypes, appid, starttime, ct, endtime, inactive
-    users: List[Tuple1[String]],
-    u2iActions: List[(String, String, String, String, String)],
-    ratings: List[(String, String, String)],
-    selectedItems: List[(String, String, String, String, String)], // id, itypes, starttime, endtime, inactive
-    itemsIndexer: Map[String, String],
-    usersIndexer: Map[String, String]) = {
-
-    val userIds = users map (x => x._1)
-    val selectedItemsTextLine = selectedItems map { x => (itemsIndexer(x._1), x.productIterator.mkString("\t")) }
-    val usersTextLine = users map { x => (usersIndexer(x._1), x._1) }
-
-    val itemsIndex = selectedItems map { x => (itemsIndexer(x._1), x._1, x._2, x._3, x._4, x._5) }
-    val usersIndex = users map { x => (usersIndexer(x._1), x._1) }
-
-    val ratingsIndexed = ratings map { x => (usersIndexer(x._1), itemsIndexer(x._2), x._3) }
-
-    val dbType = "file"
-    val dbName = "testpath/"
-    val dbHost = Seq()
-    val dbPort = Seq()
-    val hdfsRoot = "testroot/"
-
-    val engineid = 4
-    val algoid = 5
-    val evalid = None
-
-    JobTest("io.prediction.algorithms.scalding.mahout.itemsim.DataCopy")
-      .arg("dbType", dbType)
-      .arg("dbName", dbName)
-      .arg("hdfsRoot", hdfsRoot)
-      .arg("appid", appid.toString)
-      .arg("engineid", engineid.toString)
-      .arg("algoid", algoid.toString)
-      .arg("itypes", itypes)
-      .arg("viewParam", params("viewParam"))
-      .arg("likeParam", params("likeParam"))
-      .arg("dislikeParam", params("dislikeParam"))
-      .arg("conversionParam", params("conversionParam"))
-      .arg("conflictParam", params("conflictParam"))
-      .source(Items(appId = appid, itypes = Some(itypes), dbType = dbType, dbName = dbName, dbHost = dbHost, dbPort = dbPort).getSource, items)
-      .source(Users(appId = appid, dbType = dbType, dbName = dbName, dbHost = dbHost, dbPort = dbPort).getSource, users)
-      .sink[(String)](Tsv(DataFile(hdfsRoot, appid, engineid, algoid, evalid, "userIds.tsv"))) { outputBuffer =>
-        "correctly write userIds.tsv" in {
-          outputBuffer.toList must containTheSameElementsAs(userIds)
-        }
-      }
-      .sink[(String, String, String, String, String)](Tsv(DataFile(hdfsRoot, appid, engineid, algoid, evalid, "selectedItems.tsv"))) { outputBuffer =>
-        "correctly write selectedItems.tsv" in {
-          outputBuffer.toList must containTheSameElementsAs(selectedItems)
-        }
-      }
-      .run
-      .finish
-
-    JobTest("io.prediction.algorithms.scalding.mahout.itemsim.DataPreparator")
-      .arg("dbType", dbType)
-      .arg("dbName", dbName)
-      .arg("hdfsRoot", hdfsRoot)
-      .arg("appid", appid.toString)
-      .arg("engineid", engineid.toString)
-      .arg("algoid", algoid.toString)
-      .arg("itypes", itypes)
-      .arg("viewParam", params("viewParam"))
-      .arg("likeParam", params("likeParam"))
-      .arg("dislikeParam", params("dislikeParam"))
-      .arg("conversionParam", params("conversionParam"))
-      .arg("conflictParam", params("conflictParam"))
-      .source(U2iActions(appId = appid, dbType = dbType, dbName = dbName, dbHost = dbHost, dbPort = dbPort).getSource, u2iActions)
-      .source(TextLine(DataFile(hdfsRoot, appid, engineid, algoid, evalid, "selectedItems.tsv")), selectedItemsTextLine)
-      .source(TextLine(DataFile(hdfsRoot, appid, engineid, algoid, evalid, "userIds.tsv")), usersTextLine)
-      .sink[(String, String, String, String, String, String)](Tsv(DataFile(hdfsRoot, appid, engineid, algoid, evalid, "itemsIndex.tsv"))) { outputBuffer =>
-        // index, iid, itypes
-        "correctly write itemsIndex.tsv" in {
-          outputBuffer.toList must containTheSameElementsAs(itemsIndex)
-        }
-      }
-      .sink[(String, String)](Tsv(DataFile(hdfsRoot, appid, engineid, algoid, evalid, "usersIndex.tsv"))) { outputBuffer =>
-        // index, uid
-        "correctly write usersIndex.tsv" in {
-          outputBuffer.toList must containTheSameElementsAs(usersIndex)
-        }
-      }
-      .sink[(String, String, String)](Csv(DataFile(hdfsRoot, appid, engineid, algoid, evalid, "ratings.csv"))) { outputBuffer =>
-        "correctly process and write data to ratings.csv" in {
-          outputBuffer.toList must containTheSameElementsAs(ratingsIndexed)
-        }
-      }
-      .run
-      .finish
-
-  }
-
-  val noEndtime = "PIO_NONE"
-  val noInactive = "PIO_NONE"
-
-  /**
-   * Test 1. basic. Rate actions only without conflicts
-   */
-  val test1AllItypes = List("t1", "t2", "t3", "t4")
-  val test1ItemsMap = Map(
-    // id, itypes, appid, starttime, ct, endtime
-    "i0" -> ("i0", "t1,t2,t3", appid.toString, "12345", "12346", noEndtime,
-      noInactive),
-    "i1" -> ("i1", "t2,t3", appid.toString, "12347", "12348", noEndtime,
-      noInactive),
-    "i2" -> ("i2", "t4", appid.toString, "12349", "12350", noEndtime,
-      noInactive),
-    "i3" -> ("i3", "t3,t4", appid.toString, "12351", "12352", noEndtime,
-      noInactive))
-
-  val test1Items = List(
-    test1ItemsMap("i0"),
-    test1ItemsMap("i1"),
-    test1ItemsMap("i2"),
-    test1ItemsMap("i3"))
-
-  def genSelectedItems(items: List[(String, String, String, String, String, String, String)]) = {
-    items map { x =>
-      val (id, itypes, appid, starttime, ct, endtime, inactive) = x
-      (id, itypes, starttime, endtime, inactive)
-    }
-  }
-
-  val test1ItemsIndexer = Map("i0" -> "0", "i1" -> "4", "i2" -> "7", "i3" -> "8") // map iid to index
-
-  val test1Users = List(Tuple1("u0"), Tuple1("u1"), Tuple1("u2"), Tuple1("u3"))
-  val test1UsersIndexer = Map("u0" -> "0", "u1" -> "1", "u2" -> "2", "u3" -> "3") // map uid to index
-
-  val test1U2i = List(
-    (Rate, "u0", "i0", "123450", "3"),
-    (Rate, "u0", "i1", "123457", "1"),
-    (Rate, "u0", "i2", "123458", "4"),
-    (Rate, "u0", "i3", "123459", "2"),
-    (Rate, "u1", "i0", "123457", "5"),
-    (Rate, "u1", "i1", "123458", "2"))
-
-  val test1Ratings = List(
-    ("u0", "i0", "3"),
-    ("u0", "i1", "1"),
-    ("u0", "i2", "4"),
-    ("u0", "i3", "2"),
-    ("u1", "i0", "5"),
-    ("u1", "i1", "2"))
-
-  val test1Params: Map[String, String] = Map("viewParam" -> "3", "likeParam" -> "4", "dislikeParam" -> "1", "conversionParam" -> "5",
-    "conflictParam" -> "latest")
-
-  "DataPreparator with only rate actions, all itypes, no conflict" should {
-    test(test1AllItypes, test1Params, test1Items, test1Users, test1U2i, test1Ratings, genSelectedItems(test1Items), test1ItemsIndexer, test1UsersIndexer)
-  }
-
-  "DataPreparator with only rate actions, no itypes specified, no conflict" should {
-    test(List(), test1Params, test1Items, test1Users, test1U2i, test1Ratings, genSelectedItems(test1Items), test1ItemsIndexer, test1UsersIndexer)
-  }
-
-  /**
-   * Test 2. rate actions only with conflicts
-   */
-  val test2AllItypes = List("t1", "t2", "t3", "t4")
-  val test2ItemsMap = Map(
-    // id, itypes, appid, starttime, ct, endtime
-    "i0" -> ("i0", "t1,t2,t3", appid.toString, "12345", "12346", noEndtime,
-      noInactive),
-    "i1" -> ("i1", "t2,t3", appid.toString, "12347", "12348", noEndtime,
-      noInactive),
-    "i2" -> ("i2", "t4", appid.toString, "12349", "12350", noEndtime,
-      noInactive),
-    "i3" -> ("i3", "t3,t4", appid.toString, "12351", "12352", noEndtime,
-      noInactive))
-
-  val test2Items = List(
-    test2ItemsMap("i0"),
-    test2ItemsMap("i1"),
-    test2ItemsMap("i2"),
-    test2ItemsMap("i3"))
-
-  val test2ItemsIndexer = Map("i0" -> "0", "i1" -> "4", "i2" -> "7", "i3" -> "8") // map iid to index
-
-  val test2Users = List(Tuple1("u0"), Tuple1("u1"), Tuple1("u2"), Tuple1("u3"))
-  val test2UsersIndexer = Map("u0" -> "0", "u1" -> "1", "u2" -> "2", "u3" -> "3") // map uid to index
-
-  val test2U2i = List(
-    (Rate, "u0", "i0", "123448", "3"),
-    (Rate, "u0", "i0", "123449", "4"), // highest
-    (Rate, "u0", "i0", "123451", "2"), // latest
-    (Rate, "u0", "i0", "123450", "1"), // lowest
-
-    (Rate, "u0", "i1", "123456", "1"), // lowest
-    (Rate, "u0", "i1", "123457", "2"),
-    (Rate, "u0", "i1", "123458", "3"), // latest, highest
-
-    (Rate, "u0", "i2", "123461", "2"), // latest, lowest
-    (Rate, "u0", "i2", "123459", "3"),
-    (Rate, "u0", "i2", "123460", "5"), // highest
-
-    (Rate, "u0", "i3", "123459", "2"),
-    (Rate, "u1", "i0", "123457", "5"),
-
-    (Rate, "u1", "i1", "123458", "3"), // lowest
-    (Rate, "u1", "i1", "123459", "4"), // highest
-    (Rate, "u1", "i1", "123460", "3")) // latest, lowest
-
-  val test2RatingsLatest = List(
-    ("u0", "i0", "2"),
-    ("u0", "i1", "3"),
-    ("u0", "i2", "2"),
-    ("u0", "i3", "2"),
-    ("u1", "i0", "5"),
-    ("u1", "i1", "3"))
-
-  val test2RatingsHighest = List(
-    ("u0", "i0", "4"),
-    ("u0", "i1", "3"),
-    ("u0", "i2", "5"),
-    ("u0", "i3", "2"),
-    ("u1", "i0", "5"),
-    ("u1", "i1", "4"))
-
-  val test2RatingsLowest = List(
-    ("u0", "i0", "1"),
-    ("u0", "i1", "1"),
-    ("u0", "i2", "2"),
-    ("u0", "i3", "2"),
-    ("u1", "i0", "5"),
-    ("u1", "i1", "3"))
-
-  val test2Itypes_t1t4 = List("t1", "t4")
-  val test2Items_t1t4 = List(
-    test2ItemsMap("i0"),
-    test2ItemsMap("i2"),
-    test2ItemsMap("i3"))
-
-  val test2RatingsHighest_t1t4 = List(
-    ("u0", "i0", "4"),
-    ("u0", "i2", "5"),
-    ("u0", "i3", "2"),
-    ("u1", "i0", "5"))
-
-  val test2Params: Map[String, String] = Map("viewParam" -> "3", "likeParam" -> "4", "dislikeParam" -> "1", "conversionParam" -> "5",
-    "conflictParam" -> "latest")
-  val test2ParamsHighest = test2Params + ("conflictParam" -> "highest")
-  val test2ParamsLowest = test2Params + ("conflictParam" -> "lowest")
-
-  "DataPreparator with only rate actions, all itypes, conflict=latest" should {
-    test(test2AllItypes, test2Params, test2Items, test2Users, test2U2i, test2RatingsLatest, genSelectedItems(test2Items), test2ItemsIndexer, test2UsersIndexer)
-  }
-
-  "DataPreparator with only rate actions, all itypes, conflict=highest" should {
-    test(test2AllItypes, test2ParamsHighest, test2Items, test2Users, test2U2i, test2RatingsHighest, genSelectedItems(test2Items), test2ItemsIndexer, test2UsersIndexer)
-  }
-
-  "DataPreparator with only rate actions, all itypes, conflict=lowest" should {
-    test(test2AllItypes, test2ParamsLowest, test2Items, test2Users, test2U2i, test2RatingsLowest, genSelectedItems(test2Items), test2ItemsIndexer, test2UsersIndexer)
-  }
-
-  "DataPreparator with only rate actions, some itypes, conflict=highest" should {
-    test(test2Itypes_t1t4, test2ParamsHighest, test2Items, test2Users, test2U2i, test2RatingsHighest_t1t4, genSelectedItems(test2Items_t1t4), test2ItemsIndexer, test2UsersIndexer)
-  }
-
-  /**
-   * Test 3. Different Actions without conflicts
-   */
-  val test3AllItypes = List("t1", "t2", "t3", "t4")
-  val test3ItemsMap = Map(
-    // id, itypes, appid, starttime, ct, endtime
-    "i0" -> ("i0", "t1,t2,t3", appid.toString, "12345", "12346", "56789",
-      noInactive),
-    "i1" -> ("i1", "t2,t3", appid.toString, "12347", "12348", noEndtime,
-      noInactive),
-    "i2" -> ("i2", "t4", appid.toString, "12349", "12350", "56790",
-      noInactive),
-    "i3" -> ("i3", "t3,t4", appid.toString, "12351", "12352", noEndtime,
-      noInactive))
-
-  val test3Items = List(
-    test3ItemsMap("i0"),
-    test3ItemsMap("i1"),
-    test3ItemsMap("i2"),
-    test3ItemsMap("i3"))
-
-  val test3ItemsIndexer = Map("i0" -> "0", "i1" -> "4", "i2" -> "7", "i3" -> "8") // map iid to index
-
-  val test3Users = List(Tuple1("u0"), Tuple1("u1"), Tuple1("u2"), Tuple1("u3"))
-  val test3UsersIndexer = Map("u0" -> "0", "u1" -> "1", "u2" -> "2", "u3" -> "3") // map uid to index
-
-  val test3U2i = List(
-    (Rate, "u0", "i0", "123450", "4"),
-    (Like, "u0", "i1", "123457", "PIO_NONE"),
-    (Dislike, "u0", "i2", "123458", "PIO_NONE"),
-    (View, "u0", "i3", "123459", "PIO_NONE"), // NOTE: assume v field won't be missing
-    (Rate, "u1", "i0", "123457", "2"),
-    (Conversion, "u1", "i1", "123458", "PIO_NONE"))
-
-  val test3Ratings = List(
-    ("u0", "i0", "4"),
-    ("u0", "i1", "4"),
-    ("u0", "i2", "2"),
-    ("u0", "i3", "1"),
-    ("u1", "i0", "2"),
-    ("u1", "i1", "5"))
-
-  val test3Params: Map[String, String] = Map("viewParam" -> "1", "likeParam" -> "4", "dislikeParam" -> "2", "conversionParam" -> "5",
-    "conflictParam" -> "latest")
-
-  "DataPreparator with only all actions, all itypes, no conflict" should {
-    test(test3AllItypes, test3Params, test3Items, test3Users, test3U2i, test3Ratings, genSelectedItems(test3Items), test3ItemsIndexer, test3UsersIndexer)
-  }
-
-  /**
-   * test 4. Different Actions with conflicts
-   */
-  val test4Params: Map[String, String] = Map("viewParam" -> "2", "likeParam" -> "5", "dislikeParam" -> "1", "conversionParam" -> "4",
-    "conflictParam" -> "latest")
-
-  val test4AllItypes = List("t1", "t2", "t3", "t4")
-  val test4ItemsMap = Map(
-    // id, itypes, appid, starttime, ct, endtime
-    "i0" -> ("i0", "t1,t2,t3", appid.toString, "12345", "12346", "56789",
-      noInactive),
-    "i1" -> ("i1", "t2,t3", appid.toString, "12347", "12348", noEndtime,
-      "true"),
-    "i2" -> ("i2", "t4", appid.toString, "12349", "12350", "56790",
-      "true"),
-    "i3" -> ("i3", "t3,t4", appid.toString, "12351", "12352", noEndtime,
-      "false"))
-
-  val test4Items = List(
-    test4ItemsMap("i0"),
-    test4ItemsMap("i1"),
-    test4ItemsMap("i2"),
-    test4ItemsMap("i3"))
-
-  val test4ItemsIndexer = Map("i0" -> "0", "i1" -> "4", "i2" -> "7", "i3" -> "8") // map iid to index
-
-  val test4Users = List(Tuple1("u0"), Tuple1("u1"), Tuple1("u2"), Tuple1("u3"))
-  val test4UsersIndexer = Map("u0" -> "0", "u1" -> "1", "u2" -> "2", "u3" -> "3") // map uid to index
-
-  val test4U2i = List(
-    (Rate, "u0", "i0", "123448", "3"),
-    (View, "u0", "i0", "123449", "PIO_NONE"), // lowest (2)
-    (Like, "u0", "i0", "123451", "PIO_NONE"), // latest, highest (5)
-    (Conversion, "u0", "i0", "123450", "PIO_NONE"),
-
-    (Rate, "u0", "i1", "123456", "1"), // lowest
-    (Rate, "u0", "i1", "123457", "4"), // highest
-    (View, "u0", "i1", "123458", "PIO_NONE"), // latest (2)
-
-    (Conversion, "u0", "i2", "123461", "PIO_NONE"), // latest, highest  (4)
-    (Rate, "u0", "i2", "123459", "3"),
-    (View, "u0", "i2", "123460", "PIO_NONE"), // lowest
-
-    (Rate, "u0", "i3", "123459", "2"),
-    (View, "u1", "i0", "123457", "PIO_NONE"), // (2)
-
-    (Rate, "u1", "i1", "123458", "5"), // highest
-    (Conversion, "u1", "i1", "123459", "PIO_NONE"), // (4)
-    (Dislike, "u1", "i1", "123460", "PIO_NONE")) // latest, lowest (1)
-
-  val test4RatingsLatest = List(
-    ("u0", "i0", "5"),
-    ("u0", "i1", "2"),
-    ("u0", "i2", "4"),
-    ("u0", "i3", "2"),
-    ("u1", "i0", "2"),
-    ("u1", "i1", "1"))
-
-  "DataPreparator with all actions, all itypes, and conflicts=latest" should {
-    test(test4AllItypes, test4Params, test4Items, test4Users, test4U2i, test4RatingsLatest, genSelectedItems(test4Items), test4ItemsIndexer, test4UsersIndexer)
-  }
-
-  val test4ParamsIgnoreView = test4Params + ("viewParam" -> "ignore")
-
-  val test4RatingsIgnoreViewLatest = List(
-    ("u0", "i0", "5"),
-    ("u0", "i1", "4"),
-    ("u0", "i2", "4"),
-    ("u0", "i3", "2"),
-    ("u1", "i1", "1"))
-
-  "DataPreparator with all actions, all itypes, ignore View actions and conflicts=latest" should {
-    test(test4AllItypes, test4ParamsIgnoreView, test4Items, test4Users, test4U2i, test4RatingsIgnoreViewLatest, genSelectedItems(test4Items), test4ItemsIndexer, test4UsersIndexer)
-  }
-
-  // note: currently rate action can't be ignored
-  val test4ParamsIgnoreAllExceptView = test4Params + ("viewParam" -> "1", "likeParam" -> "ignore", "dislikeParam" -> "ignore", "conversionParam" -> "ignore")
-
-  val test4RatingsIgnoreAllExceptViewLatest = List(
-    ("u0", "i0", "1"),
-    ("u0", "i1", "1"),
-    ("u0", "i2", "1"),
-    ("u0", "i3", "2"),
-    ("u1", "i0", "1"),
-    ("u1", "i1", "5"))
-
-  "DataPreparator with all actions, all itypes, ignore all actions except View (and Rate) and conflicts=latest" should {
-    test(test4AllItypes, test4ParamsIgnoreAllExceptView, test4Items, test4Users, test4U2i, test4RatingsIgnoreAllExceptViewLatest, genSelectedItems(test4Items), test4ItemsIndexer, test4UsersIndexer)
-  }
-
-  // note: meaning rate action only
-  val test4ParamsIgnoreAll = test4Params + ("viewParam" -> "ignore", "likeParam" -> "ignore", "dislikeParam" -> "ignore", "conversionParam" -> "ignore")
-
-  val test4RatingsIgnoreAllLatest = List(
-    ("u0", "i0", "3"),
-    ("u0", "i1", "4"),
-    ("u0", "i2", "3"),
-    ("u0", "i3", "2"),
-    ("u1", "i1", "5"))
-
-  "DataPreparator with all actions, all itypes, ignore all actions (except Rate) and conflicts=latest" should {
-    test(test4AllItypes, test4ParamsIgnoreAll, test4Items, test4Users, test4U2i, test4RatingsIgnoreAllLatest, genSelectedItems(test4Items), test4ItemsIndexer, test4UsersIndexer)
-  }
-
-  val test4ParamsLowest: Map[String, String] = test4Params + ("conflictParam" -> "lowest")
-
-  val test4Itypes_t3 = List("t3")
-  val test4Items_t3 = List(
-    test4ItemsMap("i0"),
-    test4ItemsMap("i1"),
-    test4ItemsMap("i3"))
-
-  val test4RatingsLowest_t3 = List(
-    ("u0", "i0", "2"),
-    ("u0", "i1", "1"),
-    ("u0", "i3", "2"),
-    ("u1", "i0", "2"),
-    ("u1", "i1", "1"))
-
-  "DataPreparator with only all actions, some itypes, and conflicts=lowest" should {
-    test(test4Itypes_t3, test4ParamsLowest, test4Items, test4Users, test4U2i, test4RatingsLowest_t3, genSelectedItems(test4Items_t3), test4ItemsIndexer, test4UsersIndexer)
-  }
-
-}
diff --git a/process/engines/itemsim/algorithms/hadoop/scalding/mahout/src/test/scala/io/prediction/algorithms/scalding/mahout/itemsim/ModelConstructorTest.scala b/process/engines/itemsim/algorithms/hadoop/scalding/mahout/src/test/scala/io/prediction/algorithms/scalding/mahout/itemsim/ModelConstructorTest.scala
deleted file mode 100644
index 19b1c1a..0000000
--- a/process/engines/itemsim/algorithms/hadoop/scalding/mahout/src/test/scala/io/prediction/algorithms/scalding/mahout/itemsim/ModelConstructorTest.scala
+++ /dev/null
@@ -1,237 +0,0 @@
-package io.prediction.algorithms.scalding.mahout.itemsim
-
-import org.specs2.mutable._
-
-import com.twitter.scalding._
-
-import io.prediction.commons.filepath.{ AlgoFile, DataFile }
-import io.prediction.commons.scalding.modeldata.ItemSimScores
-import cascading.tuple.{ Tuple, TupleEntry, TupleEntryIterator, Fields }
-
-class ModelConstructorTest extends Specification with TupleConversions {
-
-  val appid = 3
-
-  def test(numSimilarItems: Int, recommendationTime: Long,
-    items: List[(String, String, String, String, String, String)], //(iindex, iid, itypes, starttime, endtime, inactive)
-    similarities: List[(String, String, String)],
-    output: List[(String, String, String, String)]) = {
-
-    val engineid = 4
-    val algoid = 7
-    val evalid = None
-    val modelSet = true
-
-    val dbType = "file"
-    val dbName = "testpath/"
-    val dbHost = Seq()
-    val dbPort = Seq()
-    val hdfsRoot = "testroot/"
-
-    val itemSimScores = output map { case (iid, simiid, score, simitypes) => (iid, simiid, score, simitypes, algoid, modelSet) }
-
-    JobTest("io.prediction.algorithms.scalding.mahout.itemsim.ModelConstructor")
-      .arg("dbType", dbType)
-      .arg("dbName", dbName)
-      .arg("hdfsRoot", hdfsRoot)
-      .arg("appid", appid.toString)
-      .arg("engineid", engineid.toString)
-      .arg("algoid", algoid.toString)
-      .arg("modelSet", modelSet.toString)
-      .arg("numSimilarItems", numSimilarItems.toString)
-      .arg("recommendationTime", recommendationTime.toString)
-      .source(Tsv(AlgoFile(hdfsRoot, appid, engineid, algoid, evalid, "similarities.tsv"), new Fields("iindex", "simiindex", "score")), similarities)
-      .source(Tsv(DataFile(hdfsRoot, appid, engineid, algoid, evalid, "itemsIndex.tsv")), items)
-      .sink[(String, String, String, String, Int, Boolean)](ItemSimScores(dbType = dbType, dbName = dbName, dbHost = dbHost, dbPort = dbPort, algoid = algoid, modelset = modelSet).getSource) { outputBuffer =>
-        "correctly write model data to a file" in {
-          outputBuffer.toList must containTheSameElementsAs(itemSimScores)
-        }
-      }
-      .run
-      .finish
-
-  }
-
-  val noEndtime = "PIO_NONE"
-  val noInactive = "PIO_NONE"
-
-  /* test 1*/
-  val test1Items = List(
-    ("0", "i0", "t1,t2,t3", "12346", noEndtime, noInactive),
-    ("1", "i1", "t1,t2", "12347", noEndtime, noInactive),
-    ("2", "i2", "t2,t3", "12348", noEndtime, noInactive),
-    ("3", "i3", "t2", "12349", noEndtime, noInactive))
-
-  val test1Similarities = List(
-    ("0", "1", "0.83"),
-    ("0", "2", "0.25"),
-    ("0", "3", "0.49"),
-    ("1", "2", "0.51"),
-    ("1", "3", "0.68"),
-    ("2", "3", "0.32"))
-
-  val test1Output = List(
-    ("i0", "i1,i3,i2", "0.83,0.49,0.25", "[t1,t2],[t2],[t2,t3]"),
-    ("i1", "i0,i3,i2", "0.83,0.68,0.51", "[t1,t2,t3],[t2],[t2,t3]"),
-    ("i2", "i1,i3,i0", "0.51,0.32,0.25", "[t1,t2],[t2],[t1,t2,t3]"),
-    ("i3", "i1,i0,i2", "0.68,0.49,0.32", "[t1,t2],[t1,t2,t3],[t2,t3]"))
-
-  val test1Output1 = List(
-    ("i0", "i1", "0.83", "[t1,t2]"),
-    ("i1", "i0", "0.83", "[t1,t2,t3]"),
-    ("i2", "i1", "0.51", "[t1,t2]"),
-    ("i3", "i1", "0.68", "[t1,t2]"))
-
-  val test1Output2 = List(
-    ("i0", "i1,i3", "0.83,0.49", "[t1,t2],[t2]"),
-    ("i1", "i0,i3", "0.83,0.68", "[t1,t2,t3],[t2]"),
-    ("i2", "i1,i3", "0.51,0.32", "[t1,t2],[t2]"),
-    ("i3", "i1,i0", "0.68,0.49", "[t1,t2],[t1,t2,t3]"))
-
-  "mahout.itemsim ModelConstructor" should {
-
-    test(100, 1234567890, test1Items, test1Similarities, test1Output)
-
-  }
-
-  "mahout.itemsim ModelConstructor with numSimilarItems=1" should {
-
-    test(1, 1234567890, test1Items, test1Similarities, test1Output1)
-
-  }
-
-  "mahout.itemsim ModelConstructor with numSimilarItems=2" should {
-
-    test(2, 1234567890, test1Items, test1Similarities, test1Output2)
-
-  }
-
-  /* test 2: score sorting */
-
-  val test2Items = List(
-    ("0", "i0", "t1,t2,t3", "12346", noEndtime, noInactive),
-    ("1", "i1", "t1,t2", "12347", noEndtime, noInactive),
-    ("2", "i2", "t2,t3", "12348", noEndtime, noInactive),
-    ("3", "i3", "t2", "12349", noEndtime, noInactive))
-
-  val test2Similarities = List(
-    ("0", "1", "83"),
-    ("0", "2", "200"),
-    ("0", "3", "4"),
-    ("1", "2", "9"),
-    ("1", "3", "68"),
-    ("2", "3", "1000"))
-
-  val test2Output = List(
-    ("i0", "i2,i1,i3", "200.0,83.0,4.0", "[t2,t3],[t1,t2],[t2]"),
-    ("i1", "i0,i3,i2", "83.0,68.0,9.0", "[t1,t2,t3],[t2],[t2,t3]"),
-    ("i2", "i3,i0,i1", "1000.0,200.0,9.0", "[t2],[t1,t2,t3],[t1,t2]"),
-    ("i3", "i2,i1,i0", "1000.0,68.0,4.0", "[t2,t3],[t1,t2],[t1,t2,t3]"))
-
-  "mahout.itemsim ModelConstructor (score should not be compared as string)" should {
-
-    test(100, 1234567890, test2Items, test2Similarities, test2Output)
-
-  }
-
-  /* test3: test starttime and endtime */
-
-  // starttime, endtime
-  // i0  A |---------|
-  // i1    B |---------|E
-  // i2       C|---------|
-  // i3           |---------|
-  //               D        F G
-
-  val tA = 123122
-  val tB = 123123
-  val tC = 123457
-  val tD = 123679
-  val tE = 543322
-  val tF = 543654
-  val tG = 543655
-
-  val test3Items = List(
-    ("0", "i0", "t1,t2,t3", "123123", "543210", noInactive),
-    ("1", "i1", "t1,t2", "123456", "543321", noInactive),
-    ("2", "i2", "t2,t3", "123567", "543432", noInactive),
-    ("3", "i3", "t2", "123678", "543654", noInactive))
-
-  val test3ItemsInactive = List(
-    ("0", "i0", "t1,t2,t3", "123123", "543210", noInactive),
-    ("1", "i1", "t1,t2", "123456", "543321", "true"),
-    ("2", "i2", "t2,t3", "123567", "543432", "false"),
-    ("3", "i3", "t2", "123678", "543654", "true"))
-
-  val test3Similarities = List(
-    ("0", "1", "83"),
-    ("0", "2", "200"),
-    ("0", "3", "4"),
-    ("1", "2", "9"),
-    ("1", "3", "68"),
-    ("2", "3", "1000"))
-
-  val test3Output = List(
-    ("i0", "i2,i1,i3", "200.0,83.0,4.0", "[t2,t3],[t1,t2],[t2]"),
-    ("i1", "i0,i3,i2", "83.0,68.0,9.0", "[t1,t2,t3],[t2],[t2,t3]"),
-    ("i2", "i3,i0,i1", "1000.0,200.0,9.0", "[t2],[t1,t2,t3],[t1,t2]"),
-    ("i3", "i2,i1,i0", "1000.0,68.0,4.0", "[t2,t3],[t1,t2],[t1,t2,t3]"))
-
-  val test3OutputInactive = List(
-    ("i0", "i2", "200.0", "[t2,t3]"),
-    ("i1", "i0,i2", "83.0,9.0", "[t1,t2,t3],[t2,t3]"),
-    ("i2", "i0", "200.0", "[t1,t2,t3]"),
-    ("i3", "i2,i0", "1000.0,4.0", "[t2,t3],[t1,t2,t3]"))
-
-  val test3OutputEmpty = List()
-
-  val test3Outputi0 = List(
-    ("i1", "i0", "83.0", "[t1,t2,t3]"),
-    ("i2", "i0", "200.0", "[t1,t2,t3]"),
-    ("i3", "i0", "4.0", "[t1,t2,t3]"))
-
-  val test3Outputi0i1 = List(
-    ("i0", "i1", "83.0", "[t1,t2]"),
-    ("i1", "i0", "83.0", "[t1,t2,t3]"),
-    ("i2", "i0,i1", "200.0,9.0", "[t1,t2,t3],[t1,t2]"),
-    ("i3", "i1,i0", "68.0,4.0", "[t1,t2],[t1,t2,t3]"))
-
-  val test3Outputi2i3 = List(
-    ("i0", "i2,i3", "200.0,4.0", "[t2,t3],[t2]"),
-    ("i1", "i3,i2", "68.0,9.0", "[t2],[t2,t3]"),
-    ("i2", "i3", "1000.0", "[t2]"),
-    ("i3", "i2", "1000.0", "[t2,t3]"))
-
-  "numSimilarItems=100 and recommendationTime < all item starttime" should {
-    test(100, tA, test3Items, test3Similarities, test3OutputEmpty)
-  }
-
-  "numSimilarItems=100 and recommendationTime == earliest starttime" should {
-    test(100, tB, test3Items, test3Similarities, test3Outputi0)
-  }
-
-  "numSimilarItems=100 and recommendationTime > some items starttime" should {
-    test(100, tC, test3Items, test3Similarities, test3Outputi0i1)
-  }
-
-  "numSimilarItems=100 and recommendationTime > all item starttime and < all item endtime" should {
-    test(100, tD, test3Items, test3Similarities, test3Output)
-  }
-
-  "numSimilarItems=100 and recommendationTime > all item starttime and < all item endtime with some inactive" should {
-    test(100, tD, test3ItemsInactive, test3Similarities, test3OutputInactive)
-  }
-
-  "numSimilarItems=100 and recommendationTime > some item endtime" should {
-    test(100, tE, test3Items, test3Similarities, test3Outputi2i3)
-  }
-
-  "numSimilarItems=100 and recommendationTime == last item endtime" should {
-    test(100, tF, test3Items, test3Similarities, test3OutputEmpty)
-  }
-
-  "numSimilarItems=100 and recommendationTime > last item endtime" should {
-    test(100, tG, test3Items, test3Similarities, test3OutputEmpty)
-  }
-
-}
diff --git a/process/engines/itemsim/algorithms/hadoop/scalding/randomrank/src/main/scala/io/prediction/algorithms/scalding/itemsim/randomrank/RandomRank.scala b/process/engines/itemsim/algorithms/hadoop/scalding/randomrank/src/main/scala/io/prediction/algorithms/scalding/itemsim/randomrank/RandomRank.scala
deleted file mode 100644
index be66ef5..0000000
--- a/process/engines/itemsim/algorithms/hadoop/scalding/randomrank/src/main/scala/io/prediction/algorithms/scalding/itemsim/randomrank/RandomRank.scala
+++ /dev/null
@@ -1,143 +0,0 @@
-package io.prediction.algorithms.scalding.itemsim.randomrank
-
-import com.twitter.scalding._
-
-import io.prediction.commons.scalding.appdata.{ Items, Users }
-import io.prediction.commons.scalding.modeldata.ItemSimScores
-import io.prediction.commons.filepath.{ AlgoFile }
-import io.prediction.commons.appdata.{ Item }
-
-/**
- * Source:
- *
- * Sink:
- *
- * Description:
- *
- * Args:
- * --training_dbType: <string> training_appdata DB type
- * --training_dbName: <string>
- * --training_dbHost: <string> optional
- * --training_dbPort: <int> optional
- *
- * --modeldata_dbType: <string> modeldata DB type
- * --modeldata_dbName: <string>
- * --modeldata_dbHost: <string> optional
- * --modeldata_dbPort <int> optional
- *
- * --hdfsRoot: <string>. Root directory of the HDFS
- *
- * --appid: <int>
- * --engineid: <int>
- * --algoid: <int>
- * --evalid: <int>. optional. Offline Evaluation if evalid is specified
- *
- * --itypes: <string separated by white space>. optional. eg "--itypes type1 type2". If no --itypes specified, then ALL itypes will be used.
- * --numSimilarItems: <int>. number of similar items to be generated
- * --modelSet: <boolean> (true/false). flag to indicate which set
- * --recommendationTime: <long> (eg. 9876543210). recommend items with starttime <= recommendationTime and endtime > recommendationTime
- *
- * Example:
- * hadoop jar PredictionIO-Process-Hadoop-Scala-assembly-0.1.jar io.prediction.algorithms.scalding.itemsim.randomrank.RandomRank --hdfs --training_dbType mongodb --training_dbName predictionio_appdata --training_dbHost localhost --training_dbPort 27017 --modeldata_dbType mongodb --modeldata_dbName predictionio_modeldata --modeldata_dbHost localhost --modeldata_dbPort 27017 --hdfsRoot predictionio/ --appid 1 --engineid 1 --algoid 18 --modelSet true
- */
-class RandomRank(args: Args) extends Job(args) {
-  /**
-   * parse args
-   */
-  val training_dbTypeArg = args("training_dbType")
-  val training_dbNameArg = args("training_dbName")
-  val training_dbHostArg = args.list("training_dbHost")
-  val training_dbPortArg = args.list("training_dbPort") map (x => x.toInt)
-
-  val modeldata_dbTypeArg = args("modeldata_dbType")
-  val modeldata_dbNameArg = args("modeldata_dbName")
-  val modeldata_dbHostArg = args.list("modeldata_dbHost")
-  val modeldata_dbPortArg = args.list("modeldata_dbPort") map (x => x.toInt)
-
-  val hdfsRootArg = args("hdfsRoot")
-
-  val appidArg = args("appid").toInt
-  val engineidArg = args("engineid").toInt
-  val algoidArg = args("algoid").toInt
-  val evalidArg = args.optional("evalid") map (x => x.toInt)
-  val OFFLINE_EVAL = (evalidArg != None) // offline eval mode
-
-  val preItypesArg = args.list("itypes")
-  val itypesArg: Option[List[String]] = if (preItypesArg.mkString(",").length == 0) None else Option(preItypesArg)
-
-  val numSimilarItemsArg = args("numSimilarItems").toInt
-
-  val modelSetArg = args("modelSet").toBoolean
-  val recommendationTimeArg = args("recommendationTime").toLong
-
-  /**
-   * source
-   */
-
-  // get appdata
-  // NOTE: if OFFLINE_EVAL, read from training set, and use evalid as appid when read Items and U2iActions
-  val trainingAppid = if (OFFLINE_EVAL) evalidArg.get else appidArg
-
-  // get items data
-  val items2 = Items(
-    appId = trainingAppid,
-    itypes = itypesArg,
-    dbType = training_dbTypeArg,
-    dbName = training_dbNameArg,
-    dbHost = training_dbHostArg,
-    dbPort = training_dbPortArg).readObj('item)
-    .mapTo('item -> ('iidx, 'itypes, 'starttime, 'endtime, 'inactive)) {
-      item: Item =>
-        (item.id,
-          item.itypes,
-          item.starttime.map(_.getMillis()).get,
-          item.endtime.map(_.getMillis()),
-          item.inactive.getOrElse(false)
-        )
-    }
-    .filter('starttime, 'endtime, 'inactive) { fields: (Long, Option[Long], Boolean) =>
-      // only keep items with valid starttime and endtime
-      val (starttimeI, endtimeI, inactive) = fields
-
-      val keepThis: Boolean = (starttimeI, endtimeI) match {
-        case (start, None) => (recommendationTimeArg >= start)
-        case (start, Some(end)) => ((recommendationTimeArg >= start) && (recommendationTimeArg < end))
-        case _ => {
-          assert(false, s"Unexpected item starttime ${starttimeI} and endtime ${endtimeI}")
-          false
-        }
-      }
-      keepThis && (!inactive)
-    }
-
-  val items = Items(
-    appId = trainingAppid,
-    itypes = itypesArg,
-    dbType = training_dbTypeArg,
-    dbName = training_dbNameArg,
-    dbHost = training_dbHostArg,
-    dbPort = training_dbPortArg).readData('iid, 'itypesx)
-
-  /**
-   * sink
-   */
-  val itemSimScores = ItemSimScores(
-    dbType = modeldata_dbTypeArg,
-    dbName = modeldata_dbNameArg,
-    dbHost = modeldata_dbHostArg,
-    dbPort = modeldata_dbPortArg,
-    algoid = algoidArg,
-    modelset = modelSetArg)
-
-  /**
-   * computation
-   */
-  val scores = items.crossWithTiny(items2)
-    .filter('iid, 'iidx) { fields: (String, String) => fields._1 != fields._2 }
-    .map(() -> 'score) { u: Unit => scala.util.Random.nextDouble() }
-    .groupBy('iid) { _.sortBy('score).reverse.take(numSimilarItemsArg) }
-    .groupBy('iid) { _.sortBy('score).reverse.toList[(String, Double, List[String])](('iidx, 'score, 'itypes) -> 'simiidsList) }
-
-  // write modeldata
-  scores.then(itemSimScores.writeData('iid, 'simiidsList, algoidArg, modelSetArg) _)
-}
diff --git a/process/engines/itemsim/algorithms/hadoop/scalding/randomrank/src/test/scala/io/prediction/algorithms/scalding/itemsim/randomrank/RandomRankTest.scala b/process/engines/itemsim/algorithms/hadoop/scalding/randomrank/src/test/scala/io/prediction/algorithms/scalding/itemsim/randomrank/RandomRankTest.scala
deleted file mode 100644
index 3ce7665..0000000
--- a/process/engines/itemsim/algorithms/hadoop/scalding/randomrank/src/test/scala/io/prediction/algorithms/scalding/itemsim/randomrank/RandomRankTest.scala
+++ /dev/null
@@ -1,269 +0,0 @@
-package io.prediction.algorithms.scalding.itemsim.randomrank
-
-import org.specs2.mutable._
-
-import com.twitter.scalding._
-
-import io.prediction.commons.scalding.appdata.Items
-import io.prediction.commons.scalding.modeldata.{ ItemSimScores }
-import io.prediction.commons.filepath.{ AlgoFile }
-
-class RandomRankTest extends Specification with TupleConversions {
-  def test(
-    algoid: Int,
-    modelSet: Boolean,
-    itypes: List[String],
-    numSimilarItems: Int,
-    recommendationTime: Long,
-    items: List[(String, String, String, String, String, String, String)], // id, itypes, appid, starttime, ct, endtime, inactive
-    itemSimScores: List[(String, String, String, String, Int, Boolean)]) = {
-    val training_dbType = "file"
-    val training_dbName = "testpath/"
-
-    val modeldata_dbType = "file"
-    val modeldata_dbName = "testpath/"
-
-    val hdfsRoot = "testpath/"
-
-    val appid = 7
-    val engineid = 10
-    val evalid = None
-
-    JobTest("io.prediction.algorithms.scalding.itemsim.randomrank.RandomRank")
-      .arg("training_dbType", training_dbType)
-      .arg("training_dbName", training_dbName)
-      .arg("modeldata_dbType", modeldata_dbType)
-      .arg("modeldata_dbName", modeldata_dbName)
-      .arg("hdfsRoot", hdfsRoot)
-      .arg("appid", appid.toString)
-      .arg("engineid", engineid.toString)
-      .arg("algoid", algoid.toString)
-      .arg("itypes", itypes)
-      .arg("numSimilarItems", numSimilarItems.toString)
-      .arg("modelSet", modelSet.toString)
-      .arg("recommendationTime", recommendationTime.toString)
-      .source(Items(appId = appid, itypes = Some(itypes), dbType = training_dbType, dbName = training_dbName, dbHost = Seq(), dbPort = Seq()).getSource, items)
-      .sink[(String, String, String, String, Int, Boolean)](ItemSimScores(dbType = modeldata_dbType, dbName = modeldata_dbName, dbHost = Seq(), dbPort = Seq(), algoid = algoid, modelset = modelSet).getSource) { outputBuffer =>
-
-        def takeOutScores(d: List[(String, String, String, String, Int, Boolean)]) = {
-          // don't check score and itypes.
-          // for iids, don't check order. convert to set
-          d map { x => (x._1, x._2.split(",").toSet, x._5, x._6) }
-        }
-
-        def getScoresOnly(d: List[(String, String, String, String, Int, Boolean)]) = {
-          d flatMap { x => x._3.split(",").toList.map(_.toDouble) }
-        }
-
-        def getIids(d: List[(String, String, String, String, Int, Boolean)]) = {
-          // List(List("i0", "i1"), List("i1", "i0"), ...)
-
-          d map { x => x._2.split(",").toList }
-        }
-
-        def getItypes(d: List[(String, String, String, String, Int, Boolean)]) = {
-          //("i0", "i2,i3", "0.0,0.0", "[t1,t2,t3],[t2,t3]", algoid, modelSet),
-          // => List( List( (i2, List(t1,t2,t3)) , (i3, List(t2,t3)) )
-          d.map { x =>
-            val itypesList = x._4.split("],").toList.map(x => x.stripPrefix("[").stripSuffix("]").split(",").toList)
-            val iidList = x._2.split(",").toList
-
-            iidList zip itypesList
-          }
-        }
-
-        "generate correct user and item pairs in modeldata" in {
-
-          // don't check scores since they are random
-          val result = takeOutScores(outputBuffer.toList)
-          val expected = takeOutScores(itemSimScores)
-
-          result must containTheSameElementsAs(expected)
-
-        }
-
-        "generate different scores for each pair in modeldata" in {
-          // very simple way to check if the scores are random
-          // (just to check if they are different)
-
-          val scoresList: List[Double] = getScoresOnly(outputBuffer.toList)
-          val scoresSet = scoresList.toSet
-
-          scoresSet.size must be_==(scoresList.size)
-
-        }
-
-        if (getIids(itemSimScores).flatMap { x => x }.toSet.size > 1) {
-          // only check this if the iids in itemRecScores are more than 1
-          "not generate same order of iid for all uid group" in {
-            if (!(getIids(outputBuffer.toList).toSet.size > 1)) {
-              println(outputBuffer)
-              println(getIids(outputBuffer.toList).toSet)
-            }
-            getIids(outputBuffer.toList).toSet.size must be_>(1)
-
-          }
-        }
-
-        "itypes order match the iids order" in {
-
-          // extract (iid, itypes) from the output
-          val itypesList = getItypes(outputBuffer.toList)
-          val itemsMap = items.map(x =>
-            (x._1, x)).toMap
-
-          // use the iid only and contruct the (iid, itypes)
-          val expected = getIids(outputBuffer.toList).map(x =>
-            // x is List of iid
-            // create the List of item types using the iid
-            x.map(x => (x, itemsMap(x)._2.split(",").toList))
-          )
-
-          itypesList must be_==(expected)
-        }
-
-      }
-      .run
-      .finish
-  }
-
-  val largeNumber: Long = scala.Long.MaxValue // larger than any item starttime
-  val noEndtime = "PIO_NONE"
-  val noInactive = "PIO_NONE"
-
-  "randomrank.RandomRank with selected itypes" should {
-    val algoid = 12
-    val modelSet = false
-    val itypes = List("t1", "t2")
-    val items = List(
-      ("i0", "t1,t2,t3", "19", "123456", "345678", noEndtime, noInactive),
-      ("i1", "t2,t3", "19", "123457", "567890", noEndtime, noInactive),
-      ("i2", "t4", "19", "21", "88", noEndtime, noInactive),
-      ("i3", "t3,t4", "19", "9876543210", "67890", noEndtime, noInactive))
-    val itemSimScores = List(
-      ("i1", "i0", "0.0", "[t1,t2,t3]", algoid, modelSet),
-      ("i0", "i1", "0.0", "[t2,t3]", algoid, modelSet))
-
-    test(algoid, modelSet, itypes, 500, largeNumber, items, itemSimScores)
-  }
-
-  "randomrank.RandomRank with all itypes" should {
-    val algoid = 12
-    val modelSet = false
-    val itypes = List("")
-    val items = List(
-      ("i0", "t1,t2,t3", "19", "123456", "345678", noEndtime, noInactive),
-      ("i1", "t2,t3", "19", "123457", "567890", noEndtime, noInactive),
-      ("i2", "t4", "19", "21", "88", noEndtime, noInactive),
-      ("i3", "t3,t4", "19", "9876543210", "67890", noEndtime, noInactive))
-    val itemSimScores = List(
-      ("i3", "i0,i1,i2", "0.0,0.0,0.0", "[t1,t2,t3],[t2,t3],[t4]", algoid, modelSet),
-      ("i2", "i0,i1,i3", "0.0,0.0,0.0", "[t1,t2,t3],[t2,t3],[t3,t4]", algoid, modelSet),
-      ("i1", "i0,i2,i3", "0.0,0.0,0.0", "[t1,t2,t3],[t4],[t3,t4]", algoid, modelSet),
-      ("i0", "i1,i2,i3", "0.0,0.0,0.0", "[t2,t3],[t4],[t3,t4]", algoid, modelSet))
-
-    test(algoid, modelSet, itypes, 500, largeNumber, items, itemSimScores)
-  }
-
-  "randomrank.RandomRank with all itypes and some inactive" should {
-    val algoid = 12
-    val modelSet = false
-    val itypes = List("")
-    val items = List(
-      ("i0", "t1,t2,t3", "19", "123456", "345678", noEndtime, noInactive),
-      ("i1", "t2,t3", "19", "123457", "567890", noEndtime, "true"),
-      ("i2", "t4", "19", "21", "88", noEndtime, "false"),
-      ("i3", "t3,t4", "19", "9876543210", "67890", noEndtime, noInactive))
-    val itemSimScores = List(
-      ("i3", "i0,i2", "0.0,0.0", "[t1,t2,t3],[t4]", algoid, modelSet),
-      ("i2", "i0,i3", "0.0,0.0", "[t1,t2,t3],[t3,t4]", algoid, modelSet),
-      ("i1", "i0,i2,i3", "0.0,0.0,0.0", "[t1,t2,t3],[t4],[t3,t4]", algoid, modelSet),
-      ("i0", "i2,i3", "0.0,0.0", "[t4],[t3,t4]", algoid, modelSet))
-
-    test(algoid, modelSet, itypes, 500, largeNumber, items, itemSimScores)
-  }
-
-  // TODO: test with smaller number of numRecommendations (but can't know expected result beacause the score is random...)
-
-  /* test 2: test starttime and endtime */
-  // starttime, endtime
-  // i0  A |---------|
-  // i1    B |---------|E
-  // i2       C|---------|
-  // i3           |---------|
-  //               D        F G
-
-  val tA = 123122
-  val tB = 123123
-  val tC = 123457
-  val tD = 123679
-  val tE = 543322
-  val tF = 543654
-  val tG = 543655
-
-  val test2Algoid = 12
-  val test2ModelSet = false
-
-  val test2ItypesAll = List("t1", "t2", "t3", "t4")
-  val test2Items = List(
-    ("i0", "t1,t2,t3", "19", "123123", "4", "543210", noInactive),
-    ("i1", "t2,t3", "19", "123456", "5", "543321", noInactive),
-    ("i2", "t4", "19", "123567", "6", "543432", noInactive),
-    ("i3", "t3,t4", "19", "123678", "7", "543654", noInactive))
-
-  val test2Users = List(("u0", "3"), ("u1", "3"), ("u2", "3"), ("u3", "3"))
-
-  val test2ItemSimScoresAll = List(
-    ("i0", "i3,i2,i1", "0.0,0.0,0.0", "[t3,t4],[t4],[t2,t3]", test2Algoid, test2ModelSet),
-    ("i1", "i3,i2,i0", "0.0,0.0,0.0", "[t3,t4],[t4],[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("i2", "i3,i1,i0", "0.0,0.0,0.0", "[t3,t4],[t2,t3],[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("i3", "i2,i1,i0", "0.0,0.0,0.0", "[t4],[t2,t3],[t1,t2,t3]", test2Algoid, test2ModelSet))
-
-  val test2ItemSimScoresEmpty = List()
-
-  val test2ItemSimScoresi0 = List(
-    ("i1", "i0", "0.0", "[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("i2", "i0", "0.0", "[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("i3", "i0", "0.0", "[t1,t2,t3]", test2Algoid, test2ModelSet))
-
-  val test2ItemSimScoresi0i1 = List(
-    ("i0", "i1", "0.0", "[t2,t3]", test2Algoid, test2ModelSet),
-    ("i1", "i0", "0.0", "[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("i2", "i1,i0", "0.0,0.0", "[t2,t3],[t1,t2,t3]", test2Algoid, test2ModelSet),
-    ("i3", "i1,i0", "0.0,0.0", "[t2,t3],[t1,t2,t3]", test2Algoid, test2ModelSet))
-
-  val test2ItemSimScoresi2i3 = List(
-    ("i0", "i3,i2", "0.0,0.0", "[t3,t4],[t4]", test2Algoid, test2ModelSet),
-    ("i1", "i3,i2", "0.0,0.0", "[t3,t4],[t4]", test2Algoid, test2ModelSet),
-    ("i2", "i3", "0.0", "[t3,t4]", test2Algoid, test2ModelSet),
-    ("i3", "i2", "0.0", "[t4]", test2Algoid, test2ModelSet))
-
-  "recommendationTime < all item starttime" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tA, test2Items, test2ItemSimScoresEmpty)
-  }
-
-  "recommendationTime == earliest starttime" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tB, test2Items, test2ItemSimScoresi0)
-  }
-
-  "recommendationTime > some items starttime" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tC, test2Items, test2ItemSimScoresi0i1)
-  }
-
-  "recommendationTime > all item starttime and < all item endtime" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tD, test2Items, test2ItemSimScoresAll)
-  }
-
-  "recommendationTime > some item endtime" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tE, test2Items, test2ItemSimScoresi2i3)
-  }
-
-  "recommendationTime == last item endtime" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tA, test2Items, test2ItemSimScoresEmpty)
-  }
-
-  "recommendationTime > last item endtime" should {
-    test(test2Algoid, test2ModelSet, test2ItypesAll, 500, tA, test2Items, test2ItemSimScoresEmpty)
-  }
-
-}
diff --git a/process/engines/itemsim/algorithms/scala/generic/build.sbt b/process/engines/itemsim/algorithms/scala/generic/build.sbt
deleted file mode 100644
index 06218c6..0000000
--- a/process/engines/itemsim/algorithms/scala/generic/build.sbt
+++ /dev/null
@@ -1,22 +0,0 @@
-import xerial.sbt.Pack._
-
-name := "predictionio-process-itemsim-algorithms-scala-generic"
-
-libraryDependencies ++= Seq(
-  "ch.qos.logback" % "logback-classic" % "1.1.1",
-  "com.twitter" %% "scalding-args" % "0.8.11",
-  "org.clapper" %% "grizzled-slf4j" % "1.0.1")
-
-packSettings
-
-packJarNameConvention := "full"
-
-packExpandedClasspath := true
-
-packGenerateWindowsBatFile := false
-
-packMain := Map(
-  "itemsim.generic.dataprep" -> "io.prediction.algorithms.generic.itemsim.GenericDataPreparator")
-
-packJvmOpts := Map(
-  "itemsim.generic.dataprep" -> Common.packCommonJvmOpts)
diff --git a/process/engines/itemsim/algorithms/scala/generic/src/main/resources/application.conf b/process/engines/itemsim/algorithms/scala/generic/src/main/resources/application.conf
deleted file mode 100644
index c85803b..0000000
--- a/process/engines/itemsim/algorithms/scala/generic/src/main/resources/application.conf
+++ /dev/null
@@ -1,30 +0,0 @@
-# Used by PredictionIO Commons
-io.prediction.base=.
-
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.host=localhost
-io.prediction.commons.appdata.db.port=27017
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.host=localhost
-io.prediction.commons.appdata.test.db.port=27017
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.host=localhost
-io.prediction.commons.appdata.training.db.port=27017
-
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.host=localhost
-io.prediction.commons.appdata.validation.db.port=27017
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.host=localhost
-io.prediction.commons.modeldata.db.port=27017
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.host=localhost
-io.prediction.commons.modeldata.training.db.port=27017
-
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.host=localhost
-io.prediction.commons.settings.db.port=27017
diff --git a/process/engines/itemsim/algorithms/scala/generic/src/main/resources/logback.xml b/process/engines/itemsim/algorithms/scala/generic/src/main/resources/logback.xml
deleted file mode 100644
index 1a2768e..0000000
--- a/process/engines/itemsim/algorithms/scala/generic/src/main/resources/logback.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<configuration>
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <encoder>
-      <pattern>%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>
-    </encoder>
-  </appender>
-  <root level="info">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
-
diff --git a/process/engines/itemsim/algorithms/scala/generic/src/main/scala/io/prediction/algorithms/itemsim/generic/GenericDataPreparator.scala b/process/engines/itemsim/algorithms/scala/generic/src/main/scala/io/prediction/algorithms/itemsim/generic/GenericDataPreparator.scala
deleted file mode 100644
index dd90d28..0000000
--- a/process/engines/itemsim/algorithms/scala/generic/src/main/scala/io/prediction/algorithms/itemsim/generic/GenericDataPreparator.scala
+++ /dev/null
@@ -1,326 +0,0 @@
-package io.prediction.algorithms.generic.itemsim
-
-import io.prediction.commons.Config
-import io.prediction.commons.appdata.{ Item, U2IAction, User }
-
-import com.github.nscala_time.time.Imports._
-import grizzled.slf4j.Logger
-import java.io.File
-import java.io.FileWriter
-import java.io.RandomAccessFile
-import java.io.BufferedWriter
-import scala.io.Source
-
-import com.twitter.scalding.Args
-
-/**
- * Generic single machine data preparator for ItemSim engine.
- * Read data from appdata and output the following files:
- * - itemsIndex.tsv (iindex iid itypes): all items
- * - validItemsIndex.tsv (iindex): valid candidate items to be recommended
- * - ratings.mm (if --matrixMarket true ): matrix market format rating
- * - ratings.csv (if --matrixMarket false): comma separated rating file
- */
-object GenericDataPreparator {
-
-  /* constants */
-  final val ACTION_RATE = "rate"
-  final val ACTION_LIKE = "like"
-  final val ACTION_DISLIKE = "dislike"
-  final val ACTION_VIEW = "view"
-  final val ACTION_CONVERSION = "conversion"
-
-  // When there are conflicting actions, e.g. a user gives an item a rating 5 but later dislikes it,
-  // determine which action will be considered as final preference.
-  final val CONFLICT_LATEST: String = "latest" // use latest action
-  final val CONFLICT_HIGHEST: String = "highest" // use the one with highest score
-  final val CONFLICT_LOWEST: String = "lowest" // use the one with lowest score
-
-  /* global */
-  val logger = Logger(GenericDataPreparator.getClass)
-
-  //println(logger.isInfoEnabled)
-
-  val commonsConfig = new Config
-
-  // argument of this job
-  case class JobArg(
-    val outputDir: String,
-    val appid: Int,
-    val evalid: Option[Int],
-    val itypes: Option[List[String]],
-    val viewParam: Option[Int],
-    val likeParam: Option[Int],
-    val dislikeParam: Option[Int],
-    val conversionParam: Option[Int],
-    val conflictParam: String,
-    val recommendationTime: Option[Long],
-    val matrixMarket: Boolean)
-
-  def main(cmdArgs: Array[String]) {
-
-    logger.info("Running generic data preparator ...")
-    logger.info(cmdArgs.mkString(","))
-
-    /* get arg */
-    val args = Args(cmdArgs)
-
-    val outputDirArg = args("outputDir")
-    val appidArg = args("appid").toInt
-    val evalidArg = args.optional("evalid") map (x => x.toInt)
-    val OFFLINE_EVAL = (evalidArg != None) // offline eval mode
-
-    val preItypesArg = args.list("itypes")
-    val itypesArg: Option[List[String]] = if (preItypesArg.mkString(",").length == 0) None else Option(preItypesArg)
-
-    // determine how to map actions to rating values
-    def getActionParam(name: String): Option[Int] = {
-      val actionParam: Option[Int] = args(name) match {
-        case "ignore" => None
-        case x => Some(x.toInt)
-      }
-      actionParam
-    }
-
-    val viewParamArg: Option[Int] = getActionParam("viewParam")
-    val likeParamArg: Option[Int] = getActionParam("likeParam")
-    val dislikeParamArg: Option[Int] = getActionParam("dislikeParam")
-    val conversionParamArg: Option[Int] = getActionParam("conversionParam")
-
-    val conflictParamArg: String = args("conflictParam")
-
-    // check if the conflictParam is valid
-    require(List(CONFLICT_LATEST, CONFLICT_HIGHEST, CONFLICT_LOWEST).contains(conflictParamArg), "conflict param " + conflictParamArg + " is not valid.")
-
-    val recommendationTimeArg = args.optional("recommendationTime").map(_.toLong)
-
-    // write data in matrix market format
-    val matrixMarketArg: Boolean = args.optional("matrixMarket").map(x => x.toBoolean).getOrElse(true)
-
-    val arg = JobArg(
-      outputDir = outputDirArg,
-      appid = appidArg,
-      evalid = evalidArg,
-      itypes = itypesArg,
-      viewParam = viewParamArg,
-      likeParam = likeParamArg,
-      dislikeParam = dislikeParamArg,
-      conversionParam = conversionParamArg,
-      conflictParam = conflictParamArg,
-      recommendationTime = recommendationTimeArg,
-      matrixMarket = matrixMarketArg
-    )
-
-    /* run job */
-    dataPrep(arg)
-    cleanup(arg)
-
-  }
-
-  case class RatingData(
-    uid: Int,
-    iid: Int,
-    rating: Int,
-    t: Long)
-
-  def dataPrep(arg: JobArg) = {
-
-    // NOTE: if OFFLINE_EVAL, read from training set, and use evalid as appid when read Items and U2iActions
-    val OFFLINE_EVAL = (arg.evalid != None)
-
-    val usersDb = if (!OFFLINE_EVAL)
-      commonsConfig.getAppdataUsers
-    else
-      commonsConfig.getAppdataTrainingUsers
-
-    val itemsDb = if (!OFFLINE_EVAL)
-      commonsConfig.getAppdataItems
-    else
-      commonsConfig.getAppdataTrainingItems
-
-    val u2iDb = if (!OFFLINE_EVAL)
-      commonsConfig.getAppdataU2IActions
-    else
-      commonsConfig.getAppdataTrainingU2IActions
-
-    val appid = if (OFFLINE_EVAL) arg.evalid.get else arg.appid
-
-    // create outputDir if doesn't exist yet.
-    val outputDir = new File(arg.outputDir)
-    outputDir.mkdirs()
-
-    /* user data */
-    // convert to Map for later lookup
-    // assuming number of users can be fit into memory.
-    val usersMap: Map[String, Int] = usersDb.getByAppid(appid).map(_.id).zipWithIndex
-      .map { case (uid, index) => (uid, index + 1) }.toMap // +1 to make it starting from 1
-
-    /* item data */
-    case class ItemData(
-      val iindex: Int,
-      val itypes: Seq[String],
-      val starttime: Option[Long],
-      val endtime: Option[Long],
-      val inactive: Boolean)
-
-    val itemsMap: Map[String, ItemData] = arg.itypes.map { itypes =>
-      itemsDb.getByAppidAndItypes(appid, itypes)
-    }.getOrElse {
-      itemsDb.getByAppid(appid)
-    }.zipWithIndex
-      .map {
-        case (item, index) =>
-          val itemData = ItemData(
-            iindex = index + 1, // +1 to make index starting from 1 (required by graphchi)
-            itypes = item.itypes,
-            starttime = item.starttime.map[Long](_.getMillis()),
-            endtime = item.endtime.map[Long](_.getMillis()),
-            inactive = item.inactive.getOrElse(false)
-          )
-          (item.id -> itemData)
-      }.toMap
-
-    /* write item index (iindex iid itypes) */
-    val itemsIndexWriter = new BufferedWriter(new FileWriter(new File(arg.outputDir + "itemsIndex.tsv")))
-    // NOTE: only write valid items (eg. valid starttime and endtime)
-    itemsMap.foreach {
-      case (iid, itemData) =>
-        val itypes = itemData.itypes.mkString(",")
-        itemsIndexWriter.write(s"${itemData.iindex}\t${iid}\t${itypes}\n")
-    }
-    itemsIndexWriter.close()
-
-    /* write valid item (iindex) */
-    val validItemsIndexWriter = new BufferedWriter(new FileWriter(new File(arg.outputDir + "validItemsIndex.tsv")))
-    // NOTE: only write valid items (eg. valid starttime and endtime)
-    itemsMap.filter {
-      case (iid, itemData) =>
-        val validTime = itemTimeFilter(true, itemData.starttime,
-          itemData.endtime, arg.recommendationTime)
-
-        validTime && (!itemData.inactive)
-    }.foreach {
-      case (iid, itemData) =>
-        validItemsIndexWriter.write(s"${itemData.iindex}\t${itemData.starttime.getOrElse(arg.recommendationTime)}\n")
-    }
-    validItemsIndexWriter.close()
-
-    /* write u2i ratings */
-
-    val u2iRatings = u2iDb.getAllByAppid(appid)
-      .filter { u2i =>
-        val validAction = isValidAction(u2i, arg.likeParam, arg.dislikeParam, arg.viewParam, arg.conversionParam)
-        val validUser = usersMap.contains(u2i.uid)
-        val validItem = itemsMap.contains(u2i.iid)
-        (validAction && validUser && validItem)
-      }.map { u2i =>
-        val rating = convertToRating(u2i, arg.likeParam, arg.dislikeParam, arg.viewParam, arg.conversionParam)
-
-        RatingData(
-          uid = usersMap(u2i.uid),
-          iid = itemsMap(u2i.iid).iindex,
-          rating = rating,
-          t = u2i.t.getMillis
-        )
-      }.toSeq
-
-    if (!u2iRatings.isEmpty) {
-
-      val ratingReduced = u2iRatings.groupBy(x => (x.iid, x.uid))
-        .mapValues { v =>
-          v.reduce { (a, b) =>
-            resolveConflict(a, b, arg.conflictParam)
-          }
-        }.values
-        .toSeq
-        .sortBy { x: RatingData =>
-          (x.iid, x.uid)
-        }
-
-      val fileName = if (arg.matrixMarket) "ratings.mm" else "ratings.csv"
-      val ratingsWriter = new BufferedWriter(new FileWriter(new File(arg.outputDir + fileName))) // intermediate file
-
-      if (arg.matrixMarket) {
-        ratingsWriter.write("%%MatrixMarket matrix coordinate real general\n")
-        ratingsWriter.write(s"${usersMap.size} ${itemsMap.size} ${ratingReduced.size}\n")
-      }
-
-      ratingReduced.foreach { r =>
-        if (arg.matrixMarket) {
-          ratingsWriter.write(s"${r.uid} ${r.iid} ${r.rating}\n")
-        } else {
-          ratingsWriter.write(s"${r.uid},${r.iid},${r.rating}\n")
-        }
-      }
-
-      ratingsWriter.close()
-    }
-
-  }
-
-  def itemTimeFilter(enable: Boolean, starttime: Option[Long], endtime: Option[Long], recommendationTime: Option[Long]): Boolean = {
-    if (enable) {
-      recommendationTime.map { recTime =>
-        (starttime, endtime) match {
-          case (Some(start), None) => (recTime >= start)
-          case (Some(start), Some(end)) => ((recTime >= start) && (recTime < end))
-          case (None, Some(end)) => (recTime < end)
-          case (None, None) => true
-        }
-      }.getOrElse(true)
-    } else true
-  }
-
-  def isValidAction(u2i: U2IAction, likeParam: Option[Int], dislikeParam: Option[Int],
-    viewParam: Option[Int], conversionParam: Option[Int]): Boolean = {
-    val keepThis: Boolean = u2i.action match {
-      case ACTION_RATE => true
-      case ACTION_LIKE => (likeParam != None)
-      case ACTION_DISLIKE => (dislikeParam != None)
-      case ACTION_VIEW => (viewParam != None)
-      case ACTION_CONVERSION => (conversionParam != None)
-      case _ => {
-        //assert(false, "Action type " + u2i.action + " in u2iActions appdata is not supported!")
-        false // all other unsupported actions
-      }
-    }
-    keepThis
-  }
-
-  def convertToRating(u2i: U2IAction, likeParam: Option[Int], dislikeParam: Option[Int],
-    viewParam: Option[Int], conversionParam: Option[Int]): Int = {
-    val rating: Int = u2i.action match {
-      case ACTION_RATE => u2i.v.get.toInt
-      case ACTION_LIKE => likeParam.getOrElse {
-        assert(false, "Action type " + u2i.action + " should have been filtered out!")
-        0
-      }
-      case ACTION_DISLIKE => dislikeParam.getOrElse {
-        assert(false, "Action type " + u2i.action + " should have been filtered out!")
-        0
-      }
-      case ACTION_VIEW => viewParam.getOrElse {
-        assert(false, "Action type " + u2i.action + " should have been filtered out!")
-        0
-      }
-      case ACTION_CONVERSION => conversionParam.getOrElse {
-        assert(false, "Action type " + u2i.action + " should have been filtered out!")
-        0
-      }
-    }
-    rating
-  }
-
-  def resolveConflict(a: RatingData, b: RatingData, conflictParam: String) = {
-    conflictParam match {
-      case CONFLICT_LATEST => if (a.t > b.t) a else b
-      case CONFLICT_HIGHEST => if (a.rating > b.rating) a else b
-      case CONFLICT_LOWEST => if (a.rating < b.rating) a else b
-    }
-  }
-
-  def cleanup(arg: JobArg) = {
-
-  }
-
-}
diff --git a/process/engines/itemsim/algorithms/scala/generic/src/test/resources/application.conf b/process/engines/itemsim/algorithms/scala/generic/src/test/resources/application.conf
deleted file mode 100644
index 9555997..0000000
--- a/process/engines/itemsim/algorithms/scala/generic/src/test/resources/application.conf
+++ /dev/null
@@ -1,37 +0,0 @@
-# Used by PredictionIO Commons
-io.prediction.base=.
-
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.host=localhost
-io.prediction.commons.appdata.db.port=27017
-io.prediction.commons.appdata.db.name=predictionio_appdata_itemsim_generic_dataprep_test
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.host=localhost
-io.prediction.commons.appdata.test.db.port=27017
-io.prediction.commons.appdata.test.db.name=predictionio_test_appdata_itemsim_generic_dataprep_test
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.host=localhost
-io.prediction.commons.appdata.training.db.port=27017
-io.prediction.commons.appdata.training.db.name=predictionio_trainig_appdata_itemsim_generic_dataprep_test
-
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.host=localhost
-io.prediction.commons.appdata.validation.db.port=27017
-io.prediction.commons.appdata.validation.db.name=predictionio_validation_appdata_itemsim_generic_dataprep_test
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.host=localhost
-io.prediction.commons.modeldata.db.port=27017
-io.prediction.commons.modeldata.db.name=predictionio_modeldata_itemsim_generic_dataprep_test
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.host=localhost
-io.prediction.commons.modeldata.training.db.port=27017
-io.prediction.commons.modeldata.training.db.name=predictionio_training_modeldata_itemsim_generic_dataprep_test
-
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.host=localhost
-io.prediction.commons.settings.db.port=27017
-io.prediction.commons.settings.db.name=predictionio_itemsim_generic_dataprep_test
diff --git a/process/engines/itemsim/algorithms/scala/generic/src/test/resources/logback.xml b/process/engines/itemsim/algorithms/scala/generic/src/test/resources/logback.xml
deleted file mode 100644
index 1a2768e..0000000
--- a/process/engines/itemsim/algorithms/scala/generic/src/test/resources/logback.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<configuration>
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <encoder>
-      <pattern>%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>
-    </encoder>
-  </appender>
-  <root level="info">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
-
diff --git a/process/engines/itemsim/algorithms/scala/generic/src/test/scala/io/prediction/algorithms/generic/itemsim/GenericDataPreparatorSpec.scala b/process/engines/itemsim/algorithms/scala/generic/src/test/scala/io/prediction/algorithms/generic/itemsim/GenericDataPreparatorSpec.scala
deleted file mode 100644
index 9e66ab9..0000000
--- a/process/engines/itemsim/algorithms/scala/generic/src/test/scala/io/prediction/algorithms/generic/itemsim/GenericDataPreparatorSpec.scala
+++ /dev/null
@@ -1,178 +0,0 @@
-package io.prediction.algorithms.generic.itemsim
-
-import io.prediction.commons.Config
-import io.prediction.commons.appdata.{ User, Item, U2IAction }
-
-import org.specs2.mutable._
-import com.github.nscala_time.time.Imports._
-import scala.io.Source
-import com.mongodb.casbah.Imports._
-
-class GenericDataPreparatorSpec extends Specification {
-
-  // note: should match the db name defined in the application.conf
-  val mongoDbName = "predictionio_appdata_itemsim_generic_dataprep_test"
-  def cleanUp() = {
-    // remove the test database
-    MongoConnection()(mongoDbName).dropDatabase()
-  }
-
-  val commonConfig = new Config
-  val appdataUsers = commonConfig.getAppdataUsers
-  val appdataItems = commonConfig.getAppdataItems
-  val appdataU2IActions = commonConfig.getAppdataU2IActions
-
-  "GenericDataPreparator with basic rate action app data" should {
-    val appid = 46
-    // insert a few users into db
-    val user = User(
-      id = "u0",
-      appid = appid,
-      ct = DateTime.now,
-      latlng = None,
-      inactive = None,
-      attributes = None)
-
-    appdataUsers.insert(user.copy(id = "u0"))
-    appdataUsers.insert(user.copy(id = "u1"))
-    appdataUsers.insert(user.copy(id = "u2"))
-
-    // insert a few items into db
-    val currentTime = DateTime.now
-    val item = Item(
-      id = "i0",
-      appid = appid,
-      ct = DateTime.now,
-      itypes = List("t1", "t2"),
-      starttime = Some(currentTime),
-      endtime = None,
-      price = None,
-      profit = None,
-      latlng = None,
-      inactive = None,
-      attributes = None)
-
-    appdataItems.insert(item.copy(id = "i0", itypes = List("t1", "t2"),
-      inactive = Some(false)))
-    appdataItems.insert(item.copy(id = "i1", itypes = List("t1")))
-    appdataItems.insert(item.copy(id = "i2", itypes = List("t2", "t3"),
-      inactive = Some(true)))
-    appdataItems.insert(item.copy(id = "i3", itypes = List("t3")))
-    appdataItems.insert(item.copy(id = "i4", itypes = List("t1"),
-      inactive = Some(true)))
-    appdataItems.insert(item.copy(id = "i5", itypes = List("t3"),
-      inactive = Some(false)))
-
-    // insert a few u2i into db
-    val u2i = U2IAction(
-      appid = appid,
-      action = "rate",
-      uid = "u0",
-      iid = "i0",
-      t = DateTime.now,
-      latlng = None,
-      v = Some(3),
-      price = None)
-
-    appdataU2IActions.insert(u2i.copy(uid = "u0", iid = "i0", action = "rate", v = Some(3)))
-    appdataU2IActions.insert(u2i.copy(uid = "u0", iid = "i1", action = "rate", v = Some(4)))
-    appdataU2IActions.insert(u2i.copy(uid = "u0", iid = "i2", action = "rate", v = Some(1)))
-
-    appdataU2IActions.insert(u2i.copy(uid = "u1", iid = "i0", action = "rate", v = Some(2)))
-    appdataU2IActions.insert(u2i.copy(uid = "u1", iid = "i1", action = "rate", v = Some(1)))
-    appdataU2IActions.insert(u2i.copy(uid = "u1", iid = "i3", action = "rate", v = Some(3)))
-
-    appdataU2IActions.insert(u2i.copy(uid = "u2", iid = "i1", action = "rate", v = Some(5)))
-    appdataU2IActions.insert(u2i.copy(uid = "u2", iid = "i2", action = "rate", v = Some(1)))
-    appdataU2IActions.insert(u2i.copy(uid = "u2", iid = "i3", action = "rate", v = Some(4)))
-
-    val outputDir = "/tmp/pio_test/io.prediction.algorithms.generic.itemsim.GenericDataPreparatorSpec"
-    val args = Map(
-      "outputDir" -> outputDir,
-      "appid" -> appid,
-      "viewParam" -> 4,
-      "likeParam" -> 3,
-      "dislikeParam" -> 1,
-      "conversionParam" -> 2,
-      "conflictParam" -> "highest"
-    )
-
-    val argsArray = args.toArray.flatMap {
-      case (k, v) =>
-        Array(s"--${k}", v.toString)
-    }
-
-    GenericDataPreparator.main(argsArray)
-
-    "correctly generate itemsIndex.tsv" in {
-      val itemsIndex = Source.fromFile(s"${outputDir}itemsIndex.tsv")
-        .getLines()
-        .toList
-
-      val expected = List(
-        "1\ti0\tt1,t2",
-        "2\ti1\tt1",
-        "3\ti2\tt2,t3",
-        "4\ti3\tt3",
-        "5\ti4\tt1",
-        "6\ti5\tt3"
-      )
-      itemsIndex must containTheSameElementsAs(expected)
-    }
-
-    "correctly write validItemsIndex.tsv" in {
-      val validItemsIndex = Source.fromFile(s"${outputDir}validItemsIndex.tsv")
-        .getLines()
-        .toList
-
-      val expected = List(
-        s"1\t${currentTime.millis}",
-        s"2\t${currentTime.millis}",
-        //s"3\t${currentTime.millis}", // inactive
-        s"4\t${currentTime.millis}",
-        //s"5\t${currentTime.millis}", // inactive
-        s"6\t${currentTime.millis}"
-      )
-      validItemsIndex must containTheSameElementsAs(expected)
-    }
-
-    "correctly generate ratings.mm" in {
-      val ratingsLines = Source.fromFile(s"${outputDir}ratings.mm")
-        .getLines()
-
-      val headers = ratingsLines.take(2).toList
-
-      val ratings = ratingsLines.toList
-
-      val expectedHeaders = List(
-        "%%MatrixMarket matrix coordinate real general",
-        "3 6 9"
-      )
-
-      val expected = List(
-        "1 1 3",
-        "1 2 4",
-        "1 3 1",
-        "2 1 2",
-        "2 2 1",
-        "2 4 3",
-        "3 2 5",
-        "3 3 1",
-        "3 4 4"
-      )
-      headers must be_==(expectedHeaders) and
-        (ratings must containTheSameElementsAs(expected))
-    }
-  }
-
-  // TODO: test csv output
-
-  // TODO: test mixed and conflict actions
-
-  // TODO: test start and end time
-
-  // TODO: test evalid != None
-
-  // clean up when finish test
-  step(cleanUp())
-}
diff --git a/process/engines/itemsim/algorithms/scala/graphchi/build.sbt b/process/engines/itemsim/algorithms/scala/graphchi/build.sbt
deleted file mode 100644
index 21566a8..0000000
--- a/process/engines/itemsim/algorithms/scala/graphchi/build.sbt
+++ /dev/null
@@ -1,23 +0,0 @@
-import xerial.sbt.Pack._
-
-name := "predictionio-process-itemsim-algorithms-scala-graphchi"
-
-libraryDependencies ++= Seq(
-  "ch.qos.logback" % "logback-classic" % "1.1.1",
-  "com.twitter" %% "scalding-args" % "0.8.11",
-  "org.clapper" %% "grizzled-slf4j" % "1.0.1",
-  "org.scalanlp" %% "breeze" % "0.7")
-
-packSettings
-
-packJarNameConvention := "full"
-
-packExpandedClasspath := true
-
-packGenerateWindowsBatFile := false
-
-packMain := Map(
-  "itemsim.graphchi.modelcon" -> "io.prediction.algorithms.graphchi.itemsim.GraphChiModelConstructor")
-
-packJvmOpts := Map(
-  "itemsim.graphchi.modelcon" -> Common.packCommonJvmOpts)
diff --git a/process/engines/itemsim/algorithms/scala/graphchi/src/main/resources/application.conf b/process/engines/itemsim/algorithms/scala/graphchi/src/main/resources/application.conf
deleted file mode 100644
index c85803b..0000000
--- a/process/engines/itemsim/algorithms/scala/graphchi/src/main/resources/application.conf
+++ /dev/null
@@ -1,30 +0,0 @@
-# Used by PredictionIO Commons
-io.prediction.base=.
-
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.host=localhost
-io.prediction.commons.appdata.db.port=27017
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.host=localhost
-io.prediction.commons.appdata.test.db.port=27017
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.host=localhost
-io.prediction.commons.appdata.training.db.port=27017
-
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.host=localhost
-io.prediction.commons.appdata.validation.db.port=27017
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.host=localhost
-io.prediction.commons.modeldata.db.port=27017
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.host=localhost
-io.prediction.commons.modeldata.training.db.port=27017
-
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.host=localhost
-io.prediction.commons.settings.db.port=27017
diff --git a/process/engines/itemsim/algorithms/scala/graphchi/src/main/resources/logback.xml b/process/engines/itemsim/algorithms/scala/graphchi/src/main/resources/logback.xml
deleted file mode 100644
index 1a2768e..0000000
--- a/process/engines/itemsim/algorithms/scala/graphchi/src/main/resources/logback.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<configuration>
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <encoder>
-      <pattern>%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>
-    </encoder>
-  </appender>
-  <root level="info">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
-
diff --git a/process/engines/itemsim/algorithms/scala/graphchi/src/main/scala/io/prediction/algorithms/graphchi/itemsim/GraphChiModelConstructor.scala b/process/engines/itemsim/algorithms/scala/graphchi/src/main/scala/io/prediction/algorithms/graphchi/itemsim/GraphChiModelConstructor.scala
deleted file mode 100644
index d0ec835..0000000
--- a/process/engines/itemsim/algorithms/scala/graphchi/src/main/scala/io/prediction/algorithms/graphchi/itemsim/GraphChiModelConstructor.scala
+++ /dev/null
@@ -1,150 +0,0 @@
-package io.prediction.algorithms.graphchi.itemsim
-
-import grizzled.slf4j.Logger
-import breeze.linalg._
-import com.twitter.scalding.Args
-import scala.io.Source
-
-import io.prediction.commons.Config
-import io.prediction.commons.modeldata.{ ItemSimScore }
-
-/**
- * Input files:
- * - itemsIndex.tsv (iindex iid itypes): all items
- * - validItemsIndex.tsv (iindex): valid candidate items to be recommended
- * - ratings.mm-topk (iindex1 iindex2 score) generated by GraphChi
- *
- */
-object GraphChiModelConstructor {
-
-  /* global */
-  val logger = Logger(GraphChiModelConstructor.getClass)
-  //println(logger.isInfoEnabled)
-  val commonsConfig = new Config
-
-  // argument of this job
-  case class JobArg(
-    val inputDir: String,
-    val appid: Int,
-    val algoid: Int,
-    val evalid: Option[Int],
-    val modelSet: Boolean,
-    val numSimilarItems: Int)
-
-  def main(cmdArgs: Array[String]) {
-    logger.info("Running model constructor for GraphChi ItemSim ...")
-    logger.info(cmdArgs.mkString(","))
-
-    /* get arg */
-    val args = Args(cmdArgs)
-
-    val arg = JobArg(
-      inputDir = args("inputDir"),
-      appid = args("appid").toInt,
-      algoid = args("algoid").toInt,
-      evalid = args.optional("evalid") map (x => x.toInt),
-      modelSet = args("modelSet").toBoolean,
-      numSimilarItems = args("numSimilarItems").toInt
-    )
-
-    /* run job */
-    modelCon(arg)
-    cleanUp(arg)
-  }
-
-  def modelCon(arg: JobArg) = {
-
-    // NOTE: if OFFLINE_EVAL, write to training modeldata and use evalid as appid
-    val OFFLINE_EVAL = (arg.evalid != None)
-
-    val modeldataDb = if (!OFFLINE_EVAL)
-      commonsConfig.getModeldataItemSimScores
-    else
-      commonsConfig.getModeldataTrainingItemSimScores
-
-    val appid = if (OFFLINE_EVAL) arg.evalid.get else arg.appid
-
-    case class ItemData(
-      val iid: String,
-      val itypes: Seq[String])
-
-    // item index file (iindex iid itypes)
-    // iindex -> ItemData
-    val itemsMap: Map[Int, ItemData] = Source.fromFile(s"${arg.inputDir}itemsIndex.tsv")
-      .getLines()
-      .map[(Int, ItemData)] { line =>
-        val (iindex, item) = try {
-          val fields = line.split("\t")
-          val itemData = ItemData(
-            iid = fields(1),
-            itypes = fields(2).split(",").toList
-          )
-          (fields(0).toInt, itemData)
-        } catch {
-          case e: Exception => {
-            throw new RuntimeException(s"Cannot get item info in line: ${line}. ${e}")
-          }
-        }
-        (iindex, item)
-      }.toMap
-
-    // valid item index file (iindex iid itypes)
-    // iindex
-    val validItemsSet: Set[Int] = Source.fromFile(s"${arg.inputDir}validItemsIndex.tsv")
-      .getLines()
-      .map[Int] { line =>
-        val iindex = try {
-          val fields = line.split("\t")
-          fields(0).toInt
-        } catch {
-          case e: Exception => {
-            throw new RuntimeException(s"Cannot get item info in line: ${line}. ${e}")
-          }
-        }
-        iindex
-      }.toSet
-
-    // iindex1 iindex2 score
-    val simScores = Source.fromFile(s"${arg.inputDir}ratings.mm-topk")
-      .getLines()
-      .map[(Int, Int, Double)] { line =>
-        val (iindex1, iindex2, score) = try {
-          val fields = line.split("""\s+""")
-          (fields(0).toInt, fields(1).toInt, fields(2).toDouble)
-        } catch {
-          case e: Exception => throw new RuntimeException(s"Cannot read item index and score from the line: ${line}. ${e}")
-        }
-        (iindex1, iindex2, score)
-      }.toSeq
-
-    val similarities = simScores ++
-      simScores.map { case (iindex1, iindex2, score) => (iindex2, iindex1, score) }
-
-    // iindex1 -> Seq[(iindex1, iindex2, score)]
-    similarities.groupBy(_._1).foreach {
-      case (iindex1, scoresSeq) =>
-
-        // only recommend items in validItems
-        val topScores = scoresSeq.filter { x => validItemsSet(x._2) }
-          .sortBy(_._3)(Ordering[Double].reverse)
-          .take(arg.numSimilarItems)
-
-        logger.debug(s"${iindex1}: ${topScores.toList}")
-        modeldataDb.insert(ItemSimScore(
-          iid = itemsMap(iindex1).iid,
-          simiids = topScores.map(x => itemsMap(x._2).iid),
-          scores = topScores.map(_._3),
-          itypes = topScores.map(x => itemsMap(x._2).itypes),
-          appid = appid,
-          algoid = arg.algoid,
-          modelset = arg.modelSet))
-
-    }
-
-  }
-
-  def cleanUp(arg: JobArg) = {
-
-  }
-
-}
diff --git a/process/engines/itemsim/algorithms/scala/graphchi/src/test/resources/application.conf b/process/engines/itemsim/algorithms/scala/graphchi/src/test/resources/application.conf
deleted file mode 100644
index 45b3078..0000000
--- a/process/engines/itemsim/algorithms/scala/graphchi/src/test/resources/application.conf
+++ /dev/null
@@ -1,37 +0,0 @@
-# Used by PredictionIO Commons
-io.prediction.base=.
-
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.host=localhost
-io.prediction.commons.appdata.db.port=27017
-io.prediction.commons.appdata.db.name=predictionio_appdata_graphchi_dataprep_test
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.host=localhost
-io.prediction.commons.appdata.test.db.port=27017
-io.prediction.commons.appdata.test.db.name=predictionio_test_appdata_graphchi_dataprep_test
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.host=localhost
-io.prediction.commons.appdata.training.db.port=27017
-io.prediction.commons.appdata.training.db.name=predictionio_trainig_appdata_graphchi_dataprep_test
-
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.host=localhost
-io.prediction.commons.appdata.validation.db.port=27017
-io.prediction.commons.appdata.validation.db.name=predictionio_validation_appdata_graphchi_dataprep_test
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.host=localhost
-io.prediction.commons.modeldata.db.port=27017
-io.prediction.commons.modeldata.db.name=predictionio_modeldata_graphchi_dataprep_test
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.host=localhost
-io.prediction.commons.modeldata.training.db.port=27017
-io.prediction.commons.modeldata.training.db.name=predictionio_training_modeldata_graphchi_dataprep_test
-
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.host=localhost
-io.prediction.commons.settings.db.port=27017
-io.prediction.commons.settings.db.name=predictionio_graphchi_dataprep_test
diff --git a/process/engines/itemsim/algorithms/scala/graphchi/src/test/resources/logback.xml b/process/engines/itemsim/algorithms/scala/graphchi/src/test/resources/logback.xml
deleted file mode 100644
index 1a2768e..0000000
--- a/process/engines/itemsim/algorithms/scala/graphchi/src/test/resources/logback.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<configuration>
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <encoder>
-      <pattern>%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>
-    </encoder>
-  </appender>
-  <root level="info">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
-
diff --git a/process/engines/itemsim/algorithms/scala/graphchi/src/test/scala/io/prediction/algorithms/graphchi/itemsim/GraphChiModelConstructorSpec.scala b/process/engines/itemsim/algorithms/scala/graphchi/src/test/scala/io/prediction/algorithms/graphchi/itemsim/GraphChiModelConstructorSpec.scala
deleted file mode 100644
index 58d4824..0000000
--- a/process/engines/itemsim/algorithms/scala/graphchi/src/test/scala/io/prediction/algorithms/graphchi/itemsim/GraphChiModelConstructorSpec.scala
+++ /dev/null
@@ -1,356 +0,0 @@
-package io.prediction.algorithms.graphchi.itemsim
-
-import io.prediction.commons.Config
-import io.prediction.commons.settings.{ App, Algo }
-import io.prediction.commons.modeldata.{ ItemSimScore }
-
-import org.specs2.mutable._
-import com.github.nscala_time.time.Imports._
-import scala.io.Source
-import java.io.File
-import java.io.FileWriter
-import java.io.BufferedWriter
-
-import com.mongodb.casbah.Imports._
-
-class GraphChiItemSimModelConstructorSpec extends Specification {
-
-  // note: should match the db name defined in the application.conf
-  val mongoDbName = "predictionio_modeldata_graphchi_dataprep_test"
-  def cleanUp() = {
-    // remove the test database
-    MongoConnection()(mongoDbName).dropDatabase()
-  }
-
-  val commonConfig = new Config
-  val modeldataItemSimScores = commonConfig.getModeldataItemSimScores
-
-  def argMapToArray(args: Map[String, Any]): Array[String] = {
-    args.toArray.flatMap {
-      case (k, v) =>
-        Array(s"--${k}", v.toString)
-    }
-  }
-
-  def writeToFile(lines: List[String], filePath: String) = {
-    val writer = new BufferedWriter(new FileWriter(new File(filePath)))
-    lines.foreach { line =>
-      writer.write(s"${line}\n")
-    }
-    writer.close()
-  }
-
-  "GraphChiItemSimModelConstructor" should {
-    val inputDir = "/tmp/pio_test/"
-
-    val inputDirFile = new File(inputDir)
-    inputDirFile.mkdirs()
-
-    val itemsIndex = List(
-      "1\ti0\tt1,t2",
-      "2\ti1\tt1",
-      "3\ti2\tt2,t3",
-      "4\ti3\tt3"
-    )
-
-    val validItemIndex = List(
-      "1",
-      "2",
-      "3",
-      "4"
-    )
-
-    val scoresTopK = List(
-      "1 2 12.6",
-      "1 3 1.5",
-      "2 4 20.4",
-      "2 3 5.6",
-      "3 4 2.3",
-      "4 1 15.4"
-    )
-
-    writeToFile(itemsIndex, s"${inputDir}itemsIndex.tsv")
-    writeToFile(validItemIndex, s"${inputDir}validItemsIndex.tsv")
-    writeToFile(scoresTopK, s"${inputDir}ratings.mm-topk")
-
-    val appid = 12
-
-    implicit val app = App(
-      id = appid,
-      userid = 0,
-      appkey = "1234",
-      display = "12345",
-      url = None,
-      cat = None,
-      desc = None,
-      timezone = "UTC"
-    )
-
-    "correctly writes ItemSimScores with larger numSimilarItems" in {
-
-      val algoid = 45
-      val modelSet = false
-
-      implicit val algo = Algo(
-        id = algoid,
-        engineid = 1234,
-        name = "",
-        infoid = "abc",
-        command = "",
-        params = Map(),
-        settings = Map(),
-        modelset = modelSet,
-        createtime = DateTime.now,
-        updatetime = DateTime.now,
-        status = "deployed",
-        offlineevalid = None,
-        offlinetuneid = None,
-        loop = None,
-        paramset = None
-      )
-
-      val args = Map(
-        "inputDir" -> inputDir,
-        "appid" -> appid,
-        "algoid" -> algoid,
-        "modelSet" -> modelSet,
-        "numSimilarItems" -> 10
-      )
-
-      val i0Expected = ItemSimScore(
-        iid = "i0",
-        simiids = Seq("i3", "i1", "i2"),
-        scores = Seq(15.4, 12.6, 1.5),
-        itypes = Seq(Seq("t3"), Seq("t1"), Seq("t2", "t3")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val i1Expected = ItemSimScore(
-        iid = "i1",
-        simiids = Seq("i3", "i0", "i2"),
-        scores = Seq(20.4, 12.6, 5.6),
-        itypes = Seq(Seq("t3"), Seq("t1", "t2"), Seq("t2", "t3")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val i2Expected = ItemSimScore(
-        iid = "i2",
-        simiids = Seq("i1", "i3", "i0"),
-        scores = Seq(5.6, 2.3, 1.5),
-        itypes = Seq(Seq("t1"), Seq("t3"), Seq("t1", "t2")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val i3Expected = ItemSimScore(
-        iid = "i3",
-        simiids = Seq("i1", "i0", "i2"),
-        scores = Seq(20.4, 15.4, 2.3),
-        itypes = Seq(Seq("t1"), Seq("t1", "t2"), Seq("t2", "t3")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      GraphChiModelConstructor.main(argMapToArray(args))
-
-      val i0ItemSim = modeldataItemSimScores.getByIid("i0")
-      val i1ItemSim = modeldataItemSimScores.getByIid("i1")
-      val i2ItemSim = modeldataItemSimScores.getByIid("i2")
-      val i3ItemSim = modeldataItemSimScores.getByIid("i3")
-
-      // don't check id
-      i0ItemSim.map(_.copy(id = None)) must beSome(i0Expected) and
-        (i1ItemSim.map(_.copy(id = None)) must beSome(i1Expected)) and
-        (i2ItemSim.map(_.copy(id = None)) must beSome(i2Expected)) and
-        (i3ItemSim.map(_.copy(id = None)) must beSome(i3Expected))
-
-    }
-
-    "correctly writes ItemSimScores with smaller numSimilarItems" in {
-
-      val algoid = 45
-      val modelSet = true
-
-      implicit val algo = Algo(
-        id = algoid,
-        engineid = 1234,
-        name = "",
-        infoid = "abc",
-        command = "",
-        params = Map(),
-        settings = Map(),
-        modelset = modelSet,
-        createtime = DateTime.now,
-        updatetime = DateTime.now,
-        status = "deployed",
-        offlineevalid = None,
-        offlinetuneid = None,
-        loop = None,
-        paramset = None
-      )
-
-      val args = Map(
-        "inputDir" -> inputDir,
-        "appid" -> appid,
-        "algoid" -> algoid,
-        "modelSet" -> modelSet,
-        "numSimilarItems" -> 1
-      )
-
-      val i0Expected = ItemSimScore(
-        iid = "i0",
-        simiids = Seq("i3"),
-        scores = Seq(15.4),
-        itypes = Seq(Seq("t3")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val i1Expected = ItemSimScore(
-        iid = "i1",
-        simiids = Seq("i3"),
-        scores = Seq(20.4),
-        itypes = Seq(Seq("t3")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val i2Expected = ItemSimScore(
-        iid = "i2",
-        simiids = Seq("i1"),
-        scores = Seq(5.6),
-        itypes = Seq(Seq("t1")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val i3Expected = ItemSimScore(
-        iid = "i3",
-        simiids = Seq("i1"),
-        scores = Seq(20.4),
-        itypes = Seq(Seq("t1")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      GraphChiModelConstructor.main(argMapToArray(args))
-
-      val i0ItemSim = modeldataItemSimScores.getByIid("i0")
-      val i1ItemSim = modeldataItemSimScores.getByIid("i1")
-      val i2ItemSim = modeldataItemSimScores.getByIid("i2")
-      val i3ItemSim = modeldataItemSimScores.getByIid("i3")
-
-      // don't check id
-      i0ItemSim.map(_.copy(id = None)) must beSome(i0Expected) and
-        (i1ItemSim.map(_.copy(id = None)) must beSome(i1Expected)) and
-        (i2ItemSim.map(_.copy(id = None)) must beSome(i2Expected)) and
-        (i3ItemSim.map(_.copy(id = None)) must beSome(i3Expected))
-
-    }
-
-    // TODO: subset valid items
-    "correctly writes ItemSimScores with subset numSimilarItems" in {
-
-      val algoid = 46
-      val modelSet = false
-
-      val inputDir = "/tmp/pio_test/subset/"
-
-      val inputDirFile = new File(inputDir)
-      inputDirFile.mkdirs()
-
-      val validItemIndex = List(
-        "1",
-        "4"
-      )
-
-      writeToFile(itemsIndex, s"${inputDir}itemsIndex.tsv")
-      writeToFile(validItemIndex, s"${inputDir}validItemsIndex.tsv")
-      writeToFile(scoresTopK, s"${inputDir}ratings.mm-topk")
-
-      implicit val algo = Algo(
-        id = algoid,
-        engineid = 1234,
-        name = "",
-        infoid = "abc",
-        command = "",
-        params = Map(),
-        settings = Map(),
-        modelset = modelSet,
-        createtime = DateTime.now,
-        updatetime = DateTime.now,
-        status = "deployed",
-        offlineevalid = None,
-        offlinetuneid = None,
-        loop = None,
-        paramset = None
-      )
-
-      val args = Map(
-        "inputDir" -> inputDir,
-        "appid" -> appid,
-        "algoid" -> algoid,
-        "modelSet" -> modelSet,
-        "numSimilarItems" -> 10
-      )
-
-      val i0Expected = ItemSimScore(
-        iid = "i0",
-        simiids = Seq("i3"),
-        scores = Seq(15.4),
-        itypes = Seq(Seq("t3")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val i1Expected = ItemSimScore(
-        iid = "i1",
-        simiids = Seq("i3", "i0"),
-        scores = Seq(20.4, 12.6),
-        itypes = Seq(Seq("t3"), Seq("t1", "t2")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val i2Expected = ItemSimScore(
-        iid = "i2",
-        simiids = Seq("i3", "i0"),
-        scores = Seq(2.3, 1.5),
-        itypes = Seq(Seq("t3"), Seq("t1", "t2")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val i3Expected = ItemSimScore(
-        iid = "i3",
-        simiids = Seq("i0"),
-        scores = Seq(15.4),
-        itypes = Seq(Seq("t1", "t2")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      GraphChiModelConstructor.main(argMapToArray(args))
-
-      val i0ItemSim = modeldataItemSimScores.getByIid("i0")
-      val i1ItemSim = modeldataItemSimScores.getByIid("i1")
-      val i2ItemSim = modeldataItemSimScores.getByIid("i2")
-      val i3ItemSim = modeldataItemSimScores.getByIid("i3")
-
-      // don't check id
-      i0ItemSim.map(_.copy(id = None)) must beSome(i0Expected) and
-        (i1ItemSim.map(_.copy(id = None)) must beSome(i1Expected)) and
-        (i2ItemSim.map(_.copy(id = None)) must beSome(i2Expected)) and
-        (i3ItemSim.map(_.copy(id = None)) must beSome(i3Expected))
-
-    }
-
-    // TODO: evalid
-
-  }
-
-  // NOTE: clean up when finish test
-  step(cleanUp())
-}
\ No newline at end of file
diff --git a/process/engines/itemsim/algorithms/scala/mahout/build.sbt b/process/engines/itemsim/algorithms/scala/mahout/build.sbt
deleted file mode 100644
index cf4f6ed..0000000
--- a/process/engines/itemsim/algorithms/scala/mahout/build.sbt
+++ /dev/null
@@ -1,27 +0,0 @@
-import xerial.sbt.Pack._
-
-name := "predictionio-process-itemsim-algorithms-scala-mahout"
-
-libraryDependencies ++= Seq(
-  "org.apache.mahout" % "mahout-core" % "0.9",
-  "ch.qos.logback" % "logback-classic" % "1.1.1",
-  "com.twitter" %% "scalding-args" % "0.8.11",
-  "org.clapper" %% "grizzled-slf4j" % "1.0.1")
-
-parallelExecution in Test := false
-
-packSettings
-
-packJarNameConvention := "full"
-
-packExpandedClasspath := true
-
-packGenerateWindowsBatFile := false
-
-packMain := Map(
-  "itemsim.mahout.mahoutjob" -> "io.prediction.algorithms.mahout.itemsim.MahoutJob",
-  "itemsim.mahout.modelcon" -> "io.prediction.algorithms.mahout.itemsim.MahoutModelConstructor")
-
-packJvmOpts := Map(
-  "itemsim.mahout.mahoutjob" -> Common.packCommonJvmOpts,
-  "itemsim.mahout.modelcon" -> Common.packCommonJvmOpts)
diff --git a/process/engines/itemsim/algorithms/scala/mahout/src/main/resources/application.conf b/process/engines/itemsim/algorithms/scala/mahout/src/main/resources/application.conf
deleted file mode 100644
index c85803b..0000000
--- a/process/engines/itemsim/algorithms/scala/mahout/src/main/resources/application.conf
+++ /dev/null
@@ -1,30 +0,0 @@
-# Used by PredictionIO Commons
-io.prediction.base=.
-
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.host=localhost
-io.prediction.commons.appdata.db.port=27017
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.host=localhost
-io.prediction.commons.appdata.test.db.port=27017
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.host=localhost
-io.prediction.commons.appdata.training.db.port=27017
-
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.host=localhost
-io.prediction.commons.appdata.validation.db.port=27017
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.host=localhost
-io.prediction.commons.modeldata.db.port=27017
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.host=localhost
-io.prediction.commons.modeldata.training.db.port=27017
-
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.host=localhost
-io.prediction.commons.settings.db.port=27017
diff --git a/process/engines/itemsim/algorithms/scala/mahout/src/main/resources/logback.xml b/process/engines/itemsim/algorithms/scala/mahout/src/main/resources/logback.xml
deleted file mode 100644
index 1a2768e..0000000
--- a/process/engines/itemsim/algorithms/scala/mahout/src/main/resources/logback.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<configuration>
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <encoder>
-      <pattern>%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>
-    </encoder>
-  </appender>
-  <root level="info">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
-
diff --git a/process/engines/itemsim/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemsim/MahoutJob.scala b/process/engines/itemsim/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemsim/MahoutJob.scala
deleted file mode 100644
index bdf4e39..0000000
--- a/process/engines/itemsim/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemsim/MahoutJob.scala
+++ /dev/null
@@ -1,216 +0,0 @@
-package io.prediction.algorithms.mahout.itemsim
-
-import grizzled.slf4j.Logger
-import java.io.File
-import java.io.FileWriter
-import java.io.BufferedWriter
-
-import scala.io.Source
-import scala.collection.JavaConversions._
-import scala.sys.process._
-import scala.collection.mutable.PriorityQueue
-
-import com.github.nscala_time.time.Imports._
-import org.apache.mahout.cf.taste.similarity.ItemSimilarity
-import org.apache.mahout.cf.taste.model.DataModel
-import org.apache.mahout.cf.taste.impl.model.file.FileDataModel
-
-/** main function to run non-distributed Mahout Job */
-object MahoutJob {
-
-  val logger = Logger(MahoutJob.getClass)
-
-  def main(args: Array[String]) {
-    if (args.size < 1) {
-      logger.error("Please specify Mahout job class name")
-      logger.error("Example. <job class name> --param1 1 --param2 2")
-      System.exit(1)
-    }
-
-    val jobName = args(0)
-
-    logger.info("Running Job %s...".format(jobName))
-
-    logger.info(args.mkString(" "))
-    val (argMap, lastkey) = args.drop(1).foldLeft((Map[String, String](), "")) { (res, data) =>
-      val (argMap, lastkey) = res
-      val key: Option[String] = if (data.startsWith("--")) Some(data.stripPrefix("--")) else None
-
-      key map { k =>
-        (argMap ++ Map(k -> ""), k)
-      } getOrElse {
-        val orgData = argMap(lastkey)
-        val newData = orgData match {
-          case "" => data
-          case _ => orgData + " " + data
-        }
-        (argMap ++ Map(lastkey -> newData), lastkey)
-      }
-    }
-    //println(argMap)
-
-    val job = Class.forName(jobName).
-      getConstructor().
-      newInstance().
-      asInstanceOf[MahoutJob]
-
-    val runArgs = job.prepare(argMap)
-
-    val finishArgs = job.run(runArgs)
-
-    val cleanupArgs = job.finish(finishArgs)
-
-    job.cleanup(cleanupArgs)
-
-    logger.info("done")
-
-  }
-
-}
-
-/** Wrapper job class for Mahout algo */
-abstract class MahoutJob {
-  /** Get required arg */
-  def getArg(args: Map[String, String], key: String): String = {
-    if (!args.contains(key)) sys.error("Please specify value for parameter --" + key)
-
-    args(key)
-  }
-
-  /** Get optional arg */
-  def getArgOpt(args: Map[String, String], key: String, default: String): String = {
-    if (args.contains(key)) args(key) else default
-  }
-
-  def getArgOpt(args: Map[String, String], key: String): Option[String] = {
-    if (args.contains(key)) Some(args(key)) else None
-  }
-
-  /** Prepare stage for algo */
-  def prepare(args: Map[String, String]): Map[String, String] = {
-    // simply pass the args to next stage
-    args
-  }
-
-  /** create and return Mahout's ItemSimilarity object. */
-  def buildItemSimilarity(dataModel: DataModel, args: Map[String, String]): ItemSimilarity
-
-  /**
-   * Run algo job.
-   * In default implementation, the prepare() function does nothing
-   * The run() function read and process this local file (defined by --input arg) file and generate the prediction
-   * output file (defined by --output arg) for each user.
-   * Then finish() does nothing
-   */
-  def run(args: Map[String, String]): Map[String, String] = {
-
-    val input = args("input")
-    val output = args("output")
-    val itemsFile = args("itemsFile") // contains valid item index can be recommended
-    val numSimilarItems: Int = getArgOpt(args, "numSimilarItems", "10").toInt
-    val recommendationTime: Long = getArg(args, "recommendationTime").toLong
-    val freshness = getArgOpt(args, "freshness", "0").toInt
-    val freshnessTimeUnit: Long = getArgOpt(args, "freshnessTimeUnit")
-      .map(_.toLong).getOrElse(1.hours.millis)
-
-    // valid item index file (iindex)
-    // iindex
-    val validItemsMap: Map[Long, Long] = Source.fromFile(itemsFile).getLines()
-      .map { line =>
-        val (iindex, starttime) = try {
-          val fields = line.split("\t")
-          (fields(0).toLong, fields(1).toLong)
-        } catch {
-          case e: Exception => {
-            throw new RuntimeException(s"Cannot get item info in line: ${line}. ${e}")
-          }
-        }
-        (iindex, starttime)
-      }.toMap
-
-    val validItemsSet = validItemsMap.keys.toSet
-
-    val dataModel: DataModel = new FileDataModel(new File(input))
-    val similarity: ItemSimilarity = buildItemSimilarity(dataModel, args)
-
-    val outputFile = new File(output)
-    // create dir if it doesn't exist yet.
-    outputFile.getParentFile().mkdirs()
-
-    // generate prediction output file
-    val outputWriter = new BufferedWriter(new FileWriter(outputFile))
-
-    val itemIds = dataModel.getItemIDs.toSeq.map(_.toLong)
-    val candidateItemsIds = itemIds.filter(validItemsSet(_))
-
-    val allTopScores = itemIds.par.map { iid =>
-      val simScores = candidateItemsIds
-        .map { simiid =>
-          val originalScore = similarity.itemSimilarity(iid, simiid)
-          val score = if (freshness > 0) {
-            validItemsMap.get(simiid) map { starttime =>
-              val timeDiff = (recommendationTime - starttime) / 1000.0 /
-                freshnessTimeUnit
-              if (timeDiff > 0)
-                originalScore * scala.math.exp(-timeDiff / (11 - freshness))
-              else
-                originalScore
-            } getOrElse originalScore
-          } else originalScore
-          (simiid, score)
-        }
-        // filter out invalid score or the same iid itself
-        .filter { x: (Long, Double) => (!x._2.isNaN()) && (x._1 != iid) }
-
-      (iid, getTopN(simScores, numSimilarItems)(ScoreOrdering.reverse))
-    }
-
-    allTopScores.seq.foreach {
-      case (iid, simScores) =>
-        if (!simScores.isEmpty) {
-          val scoresString = simScores.map(x => s"${x._1}:${x._2}")
-            .mkString(",")
-          outputWriter.write(s"${iid}\t[${scoresString}]\n")
-        }
-    }
-
-    outputWriter.close()
-
-    args
-  }
-
-  /** finish stage for algo */
-  def finish(args: Map[String, String]): Map[String, String] = {
-    // simply pass the args to next stage
-    args
-  }
-
-  /** Cleanup stage for algo */
-  def cleanup(args: Map[String, String]) = {
-    // simpley pass the args to next stage
-    args
-  }
-
-  object ScoreOrdering extends Ordering[(Long, Double)] {
-    override def compare(a: (Long, Double), b: (Long, Double)) =
-      a._2 compare b._2
-  }
-
-  def getTopN[T](s: Seq[T], n: Int)(ord: Ordering[T]): Seq[T] = {
-    val q = PriorityQueue()(ord)
-
-    for (x <- s) {
-      if (q.size < n)
-        q.enqueue(x)
-      else {
-        // q is full
-        if (ord.compare(x, q.head) < 0) {
-          q.dequeue()
-          q.enqueue(x)
-        }
-      }
-    }
-
-    q.dequeueAll.toSeq.reverse
-  }
-}
diff --git a/process/engines/itemsim/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemsim/MahoutModelConstructor.scala b/process/engines/itemsim/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemsim/MahoutModelConstructor.scala
deleted file mode 100644
index ff48564..0000000
--- a/process/engines/itemsim/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemsim/MahoutModelConstructor.scala
+++ /dev/null
@@ -1,168 +0,0 @@
-package io.prediction.algorithms.mahout.itemsim
-
-import grizzled.slf4j.Logger
-import com.twitter.scalding.Args
-import scala.io.Source
-
-import io.prediction.commons.Config
-import io.prediction.commons.modeldata.{ ItemSimScore }
-
-/*
- * Description:
- * input file:
- * - itemsIndex.tsv (iindex iid itypes): all items
- * - similarities.tsv (iindex [iindex1:score,iindex2:score,...]: output of MahotJob
- *
- * Required args:
- * --inputDir: <string>
- * --appid: <int>
- * --engineid: <int>
- * --algoid: <int>
- * --modelSet: <boolean> (true/false). flag to indicate which set
- * --numSimilarItems: <int>. number of similar items to be generated
- *
- * Optionsl args:
- * --evalid: <int>. Offline Evaluation if evalid is specified
- *
- * Example:
- */
-object MahoutModelConstructor {
-  /* global */
-  val logger = Logger(MahoutModelConstructor.getClass)
-  val commonsConfig = new Config
-
-  // argument of this job
-  case class JobArg(
-    val inputDir: String,
-    val appid: Int,
-    val algoid: Int,
-    val evalid: Option[Int],
-    val modelSet: Boolean,
-    val numSimilarItems: Int)
-
-  def main(cmdArgs: Array[String]) {
-    logger.info("Running model constructor for Mahout ...")
-    logger.info(cmdArgs.mkString(","))
-
-    /* get arg */
-    val args = Args(cmdArgs)
-
-    val arg = JobArg(
-      inputDir = args("inputDir"),
-      appid = args("appid").toInt,
-      algoid = args("algoid").toInt,
-      evalid = args.optional("evalid") map (x => x.toInt),
-      modelSet = args("modelSet").toBoolean,
-      numSimilarItems = args("numSimilarItems").toInt
-    )
-
-    /* run job */
-    modelCon(arg)
-    cleanUp(arg)
-  }
-
-  def modelCon(arg: JobArg) = {
-
-    // NOTE: if OFFLINE_EVAL, write to training modeldata and use evalid as appid
-    val OFFLINE_EVAL = (arg.evalid != None)
-
-    val modeldataDb = if (!OFFLINE_EVAL)
-      commonsConfig.getModeldataItemSimScores
-    else
-      commonsConfig.getModeldataTrainingItemSimScores
-
-    val appid = if (OFFLINE_EVAL) arg.evalid.get else arg.appid
-
-    case class ItemData(
-      val iid: String,
-      val itypes: Seq[String])
-
-    // item index file (iindex iid itypes)
-    // iindex -> ItemData
-    val itemsMap: Map[Int, ItemData] = Source.fromFile(s"${arg.inputDir}itemsIndex.tsv")
-      .getLines()
-      .map[(Int, ItemData)] { line =>
-        val (iindex, item) = try {
-          val fields = line.split("\t")
-          val itemData = ItemData(
-            iid = fields(1),
-            itypes = fields(2).split(",").toList
-          )
-          (fields(0).toInt, itemData)
-        } catch {
-          case e: Exception => {
-            throw new RuntimeException(s"Cannot get item info in line: ${line}. ${e}")
-          }
-        }
-        (iindex, item)
-      }.toMap
-
-    // prediction
-    Source.fromFile(s"${arg.inputDir}similarities.tsv")
-      .getLines()
-      .foreach { line =>
-        val fields = line.split("\t")
-
-        val (iindex, predictedData) = try {
-          (fields(0).toInt, fields(1))
-        } catch {
-          case e: Exception => throw new RuntimeException(s"Cannot extract uindex and prediction output from this line: ${line}. ${e}")
-        }
-
-        val predicted: Seq[(Int, Double)] = parsePredictedData(predictedData)
-          .map { case (iindex, rating) => (iindex.toInt, rating) }
-
-        val topScores = predicted
-          // valid item filtering is donw inside MahoutJob
-          .sortBy(_._2)(Ordering[Double].reverse)
-          .take(arg.numSimilarItems)
-
-        logger.debug(s"${iindex}: ${topScores}")
-
-        val itemid = try {
-          itemsMap(iindex).iid
-        } catch {
-          case e: Exception => throw new RuntimeException(s"Cannot get iid for this iindex: ${line}. ${e}")
-        }
-        modeldataDb.insert(ItemSimScore(
-          iid = itemid,
-          simiids = topScores.map(x => itemsMap(x._1).iid),
-          scores = topScores.map(_._2),
-          itypes = topScores.map(x => itemsMap(x._1).itypes),
-          appid = appid,
-          algoid = arg.algoid,
-          modelset = arg.modelSet))
-
-      }
-  }
-
-  def cleanUp(arg: JobArg) = {
-
-  }
-
-  /* TODO refactor this
-  Mahout ItemRec output format
-  [24:3.2] => (24, 3.2)
-  [8:2.5,0:2.5]  => (8, 2.5), (0, 2.5)
-  [0:2.0]
-  [16:3.0]
-  */
-  def parsePredictedData(data: String): List[(String, Double)] = {
-    val dataLen = data.length
-    data.take(dataLen - 1).tail.split(",").toList.map { ratingData =>
-      val ratingDataArray = ratingData.split(":")
-      val item = ratingDataArray(0)
-      val rating: Double = try {
-        ratingDataArray(1).toDouble
-      } catch {
-        case e: Exception =>
-          {
-            assert(false, s"Cannot convert rating value of item ${item} to double: " + ratingDataArray + ". Exception: " + e)
-          }
-          0.0
-      }
-      (item, rating)
-    }
-  }
-
-}
diff --git a/process/engines/itemsim/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemsim/itemsimcf/ItemSimCFJob.scala b/process/engines/itemsim/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemsim/itemsimcf/ItemSimCFJob.scala
deleted file mode 100644
index 8038065..0000000
--- a/process/engines/itemsim/algorithms/scala/mahout/src/main/scala/io/prediction/algorithms/mahout/itemsim/itemsimcf/ItemSimCFJob.scala
+++ /dev/null
@@ -1,42 +0,0 @@
-package io.prediction.algorithms.mahout.itemsim.itemsimcf
-
-import io.prediction.algorithms.mahout.itemsim.MahoutJob
-
-import org.apache.mahout.cf.taste.model.DataModel
-import org.apache.mahout.cf.taste.common.Weighting
-import org.apache.mahout.cf.taste.similarity.ItemSimilarity
-import org.apache.mahout.cf.taste.impl.similarity.{
-  CityBlockSimilarity,
-  EuclideanDistanceSimilarity,
-  LogLikelihoodSimilarity,
-  PearsonCorrelationSimilarity,
-  TanimotoCoefficientSimilarity,
-  UncenteredCosineSimilarity
-}
-
-class ItemSimCFJob extends MahoutJob {
-
-  val defaultItemSimilarity = "LogLikelihoodSimilarity"
-
-  override def buildItemSimilarity(dataModel: DataModel, args: Map[String, String]): ItemSimilarity = {
-
-    val booleanData: Boolean = getArgOpt(args, "booleanData", "false").toBoolean
-    val itemSimilarity: String = getArgOpt(args, "itemSimilarity", defaultItemSimilarity)
-    val weighted: Boolean = getArgOpt(args, "weighted", "false").toBoolean
-
-    val weightedParam: Weighting = if (weighted) Weighting.WEIGHTED else Weighting.UNWEIGHTED
-
-    val similarity: ItemSimilarity = itemSimilarity match {
-      case "CityBlockSimilarity" => new CityBlockSimilarity(dataModel)
-      case "EuclideanDistanceSimilarity" => new EuclideanDistanceSimilarity(dataModel, weightedParam)
-      case "LogLikelihoodSimilarity" => new LogLikelihoodSimilarity(dataModel)
-      case "PearsonCorrelationSimilarity" => new PearsonCorrelationSimilarity(dataModel, weightedParam)
-      case "TanimotoCoefficientSimilarity" => new TanimotoCoefficientSimilarity(dataModel)
-      case "UncenteredCosineSimilarity" => new UncenteredCosineSimilarity(dataModel, weightedParam)
-      case _ => throw new RuntimeException("Invalid ItemSimilarity: " + itemSimilarity)
-    }
-
-    similarity
-  }
-
-}
\ No newline at end of file
diff --git a/process/engines/itemsim/algorithms/scala/mahout/src/test/resources/application.conf b/process/engines/itemsim/algorithms/scala/mahout/src/test/resources/application.conf
deleted file mode 100644
index 28ac0ee..0000000
--- a/process/engines/itemsim/algorithms/scala/mahout/src/test/resources/application.conf
+++ /dev/null
@@ -1,37 +0,0 @@
-# Used by PredictionIO Commons
-io.prediction.base=.
-
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.host=localhost
-io.prediction.commons.appdata.db.port=27017
-io.prediction.commons.appdata.db.name=predictionio_appdata_mahout_dataprep_test
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.host=localhost
-io.prediction.commons.appdata.test.db.port=27017
-io.prediction.commons.appdata.test.db.name=predictionio_test_appdata_mahout_dataprep_test
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.host=localhost
-io.prediction.commons.appdata.training.db.port=27017
-io.prediction.commons.appdata.training.db.name=predictionio_trainig_appdata_mahout_dataprep_test
-
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.host=localhost
-io.prediction.commons.appdata.validation.db.port=27017
-io.prediction.commons.appdata.validation.db.name=predictionio_validation_appdata_mahout_dataprep_test
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.host=localhost
-io.prediction.commons.modeldata.db.port=27017
-io.prediction.commons.modeldata.db.name=predictionio_modeldata_mahout_dataprep_test
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.host=localhost
-io.prediction.commons.modeldata.training.db.port=27017
-io.prediction.commons.modeldata.training.db.name=predictionio_training_modeldata_mahout_dataprep_test
-
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.host=localhost
-io.prediction.commons.settings.db.port=27017
-io.prediction.commons.settings.db.name=predictionio_mahout_dataprep_test
diff --git a/process/engines/itemsim/algorithms/scala/mahout/src/test/resources/logback.xml b/process/engines/itemsim/algorithms/scala/mahout/src/test/resources/logback.xml
deleted file mode 100644
index 1a2768e..0000000
--- a/process/engines/itemsim/algorithms/scala/mahout/src/test/resources/logback.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<configuration>
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <encoder>
-      <pattern>%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>
-    </encoder>
-  </appender>
-  <root level="info">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
-
diff --git a/process/engines/itemsim/algorithms/scala/mahout/src/test/scala/io/prediction/algorithms/mahout/itemsim/MahoutModelConstructorSpec.scala b/process/engines/itemsim/algorithms/scala/mahout/src/test/scala/io/prediction/algorithms/mahout/itemsim/MahoutModelConstructorSpec.scala
deleted file mode 100644
index d48b50c..0000000
--- a/process/engines/itemsim/algorithms/scala/mahout/src/test/scala/io/prediction/algorithms/mahout/itemsim/MahoutModelConstructorSpec.scala
+++ /dev/null
@@ -1,353 +0,0 @@
-package io.prediction.algorithms.mahout.itemsim
-
-import io.prediction.commons.Config
-import io.prediction.commons.settings.{ App, Algo }
-import io.prediction.commons.modeldata.{ ItemSimScore }
-
-import org.specs2.mutable._
-import com.github.nscala_time.time.Imports._
-import scala.io.Source
-import java.io.File
-import java.io.FileWriter
-import java.io.BufferedWriter
-
-import com.mongodb.casbah.Imports._
-
-class MahoutItemSimModelConstructorSpec extends Specification {
-
-  // note: should match the db name defined in the application.conf
-  val mongoDbName = "predictionio_modeldata_mahout_dataprep_test"
-  def cleanUp() = {
-    // remove the test database
-    MongoConnection()(mongoDbName).dropDatabase()
-  }
-
-  val commonConfig = new Config
-  val modeldataItemSimScores = commonConfig.getModeldataItemSimScores
-
-  def argMapToArray(args: Map[String, Any]): Array[String] = {
-    args.toArray.flatMap {
-      case (k, v) =>
-        Array(s"--${k}", v.toString)
-    }
-  }
-
-  def writeToFile(lines: List[String], filePath: String) = {
-    val writer = new BufferedWriter(new FileWriter(new File(filePath)))
-    lines.foreach { line =>
-      writer.write(s"${line}\n")
-    }
-    writer.close()
-  }
-
-  "MahoutItemSimModelConstructor" should {
-    val inputDir = "/tmp/pio_test/"
-
-    val inputDirFile = new File(inputDir)
-    inputDirFile.mkdirs()
-
-    val itemsIndex = List(
-      "1\ti1\tt1,t2",
-      "2\ti2\tt1",
-      "3\ti3\tt2,t3",
-      "4\ti4\tt3"
-    )
-
-    val validItemIndex = List(
-      "1",
-      "2",
-      "3",
-      "4"
-    )
-
-    val similarities = List(
-      "1\t[2:3.2,3:12.5,4:20]",
-      "2\t[1:3.2,3:9.0]",
-      "3\t[1:12.5,2:9.0,4:12.0]",
-      "4\t[3:12.0,1:20]"
-    )
-
-    writeToFile(itemsIndex, s"${inputDir}itemsIndex.tsv")
-    writeToFile(validItemIndex, s"${inputDir}validItemsIndex.tsv")
-    writeToFile(similarities, s"${inputDir}similarities.tsv")
-
-    val appid = 12
-
-    implicit val app = App(
-      id = appid,
-      userid = 0,
-      appkey = "1234",
-      display = "12345",
-      url = None,
-      cat = None,
-      desc = None,
-      timezone = "UTC"
-    )
-
-    "correctly writes ItemSimScores with larger numSimilarItems" in {
-
-      val algoid = 45
-      val modelSet = false
-
-      implicit val algo = Algo(
-        id = algoid,
-        engineid = 1234,
-        name = "",
-        infoid = "abc",
-        command = "",
-        params = Map(),
-        settings = Map(),
-        modelset = modelSet,
-        createtime = DateTime.now,
-        updatetime = DateTime.now,
-        status = "deployed",
-        offlineevalid = None,
-        offlinetuneid = None,
-        loop = None,
-        paramset = None
-      )
-
-      val args = Map(
-        "inputDir" -> inputDir,
-        "appid" -> appid,
-        "algoid" -> algoid,
-        "modelSet" -> modelSet,
-        "numSimilarItems" -> 10
-      )
-
-      val i1Expected = ItemSimScore(
-        iid = "i1",
-        simiids = Seq("i4", "i3", "i2"),
-        scores = Seq(20.0, 12.5, 3.2),
-        itypes = Seq(Seq("t3"), Seq("t2", "t3"), Seq("t1")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val i2Expected = ItemSimScore(
-        iid = "i2",
-        simiids = Seq("i3", "i1"),
-        scores = Seq(9.0, 3.2),
-        itypes = Seq(Seq("t2", "t3"), Seq("t1", "t2")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val i3Expected = ItemSimScore(
-        iid = "i3",
-        simiids = Seq("i1", "i4", "i2"),
-        scores = Seq(12.5, 12.0, 9.0),
-        itypes = Seq(Seq("t1", "t2"), Seq("t3"), Seq("t1")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val i4Expected = ItemSimScore(
-        iid = "i4",
-        simiids = Seq("i1", "i3"),
-        scores = Seq(20.0, 12.0),
-        itypes = Seq(Seq("t1", "t2"), Seq("t2", "t3")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      MahoutModelConstructor.main(argMapToArray(args))
-
-      val i1ItemSim = modeldataItemSimScores.getByIid("i1")
-      val i2ItemSim = modeldataItemSimScores.getByIid("i2")
-      val i3ItemSim = modeldataItemSimScores.getByIid("i3")
-      val i4ItemSim = modeldataItemSimScores.getByIid("i4")
-
-      // don't check id
-      i1ItemSim.map(_.copy(id = None)) must beSome(i1Expected) and
-        (i2ItemSim.map(_.copy(id = None)) must beSome(i2Expected)) and
-        (i3ItemSim.map(_.copy(id = None)) must beSome(i3Expected)) and
-        (i4ItemSim.map(_.copy(id = None)) must beSome(i4Expected))
-
-    }
-
-    "correctly writes ItemSimScores with smaller numSimilarItems" in {
-
-      val algoid = 45
-      val modelSet = true
-
-      implicit val algo = Algo(
-        id = algoid,
-        engineid = 1234,
-        name = "",
-        infoid = "abc",
-        command = "",
-        params = Map(),
-        settings = Map(),
-        modelset = modelSet,
-        createtime = DateTime.now,
-        updatetime = DateTime.now,
-        status = "deployed",
-        offlineevalid = None,
-        offlinetuneid = None,
-        loop = None,
-        paramset = None
-      )
-
-      val args = Map(
-        "inputDir" -> inputDir,
-        "appid" -> appid,
-        "algoid" -> algoid,
-        "modelSet" -> modelSet,
-        "numSimilarItems" -> 1
-      )
-
-      val i1Expected = ItemSimScore(
-        iid = "i1",
-        simiids = Seq("i4"),
-        scores = Seq(20.0),
-        itypes = Seq(Seq("t3")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val i2Expected = ItemSimScore(
-        iid = "i2",
-        simiids = Seq("i3"),
-        scores = Seq(9.0),
-        itypes = Seq(Seq("t2", "t3")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val i3Expected = ItemSimScore(
-        iid = "i3",
-        simiids = Seq("i1"),
-        scores = Seq(12.5),
-        itypes = Seq(Seq("t1", "t2")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val i4Expected = ItemSimScore(
-        iid = "i4",
-        simiids = Seq("i1"),
-        scores = Seq(20.0),
-        itypes = Seq(Seq("t1", "t2")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      MahoutModelConstructor.main(argMapToArray(args))
-
-      val i1ItemSim = modeldataItemSimScores.getByIid("i1")
-      val i2ItemSim = modeldataItemSimScores.getByIid("i2")
-      val i3ItemSim = modeldataItemSimScores.getByIid("i3")
-      val i4ItemSim = modeldataItemSimScores.getByIid("i4")
-
-      // don't check id
-      i1ItemSim.map(_.copy(id = None)) must beSome(i1Expected) and
-        (i2ItemSim.map(_.copy(id = None)) must beSome(i2Expected)) and
-        (i3ItemSim.map(_.copy(id = None)) must beSome(i3Expected)) and
-        (i4ItemSim.map(_.copy(id = None)) must beSome(i4Expected))
-
-    }
-    /* don't test, valid item filtering is not done in mahout itemsim modelcon
-    "correctly writes ItemSimScores with subset numSimilarItems" in {
-
-      val algoid = 46
-      val modelSet = false
-
-      val inputDir = "/tmp/pio_test/subset/"
-
-      val inputDirFile = new File(inputDir)
-      inputDirFile.mkdirs()
-
-      val validItemIndex = List(
-        "1",
-        "4"
-      )
-
-      writeToFile(itemsIndex, s"${inputDir}itemsIndex.tsv")
-      writeToFile(validItemIndex, s"${inputDir}validItemsIndex.tsv")
-      writeToFile(similarities, s"${inputDir}similarities.tsv")
-
-      implicit val algo = Algo(
-        id = algoid,
-        engineid = 1234,
-        name = "",
-        infoid = "abc",
-        command = "",
-        params = Map(),
-        settings = Map(),
-        modelset = modelSet,
-        createtime = DateTime.now,
-        updatetime = DateTime.now,
-        status = "deployed",
-        offlineevalid = None,
-        offlinetuneid = None,
-        loop = None,
-        paramset = None
-      )
-
-      val args = Map(
-        "inputDir" -> inputDir,
-        "appid" -> appid,
-        "algoid" -> algoid,
-        "modelSet" -> modelSet,
-        "numSimilarItems" -> 10
-      )
-
-      val i1Expected = ItemSimScore(
-        iid = "i1",
-        simiids = Seq("i4"),
-        scores = Seq(20.0),
-        itypes = Seq(Seq("t3")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val i2Expected = ItemSimScore(
-        iid = "i2",
-        simiids = Seq("i1"),
-        scores = Seq(3.2),
-        itypes = Seq(Seq("t1", "t2")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val i3Expected = ItemSimScore(
-        iid = "i3",
-        simiids = Seq("i1", "i4"),
-        scores = Seq(12.5, 12.0),
-        itypes = Seq(Seq("t1", "t2"), Seq("t3")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      val i4Expected = ItemSimScore(
-        iid = "i4",
-        simiids = Seq("i1"),
-        scores = Seq(20.0),
-        itypes = Seq(Seq("t1", "t2")),
-        appid = appid,
-        algoid = algoid,
-        modelset = modelSet)
-
-      MahoutModelConstructor.main(argMapToArray(args))
-
-      val i1ItemSim = modeldataItemSimScores.getByIid("i1")
-      val i2ItemSim = modeldataItemSimScores.getByIid("i2")
-      val i3ItemSim = modeldataItemSimScores.getByIid("i3")
-      val i4ItemSim = modeldataItemSimScores.getByIid("i4")
-
-      // don't check id
-      i1ItemSim.map(_.copy(id = None)) must beSome(i1Expected) and
-        (i2ItemSim.map(_.copy(id = None)) must beSome(i2Expected)) and
-        (i3ItemSim.map(_.copy(id = None)) must beSome(i3Expected)) and
-        (i4ItemSim.map(_.copy(id = None)) must beSome(i4Expected))
-
-    }*/
-
-    // TODO: evalid
-
-  }
-
-  // clean up when finish test
-  step(cleanUp())
-}
\ No newline at end of file
diff --git a/process/engines/itemsim/evaluations/hadoop/scalding/build.sbt b/process/engines/itemsim/evaluations/hadoop/scalding/build.sbt
deleted file mode 100644
index 180a570..0000000
--- a/process/engines/itemsim/evaluations/hadoop/scalding/build.sbt
+++ /dev/null
@@ -1,38 +0,0 @@
-import AssemblyKeys._
-
-name := "predictionio-process-itemsim-evaluations-hadoop-scalding"
-
-packageOptions += Package.ManifestAttributes(java.util.jar.Attributes.Name.MAIN_CLASS -> "com.twitter.scalding.Tool")
-
-parallelExecution in Test := false
-
-resolvers ++= Seq("Concurrent Maven Repo" at "http://conjars.org/repo")
-
-assemblySettings
-
-test in assembly := {}
-
-assembleArtifact in packageScala := true
-
-excludedJars in assembly <<= (fullClasspath in assembly) map { cp =>
-  val excludes = Set(
-    "jsp-api-2.1-6.1.14.jar",
-    "jsp-2.1-6.1.14.jar",
-    "jasper-compiler-5.5.12.jar",
-    "janino-2.5.16.jar",
-    "minlog-1.2.jar",
-    "hadoop-core-1.0.4.jar")
-  cp filter { jar => excludes(jar.data.getName)}
-}
-
-// Some of these files have duplicates, let's ignore:
-mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) =>
-  {
-    case s if s.endsWith(".class") => MergeStrategy.last
-    case s if s.endsWith("project.clj") => MergeStrategy.concat
-    case s if s.endsWith(".html") => MergeStrategy.last
-    case s if s.endsWith(".properties") => MergeStrategy.last
-    case s if s.endsWith(".xml") => MergeStrategy.last
-    case x => old(x)
-  }
-}
diff --git a/process/engines/itemsim/evaluations/hadoop/scalding/metrics/ismap/src/main/scala/io/prediction/metrics/scalding/itemsim/ismap/ISMAPAtK.scala b/process/engines/itemsim/evaluations/hadoop/scalding/metrics/ismap/src/main/scala/io/prediction/metrics/scalding/itemsim/ismap/ISMAPAtK.scala
deleted file mode 100644
index 0963bac..0000000
--- a/process/engines/itemsim/evaluations/hadoop/scalding/metrics/ismap/src/main/scala/io/prediction/metrics/scalding/itemsim/ismap/ISMAPAtK.scala
+++ /dev/null
@@ -1,128 +0,0 @@
-package io.prediction.metrics.scalding.itemsim.ismap
-
-import com.twitter.scalding._
-
-import cascading.pipe.joiner.LeftJoin
-import cascading.pipe.joiner.RightJoin
-
-import io.prediction.commons.filepath.OfflineMetricFile
-import io.prediction.commons.scalding.settings.OfflineEvalResults
-
-/**
- * Source:
- *   relevantUsers.tsv
- *     iid     uid
- *     i0      u0
- *     i0      u1
- *     i0      u2
- *   relevantItems.tsv
- *     uid     iid
- *     u0      i0
- *     u0      i1
- *     u0      i2
- *   topKItems.tsv
- *     iid     simiid  score
- *     i0      i1      3.2
- *     i0      i4      2.5
- *     i0      i5      1.4
- *
- * Sink:
- *   offlineEvalResults DB
- *   averagePrecision.tsv
- *     iid     ap
- *     i0      0.03
- *
- *
- * Description:
- *   Calculate Item Similarity Mean Average Precision @ k score
- *   There is an assumption that the number of missing similar items per item is always equal to k.
- *
- * Required args:
- * --dbType: <string> The OfflineEvalResults DB Type (eg. mongodb) (see --dbHost, --dbPort)
- * --dbName: <string>
- *
- * --hdfsRoot: <string>. Root directory of the HDFS
- *
- * --appid: <int>
- * --engineid: <int>
- * --evalid: <int>
- * --metricid: <int>
- * --algoid: <int>
- * --iteration: <int>
- * --splitset: <string>
- *
- * --kParam: <int>
- *
- * Optional args:
- * --dbHost: <string> (eg. "127.0.0.1")
- * --dbPort: <int> (eg. 27017)
- *
- * --debug: <String>. "test" - for testing purpose
- *
- * Example:
- * scald.rb --hdfs-local io.prediction.metrics.scalding.itemsim.ismap.ISMAPAtK --dbType mongodb --dbName predictionio --dbHost 127.0.0.1 --dbPort 27017 --hdfsRoot hdfs/predictionio/ --appid 34 --engineid 3 --evalid 15 --metricid 10 --algoid 9 --kParam 30
- */
-class ISMAPAtK(args: Args) extends Job(args) {
-  /** parse args */
-  val dbTypeArg = args("dbType")
-  val dbNameArg = args("dbName")
-  val dbHostArg = args.list("dbHost")
-  val dbPortArg = args.list("dbPort") map (x => x.toInt)
-
-  val hdfsRootArg = args("hdfsRoot")
-
-  val appidArg = args("appid").toInt
-  val engineidArg = args("engineid").toInt
-  val evalidArg = args("evalid").toInt
-  val metricidArg = args("metricid").toInt
-  val algoidArg = args("algoid").toInt
-  val iterationArg = args.getOrElse("iteration", "1").toInt
-  val splitsetArg = args.getOrElse("splitset", "")
-
-  val kParamArg = args("kParam").toInt
-
-  val debugArg = args.list("debug")
-  val DEBUG_TEST = debugArg.contains("test") // test mode
-
-  /** sources */
-  val relevantUsers = TypedTsv[(String, String)](OfflineMetricFile(hdfsRootArg, appidArg, engineidArg, evalidArg, metricidArg, algoidArg, "relevantUsers.tsv"), ('ruiid, 'ruuid))
-  val relevantItems = TypedTsv[(String, String)](OfflineMetricFile(hdfsRootArg, appidArg, engineidArg, evalidArg, metricidArg, algoidArg, "relevantItems.tsv"), ('riuid, 'riiid))
-  val relevantItemsAsList = relevantItems.groupBy('riuid) { _.toList[String]('riiid -> 'riiids) }
-  val topKItems = TypedTsv[(String, String, Double)](OfflineMetricFile(hdfsRootArg, appidArg, engineidArg, evalidArg, metricidArg, algoidArg, "topKItems.tsv"), ('iid, 'simiid, 'score))
-
-  /** sinks */
-  val averagePrecisionSink = Tsv(OfflineMetricFile(hdfsRootArg, appidArg, engineidArg, evalidArg, metricidArg, algoidArg, "averagePrecision.tsv"))
-  val offlineEvalResultsSink = OfflineEvalResults(dbType = dbTypeArg, dbName = dbNameArg, dbHost = dbHostArg, dbPort = dbPortArg)
-
-  /** computation */
-  val itemsMapAtK = topKItems
-    .joinWithSmaller('iid -> 'ruiid, relevantUsers)
-    .joinWithSmaller('ruuid -> 'riuid, relevantItemsAsList, joiner = new LeftJoin)
-    .groupBy('iid, 'ruuid) {
-      _.sortBy('score).reverse.scanLeft(('simiid, 'riiids) -> ('precision, 'hit, 'count))((0.0, 0, 0)) {
-        (newFields: (Double, Int, Int), fields: (String, List[String])) =>
-          val (simiid, riiids) = fields
-          val (precision, hit, count) = newFields
-          Option(riiids) map { r =>
-            if (r.contains(simiid)) {
-              ((hit + 1).toDouble / (count + 1).toDouble, hit + 1, count + 1)
-            } else {
-              (0.0, hit, count + 1)
-            }
-          } getOrElse {
-            (0.0, hit, count + 1)
-          }
-      }
-    }
-    .filter('count) { count: Int => count > 0 }
-    .groupBy('iid, 'ruuid) { _.average('precision) }
-    .groupBy('iid) { _.average('precision) }
-
-  itemsMapAtK.write(averagePrecisionSink)
-
-  itemsMapAtK.groupAll { _.average('precision) }
-    .mapTo('precision -> ('evalid, 'metricid, 'algoid, 'score, 'iteration, 'splitset)) { precision: Double =>
-      (evalidArg, metricidArg, algoidArg, precision, iterationArg, splitsetArg)
-    }
-    .then(offlineEvalResultsSink.writeData('evalid, 'metricid, 'algoid, 'score, 'iteration, 'splitset) _)
-}
diff --git a/process/engines/itemsim/evaluations/hadoop/scalding/metrics/ismap/src/main/scala/io/prediction/metrics/scalding/itemsim/ismap/ISMAPAtKDataPreparator.scala b/process/engines/itemsim/evaluations/hadoop/scalding/metrics/ismap/src/main/scala/io/prediction/metrics/scalding/itemsim/ismap/ISMAPAtKDataPreparator.scala
deleted file mode 100644
index 1d41f40..0000000
--- a/process/engines/itemsim/evaluations/hadoop/scalding/metrics/ismap/src/main/scala/io/prediction/metrics/scalding/itemsim/ismap/ISMAPAtKDataPreparator.scala
+++ /dev/null
@@ -1,163 +0,0 @@
-package io.prediction.metrics.scalding.itemsim.ismap
-
-import com.twitter.scalding._
-
-import io.prediction.commons.filepath.OfflineMetricFile
-import io.prediction.commons.scalding.appdata.U2iActions
-
-/**
- * Source:
- *   Test set u2iActions.
- *
- * Sink:
- *   relevantUsers.tsv
- *     iid     uid
- *     i0      u0
- *     i0      u1
- *     i0      u2
- *   relevantItems.tsv
- *     uid     iid
- *     u0      i0
- *     u0      i1
- *     u0      i2
- *
- * Description:
- *   Generate relevantUsers and relevantItems for ISMAP@k
- *
- * Required args:
- * --test_dbType: <string> test_appdata DB type (eg. mongodb)
- * --test_dbName: <string>
- *
- * --training_dbType: <string> training_appdata DB type
- * --training_dbName: <string>
- *
- * --modeldata_dbType: <string> modeldata DB type
- * --modeldata_dbName: <string>
- *
- * --hdfsRoot: <string>. Root directory of the HDFS
- *
- * --appid: <int>
- * --engineid: <int>
- * --evalid: <int>
- * --metricid: <int>
- * --algoid: <int>
- *
- * --kParam: <int>
- * --goalParam: <string> ("view", "conversion", "like", "rate3", "rate4", "rate5)
- *
- * Optional args:
- * --test_dbHost: <string> (eg. "127.0.0.1")
- * --test_dbPort: <int> (eg. 27017)
- *
- * --training_dbHost: <string>
- * --training_dbPort: <int>
- *
- * --modeldata_dbHost: <string>
- * --modeldata_dbPort <int>
- *
- * --debug: <String>. "test" - for testing purpose
- *
- * Example:
- * scald.rb --hdfs-local io.prediction.metrics.scalding.itemsim.map.ISMAPAtKDataPreparator --test_dbType mongodb --test_dbName test_appdata --test_dbHost 127.0.0.1 --test_dbPort 27017 --training_dbType mongodb --training_dbName training_appdata --training_dbHost 127.0.0.1 --training_dbPort 27017 --modeldata_dbType file --modeldata_dbName modeldata_path/ --hdfsRoot hdfs/predictionio/ --appid 34 --engineid 3 --evalid 15 --metricid 10 --algoid 9 --kParam 30 --goalParam rate3
- *
- */
-class ISMAPAtKDataPreparator(args: Args) extends Job(args) {
-  val test_dbTypeArg = args("test_dbType")
-  val test_dbNameArg = args("test_dbName")
-  val test_dbHostArg = args.list("test_dbHost")
-  val test_dbPortArg = args.list("test_dbPort") map (x => x.toInt)
-
-  val training_dbTypeArg = args("training_dbType")
-  val training_dbNameArg = args("training_dbName")
-  val training_dbHostArg = args.list("training_dbHost")
-  val training_dbPortArg = args.list("training_dbPort") map (x => x.toInt)
-
-  val modeldata_dbTypeArg = args("modeldata_dbType")
-  val modeldata_dbNameArg = args("modeldata_dbName")
-  val modeldata_dbHostArg = args.list("modeldata_dbHost")
-  val modeldata_dbPortArg = args.list("modeldata_dbPort") map (x => x.toInt)
-
-  val hdfsRootArg = args("hdfsRoot")
-
-  val appidArg = args("appid").toInt
-  val engineidArg = args("engineid").toInt
-  val evalidArg = args("evalid").toInt
-  val metricidArg = args("metricid").toInt
-  val algoidArg = args("algoid").toInt
-
-  val GOAL_VIEW: String = "view"
-  val GOAL_CONVERSION: String = "conversion"
-  val GOAL_LIKE: String = "like"
-  val GOAL_RATE3: String = "rate3"
-  val GOAL_RATE4: String = "rate4"
-  val GOAL_RATE5: String = "rate5"
-  val GOAL_ARG_LIST: List[String] = List(GOAL_VIEW, GOAL_CONVERSION, GOAL_LIKE, GOAL_RATE3, GOAL_RATE4, GOAL_RATE5)
-
-  val goalParamArg = args("goalParam")
-
-  require(GOAL_ARG_LIST.contains(goalParamArg), "goalParam " + goalParamArg + " is not valid.")
-
-  val kParamArg = args("kParam").toInt
-
-  /** constants */
-  final val ACTION_RATE = "rate"
-  final val ACTION_LIKE = "like"
-  final val ACTION_DISLIKE = "dislike"
-  final val ACTION_VIEW = "view"
-  final val ACTION_CONVERSION = "conversion"
-
-  /** source */
-  val testU2i = U2iActions(appId = evalidArg,
-    dbType = test_dbTypeArg, dbName = test_dbNameArg, dbHost = test_dbHostArg, dbPort = test_dbPortArg).readData('actionTest, 'uidTest, 'iidTest, 'tTest, 'vTest)
-
-  /**
-   * computation
-   *
-   * for each user, get a list of items which match the goalParam
-   * TODO: filter out items appeared in trainingU2i?
-   */
-  testU2i
-    .filter('actionTest, 'vTest) { fields: (String, Option[String]) =>
-      val (action, v) = fields
-
-      goalParamArg match {
-        case GOAL_VIEW => (action == ACTION_VIEW)
-        case GOAL_CONVERSION => (action == ACTION_CONVERSION)
-        case GOAL_LIKE => (action == ACTION_LIKE)
-        case GOAL_RATE3 => try {
-          (action == ACTION_RATE) && (v.get.toInt >= 3)
-        } catch {
-          case e: Exception => {
-            assert(false, s"Failed to convert v field ${v} to int. Exception:" + e)
-            false
-          }
-        }
-        case GOAL_RATE4 => try {
-          (action == ACTION_RATE) && (v.get.toInt >= 4)
-        } catch {
-          case e: Exception => {
-            assert(false, s"Failed to convert v field ${v} to int. Exception:" + e)
-            false
-          }
-        }
-        case GOAL_RATE5 => try {
-          (action == ACTION_RATE) && (v.get.toInt >= 5)
-        } catch {
-          case e: Exception => {
-            assert(false, s"Failed to convert v field ${v} to int. Exception:" + e)
-            false
-          }
-        }
-        case _ => {
-          assert(false, "Invalid goalParam " + goalParamArg + ".")
-          false
-        }
-      }
-    }
-    .project('uidTest, 'iidTest)
-    .write(Tsv(OfflineMetricFile(hdfsRootArg, appidArg, engineidArg, evalidArg, metricidArg, algoidArg, "relevantItems.tsv")))
-
-  testU2i
-    .project('iidTest, 'uidTest)
-    .write(Tsv(OfflineMetricFile(hdfsRootArg, appidArg, engineidArg, evalidArg, metricidArg, algoidArg, "relevantUsers.tsv")))
-}
diff --git a/process/engines/itemsim/evaluations/hadoop/scalding/metrics/ismap/src/test/scala/io/prediction/metrics/scalding/itemsim/ismap/ISMAPAtKDataPreparatorTest.scala b/process/engines/itemsim/evaluations/hadoop/scalding/metrics/ismap/src/test/scala/io/prediction/metrics/scalding/itemsim/ismap/ISMAPAtKDataPreparatorTest.scala
deleted file mode 100644
index 8244676..0000000
--- a/process/engines/itemsim/evaluations/hadoop/scalding/metrics/ismap/src/test/scala/io/prediction/metrics/scalding/itemsim/ismap/ISMAPAtKDataPreparatorTest.scala
+++ /dev/null
@@ -1,156 +0,0 @@
-package io.prediction.metrics.scalding.itemsim.ismap
-
-import org.specs2.mutable._
-
-import com.twitter.scalding._
-
-import io.prediction.commons.filepath.OfflineMetricFile
-import io.prediction.commons.scalding.appdata.U2iActions
-import io.prediction.commons.scalding.modeldata.ItemRecScores
-
-class ISMAPAtKDataPreparatorTest extends Specification with TupleConversions {
-  val Rate = "rate"
-  val Like = "like"
-  val Dislike = "dislike"
-  val View = "view"
-  val Conversion = "conversion"
-
-  def test(
-    params: Map[String, String],
-    testU2i: List[(String, String, String, String, String)],
-    relevantUsers: List[(String, String)],
-    relevantItems: List[(String, String)]) = {
-
-    val test_dbType = "file"
-    val test_dbName = "testsetpath/"
-    val test_dbHost = Seq()
-    val test_dbPort = Seq()
-
-    val training_dbType = "file"
-    val training_dbName = "trainingsetpath/"
-    val training_dbHost = Seq()
-    val training_dbPort = Seq()
-
-    val modeldata_dbType = "file"
-    val modeldata_dbName = "modeldatapath/"
-    val modeldata_dbHost = Seq()
-    val modeldata_dbPort = Seq()
-
-    val hdfsRoot = "testroot/"
-
-    def splitAndSortList(t: List[(String, String)]): List[(String, List[String])] = {
-      t map { x => (x._1, x._2.split(",").toList.sorted) }
-    }
-
-    JobTest("io.prediction.metrics.scalding.itemsim.ismap.ISMAPAtKDataPreparator")
-      .arg("test_dbType", test_dbType)
-      .arg("test_dbName", test_dbName)
-      .arg("training_dbType", training_dbType)
-      .arg("training_dbName", training_dbName)
-      .arg("modeldata_dbType", modeldata_dbType)
-      .arg("modeldata_dbName", modeldata_dbName)
-      .arg("hdfsRoot", hdfsRoot)
-      .arg("appid", "2")
-      .arg("engineid", "4")
-      .arg("evalid", "5")
-      .arg("metricid", "6")
-      .arg("algoid", "8")
-      .arg("goalParam", params("goalParam"))
-      .arg("kParam", params("kParam"))
-      .source(U2iActions(appId = 5, dbType = test_dbType, dbName = test_dbName, dbHost = test_dbHost, dbPort = test_dbPort).getSource, testU2i)
-      .sink[(String, String)](Tsv(OfflineMetricFile(hdfsRoot, 2, 4, 5, 6, 8, "relevantItems.tsv"))) { outputBuffer =>
-        "correctly generates relevantItems for each user" in {
-          val output = splitAndSortList(outputBuffer.toList)
-          val expected = splitAndSortList(relevantItems)
-          outputBuffer.toList must containTheSameElementsAs(relevantItems)
-        }
-      }
-      .sink[(String, String)](Tsv(OfflineMetricFile(hdfsRoot, 2, 4, 5, 6, 8, "relevantUsers.tsv"))) { outputBuffer =>
-        "correctly generates relevantUsers for each item" in {
-          val output = splitAndSortList(outputBuffer.toList)
-          val expected = splitAndSortList(relevantUsers)
-          outputBuffer.toList must containTheSameElementsAs(relevantUsers)
-        }
-      }
-      .run
-      .finish
-  }
-
-  val testU2i = List(
-    // u0
-    (Rate, "u0", "i0", "123450", "4"),
-    (View, "u0", "i1", "123457", "PIO_NONE"),
-    (Dislike, "u0", "i2", "123458", "PIO_NONE"),
-    (View, "u0", "i3", "123459", "PIO_NONE"),
-    (View, "u0", "i7", "123460", "PIO_NONE"),
-
-    // u1
-    (View, "u1", "i0", "123457", "PIO_NONE"),
-    (Conversion, "u1", "i1", "123458", "PIO_NONE"),
-    (Conversion, "u1", "i4", "123457", "PIO_NONE"),
-    (Conversion, "u1", "i5", "123456", "PIO_NONE"),
-    (Rate, "u1", "i7", "123456", "3"),
-    (Rate, "u1", "i8", "123454", "3"),
-    (Rate, "u1", "i9", "123453", "4"),
-
-    // u2
-    (View, "u2", "i3", "123458", "PIO_NONE"),
-    (Conversion, "u2", "i4", "123451", "PIO_NONE"),
-    (Conversion, "u2", "i5", "123452", "PIO_NONE"))
-
-  "itemsim.ismap ISMAPAtKDataPreparator with goal = view" should {
-    val params = Map("goalParam" -> "view", "kParam" -> "4")
-    val relevantUsers = List(
-      ("i0", "u0"),
-      ("i1", "u0"),
-      ("i2", "u0"),
-      ("i3", "u0"),
-      ("i7", "u0"),
-      ("i0", "u1"),
-      ("i1", "u1"),
-      ("i4", "u1"),
-      ("i5", "u1"),
-      ("i7", "u1"),
-      ("i8", "u1"),
-      ("i9", "u1"),
-      ("i3", "u2"),
-      ("i4", "u2"),
-      ("i5", "u2"))
-    val relevantItems = List(
-      ("u0", "i1"),
-      ("u0", "i3"),
-      ("u0", "i7"),
-      ("u1", "i0"),
-      ("u2", "i3"))
-
-    test(params, testU2i, relevantUsers, relevantItems)
-  }
-
-  "itemsim.ismap ISMAPAtKDataPreparator with goal = conversion" should {
-    val params = Map("goalParam" -> "conversion", "kParam" -> "8")
-    val relevantUsers = List(
-      ("i0", "u0"),
-      ("i1", "u0"),
-      ("i2", "u0"),
-      ("i3", "u0"),
-      ("i7", "u0"),
-      ("i0", "u1"),
-      ("i1", "u1"),
-      ("i4", "u1"),
-      ("i5", "u1"),
-      ("i7", "u1"),
-      ("i8", "u1"),
-      ("i9", "u1"),
-      ("i3", "u2"),
-      ("i4", "u2"),
-      ("i5", "u2"))
-    val relevantItems = List(
-      ("u1", "i1"),
-      ("u1", "i4"),
-      ("u1", "i5"),
-      ("u2", "i4"),
-      ("u2", "i5"))
-
-    test(params, testU2i, relevantUsers, relevantItems)
-  }
-}
diff --git a/process/engines/itemsim/evaluations/hadoop/scalding/metrics/ismap/src/test/scala/io/prediction/metrics/scalding/itemsim/ismap/ISMAPAtKTest.scala b/process/engines/itemsim/evaluations/hadoop/scalding/metrics/ismap/src/test/scala/io/prediction/metrics/scalding/itemsim/ismap/ISMAPAtKTest.scala
deleted file mode 100644
index bf9b78e..0000000
--- a/process/engines/itemsim/evaluations/hadoop/scalding/metrics/ismap/src/test/scala/io/prediction/metrics/scalding/itemsim/ismap/ISMAPAtKTest.scala
+++ /dev/null
@@ -1,117 +0,0 @@
-package io.prediction.metrics.scalding.itemsim.ismap
-
-import org.specs2.mutable._
-
-import com.twitter.scalding._
-import com.twitter.scalding.Dsl._
-
-import io.prediction.commons.filepath.{ OfflineMetricFile }
-import io.prediction.commons.scalding.settings.OfflineEvalResults
-
-class ISMAPAtKTest extends Specification {
-  def test(
-    evalid: Int,
-    metricid: Int,
-    algoid: Int,
-    iteration: Int,
-    splitset: String,
-    params: Map[String, String],
-    relevantUsers: List[(String, String)],
-    relevantItems: List[(String, String)],
-    topKItems: List[(String, String, Double)],
-    averagePrecision: List[(String, Double)],
-    meanAveragePrecision: Double) = {
-    val dbType = "file"
-    val dbName = "testpath/"
-    val dbHost = Seq()
-    val dbPort = Seq()
-    val hdfsRoot = "testroot/"
-
-    val appid = 20
-    val engineid = 1
-
-    val offlineEvalResults = List((evalid, metricid, algoid, meanAveragePrecision, iteration, splitset))
-
-    val relevantUsersSource = TypedTsv[(String, String)](OfflineMetricFile(hdfsRoot, appid, engineid, evalid, metricid, algoid, "relevantUsers.tsv"), ('ruiid, 'ruuid))
-    val relevantItemsSource = TypedTsv[(String, String)](OfflineMetricFile(hdfsRoot, appid, engineid, evalid, metricid, algoid, "relevantItems.tsv"), ('riuid, 'riiid))
-    val topKItemsSource = TypedTsv[(String, String, Double)](OfflineMetricFile(hdfsRoot, appid, engineid, evalid, metricid, algoid, "topKItems.tsv"), ('iid, 'simiid, 'score))
-
-    JobTest("io.prediction.metrics.scalding.itemsim.ismap.ISMAPAtK")
-      .arg("dbType", dbType)
-      .arg("dbName", dbName)
-      .arg("hdfsRoot", hdfsRoot)
-      .arg("appid", appid.toString)
-      .arg("engineid", engineid.toString)
-      .arg("evalid", evalid.toString)
-      .arg("metricid", metricid.toString)
-      .arg("algoid", algoid.toString)
-      .arg("iteration", iteration.toString)
-      .arg("splitset", splitset)
-      .arg("kParam", params("kParam"))
-      .source(relevantUsersSource, relevantUsers)
-      .source(relevantItemsSource, relevantItems)
-      .source(topKItemsSource, topKItems)
-      .sink[(String, Double)](Tsv(OfflineMetricFile(hdfsRoot, appid, engineid, evalid, metricid, algoid, "averagePrecision.tsv"))) { outputBuffer =>
-        "correctly calculate Average Precision for each user" in {
-          // only compare double up to 6 decimal places
-          def roundingData(orgList: List[(String, Double)]) = {
-            orgList map { x =>
-              val (t1, t2) = x
-              // NOTE: use HALF_UP mode to avoid error caused by rounding when compare data
-              // (eg. 3.5 vs 3.499999999999, 0.6666666666 vs 0.666666667)
-              (t1, BigDecimal(t2).setScale(6, BigDecimal.RoundingMode.HALF_UP).toDouble)
-            }
-          }
-
-          roundingData(outputBuffer.toList) must containTheSameElementsAs(roundingData(averagePrecision))
-        }
-      }
-      .sink[(Int, Int, Int, Double, Int, String)](OfflineEvalResults(dbType = dbType, dbName = dbName, dbHost = dbHost, dbPort = dbPort).getSource) { outputBuffer =>
-        def roundingData(orgList: List[(Int, Int, Int, Double, Int, String)]) = {
-          orgList map { x =>
-            val (t1, t2, t3, t4, t5, t6) = x
-            // NOTE: use HALF_UP mode to avoid error caused by rounding when compare data
-            // (eg. 3.5 vs 3.499999999999, 0.6666666666 vs 0.666666667)
-            (t1, t2, t3, BigDecimal(t4).setScale(6, BigDecimal.RoundingMode.HALF_UP).toDouble, t5, t6)
-          }
-        }
-        "correctly write MAP@k score into a file" in {
-          roundingData(outputBuffer.toList) must containTheSameElementsAs(roundingData(offlineEvalResults))
-        }
-      }
-      .run
-      .finish
-  }
-
-  "itemsim.ismap" should {
-    val relevantUsers = List(
-      ("i0", "u1"),
-      ("i1", "u1"),
-      ("i3", "u0"),
-      ("i4", "u0"),
-      ("i5", "u0"))
-    val relevantItems = List(
-      ("u0", "i3"),
-      ("u0", "i4"),
-      ("u0", "i5"),
-      ("u1", "i0"),
-      ("u1", "i1"),
-      ("u1", "i5"),
-      ("u3", "i0"))
-    val topKItems = List(
-      ("i0", "i6", 5.0),
-      ("i0", "i4", 4.0),
-      ("i0", "i3", 3.0),
-      ("i0", "i5", 2.0),
-      ("i1", "i4", 3.0),
-      ("i1", "i5", 2.0),
-      ("i1", "i0", 1.0))
-    val averagePrecision = List(("i0", 0.0625), ("i1", 0.38888888888888884))
-    val meanAveragePrecision = 0.225694
-
-    val params = Map("kParam" -> "5")
-
-    test(12, 2, 54, 9, "validation",
-      params, relevantUsers, relevantItems, topKItems, averagePrecision, meanAveragePrecision)
-  }
-}
diff --git a/project/Common.scala b/project/Common.scala
deleted file mode 100644
index 9988eac..0000000
--- a/project/Common.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-import sbt._
-import Keys._
-
-object Common {
-  def packCommonJvmOpts = Seq("-Dconfig.file=${PROG_HOME}/conf/predictionio.conf", "-Dio.prediction.base=${PROG_HOME}")
-}
diff --git a/project/plugins.sbt b/project/plugins.sbt
deleted file mode 100644
index 1593a07..0000000
--- a/project/plugins.sbt
+++ /dev/null
@@ -1,5 +0,0 @@
-addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.10.1")
-
-addSbtPlugin("org.xerial.sbt" % "sbt-pack" % "0.5.1")
-
-addSbtPlugin("com.typesafe.sbt" % "sbt-scalariform" % "1.2.1")
diff --git a/servers/admin/.gitignore b/servers/admin/.gitignore
deleted file mode 100644
index bf37cc9..0000000
--- a/servers/admin/.gitignore
+++ /dev/null
@@ -1,28 +0,0 @@
-!vendors
-logs
-project/project
-project/target
-project/boot
-project/target
-project/plugins/target
-target
-.target
-tmp
-.history
-dist
-/.idea
-/*.iml
-/out
-/.idea_modules
-/.classpath
-/.project
-logs
-/RUNNING_PID
-
-# Eclipse
-.settings
-.cache
-.project
-.classpath
-.scala_dependencies
-bin
diff --git a/servers/admin/README b/servers/admin/README
deleted file mode 100644
index 6373f4a..0000000
--- a/servers/admin/README
+++ /dev/null
@@ -1,4 +0,0 @@
-This is your new Play 2.0 application
-=====================================
-
-This file will be packaged with your application, when using `play dist`.
diff --git a/servers/admin/README.md b/servers/admin/README.md
deleted file mode 100644
index fc1576c..0000000
--- a/servers/admin/README.md
+++ /dev/null
@@ -1,27 +0,0 @@
-How to change layout in Admin server
-====================================
-
-When you add / change / remove setings for engines / algorithms, you have to configure the UI in admin server so that can change the settings accordingly. The UI is configured by a json file `dist/conf/init.json`. This doc illustrates how to populate the change and have them show up in admin's UI.
-
-## Instructions
-Install [PredictionIO from source](http://docs.prediction.io/current/installation/install-predictionio-from-source.html)
-
-````
-# Start admin server in the distribution directory.
-cd dist/target/PredictionIO-<version>/
-bin/start-admin.sh
-
-# Edit init.json in the repository
-vim ../../conf/init.json
-
-# Copy it to the distribution directory. Unless you know what you are doing, don't edit conf/init.json directly in the distribution directory.
-cp ../../conf/init.json conf/init.json
-
-# Populate the change
-bin/setup.sh
-
-# After populating, you will see your change in Admin server.
-````
-
-## Troubleshooting
-`setup.sh` fails if the json file is malformed. You can use python's json package for error checking: `python -m json.tool ../../conf/init.json`.
diff --git a/servers/admin/app/controllers/Application.scala b/servers/admin/app/controllers/Application.scala
deleted file mode 100644
index 9dc65a9..0000000
--- a/servers/admin/app/controllers/Application.scala
+++ /dev/null
@@ -1,2609 +0,0 @@
-package controllers
-
-import io.prediction.commons.Config
-import io.prediction.commons.settings._
-import io.prediction.commons.modeldata.ItemRecScores
-import io.prediction.commons.appdata.{ Users, Items, U2IActions }
-import io.prediction.output.AlgoOutputSelector
-
-import Helper.{ algoToJson, offlineEvalMetricToJson }
-import Helper.{ dateTimeToString, algoParamToString, offlineEvalSplitterParamToString }
-import Helper.{ getSimEvalStatus, getOfflineTuneStatus, createOfflineEval }
-
-import play.api._
-import play.api.mvc._
-import play.api.data._
-import play.api.data.Forms._
-import play.api.data.format.Formats._
-import play.api.data.validation.{ Constraints }
-import play.api.i18n.{ Messages, Lang }
-import play.api.libs.concurrent.Execution.Implicits._
-import play.api.libs.json.Json.toJson
-import play.api.libs.json.{ JsNull, JsArray, Json, JsValue, Writes, JsObject }
-import play.api.libs.ws.WS
-import play.api.Play.current
-import play.api.http
-
-import scala.concurrent.{ Await, Future }
-import scala.concurrent.duration._
-import scala.util.Random
-
-import com.github.nscala_time.time.Imports._
-import org.apache.commons.codec.digest.DigestUtils
-
-import Forms._
-
-/*
- * TODO:
- * - decodeURIComponent any GET custom param
- */
-
-/*
- * Backend of ControlPanel.
- * Pure REST APIs in JSON.
- */
-object Application extends Controller {
-  /** PredictionIO Commons settings*/
-  val config = new Config()
-  val users = config.getSettingsUsers()
-  val apps = config.getSettingsApps()
-  val engines = config.getSettingsEngines()
-  val engineInfos = config.getSettingsEngineInfos()
-  val algos = config.getSettingsAlgos()
-  val algoInfos = config.getSettingsAlgoInfos()
-  val offlineEvalMetricInfos = config.getSettingsOfflineEvalMetricInfos()
-  val offlineEvalSplitterInfos = config.getSettingsOfflineEvalSplitterInfos()
-  val offlineEvals = config.getSettingsOfflineEvals()
-  val offlineEvalMetrics = config.getSettingsOfflineEvalMetrics()
-  val offlineEvalResults = config.getSettingsOfflineEvalResults()
-  val offlineEvalSplitters = config.getSettingsOfflineEvalSplitters()
-  val offlineTunes = config.getSettingsOfflineTunes()
-  val paramGens = config.getSettingsParamGens()
-
-  /** PredictionIO Commons modeldata */
-  val itemRecScores = config.getModeldataItemRecScores()
-  val itemSimScores = config.getModeldataItemSimScores()
-
-  /** PredictionIO Commons modeldata */
-  val trainingItemRecScores = config.getModeldataTrainingItemRecScores()
-  val trainingItemSimScores = config.getModeldataTrainingItemSimScores()
-
-  /** PredictionIO Commons appdata */
-  val appDataUsers = config.getAppdataUsers()
-  val appDataItems = config.getAppdataItems()
-  val appDataU2IActions = config.getAppdataU2IActions()
-
-  /** PredictionIO Commons training set appdata */
-  val trainingSetUsers = config.getAppdataTrainingUsers()
-  val trainingSetItems = config.getAppdataTrainingItems()
-  val trainingSetU2IActions = config.getAppdataTrainingU2IActions()
-
-  /** PredictionIO Commons validation set appdata */
-  val validationSetUsers = config.getAppdataValidationUsers()
-  val validationSetItems = config.getAppdataValidationItems()
-  val validationSetU2IActions = config.getAppdataValidationU2IActions()
-
-  /** PredictionIO Commons test set appdata */
-  val testSetUsers = config.getAppdataTestUsers()
-  val testSetItems = config.getAppdataTestItems()
-  val testSetU2IActions = config.getAppdataTestU2IActions()
-
-  /** Scheduler setting */
-  val settingsSchedulerUrl = config.settingsSchedulerUrl
-
-  /** PredictionIO Output */
-  val algoOutputSelector = new AlgoOutputSelector(algos)
-
-  /** misc */
-  val nameRegex = """\b[a-zA-Z][a-zA-Z0-9_-]*\b""".r
-
-  /** Play Framework security */
-  def username(request: RequestHeader) = request.session.get(Security.username)
-
-  def onUnauthorized(request: RequestHeader) = Forbidden(toJson(Map("message" -> toJson("Haven't signed in yet."))))
-
-  def withAuth(f: => String => Request[AnyContent] => Result) = {
-    Security.Authenticated(username, onUnauthorized) { user =>
-      Action(request => f(user)(request))
-    }
-  }
-
-  def withAuthAsync(f: => String => Request[AnyContent] => Future[SimpleResult]) = {
-    Security.Authenticated(username, onUnauthorized) { user =>
-      Action.async(request => f(user)(request))
-    }
-  }
-
-  object WithUser {
-    def apply(f: User => Request[AnyContent] => SimpleResult) = async { user =>
-      implicit request =>
-        Future.successful(f(user)(request))
-    }
-
-    def async(f: User => Request[AnyContent] => Future[SimpleResult]) = withAuthAsync { username =>
-      implicit request =>
-        users.getByEmail(username).map { user =>
-          f(user)(request)
-        }.getOrElse(Future.successful(onUnauthorized(request)))
-    }
-  }
-
-  object WithApp {
-    def apply(appid: Int)(f: (User, App) => Request[AnyContent] => SimpleResult) = async(appid) { (user, app) =>
-      implicit request =>
-        Future.successful(f(user, app)(request))
-    }
-
-    def async(appid: Int)(f: (User, App) => Request[AnyContent] => Future[SimpleResult]) = WithUser.async { user =>
-      implicit request =>
-        apps.getByIdAndUserid(appid, user.id).map { app =>
-          f(user, app)(request)
-        }.getOrElse(Future.successful(NotFound(Json.obj("message" -> s"Invalid appid ${appid}."))))
-    }
-  }
-
-  object WithEngine {
-    def apply(appid: Int, engineid: Int)(f: (User, App, Engine) => Request[AnyContent] => SimpleResult) = async(appid, engineid) {
-      (user, app, eng) =>
-        implicit request =>
-          Future.successful(f(user, app, eng)(request))
-    }
-
-    def async(appid: Int, engineid: Int)(f: (User, App, Engine) => Request[AnyContent] => Future[SimpleResult]) = WithApp.async(appid) {
-      (user, app) =>
-        implicit request =>
-          engines.getByIdAndAppid(engineid, appid).map { eng =>
-            f(user, app, eng)(request)
-          }.getOrElse(Future.successful(NotFound(Json.obj("message" -> s"Invalid engineid ${engineid}."))))
-    }
-  }
-
-  object WithAlgo {
-    def apply(appid: Int, engineid: Int, algoid: Int)(f: (User, App, Engine, Algo) => Request[AnyContent] => SimpleResult) = async(appid, engineid, algoid) {
-      (user, app, eng, algo) =>
-        implicit request =>
-          Future.successful(f(user, app, eng, algo)(request))
-    }
-
-    def async(appid: Int, engineid: Int, algoid: Int)(f: (User, App, Engine, Algo) => Request[AnyContent] => Future[SimpleResult]) = WithEngine.async(appid, engineid) {
-      (user, app, eng) =>
-        implicit request =>
-          algos.getByIdAndEngineid(algoid, engineid).map { algo =>
-            f(user, app, eng, algo)(request)
-          }.getOrElse(Future.successful(NotFound(Json.obj("message" -> s"Invalid algoid ${algoid}."))))
-    }
-  }
-
-  object WithOfflineEval {
-    def apply(appid: Int, engineid: Int, offlineevalid: Int)(f: (User, App, Engine, OfflineEval) => Request[AnyContent] => SimpleResult) = async(appid, engineid, offlineevalid) {
-      (user, app, eng, eval) =>
-        implicit request =>
-          Future.successful(f(user, app, eng, eval)(request))
-    }
-
-    def async(appid: Int, engineid: Int, offlineevalid: Int)(f: (User, App, Engine, OfflineEval) => Request[AnyContent] => Future[SimpleResult]) = WithEngine.async(appid, engineid) {
-      (user, app, eng) =>
-        implicit request =>
-          offlineEvals.getByIdAndEngineid(offlineevalid, engineid).map { eval =>
-            f(user, app, eng, eval)(request)
-          }.getOrElse(Future.successful(NotFound(Json.obj("message" -> s"Invalid offlineevalid ${offlineevalid}."))))
-    }
-  }
-
-  private def md5password(password: String) = DigestUtils.md5Hex(password)
-
-  /** Appkey Generation */
-  def randomAlphanumeric(n: Int): String = {
-    Random.alphanumeric.take(n).mkString
-  }
-
-  def showWeb() = Action {
-    Ok(views.html.Web.index())
-  }
-
-  /* Serve Engines/Algorithms Static Files (avoid PlayFramework's Assets cache problem during development)*/
-  def enginebase(path: String) = Action {
-    Ok.sendFile(new java.io.File(Play.application.path, "/enginebase/" + path))
-    //TODO: Fix Content-Disposition
-  }
-
-  def redirectToWeb = Action {
-    Redirect("web/")
-  }
-
-  /* case class to json conversion */
-  implicit val userWrites = new Writes[User] {
-    /* note: do not return password */
-    def writes(u: User): JsValue = {
-      Json.obj(
-        "id" -> u.id,
-        "username" -> (u.firstName + u.lastName.map(" " + _).getOrElse("")),
-        "email" -> u.email
-      )
-    }
-  }
-
-  /**
-   * Authenticates user
-   *
-   * {{{
-   * POST
-   * JSON parameters:
-   *   {
-   *     "email" : <string>,
-   *     "password" : <string>,
-   *     "remember" : <optional string "on">
-   *   }
-   * JSON response:
-   *   {
-   *     "id" : <string>,
-   *     "username" : <string>,
-   *     "email" : <string>
-   *   }
-   * }}}
-   *
-   */
-  def signin = Action { implicit request =>
-    val loginForm = Form(
-      tuple(
-        "email" -> text,
-        "password" -> text,
-        "remember" -> optional(text)
-      ) verifying ("Invalid email or password", result => result match {
-          case (email, password, remember) => users.authenticateByEmail(email, md5password(password)) map { _ => true } getOrElse false
-        })
-    )
-
-    loginForm.bindFromRequest.fold(
-      formWithErrors => Forbidden(toJson(Map("message" -> toJson("Incorrect Email or Password.")))),
-      form => {
-        users.getByEmail(form._1).map(user =>
-          Ok(Json.toJson(user)).withSession(Security.username -> user.email)
-        ).getOrElse(
-          InternalServerError(Json.obj("message" -> "Could not find your user account."))
-        )
-      }
-    )
-  }
-
-  /**
-   * Signs out
-   *
-   * {{{
-   * POST
-   * JSON parameters:
-   *   None
-   * JSON response:
-   *   None
-   * }}}
-   */
-  def signout = Action {
-    Ok.withNewSession
-  }
-
-  /**
-   * Returns authenticated user info
-   * (from session cookie)
-   *
-   * {{{
-   * GET
-   * JSON parameters:
-   *   None
-   * JSON response:
-   *   If authenticated
-   *   OK
-   *   {
-   *     "id" : <string>,
-   *     "username" : <string>,
-   *     "email": <string>
-   *   }
-   *
-   *   If not authenticated:
-   *   Forbidden
-   *   {
-   *     "message" : "Haven't signed in yet."
-   *   }
-   * }}}
-   */
-  def getAuth = WithUser { user =>
-    implicit request =>
-      Ok(Json.toJson(user))
-  }
-
-  /**
-   * Returns list of apps of the authenticated user
-   *
-   * {{{
-   * GET
-   * JSON parameters:
-   *   None
-   * JSON response:
-   *   If not authenticated:
-   *   Forbidden
-   *   {
-   *     "message" : "Haven't signed in yet."
-   *   }
-   *
-   *   If no app:
-   *   No Content
-   *
-   *   If apps are found:
-   *   OK
-   *   [ { "id" : <appid int>,  "appname" : <string> },
-   *     ...
-   *   ]
-   *
-   * }}}
-   */
-  def getApplist = WithUser { user =>
-    implicit request =>
-
-      val userApps = apps.getByUserid(user.id)
-      if (!userApps.hasNext) NoContent
-      else {
-        Ok(JsArray(userApps.map { app =>
-          Json.obj("id" -> app.id, "appname" -> app.display)
-        }.toSeq))
-      }
-  }
-
-  /**
-   * Returns the app details of this appid
-   *
-   * {{{
-   * GET
-   * JSON parameters:
-   *   None
-   * JSON response:
-   *   If not authenticated:
-   *   Forbidden
-   *   {
-   *     "message" : "Haven't signed in yet."
-   *   }
-   *
-   *   If app is not found:
-   *   NotFound
-   *   {
-   *     "message" : "Invalid appid."
-   *   }
-   *
-   *   If app is found:
-   *   Ok
-   *   {
-   *     "id" : <appid int>,
-   *     "updatedtime" : <string>,
-   *     "userscount": <num of users int>
-   *     "itemscount": <num of items int>
-   *     "u2icount": <num of u2i Actions int>
-   *     "apiurl": <url of API server, string>
-   *     "appkey": <string>
-   *   }
-   * }}}
-   *
-   * @param id the App ID
-   */
-  def getAppDetails(id: Int) = WithApp(id) { (user, app) =>
-    implicit request =>
-      val numUsers = appDataUsers.countByAppid(app.id)
-      val numItems = appDataItems.countByAppid(app.id)
-      val numU2IActions = appDataU2IActions.countByAppid(app.id)
-      Ok(Json.obj(
-        "id" -> app.id,
-        "updatedtime" -> dateTimeToString(DateTime.now),
-        "userscount" -> numUsers,
-        "itemscount" -> numItems,
-        "u2icount" -> numU2IActions,
-        "apiurl" -> "http://yourhost.com:123/appid12",
-        "appkey" -> app.appkey
-      ))
-  }
-
-  /**
-   * Returns an app
-   *
-   * {{{
-   * GET
-   * JSON parameters:
-   *   None
-   * JSON response:
-   *   If not authenticated:
-   *   Forbidden
-   *   {
-   *     "message" : "Haven't signed in yet."
-   *   }
-   *
-   *   If app is found:
-   *   Ok
-   *   {
-   *     "id" : <appid int>
-   *     "appname" : <string>
-   *   }
-   *
-   * }}}
-   *
-   * @param id the App ID
-   */
-  def getApp(id: Int) = WithApp(id) { (user, app) =>
-    implicit request =>
-      Ok(Json.obj(
-        "id" -> app.id,
-        "appname" -> app.display
-      ))
-  }
-
-  /**
-   * Create an app
-   *
-   * {{{
-   * POST
-   * JSON Parameters:
-   *   {
-   *     "appname" : <the new app name. string>
-   *   }
-   * JSON Response:
-   *   If not authenticated:
-   *   Forbidden
-   *   {
-   *     "message" : "Haven't signed in yet."
-   *   }
-   *
-   *   If creation failed:
-   *   BadRequest
-   *   {
-   *     "message" : "Invalid character for app name."
-   *    }
-   *
-   *   If app is created:
-   *   OK
-   *   {
-   *     "id" : <the appid of the created app. int>,
-   *     "appname" : <string>
-   *   }
-   * }}}
-   *
-   */
-  def createApp = WithUser { user =>
-    implicit request =>
-
-      val appForm = Form(single(
-        "appname" -> nonEmptyText
-      ))
-
-      appForm.bindFromRequest.fold(
-        formWithError => {
-          val msg = formWithError.errors(0).message // extract 1st error message only
-          BadRequest(toJson(Map("message" -> toJson(msg))))
-        },
-        formData => {
-          val an = formData
-          val appid = apps.insert(App(
-            id = 0,
-            userid = user.id,
-            appkey = randomAlphanumeric(64),
-            display = an,
-            url = None,
-            cat = None,
-            desc = None,
-            timezone = "UTC"
-          ))
-          Logger.info("Create app ID " + appid)
-
-          Ok(Json.obj(
-            "id" -> appid,
-            "appname" -> an
-          ))
-        }
-      )
-  }
-
-  /**
-   * Remove an app
-   *
-   * {{{
-   * DELETE
-   * JSON Parameters:
-   *   None
-   * JSON Response:
-   *   If not authenticated:
-   *   Forbidden
-   *   {
-   *     "message" : "Haven't signed in yet."
-   *   }
-   *
-   *   If not found:
-   *   NotFound
-   *   {
-   *     "message" : <error message>
-   *   }
-   *
-   *   If error:
-   *   InternalServerError
-   *   {
-   *     "message" : <error message>
-   *   }
-   *
-   *   If deleted successfully:
-   *   Ok
-   * }}}
-   *
-   * @param id the App ID
-   */
-  def removeApp(id: Int) = WithApp.async(id) { (user, app) =>
-    implicit request =>
-
-      // don't delete if there is any deployed aglo, sim eval or offline tune pending
-      val appEngines = engines.getByAppid(app.id).toList
-
-      val enginesDeployed = appEngines.filter(eng =>
-        !(algos.getDeployedByEngineid(eng.id).isEmpty)
-      )
-      val msgDeployed = "There are deployed algorithms in engines: " + enginesDeployed.map(_.name).mkString(", ") + ". Please undeploy them before delete this app."
-
-      val enginesSimEvals = appEngines.filter(eng =>
-        !(Helper.getSimEvalsByEngineid(eng.id).filter(Helper.isPendingSimEval(_)).isEmpty)
-      )
-      val msgSimEvals = "There are running simulated evaluations in engines: " + enginesSimEvals.map(_.name).mkString(", ") + ". Please stop and delete them before delete this app."
-
-      val enginesOfflineTunes = appEngines.filter(eng =>
-        !(offlineTunes.getByEngineid(eng.id).filter(Helper.isPendingOfflineTune(_)).isEmpty)
-      )
-      val msgOfflineTunes = "There are auto-tuning algorithms in engines: " + enginesOfflineTunes.map(_.name).mkString(", ") + ". Please stop and delete them before delete this app."
-
-      val runningEngines = List(
-        (enginesDeployed, msgDeployed),
-        (enginesSimEvals, msgSimEvals),
-        (enginesOfflineTunes, msgOfflineTunes)
-      ).filter { case (x, y) => (!x.isEmpty) }
-
-      if (!runningEngines.isEmpty) {
-        val msg = runningEngines.map { case (x, y) => y }.mkString(" ")
-        concurrent.Future(Forbidden(Json.obj("message" -> msg)))
-      } else {
-
-        val timeout = play.api.libs.concurrent.Promise.timeout("Scheduler is unreachable. Giving up.", concurrent.duration.Duration(10, concurrent.duration.MINUTES))
-        val delete = Helper.deleteAppScheduler(app.id)
-
-        concurrent.Future.firstCompletedOf(Seq(delete, timeout)).map {
-          case r: SimpleResult => {
-            if (r.header.status == http.Status.OK) {
-              Helper.deleteApp(id, user.id, keepSettings = false)
-            }
-            r
-          }
-          case t: String => InternalServerError(Json.obj("message" -> t))
-        }
-      }
-  }
-
-  /**
-   * Erase appdata of this appid
-   *
-   * {{{
-   * POST
-   * JSON Parameters:
-   *   None
-   * JSON Response:
-   *   If not authenticated:
-   *   Forbidden
-   *   {
-   *     "message" : "Haven't signed in yet."
-   *   }
-   *
-   *   If erased successfully:
-   *   Ok
-   * }}}
-   *
-   * @param id the App ID
-   */
-  def eraseAppData(id: Int) = WithApp.async(id) { (user, app) =>
-    implicit request =>
-
-      val timeout = play.api.libs.concurrent.Promise.timeout("Scheduler is unreachable. Giving up.", concurrent.duration.Duration(10, concurrent.duration.MINUTES))
-      val delete = Helper.deleteAppScheduler(app.id)
-
-      concurrent.Future.firstCompletedOf(Seq(delete, timeout)).map {
-        case r: SimpleResult => {
-          if (r.header.status == http.Status.OK) {
-            Helper.deleteApp(id, user.id, keepSettings = true)
-          }
-          r
-        }
-        case t: String => InternalServerError(Json.obj("message" -> t))
-      }
-  }
-
-  /**
-   * Returns a list of available engine infos in the system
-   *
-   * {{{
-   * GET
-   * JSON Parameters:
-   *   None
-   * JSON Response:
-   *   Ok
-   *   [ { "id" : <engine info id stirng>,
-   *       "engineinfoname" : <name of the engine info>,
-   *       "description": <description in html string>
-   *     },
-   *     ...
-   *   ]
-   * }}}
-   */
-  def getEngineInfoList = Action {
-    Ok(JsArray(engineInfos.getAll() map {
-      eng =>
-        Json.obj(
-          "id" -> eng.id,
-          "engineinfoname" -> eng.name,
-          "description" -> eng.description
-        )
-    }))
-  }
-
-  /**
-   * Returns a list of available algo infos of a specific engine info
-   *
-   * {{{
-   * GET
-   * JSON Parameters:
-   *   None
-   * JSON Response:
-   *   If the engine info id is not found:
-   *   InternalServerError
-   *   {
-   *     "message" : "Invalid EngineInfo ID."
-   *   }
-   *
-   *   If found:
-   *   Ok
-   *   { "engineinfoname" : <the name of the engine info>,
-   *     "algotypelist" : [ { "id" : <algo info id>,
-   *                          "algoinfoname" : <name of the algo info>,
-   *                          "description" : <string>,
-   *                          "req" : [<technology requirement string>],
-   *                          "datareq" : [<data requirement string>]
-   *                        }, ...
-   *                      ]
-   *   }
-   * }}}
-   *
-   * @param id the engine info id
-   */
-  def getEngineInfoAlgoInfoList(id: String) = Action {
-    engineInfos.get(id) map { engineInfo =>
-      Ok(Json.obj(
-        "engineinfoname" -> engineInfo.name,
-        "algotypelist" -> JsArray(
-          algoInfos.getByEngineInfoId(id).map { algoInfo =>
-            Json.obj(
-              "id" -> algoInfo.id,
-              "algoinfoname" -> algoInfo.name,
-              "description" -> algoInfo.description.getOrElse[String](""),
-              "req" -> Json.toJson(algoInfo.techreq),
-              "datareq" -> Json.toJson(algoInfo.datareq)
-            )
-          }
-        )
-      ))
-    } getOrElse InternalServerError(Json.obj("message" -> s"Invalid EngineInfo ID: ${id}."))
-  }
-
-  /**
-   * Returns a list of available metric infos of a specific engine info
-   *
-   * {{{
-   * GET
-   * JSON Parameters:
-   *   None
-   * JSON Response:
-   *   If the engine info id is not found:
-   *   InternalServerError
-   *   {
-   *     "message" : "Invalid EngineInfo ID."
-   *   }
-   *
-   *   If found:
-   *   Ok
-   *   { "engineinfoname" : <the name of the engine info>,
-   *     "defaultmetric" : <default metric info id>,
-   *     "metricslist" : [ { "id" : <metric info id>,
-   *                         "name" : <short name of the metric info>,
-   *                         "description" : <long name of the metric info>,
-   *                       }, ...
-   *                     ]
-   *   }
-   * }}}
-   *
-   * @param id the engine info id
-   */
-  def getEngineInfoMetricInfoList(id: String) = Action {
-    engineInfos.get(id) map { engInfo =>
-      val metrics = offlineEvalMetricInfos.getByEngineinfoid(engInfo.id).map { m =>
-        Json.obj(
-          "id" -> m.id,
-          "name" -> m.name,
-          "description" -> m.description
-        )
-      }
-      Ok(Json.obj(
-        "engineinfoname" -> engInfo.name,
-        "defaultmetric" -> engInfo.defaultofflineevalmetricinfoid,
-        "metricslist" -> JsArray(metrics)
-      ))
-    } getOrElse {
-      InternalServerError(Json.obj("message" -> s"Invalid engineinfo ID: ${id}."))
-    }
-  }
-
-  /**
-   * Returns a list of available splitter infos of a specific engine info
-   *
-   * {{{
-   * GET
-   * JSON Parameters:
-   *   None
-   * JSON Response:
-   *   If the engine info id is not found:
-   *   InternalServerError
-   *   {
-   *     "message" : "Invalid EngineInfo ID."
-   *   }
-   *
-   *   If found:
-   *   Ok
-   *   { "engineinfoname" : <the name of the engine info>,
-   *     "defaultsplitter": <default splitter info id>,
-   *     "splitterlist" : [ { "id" : <splitter info id>,
-   *                          "name" : <name of splitter>,
-   *                          "description" : <splitter description>,
-   *                       }, ...
-   *                     ]
-   *   }
-   * }}}
-   *
-   * @param id the engine info id
-   */
-  def getEngineInfoSplitterInfoList(id: String) = Action {
-    engineInfos.get(id).map { engInfo =>
-      val splitters = offlineEvalSplitterInfos.getByEngineinfoid(engInfo.id).map { m =>
-        Json.obj(
-          "id" -> m.id,
-          "name" -> m.name,
-          "description" -> m.description
-        )
-      }
-      Ok(Json.obj(
-        "engineinfoname" -> engInfo.name,
-        "defaultsplitter" -> engInfo.defaultofflineevalsplitterinfoid,
-        "splitterlist" -> JsArray(splitters)
-      ))
-    }.getOrElse {
-      InternalServerError(Json.obj("message" -> s"Invalid engineinfo ID: ${id}."))
-    }
-  }
-
-  /**
-   * Returns list of engines of this appid
-   *
-   * {{{
-   * GET
-   * JSON parameters:
-   *   None
-   * JSON response:
-   *   If not authenticated:
-   *   Forbidden
-   *   {
-   *     "message" : "Haven't signed in yet."
-   *   }
-   *
-   *   If no engine:
-   *   NoContent
-   *
-   *   If engines found:
-   *   Ok
-   *   {
-   *     "id" : <appid int>,
-   *     "enginelist" : [ { "id" : <engineid int>, "enginename" : <string>, "engineinfoid" : <string> },
-   *                       ....,
-   *                      { "id" : <engineid int>, "enginename" : <string>, "engineinfoid" : <string> } ]
-   *
-   *   }
-   * }}}
-   *
-   * @param id the App ID
-   */
-  def getAppEnginelist(appid: Int) = WithApp(appid) { (user, app) =>
-    implicit request =>
-
-      val appEngines = engines.getByAppid(appid)
-
-      if (!appEngines.hasNext) NoContent
-      else
-        Ok(Json.obj(
-          "id" -> appid,
-          "enginelist" -> JsArray(appEngines.map { eng =>
-            Json.obj("id" -> eng.id, "enginename" -> eng.name, "engineinfoid" -> eng.infoid)
-          }.toSeq)
-        ))
-  }
-
-  /**
-   * Returns the engine of this engineid
-   *
-   * {{{
-   * GET
-   * JSON Parameters:
-   *   None
-   * JSON Response:
-   *   If not authenticated:
-   *   Forbidden
-   *   {
-   *     "message" : "Haven't signed in yet."
-   *   }
-   *
-   *   If engine not found:
-   *   NotFound
-   *   {
-   *     "message" : "Invalid app id or engine id."
-   *   }
-   *
-   *   If engine found:
-   *   Ok
-   *   {
-   *     "id" : <engine id>,
-   *     "engineinfoid" : <engine info id>,
-   *     "enginename" : <engine name>,
-   *     "enginestatus" : <engine status>
-   *   }
-   * }}}
-   * @note engine status:
-   *   noappdata
-   *   nodeployedalgo
-   *   firsttraining
-   *   nomodeldata
-   *   nomodeldatanoscheduler
-   *   training
-   *   running
-   *   runningnoscheduler
-   *
-   * @param appid the App ID
-   * @param id the engine ID
-   */
-  def getEngine(appid: Int, id: Int) = WithEngine(appid, id) { (user, app, eng) =>
-    implicit request =>
-
-      val modelDataExist: Boolean = eng.infoid match {
-        case "itemrec" => try { itemRecScores.existByAlgo(algoOutputSelector.itemRecAlgoSelection(eng)) } catch { case e: RuntimeException => false }
-        case "itemrank" => try { itemRecScores.existByAlgo(algoOutputSelector.itemRankAlgoSelection(eng)) } catch { case e: RuntimeException => false }
-        case "itemsim" => try { itemSimScores.existByAlgo(algoOutputSelector.itemSimAlgoSelection(eng)) } catch { case e: RuntimeException => false }
-        case _ => false
-      }
-      val deployedAlgos = algos.getDeployedByEngineid(eng.id)
-      val hasDeployedAlgo = deployedAlgos.hasNext
-      val algo = if (deployedAlgos.hasNext) Some(deployedAlgos.next()) else None
-      val engineStatus: String =
-        if (appDataUsers.countByAppid(eng.appid) == 0 && appDataItems.countByAppid(eng.appid) == 0 && appDataU2IActions.countByAppid(eng.appid) == 0)
-          "noappdata"
-        else if (!hasDeployedAlgo)
-          "nodeployedalgo"
-        else if (!modelDataExist)
-          try {
-            (Await.result(WS.url(s"${settingsSchedulerUrl}/apps/${eng.appid}/engines/${eng.id}/algos/${algo.get.id}/status").get(), scala.concurrent.duration.Duration(5, SECONDS)).json \ "status").as[String] match {
-              case "jobrunning" => "firsttraining"
-              case _ => "nomodeldata"
-            }
-          } catch {
-            case e: java.net.ConnectException => "nomodeldatanoscheduler"
-          }
-        else
-          try {
-            (Await.result(WS.url(s"${settingsSchedulerUrl}/apps/${eng.appid}/engines/${eng.id}/algos/${algo.get.id}/status").get(), scala.concurrent.duration.Duration(5, SECONDS)).json \ "status").as[String] match {
-              case "jobrunning" => "training"
-              case _ => "running"
-            }
-          } catch {
-            case e: java.net.ConnectException => "runningnoscheduler"
-          }
-      val engineObj = Json.obj(
-        "id" -> eng.id, // engine id
-        "engineinfoid" -> eng.infoid,
-        "appid" -> eng.appid,
-        "enginename" -> eng.name,
-        "enginestatus" -> engineStatus)
-
-      Ok(
-        algo map { a =>
-          val lasttraintime: String = a.lasttraintime map { _.toString() } getOrElse "unknown"
-          engineObj ++ Json.obj("lasttraintime" -> lasttraintime)
-        } getOrElse engineObj)
-  }
-
-  /**
-   * Creates an Engine
-   *
-   * {{{
-   * POST
-   * JSON parameters:
-   *   {
-   *     "engineinfoid" : <engine info id>,
-   *     "enginename" : <engine name>
-   *   }
-   * JSON response:
-   *   If not authenticated:
-   *   Forbidden
-   *   {
-   *     "message" : "Haven't signed in yet."
-   *   }
-   *
-   *   if invalid appid:
-   *   NotFound
-   *   {
-   *     "message" : <error message>
-   *   }
-   *
-   *   If bad param:
-   *   BadRequest
-   *   {
-   *     "message" : <error message>
-   *   }
-   *
-   *   If created:
-   *   Ok
-   *   {
-   *     "id" : <new engine id>,
-   *     "engineinfoid" : <engine info id>,
-   *     "appid" : <app id>,
-   *     "enginename" : <engine name>
-   *   }
-   *
-   * }}}
-   *
-   * @param appid the App ID
-   */
-  def createEngine(appid: Int) = WithApp(appid) { (user, app) =>
-    implicit request =>
-
-      val supportedEngineTypes: Seq[String] = engineInfos.getAll() map { _.id }
-      val enginenameConstraint = Constraints.pattern(nameRegex, "constraint.enginename", "Engine names should only contain alphanumerical characters, underscores, or dashes. The first character must be an alphabet.")
-
-      val engineForm = Form(tuple(
-        "engineinfoid" -> (text verifying ("This feature will be available soon.", e => supportedEngineTypes.contains(e))),
-        "enginename" -> (text verifying ("Please name your engine.", enginename => enginename.length > 0)
-          verifying enginenameConstraint)
-      ) verifying ("Engine name must be unique.", f => !engines.existsByAppidAndName(appid, f._2))
-        verifying ("Engine type is invalid.", f => engineInfos.get(f._1).map(_ => true).getOrElse(false)))
-
-      engineForm.bindFromRequest.fold(
-        formWithError => {
-          val msg = formWithError.errors(0).message // extract 1st error message only
-          BadRequest(toJson(Map("message" -> toJson(msg))))
-        },
-        formData => {
-          val (enginetype, enginename) = formData
-          val engineInfo = engineInfos.get(enginetype).get
-          val engineId = engines.insert(Engine(
-            id = -1,
-            appid = appid,
-            name = enginename,
-            infoid = enginetype,
-            itypes = None, // NOTE: default None (means all itypes)
-            params = engineInfo.params.map(s => (s._2.id, s._2.defaultvalue))
-          ))
-          Logger.info("Create engine ID " + engineId)
-
-          // automatically create default algo
-          val defaultAlgoType = engineInfo.defaultalgoinfoid
-          val params = algoInfos.get(defaultAlgoType).get.params.mapValues(_.defaultvalue)
-
-          val defaultAlgo = Algo(
-            id = -1,
-            engineid = engineId,
-            name = "Default-Algo",
-            infoid = defaultAlgoType,
-            command = "",
-            params = params,
-            settings = Map(), // no use for now
-            modelset = false, // init value
-            createtime = DateTime.now,
-            updatetime = DateTime.now,
-            status = "deployed", // this is default deployed algo
-            offlineevalid = None,
-            loop = None
-          )
-
-          val algoId = algos.insert(defaultAlgo)
-          Logger.info("Create algo ID " + algoId)
-
-          WS.url(settingsSchedulerUrl + "/users/" + user.id + "/sync").get()
-
-          Ok(Json.obj(
-            "id" -> engineId, // engine id
-            "engineinfoid" -> enginetype,
-            "appid" -> appid,
-            "enginename" -> enginename))
-        }
-      )
-
-  }
-
-  /**
-   * Removes an engine
-   *
-   * {{{
-   * DELETE
-   * JSON parameters:
-   *   None
-   * JSON response:
-   *   If not authenticated:
-   *   Forbidden
-   *   {
-   *     "message" : "Haven't signed in yet."
-   *   }
-   *
-   *   If deleted:
-   *   Ok
-   *
-   * }}}
-   *
-   * @param appid the App ID
-   * @param engineid the engine ID
-   */
-  def removeEngine(appid: Int, engineid: Int) = WithEngine.async(appid, engineid) { (user, app, eng) =>
-    implicit request =>
-      // don't delete if there is any sim eval and offline tune pending, or deployed algorithm
-      val pendingSimEvals = Helper.getSimEvalsByEngineid(eng.id).filter(x => Helper.isPendingSimEval(x)).toList
-      val pendingOfflineTunes = offlineTunes.getByEngineid(eng.id).filter(x => Helper.isPendingOfflineTune(x)).toList
-      val deployedAlgos = algos.getDeployedByEngineid(eng.id).toList
-
-      if (deployedAlgos.size != 0) {
-        val names = deployedAlgos map (x => x.name) mkString (",")
-        Future.successful(Forbidden(Json.obj("message" -> s"This engine has deployed algorithms (${names}). Please undeploy them before delete this engine.")))
-      } else if (pendingSimEvals.size != 0) {
-        Future.successful(Forbidden(Json.obj("message" -> "There are running simulated evaluations. Please stop and delete them before delete this engine.")))
-      } else if (pendingOfflineTunes.size != 0) {
-        Future.successful(Forbidden(Json.obj("message" -> "There are auto-tuning algorithms. Please stop and delete them before delete this engine.")))
-      } else {
-        /** Deletion could take a while */
-        val timeout = play.api.libs.concurrent.Promise.timeout("Scheduler is unreachable. Giving up.", concurrent.duration.Duration(10, concurrent.duration.MINUTES))
-
-        // to scheduler: delete engine
-        val delete = Helper.deleteEngineScheduler(appid, engineid)
-
-        concurrent.Future.firstCompletedOf(Seq(delete, timeout)).map {
-          case r: SimpleResult => {
-            if (r.header.status == http.Status.OK) {
-              Helper.deleteEngine(engineid, appid, keepSettings = false)
-            }
-            r
-          }
-          case t: String => InternalServerError(Json.obj("message" -> t))
-        }
-      }
-  }
-
-  /**
-   * Returns a list of available (added but not deployed) algorithms of this engine
-   * {{{
-   * GET
-   * JSON parameters:
-   *   None
-   * JSON response:
-   *   If not authenticated:
-   *   Forbidden
-   *   {
-   *     "message" : "Haven't signed in yet."
-   *   }
-   *
-   *   If no algo:
-   *   NoContent
-   *
-   *   If algos found:
-   *   [ { see algoToJson
-   *     }, ...
-   *   ]
-   * }}}
-   * @note algo status
-   *   TODO: add more info here...
-   *
-   * @param appid the App ID
-   * @param engineid the engine ID
-   */
-  def getAvailableAlgoList(appid: Int, engineid: Int) = WithEngine(appid, engineid) { (user, app, eng) =>
-    implicit request =>
-
-      val engineAlgos = algos.getByEngineid(engineid).filter { Helper.isAvailableAlgo(_) }
-
-      if (!engineAlgos.hasNext) NoContent
-      else
-        Ok(Json.toJson( // NOTE: only display algos which are not "deployed", nor "simeval"
-          engineAlgos.map { algo =>
-            val algoInfo = algoInfos.get(algo.infoid)
-            algoToJson(algo, appid, algoInfo)
-          }.toSeq
-        ))
-  }
-
-  /**
-   * Returns an available algorithm
-   * {{{
-   * GET
-   * JSON parameters:
-   *   None
-   * JSON response:
-   *   If not authenticated:
-   *   Forbidden
-   *   {
-   *     "message" : "Haven't signed in yet."
-   *   }
-   *
-   *   If algo not found:
-   *   NotFound
-   *   {
-   *     "message" : "Invalid app id, engine id or algo id."
-   *   }
-   *
-   *   If found:
-   *   Ok
-   *   {
-   *     see algoToJson
-   *   }
-   * }}}
-   *
-   * @param appid the App ID
-   * @param engineid the engine ID
-   * @param id the algo ID
-   */
-  def getAvailableAlgo(appid: Int, engineid: Int, id: Int) = WithAlgo(appid, engineid, id) { (user, app, eng, algo) =>
-    implicit request =>
-      algoInfos.get(algo.infoid).map { info =>
-        Ok(algoToJson(algo, appid, Some(info)))
-      }.getOrElse {
-        InternalServerError(Json.obj("message" -> s"Algoinfo ${algo.infoid} not found."))
-      }
-  }
-
-  /**
-   * Creates an new algorithm
-   * {{{
-   * POST
-   * JSON parameters:
-   *   {
-   *     "algoinfoid" : <algo info id>,
-   *     "algoname" : <algo name>,
-   *   }
-   * JSON response:
-   *   If not authenticated:
-   *   Forbidden
-   *   {
-   *     "message" : "Haven't signed in yet."
-   *   }
-   *
-   *   If invalid appid or engineid:
-   *   NotFound
-   *   {
-   *     "message" : <error message>
-   *   }
-   *
-   *   If creation failed:
-   *   BadRequest
-   *   {
-   *     "message" : <error message>
-   *   }
-   *
-   *   If created:
-   *   Ok
-   *   {
-   *     see algoToJson
-   *   }
-   *
-   * }}}
-   *
-   * @param appid the App ID
-   * @param engineid the engine ID
-   */
-  def createAvailableAlgo(appid: Int, engineid: Int) = WithEngine(appid, engineid) { (user, app, eng) =>
-    implicit request =>
-
-      val supportedAlgoTypes: Seq[String] = algoInfos.getAll map { _.id }
-      val algonameConstraint = Constraints.pattern(nameRegex, "constraint.algoname", "Algorithm names should only contain alphanumerical characters, underscores, or dashes. The first character must be an alphabet.")
-
-      val createAlgoForm = Form(tuple(
-        "algoinfoid" -> (nonEmptyText verifying ("This feature will be available soon.", t => supportedAlgoTypes.contains(t))),
-        "algoname" -> (text verifying ("Please name your algo.", name => name.length > 0)
-          verifying algonameConstraint) // same name constraint as engine
-      ) verifying ("Algo name must be unique.", f => !algos.existsByEngineidAndName(engineid, f._2)))
-
-      createAlgoForm.bindFromRequest.fold(
-        formWithError => {
-          val msg = formWithError.errors(0).message // extract 1st error message only
-          BadRequest(toJson(Map("message" -> toJson(msg))))
-        },
-        formData => {
-          val (algoType, algoName) = formData
-
-          algoInfos.get(algoType).map { algoInfo =>
-
-            val newAlgo = Algo(
-              id = -1,
-              engineid = engineid,
-              name = algoName,
-              infoid = algoType,
-              command = "",
-              params = algoInfo.params.mapValues(_.defaultvalue),
-              settings = Map(), // no use for now
-              modelset = false, // init value
-              createtime = DateTime.now,
-              updatetime = DateTime.now,
-              status = "ready", // default status
-              offlineevalid = None,
-              loop = None
-            )
-
-            val algoId = algos.insert(newAlgo)
-            Logger.info("Create algo ID " + algoId)
-
-            Ok(algoToJson(newAlgo.copy(id = algoId), appid, Some(algoInfo)))
-          }.getOrElse {
-            InternalServerError(Json.obj("message" -> s"Algoinfo ${algoType} not found."))
-          }
-        }
-      )
-  }
-
-  /**
-   * Deletes an algorithm
-   * {{{
-   * DELETE
-   * JSON parameters:
-   *   None
-   * JSON response:
-   *   If not authenticated:
-   *   Forbidden
-   *   {
-   *     "message" : "Haven't signed in yet."
-   *   }
-   *
-   *   If deleted:
-   *   Ok
-   * }}}
-   *
-   * @param appid the App ID
-   * @param engineid the engine ID
-   * @param id the algo ID
-   */
-  def removeAvailableAlgo(appid: Int, engineid: Int, id: Int) = WithAlgo.async(appid, engineid, id) { (user, app, eng, algo) =>
-    implicit request =>
-      /** Deletion could take a while */
-      val timeout = play.api.libs.concurrent.Promise.timeout("Scheduler is unreachable. Giving up.", concurrent.duration.Duration(10, concurrent.duration.MINUTES))
-
-      val deleteTune = algo.offlinetuneid map { tuneid =>
-        offlineTunes.get(tuneid) map { tune =>
-          /** Make sure to unset offline tune's creation time to prevent scheduler from picking up */
-          offlineTunes.update(tune.copy(createtime = None))
-
-          Helper.stopAndDeleteOfflineTuneScheduler(appid, engineid, tuneid)
-        } getOrElse {
-          concurrent.Future { Ok }
-        }
-      } getOrElse {
-        concurrent.Future { Ok }
-      }
-
-      val deleteAlgo: concurrent.Future[SimpleResult] = Helper.deleteAlgoScheduler(appid, engineid, algo.id)
-
-      val complete: concurrent.Future[SimpleResult] = concurrent.Future.reduce(Seq(deleteTune, deleteAlgo)) { (a, b) =>
-        if (a.header.status != http.Status.OK) // keep the 1st error
-          a
-        else
-          b
-      }
-
-      concurrent.Future.firstCompletedOf(Seq(complete, timeout)).map {
-        case r: SimpleResult => {
-          if (r.header.status == http.Status.OK) {
-            algo.offlinetuneid map { tuneid =>
-              Helper.deleteOfflineTune(tuneid, keepSettings = false)
-            }
-            Helper.deleteAlgo(algo.id, keepSettings = false)
-          }
-          r
-        }
-        case t: String => InternalServerError(Json.obj("message" -> t))
-      }
-  }
-
-  /**
-   * Returns a list of deployed algorithms
-   * {{{
-   * GET
-   * JSON parameters:
-   *   None
-   * JSON repseon:
-   *   If not authenticated:
-   *   Forbidden
-   *   {
-   *     "message" : "Haven't signed in yet."
-   *   }
-   *
-   *   If no deployed algo:
-   *   NoContent
-   *
-   *   If deployed algos found:
-   *   {
-   *     "updatedtime" : <TODO>,
-   *     "status" : <TODO>,
-   *     "algolist" : [ { see algoToJson
-   *                    }, ...
-   *                  ]
-   *   }
-   * }}}
-   *
-   * @param appid the App ID
-   * @param engineid the engine ID
-   */
-  def getDeployedAlgoList(appid: Int, engineid: Int) = WithEngine(appid, engineid) { (user, app, eng) =>
-    implicit request =>
-
-      val deployedAlgos = algos.getDeployedByEngineid(engineid)
-
-      if (!deployedAlgos.hasNext) NoContent
-      else
-        Ok(Json.obj(
-          "updatedtime" -> "12-03-2012 12:32:12", // TODO: what's this time for?
-          "status" -> "Running",
-          "algolist" -> Json.toJson(deployedAlgos.map { algo =>
-            val algoInfo = algoInfos.get(algo.infoid)
-            algoToJson(algo, appid, algoInfo)
-          }.toSeq)
-        ))
-  }
-
-  /**
-   * Deploys a list of algorithms (also undeploys any existing deployed algorithms)
-   * The status of deployed algorithms change to "deployed"
-   *
-   * {{{
-   * POST
-   * JSON parameters:
-   *   {
-   *     "algoidlist" : [ array of algo ids ]
-   *   }
-   * JSON response:
-   *   If not authenticated:
-   *   Forbidden
-   *   {
-   *     "message" : "Haven't signed in yet."
-   *   }
-   *
-   *   If any of the algo id is not valid:
-   *   BadRequest
-   *   {
-   *     "message" : <error message>
-   *   }
-   *
-   *   If done:
-   *   Ok
-   *
-   * }}}
-   *
-   * @param appid the App ID
-   * @param engineid the engine ID
-   */
-  def algoDeploy(appid: Int, engineid: Int) = WithEngine(appid, engineid) { (user, app, eng) =>
-    implicit request =>
-      val deployForm = Form(
-        "algoidlist" -> list(number)
-      )
-      deployForm.bindFromRequest.fold(
-        formWithErrors => Ok,
-        form => {
-          val algoidList = form
-          val algoList = algoidList.map(id => (id, algos.getByIdAndEngineid(id, engineid)))
-          val invalidAlgos = algoList.filter {
-            case (id, algoOpt) => algoOpt match {
-              case None => true // not exist
-              case Some(x) => (x.status != "ready") // not ready
-            }
-          }
-
-          // make sure all algoids are valid
-          if (!invalidAlgos.isEmpty) {
-            val ids = invalidAlgos.map { case (id, algoOpt) => id }.mkString(", ")
-            BadRequest(Json.obj("message" -> s"Invalid algo ids: ${ids}."))
-          } else {
-            algos.getDeployedByEngineid(engineid).foreach { algo =>
-              algos.update(algo.copy(status = "ready"))
-            }
-            algoList.foreach {
-              case (id, algoOpt) =>
-                // algoOpt can't be None because of invalidAlgos check
-                algos.update(algoOpt.get.copy(status = "deployed"))
-            }
-            WS.url(settingsSchedulerUrl + "/users/" + user.id + "/sync").get()
-            Ok
-          }
-        }
-      )
-  }
-
-  /**
-   * Undeploys all deployed algorithms
-   * {{{
-   * POST
-   * JSON parameters:
-   *   None
-   * JSON response:
-   *   If not authenticated:
-   *   Forbidden
-   *   {
-   *     "message" : "Haven't signed in yet."
-   *   }
-   *
-   *   If done:
-   *   Ok
-   * }}}
-   *
-   * @param appid the App ID
-   * @param engineid the engine ID
-   */
-  def algoUndeploy(appid: Int, engineid: Int) = WithEngine(appid, engineid) { (user, app, eng) =>
-    implicit request =>
-
-      algos.getDeployedByEngineid(engineid) foreach { algo =>
-        algos.update(algo.copy(status = "ready"))
-      }
-      WS.url(settingsSchedulerUrl + "/users/" + user.id + "/sync").get()
-      Ok
-  }
-
-  /**
-   * Requests to train model now
-   * {{{
-   * POST
-   * JSON parameters:
-   *   None
-   * JSON response:
-   *   If not authenticated:
-   *   Forbidden
-   *   {
-   *     "message" : "Haven't signed in yet."
-   *   }
-   *
-   *   If error:
-   *   InternalServerError
-   *   {
-   *     "message" : <error message>
-   *   }
-   *
-   *   If done:
-   *   Ok
-   *   {
-   *     "message" : <message from scheduler>
-   *   }
-   * }}}
-   *
-   * @param appid the App ID
-   * @param engineid the engine ID
-   */
-  def algoTrainNow(appid: Int, engineid: Int) = WithEngine.async(appid, engineid) { (user, app, eng) =>
-    implicit request =>
-      // No extra param required
-      val timeout = play.api.libs.concurrent.Promise.timeout("Scheduler is unreachable. Giving up.", concurrent.duration.Duration(10, concurrent.duration.MINUTES))
-      val request = WS.url(s"${settingsSchedulerUrl}/apps/${appid}/engines/${engineid}/trainoncenow").get() map { r =>
-        Ok(Json.obj("message" -> (r.json \ "message").as[String]))
-      } recover {
-        case e: Exception => InternalServerError(Json.obj("message" -> e.getMessage()))
-      }
-
-      /** Detect timeout (10 minutes by default) */
-      concurrent.Future.firstCompletedOf(Seq(request, timeout)).map {
-        case r: SimpleResult => r
-        case t: String => InternalServerError(Json.obj("message" -> t))
-      }
-  }
-
-  /**
-   * Returns a list of simulated evalulation for this engine
-   *
-   * {{{
-   * GET
-   * JSON parameters:
-   *   None
-   * JSON response:
-   *   If not authenticated:
-   *   Forbidden
-   *   {
-   *     "message" : "Haven't signed in yet."
-   *   }
-   *
-   *   If no sim evals:
-   *   NoContent
-   *
-   *   If found:
-   *   Ok
-   *   [
-   *     { "id" : <sim eval id>,
-   *       "appid" : <app id>,
-   *       "engineid" : <engine id>,
-   *       "algolist" : [
-   *                      { "id" : <algo id>,
-   *                        "algoname" : <algo name>,
-   *                        "appid" : <app id>,
-   *                        "engineid" : <engine id>,
-   *                        "algoinfoid" : <algo info id>,
-   *                        "algoinfoname" : <algo info name>,
-   *                        "settingsstring" : <algo setting string>
-   *                      }, ...
-   *                    ],
-   *       "status" : <sim eval status>,
-   *       "createtime" : <sim eval create time>,
-   *       "endtime" : <sim eval end time>
-   *     }, ...
-   *   ]
-   * }}}
-   *
-   * @param appid the App ID
-   * @param engineid the engine ID
-   */
-  def getSimEvalList(appid: Int, engineid: Int) = WithEngine(appid, engineid) { (user, app, eng) =>
-    implicit request =>
-
-      // get offlineeval for this engine
-      val engineOfflineEvals = Helper.getSimEvalsByEngineid(engineid)
-
-      if (!engineOfflineEvals.hasNext) NoContent
-      else {
-        val resp = Json.toJson(
-
-          engineOfflineEvals.map { eval =>
-
-            val algolist = Json.toJson(
-              algos.getByOfflineEvalid(eval.id).map { algo =>
-                val algoInfo = algoInfos.get(algo.infoid)
-                algoToJson(algo, appid, algoInfo, withParam = true)
-              }.toSeq
-            )
-
-            val createtime = eval.createtime.map(dateTimeToString(_)).getOrElse("-")
-            val starttime = eval.starttime.map(dateTimeToString(_)).getOrElse("-")
-            val endtime = eval.endtime.map(dateTimeToString(_)).getOrElse("-")
-
-            Json.obj(
-              "id" -> eval.id,
-              "appid" -> appid,
-              "engineid" -> eval.engineid,
-              "algolist" -> algolist,
-              "status" -> getSimEvalStatus(eval),
-              "createtime" -> createtime, // NOTE: use createtime here for test date
-              "endtime" -> endtime
-            )
-          }.toSeq
-        )
-        Ok(resp)
-      }
-  }
-
-  /**
-   * Creates a simulated evalution
-   *
-   * {{{
-   * POST
-   * JSON parameters:
-   *
-   *  {
-   *    "infoid[i]": <metric or splitter info id>
-   *    "infotype[i]": <"offlineevalmetric" or "offlineevalsplitter">
-   *    "other param [i]": <the parameter value for corresponding infoid[i]>
-   *    "algo" : <list of algo ids to be evaluated>
-   *    "splittrain": <training set split percentage 1 to 100>,
-   *    "splittest": <test set split percentage 1 to 100>,
-   *    "evaliteration": <number of iterations>
-   *  }
-   *
-   * JSON response:
-   *   If not authenticated:
-   *   Forbidden
-   *   {
-   *     "message" : "Haven't signed in yet."
-   *   }
-   *
-   *   If error:
-   *   BadRequest
-   *   {
-   *     "message" : <error message>
-   *   }
-   *
-   *   If created:
-   *   Ok
-   *
-   * }}}
-   * @param appid the App ID
-   * @param engineid the engine ID
-   */
-  def createSimEval(appid: Int, engineid: Int) = WithEngine(appid, engineid) { (user, app, eng) =>
-    implicit request =>
-      val simEvalForm = Form(tuple(
-        "infoid" -> seqOfMapOfStringToAny,
-        "algoids" -> list(number), // algo id
-        "splittrain" -> number(1, 100),
-        "splittest" -> number(1, 100),
-        "evaliteration" -> (number verifying ("Number of Iteration must be greater than 0", x => (x > 0)))
-      ))
-
-      simEvalForm.bindFromRequest.fold(
-        e => BadRequest(Json.obj("message" -> e.toString)),
-        f => {
-          val (params, algoids, splitTrain, splitTest, evalIteration) = f
-
-          val metricList = params.filter(p => (p("infotype") == "offlineevalmetric")).map(p =>
-            OfflineEvalMetric(
-              id = 0,
-              infoid = p("infoid").asInstanceOf[String],
-              evalid = 0, // will be assigned later
-              params = p - "infoid" - "infotype" // remove these keys from params
-            )).toList
-
-          // percentage param is standard for all splitter
-          val percentageParam = Map(
-            "trainingPercent" -> (splitTrain.toDouble / 100),
-            "validationPercent" -> 0.0, // no validatoin set for sim eval
-            "testPercent" -> (splitTest.toDouble / 100)
-          )
-
-          // get list of algo obj
-          val optAlgos: List[Option[Algo]] = algoids.map { algos.get(_) }
-
-          // TODO: Allow selection of splitter
-          // Use Hadoop version if any algo in the list requires Hadoop
-          val hadoopRequired = optAlgos.map { optAlgo =>
-            optAlgo map { algo =>
-              algoInfos.get(algo.infoid) map { info =>
-                info.techreq.contains("Hadoop")
-              } getOrElse false
-            } getOrElse false
-          } reduce { _ || _ }
-
-          val splitterList = params.filter(p => (p("infotype") == "offlineevalsplitter")).map(p =>
-            OfflineEvalSplitter(
-              id = 0,
-              evalid = 0, // will be assigned later
-              name = "", // will be assigned later
-              //infoid = p("infoid").asInstanceOf[String],
-              infoid = if (hadoopRequired) "pio-distributed-trainingtestsplit" else "pio-single-trainingtestsplit",
-              settings = p ++ percentageParam - "infoid" - "infotype" // remove these keys from params
-            )).toList
-
-          if (metricList.length == 0)
-            BadRequest(Json.obj("message" -> "At least one metric is required."))
-          else if (splitterList.length == 0)
-            BadRequest(Json.obj("message" -> "One Splitter is required."))
-          else if (splitterList.length > 1)
-            BadRequest(Json.obj("message" -> "Multiple Splitters are not supported now."))
-          else if (optAlgos.contains(None))
-            BadRequest(Json.obj("message" -> "Invalid algo ids."))
-          else {
-            val algoList: List[Algo] = optAlgos.map(_.get) // NOTE: already check optAlgos does not contain None
-
-            val evalid = createOfflineEval(eng, algoList, metricList, splitterList(0), evalIteration)
-
-            WS.url(settingsSchedulerUrl + "/users/" + user.id + "/sync").get()
-
-            Ok
-          }
-        }
-      )
-  }
-
-  /**
-   * Requests to stop and delete simulated evalution (including running/pending job)
-   *
-   * {{{
-   * DELETE
-   * JSON parameters:
-   *   None
-   * JSON response:
-   *   If not authenticated:
-   *   Forbidden
-   *   {
-   *     "message" : "Haven't signed in yet."
-   *   }
-   *
-   *   If not found:
-   *   NotFound
-   *   {
-   *     "message" : <error message>
-   *   }
-   *
-   *   If error:
-   *   InternalServerError
-   *   {
-   *     "message" : <error message>
-   *   }
-   *
-   *   If deleted:
-   *   Ok
-   *   {
-   *      "message" : "Offline evaluation ID $id has been deleted"
-   *   }
-   * }}}
-   *
-   * @param appid the App ID
-   * @param engineid the engine ID
-   * @param id the offline evaluation ID
-   *
-   */
-  def removeSimEval(appid: Int, engineid: Int, id: Int) = WithOfflineEval.async(appid, engineid, id) { (user, app, eng, oe) =>
-    implicit request =>
-      // remove algo, remove metric, remove offline eval
-      /** Make sure to unset offline eval's creation time to prevent scheduler from picking up */
-      offlineEvals.update(oe.copy(createtime = None))
-
-      /** Deletion of app data and model data could take a while */
-      val timeout = play.api.libs.concurrent.Promise.timeout("Scheduler is unreachable. Giving up.", concurrent.duration.Duration(10, concurrent.duration.MINUTES))
-
-      val complete = Helper.stopAndDeleteSimEvalScheduler(appid, engineid, oe.id)
-
-      /** Detect timeout (10 minutes by default) */
-      concurrent.Future.firstCompletedOf(Seq(complete, timeout)).map {
-        case r: SimpleResult => {
-          if (r.header.status == http.Status.OK) {
-            Helper.deleteOfflineEval(oe.id, keepSettings = false)
-          }
-          r
-        }
-        case t: String => InternalServerError(Json.obj("message" -> t))
-      }
-  }
-
-  /**
-   * Returns the simulated evaluation report
-   *
-   * {{{
-   * GET
-   * JSON parameters:
-   *   None
-   * JSON response:
-   *   If not authenticated:
-   *   Forbidden
-   *   {
-   *     "message" : "Haven't signed in yet."
-   *   }
-   *
-   *   If not found:
-   *   {
-   *     "message" : <error message>
-   *   }
-   *
-   *   If found:
-   *   Ok
-   *   {
-   *     "id" : <sim eval id>,
-   *     "appid" : <app id>,
-   *     "engineid" : <engine id>,
-   *     "algolist" : [
-   *                    {
-   *                      "id" : <algo id>,
-   *                      "algoname" : <algo name>,
-   *                      "appid" : <app id>,
-   *                      "engineid" : <engine id>,
-   *                      "algoinfoid" : <algo info id>,
-   *                      "algoinfoname" : <algo info name>,
-   *                      "settingsstring" : <algo setting string>
-   *                    }, ...
-   *                  ],
-   *     "metricslist" : [
-   *                       {
-   *                         "id" : <metric id>,
-   *                         "metricsinfoid" : <metric info id>,
-   *                         "metricsname" : <metric info name>,
-   *                         "settingsstring" : <metric setting string>
-   *                       }, ...
-   *                     ],
-   *     "metricscorelist" : [
-   *                           {
-   *                             "algoid" : <algo id>,
-   *                             "metricsid" : <metric id>,
-   *                             "score" : <average score>
-   *                           }, ...
-   *                         ],
-   *     "metricscoreiterationlist" : [
-   *                                    [{
-   *                                      "algoid" : <algo id>,
-   *                                      "metricsid" : <metric id>,
-   *                                      "score" : <score of 1st iteration>
-   *                                     }, ...
-   *                                    ],
-   *                                    [{
-   *                                      "algoid" : <algo id>,
-   *                                      "metricsid" : <metric id>,
-   *                                      "score" : <score of 2nd iteration>
-   *                                     }, ...
-   *                                    ],
-   *                                  ],
-   *     "splittrain" : <training set split percentage 1 to 100>,
-   *     "splittest" : <test set split percentage 1 to 100>,
-   *     "splittersettingsstring" : <splitter setting string>,
-   *     "evaliteration" : <number of iterations>,
-   *     "status" : <eval status>,
-   *     "starttime" : <start time>,
-   *     "endtime" : <end time>
-   *   }
-   * }}}
-   *
-   * @param appid the App ID
-   * @param engineid the engine ID
-   * @param id the offline evaluation ID
-   */
-  def getSimEvalReport(appid: Int, engineid: Int, id: Int) = WithOfflineEval(appid, engineid, id) { (user, app, eng, eval) =>
-    implicit request =>
-
-      val status = getSimEvalStatus(eval)
-
-      val evalAlgos = algos.getByOfflineEvalid(eval.id).toArray
-
-      val algolist = Json.toJson(
-        evalAlgos.map { algo =>
-          val algoInfo = algoInfos.get(algo.infoid)
-          algoToJson(algo, appid, algoInfo, withParam = true)
-        }.toSeq
-      )
-
-      val evalMetrics = offlineEvalMetrics.getByEvalid(eval.id).toArray
-
-      val metricslist = Json.toJson(
-        evalMetrics.map { metric =>
-          val metricInfo = offlineEvalMetricInfos.get(metric.infoid)
-          offlineEvalMetricToJson(metric, metricInfo, withParam = true)
-        }.toSeq
-      )
-
-      val evalResults = offlineEvalResults.getByEvalid(eval.id).toArray
-
-      val metricscorelist = Json.toJson(
-        (for (algo <- evalAlgos; metric <- evalMetrics) yield {
-
-          val results = evalResults
-            .filter(x => ((x.metricid == metric.id) && (x.algoid == algo.id)))
-            .map(x => x.score)
-
-          val num = results.length
-          val avg = if ((results.isEmpty) || (num != eval.iterations)) "N/A" else ((results.reduceLeft(_ + _) / num).toString)
-
-          Json.obj(
-            "algoid" -> algo.id,
-            "metricsid" -> metric.id,
-            "score" -> avg
-          )
-        }).toSeq
-      )
-
-      val metricscoreiterationlist = Json.toJson((for (i <- 1 to eval.iterations) yield {
-        val defaultScore = (for (algo <- evalAlgos; metric <- evalMetrics) yield {
-          ((algo.id, metric.id) -> "N/A") // default score
-        }).toMap
-
-        val evalScore = evalResults.filter(x => (x.iteration == i)).map(r =>
-          ((r.algoid, r.metricid) -> r.score.toString)).toMap
-
-        // overwrite defaultScore with evalScore
-        (defaultScore ++ evalScore).map {
-          case ((algoid, metricid), score) =>
-            Json.obj("algoid" -> algoid, "metricsid" -> metricid, "score" -> score)
-        }
-      }).toSeq)
-
-      val starttime = eval.starttime map (dateTimeToString(_)) getOrElse ("-")
-      val endtime = eval.endtime map (dateTimeToString(_)) getOrElse ("-")
-
-      // get splitter data
-      val splitters = offlineEvalSplitters.getByEvalid(eval.id)
-
-      if (splitters.hasNext) {
-        val splitter = splitters.next
-
-        val splitTrain = ((splitter.settings("trainingPercent").asInstanceOf[Double]) * 100).toInt
-        val splitTest = ((splitter.settings("testPercent").asInstanceOf[Double]) * 100).toInt
-
-        if (splitters.hasNext) {
-          InternalServerError(Json.obj("message" -> s"More than one splitter found for this Offline Eval ID: ${eval.id}"))
-        } else {
-          Ok(Json.obj(
-            "id" -> eval.id,
-            "appid" -> appid,
-            "engineid" -> eval.engineid,
-            "algolist" -> algolist,
-            "metricslist" -> metricslist,
-            "metricscorelist" -> metricscorelist,
-            "metricscoreiterationlist" -> metricscoreiterationlist,
-            "splittrain" -> splitTrain,
-            "splittest" -> splitTest,
-            "splittersettingsstring" -> offlineEvalSplitterParamToString(splitter, offlineEvalSplitterInfos.get(splitter.infoid)),
-            "evaliteration" -> eval.iterations,
-            "status" -> status,
-            "starttime" -> starttime,
-            "endtime" -> endtime
-          ))
-        }
-      } else {
-        InternalServerError(Json.obj("message" -> s"No splitter found fo this Offline Eval ID ${eval.id}."))
-      }
-
-  }
-
-  /**
-   * Returns the algorithm auto tune report
-   *
-   * {{{
-   * GET
-   * JSON parameters:
-   *   None
-   * JSON response:
-   *   If not authenticated:
-   *   Forbidden
-   *   {
-   *     "message" : "Haven't signed in yet."
-   *   }
-   *
-   *   If not found:
-   *   NotFound
-   *   {
-   *     "message" : <error message>
-   *   }
-   *
-   *   If found:
-   *   Ok
-   *   {
-   *     "id" : <original algo id>,
-   *     "appid" : <app id>,
-   *     "engineid" : <engine id>,
-   *     "algo" : {
-   *                "id" : <original algo id>,
-   *                "algoname" : <algo name>,
-   *                "appid" : <app id>,
-   *                "engineid" : <engine id>,
-   *                "algoinfoid" : <algo info id>,
-   *                "algoinfoname" : <algo info name>,
-   *                "settingsstring" : <algo setting string>
-   *              },
-   *     "metric" : {
-   *                  "id" : <metric id>,
-   *                  "metricsinfoid" : <metric info id>,
-   *                  "metricsname" : <metric info name>,
-   *                  "settingsstring" : <metric setting string>
-   *                },
-   *     "metricscorelist" : [
-   *                           {
-   *                             "algoautotuneid" : <tuned algo id>,
-   *                             "algoinfoname" : <algo info name>,
-   *                             "settingsstring" : <algo setting string>,
-   *                             "score" : <average score>
-   *                           }, ...
-   *                         ],
-   *     "metricscoreiterationlist" : [
-   *                                    [ {
-   *                                        "algoautotuneid" : <tuned algo id 1>,
-   *                                        "algoinfoname" : <algo info name>,
-   *                                        "settingsstring" : <algo setting string>,
-   *                                        "score" : <score of 1st iteration for this tuned algo id>
-   *                                      },
-   *                                      {
-   *                                        "algoautotuneid" : <tuned algo id 2>,
-   *                                        "algoinfoname" : <algo info name>,
-   *                                        "settingsstring" : <algo setting string>,
-   *                                        "score" : <score of 1st iteration for this tuned algo id>
-   *                                      }, ...
-   *                                    ],
-   *                                    [ {
-   *                                        "algoautotuneid" : <tuned algo id 1>,
-   *                                        "algoinfoname" : <algo info name>,
-   *                                        "settingsstring" : <algo setting string>,
-   *                                        "score" : <score of 2nd iteration for this tuned algo id>
-   *                                      },
-   *                                      {
-   *                                        "algoautotuneid" : <tuned algo id 2>,
-   *                                        "algoinfoname" : <algo info name>,
-   *                                        "settingsstring" : <algo setting string>,
-   *                                        "score" : <score of 2nd iteration for this tuned algo id>
-   *                                      }, ...
-   *                                    ], ...
-   *                                  ],
-   *     "splittrain" : <training set split percentage 1 to 100>,
-   *     "splitvalidation" : <validation set split percentage 1 to 100>,
-   *     "splittest" : <test set split percentage 1 to 100>,
-   *     "splitmethod" : <split method string: randome, time>
-   *     "splittersettingsstring" : <splitter setting string>,
-   *     "evaliteration" : <number of iterations>,
-   *     "status" : <auto tune status>,
-   *     "starttime" : <start time>,
-   *     "endtime" : <end time>
-   *   }
-   * }}}
-   *
-   * @param appid the App ID
-   * @param engineid the engine ID
-   * @param algoid the algo ID
-   */
-  def getAlgoAutotuningReport(appid: Int, engineid: Int, algoid: Int) = WithAlgo(appid, engineid, algoid) { (user, app, eng, algo) =>
-    implicit request =>
-
-      algo.offlinetuneid map { tuneid =>
-        offlineTunes.get(tuneid) map { tune =>
-
-          val algoInfo = algoInfos.get(algo.infoid)
-
-          // get all offlineeval of this offlinetuneid
-          val tuneOfflineEvals: Array[OfflineEval] = offlineEvals.getByTuneid(tuneid).toArray.sortBy(_.id)
-
-          val tuneMetrics: Array[OfflineEvalMetric] = tuneOfflineEvals.flatMap { e => offlineEvalMetrics.getByEvalid(e.id) }
-
-          val tuneSplitters: Array[OfflineEvalSplitter] = tuneOfflineEvals.flatMap { e => offlineEvalSplitters.getByEvalid(e.id) }
-
-          // get all offlineeavlresults of each offlineevalid
-          val tuneOfflineEvalResults: Array[OfflineEvalResult] = tuneOfflineEvals.flatMap { e => offlineEvalResults.getByEvalid(e.id) }
-
-          // test set score
-          val tuneOfflineEvalResultsTestSet: Array[OfflineEvalResult] = tuneOfflineEvalResults.filter(x => (x.splitset == "test"))
-
-          val tuneOfflineEvalResultsTestSetAlgoidMap: Map[Int, Double] = tuneOfflineEvalResultsTestSet.map(x => (x.algoid -> x.score)).toMap
-
-          // get all algos of each offlineevalid
-          // note: this happen after getting all available offlineEvalResults,
-          // so these retrieved algos may have more algo than those used in offlineEvalResults.
-          val tuneAlgos: Array[Algo] = tuneOfflineEvals flatMap { e => algos.getByOfflineEvalid(e.id) }
-
-          val tuneAlgosMap: Map[Int, Algo] = tuneAlgos.map { a => (a.id -> a) }.toMap
-
-          // group by (loop, paramset)
-          type AlgoGroupIndex = (Option[Int], Option[Int])
-
-          val tuneAlgosGroup: Map[AlgoGroupIndex, Array[Algo]] = tuneAlgos.groupBy(a => (a.loop, a.paramset))
-
-          // get param of each group
-          val tuneAlgosGroupParams: Map[AlgoGroupIndex, (Int, String, String)] = tuneAlgosGroup.map {
-            case (index, arrayOfAlgos) =>
-              val tAlgo = arrayOfAlgos(0) // just take 1, all algos of this group will have same params
-              val tAlgoInfo: Option[AlgoInfo] = algoInfos.get(tAlgo.infoid)
-              val infoName = tAlgoInfo.map(_.name).getOrElse("Algo info ${tAlgo.infoid} not found")
-              val settings = algoParamToString(tAlgo, tAlgoInfo)
-
-              (index -> (tAlgo.id, settings, infoName))
-          }
-
-          // calculate avg
-          val avgScores: Map[AlgoGroupIndex, String] = tuneAlgosGroup.mapValues { arrayOfAlgos =>
-            // check if all scores available
-            val allAvailable = arrayOfAlgos.map(algo => tuneOfflineEvalResultsTestSetAlgoidMap.contains(algo.id)).reduceLeft(_ && _)
-
-            if (allAvailable) {
-              val scores: Array[Double] = arrayOfAlgos.map(algo => tuneOfflineEvalResultsTestSetAlgoidMap(algo.id))
-
-              (scores.sum / scores.size).toString
-            } else {
-              "N/A"
-            }
-          }
-
-          val metricscorelist = avgScores.toSeq.sortBy(_._1).map {
-            case (k, v) =>
-              Json.obj(
-                "algoautotuneid" -> tuneAlgosGroupParams(k)._1,
-                "algoinfoname" -> tuneAlgosGroupParams(k)._3,
-                "settingsstring" -> tuneAlgosGroupParams(k)._2,
-                "score" -> v)
-          }
-
-          val metricscoreiterationlist = tuneOfflineEvals.map { e =>
-            tuneOfflineEvalResultsTestSet.filter(x => (x.evalid == e.id)).sortBy(_.algoid).map { r =>
-
-              val tAlgo = tuneAlgosMap(r.algoid)
-              val tAlgoInfo: Option[AlgoInfo] = algoInfos.get(tAlgo.infoid)
-              val infoName = tAlgoInfo.map(_.name).getOrElse("Algo info ${tAlgo.infoid} not found")
-
-              Json.obj(
-                "algoautotuneid" -> r.algoid,
-                "algoinfoname" -> infoName,
-                "settingsstring" -> algoParamToString(tAlgo, tAlgoInfo),
-                "score" -> r.score)
-            }.toSeq
-          }.toSeq
-
-          val metric = tuneMetrics(0)
-          val metricInfo = offlineEvalMetricInfos.get(metric.infoid)
-          val splitter = tuneSplitters(0)
-          val splitTrain = ((splitter.settings("trainingPercent").asInstanceOf[Double]) * 100).toInt
-          val splitValidation = ((splitter.settings("validationPercent").asInstanceOf[Double]) * 100).toInt
-          val splitTest = ((splitter.settings("testPercent").asInstanceOf[Double]) * 100).toInt
-          val evalIteration = tuneOfflineEvals.size // NOTE: for autotune, number of offline eval is the iteration
-          val engineinfoid = engines.get(engineid) map { _.infoid } getOrElse { "unkown-engine" }
-
-          val starttime = tune.starttime map (dateTimeToString(_)) getOrElse ("-")
-          val endtime = tune.endtime map (dateTimeToString(_)) getOrElse ("-")
-
-          Ok(Json.obj(
-            "id" -> algoid,
-            "appid" -> appid,
-            "engineid" -> engineid,
-            "algo" -> algoToJson(algo, appid, algoInfo, withParam = true),
-            "metric" -> offlineEvalMetricToJson(metric, metricInfo, withParam = true),
-            "metricscorelist" -> Json.toJson(metricscorelist),
-            "metricscoreiterationlist" -> Json.toJson(metricscoreiterationlist),
-            "splittrain" -> splitTrain,
-            "splitvalidation" -> splitValidation,
-            "splittest" -> splitTest,
-            "splittersettingsstring" -> offlineEvalSplitterParamToString(splitter, offlineEvalSplitterInfos.get(splitter.infoid)),
-            "evaliteration" -> evalIteration,
-            "status" -> getOfflineTuneStatus(tune),
-            "starttime" -> starttime,
-            "endtime" -> endtime
-          ))
-        } getOrElse {
-          InternalServerError(Json.obj("message" -> s"The offline tune id ${tuneid} does not exist."))
-        }
-      } getOrElse {
-        InternalServerError(Json.obj("message" -> "This algo does not have offline tune."))
-      }
-  }
-
-  /**
-   * Applies the selected tuned algo's params to this algo
-   *
-   * {{{
-   * POST
-   * JSON parameters:
-   *   {
-   *     "tunedalgoid" : <the tuned algo id. This algo's parameters will be used>
-   *   }
-   * JSON response:
-   *   If not authenticated:
-   *   Forbidden
-   *   {
-   *     "message" : "Haven't signed in yet."
-   *   }
-   *
-   *   If error:
-   *   BadRequest
-   *   {
-   *     "message" : <error message>
-   *   }
-   *
-   *   If algo not found:
-   *   NotFound
-   *   {
-   *     "message" : <error message>
-   *   }
-   *   If applied:
-   *   Ok
-   *
-   * }}}
-   *
-   * @param appid the App ID
-   * @param engineid the engine ID
-   * @param algoid the algo ID to which the tuned parameters are applied
-   */
-  def algoAutotuningSelect(appid: Int, engineid: Int, algoid: Int) = WithAlgo(appid, engineid, algoid) { (user, app, eng, algo) =>
-    implicit request =>
-
-      // Apply POST request params of tunedalgoid to algoid
-      // update the status of algoid from 'tuning' or 'tuned' to 'ready'
-
-      val form = Form("tunedalgoid" -> number)
-
-      form.bindFromRequest.fold(
-        formWithError => {
-          val msg = formWithError.errors(0).message // extract 1st error message only
-          BadRequest(toJson(Map("message" -> toJson(msg))))
-        },
-        formData => {
-          val tunedAlgoid = formData
-
-          val orgAlgo = algos.get(algoid)
-          val tunedAlgo = algos.get(tunedAlgoid)
-
-          if ((orgAlgo == None) || (tunedAlgo == None)) {
-            NotFound(toJson(Map("message" -> toJson("Invalid app id, engine id or algo id."))))
-          } else {
-            val tunedAlgoParams = tunedAlgo.get.params ++ Map("tune" -> "manual")
-            algos.update(orgAlgo.get.copy(
-              params = tunedAlgoParams,
-              status = "ready"
-            ))
-
-            Ok
-          }
-        }
-      )
-  }
-
-  def getEngineSettings(appid: Int, engineid: Int) = WithEngine(appid, engineid) { (user, app, engine) =>
-    implicit request =>
-      engineInfos.get(engine.infoid) map { engineInfo =>
-        val params = engineInfo.params.mapValues(_.defaultvalue) ++ engine.params
-
-        Ok(toJson(Map(
-          "id" -> toJson(engine.id), // engine id
-          "appid" -> toJson(engine.appid),
-          "allitemtypes" -> toJson(engine.itypes == None),
-          "itemtypelist" -> engine.itypes.map(x => toJson(x.toIterator.toSeq)).getOrElse(JsNull),
-          "trainingdisabled" -> engine.trainingdisabled.map(toJson(_)).getOrElse(toJson(false)),
-          "trainingschedule" -> engine.trainingschedule.map(toJson(_)).getOrElse(toJson("0 0 * * * ?"))) ++
-          (params map { case (k, v) => (k, toJson(v.toString)) })))
-      } getOrElse {
-        NotFound(toJson(Map("message" -> toJson(s"Invalid EngineInfo ID: ${engine.infoid}"))))
-      }
-  }
-
-  def updateEngineSettings(appid: Int, engineid: Int) = WithEngine(appid, engineid) { (user, app, engine) =>
-    implicit request =>
-      val f = Form(tuple(
-        "infoid" -> mapOfStringToAny,
-        "allitemtypes" -> boolean,
-        "itemtypelist" -> list(text),
-        "trainingdisabled" -> boolean,
-        "trainingschedule" -> text))
-      f.bindFromRequest.fold(
-        e => BadRequest(toJson(Map("message" -> toJson(e.toString)))),
-        f => {
-          val (params, allitemtypes, itemtypelist, trainingdisabled, trainingschedule) = f
-          // NOTE: read-modify-write the original param
-          val itypes = if (itemtypelist.isEmpty) None else Option(itemtypelist)
-          val updatedParams = engine.params ++ params - "infoid"
-          val updatedEngine = engine.copy(itypes = itypes, params = updatedParams, trainingdisabled = Some(trainingdisabled), trainingschedule = Some(trainingschedule))
-          engines.update(updatedEngine)
-          WS.url(settingsSchedulerUrl + "/users/" + user.id + "/sync").get()
-          Ok
-        })
-  }
-
-  def getEngineTemplateHtml(appid: Int, engineid: Int) = WithEngine(appid, engineid) { (user, app, engine) =>
-    implicit request =>
-      //Ok(views.html.engines.template(engine.infoid))
-      engineInfos.get(engine.infoid) map { engineInfo =>
-        if (engineInfo.paramsections.isEmpty)
-          Ok(views.html.engines.template(handleParamSections[EngineInfo](Seq(ParamSection(
-            name = "Parameter Settings",
-            description = Some("No extra setting is required for this engine."))), engineInfo, 1), true))
-        else
-          Ok(views.html.engines.template(handleParamSections[EngineInfo](engineInfo.paramsections, engineInfo, 1), false))
-      } getOrElse {
-        NotFound(s"EngineInfo ID ${engine.infoid} not found")
-      }
-  }
-
-  def getEngineTemplateJs(appid: Int, engineid: Int) = WithEngine(appid, engineid) { (user, app, engine) =>
-    implicit request =>
-      Ok(views.js.engines.template(engine.infoid, Seq()))
-      engineInfos.get(engine.infoid) map { engineInfo =>
-        Ok(views.js.engines.template(
-          engineInfo.id,
-          engineInfo.paramsections.map(collectParams(engineInfo, _)).foldLeft(Set[Param]())(_ ++ _).toSeq))
-      } getOrElse {
-        NotFound(s"EngineInfo ID ${engine.infoid} not found")
-      }
-  }
-
-  def getAlgoSettings(appid: Int, engineid: Int, algoid: Int) = WithAlgo(appid, engineid, algoid) { (user, app, engine, algo) =>
-    implicit request =>
-      algoInfos.get(algo.infoid) map { algoInfo =>
-        // get default params from algoinfo and combined with existing params
-        val params = algoInfo.params.mapValues(_.defaultvalue) ++ algo.params
-
-        Ok(toJson(Map(
-          "id" -> toJson(algo.id),
-          "appid" -> toJson(appid),
-          "engineid" -> toJson(engineid)) ++
-          (params map { case (k, v) => (k, toJson(v.toString)) })))
-      } getOrElse {
-        NotFound(toJson(Map("message" -> toJson(s"Invalid AlgoInfo ID: ${algo.infoid}"))))
-      }
-  }
-
-  def updateAlgoSettings(appid: Int, engineid: Int, algoid: Int) = WithAlgo(appid, engineid, algoid) { (user, app, engine, algo) =>
-    implicit request =>
-      val f = Form(tuple("infoid" -> mapOfStringToAny, "tune" -> optional(text), "tuneMethod" -> optional(text)))
-      f.bindFromRequest.fold(
-        e => BadRequest(toJson(Map("message" -> toJson(e.toString)))),
-        bound => {
-          val (params, tune, tuneMethod) = bound
-          // NOTE: read-modify-write the original param
-          val tuneObj = (tune, tuneMethod) match {
-            case (Some("manual"), _) => Map("tune" -> "manual")
-            case (Some("auto"), Some(m)) => Map("tune" -> "auto", "tuneMethod" -> m)
-            case (_, _) => Map()
-          }
-          val updatedParams = algo.params ++ params ++ tuneObj - "infoid"
-          val updatedAlgo = algo.copy(params = updatedParams)
-
-          // NOTE: "tune" is optional param. default to "manual"
-          if (updatedParams.getOrElse("tune", "manual") != "auto") {
-            algos.update(updatedAlgo)
-            Ok
-          } else {
-            // create offline eval with baseline algo
-            // TODO: get from UI
-            val defaultBaseLineAlgoType = engine.infoid match {
-              case "itemrec" => "pio-itemrec-single-random"
-              case "itemsim" => "pio-itemsim-single-random"
-            }
-
-            engineInfos.get(engine.infoid).map { engineInfo =>
-              val hadoopRequired = algoInfos.get(algo.infoid) map { _.techreq.contains("Hadoop") } getOrElse false
-              val metricinfoid = (hadoopRequired, engine.infoid) match {
-                case (true, "itemrec") => "pio-itemrec-distributed-map_k"
-                case (true, "itemsim") => "pio-itemsim-distributed-ismap_k"
-                case (false, "itemrec") => "pio-itemrec-single-map_k"
-                case (false, "itemsim") => "pio-itemsim-single-ismap_k"
-              } // TODO: from UI
-              val splitterinfoid = if (hadoopRequired) "pio-distributed-trainingtestsplit" else "pio-single-trainingtestsplit" // TODO: from UI
-              algoInfos.get(defaultBaseLineAlgoType).map { baseLineAlgoInfo =>
-                offlineEvalMetricInfos.get(metricinfoid).map { metricInfo =>
-                  offlineEvalSplitterInfos.get(splitterinfoid).map { splitterInfo =>
-
-                    // delete previous offlinetune stuff if the algo's offlinetuneid != None
-                    if (updatedAlgo.offlinetuneid != None) {
-                      val tuneid = updatedAlgo.offlinetuneid.get
-
-                      offlineTunes.get(tuneid) map { tune =>
-                        /** Make sure to unset offline tune's creation time to prevent scheduler from picking up */
-                        offlineTunes.update(tune.copy(createtime = None))
-
-                        // TODO: check scheduler err
-                        Helper.stopAndDeleteOfflineTuneScheduler(appid.toInt, engineid.toInt, tuneid)
-                        Future {
-                          Helper.deleteOfflineTune(tuneid, keepSettings = false)
-                        }
-                      }
-                    }
-
-                    // auto tune
-                    algos.update(updatedAlgo)
-
-                    // create an OfflineTune and paramGen
-                    val offlineTune = OfflineTune(
-                      id = -1,
-                      engineid = updatedAlgo.engineid,
-                      loops = 5, // TODO: default 5 now
-                      createtime = None, // NOTE: no createtime yet
-                      starttime = None,
-                      endtime = None
-                    )
-
-                    val tuneid = offlineTunes.insert(offlineTune)
-                    Logger.info("Create offline tune ID " + tuneid)
-
-                    paramGens.insert(ParamGen(
-                      id = -1,
-                      infoid = "pio-single-random", // TODO: default random scan param gen now
-                      tuneid = tuneid,
-                      params = Map() // TODO: param for param gen
-                    ))
-
-                    // update original algo status to tuning
-                    algos.update(updatedAlgo.copy(
-                      offlinetuneid = Some(tuneid),
-                      status = "tuning"
-                    ))
-
-                    val baseLineAlgo = Algo(
-                      id = -1,
-                      engineid = updatedAlgo.engineid,
-                      name = "Default-BasedLine-Algo-for-OfflineTune-" + tuneid,
-                      infoid = baseLineAlgoInfo.id,
-                      command = "",
-                      params = baseLineAlgoInfo.params.mapValues(_.defaultvalue),
-                      settings = Map(), // no use for now
-                      modelset = false, // init value
-                      createtime = DateTime.now,
-                      updatetime = DateTime.now,
-                      status = "simeval",
-                      offlineevalid = None,
-                      offlinetuneid = Some(tuneid),
-                      loop = Some(0), // loop=0 reserved for autotune baseline
-                      paramset = None
-                    )
-
-                    val metric = OfflineEvalMetric(
-                      id = 0,
-                      infoid = metricInfo.id,
-                      evalid = 0, // will be assigned later
-                      params = metricInfo.params.mapValues(_.defaultvalue)
-                    )
-
-                    // percentage param is standard for all splitter
-                    // TODO: hardcode percentage for auto tune for now. get from UI
-                    val percentageParam = Map(
-                      "trainingPercent" -> 0.55,
-                      "validationPercent" -> 0.2,
-                      "testPercent" -> 0.2
-                    )
-
-                    val splitter = OfflineEvalSplitter(
-                      id = 0,
-                      evalid = 0, // will be assigned later
-                      name = "", // will be assigned later
-                      infoid = splitterInfo.id,
-                      settings = splitterInfo.params.mapValues(_.defaultvalue) ++ percentageParam
-                    )
-
-                    // TODO: get iterations, metric info, etc from UI, now hardcode to 3.
-                    for (i <- 1 to 3) {
-                      createOfflineEval(engine, List(baseLineAlgo), List(metric), splitter, 1, Some(tuneid))
-                    }
-
-                    // after everything has setup,
-                    // update with createtime, so scheduler can know it's ready to be picked up
-                    offlineTunes.update(offlineTune.copy(
-                      id = tuneid,
-                      createtime = Some(DateTime.now)
-                    ))
-
-                    // call sync to scheduler here
-                    WS.url(settingsSchedulerUrl + "/users/" + user.id + "/sync").get()
-
-                    Ok
-
-                  }.getOrElse(InternalServerError(Json.obj("message" -> s"OfflineEvalSplitterInfo ID ${splitterinfoid} not found.")))
-                }.getOrElse(InternalServerError(Json.obj("message" -> s"OfflineEvalMetricInfo ID ${metricinfoid} not found.")))
-              }.getOrElse(InternalServerError(Json.obj("message" -> s"AlgoInfo ID ${defaultBaseLineAlgoType} not found.")))
-            }.getOrElse(InternalServerError(Json.obj("message" -> s"EngineInfo ID ${engine.infoid} not found.")))
-          }
-        })
-  }
-
-  def getAlgoTemplateHtml(appid: Int, engineid: Int, algoid: Int) = WithAlgo(appid, engineid, algoid) { (user, app, engine, algo) =>
-    implicit request =>
-      algoInfos.get(algo.infoid) map { algoInfo =>
-        if (algoInfo.paramsections.isEmpty)
-          Ok(views.html.algos.template(handleParamSections[AlgoInfo](Seq(ParamSection(
-            name = "Parameter Settings",
-            description = Some("No extra setting is required for this algorithm."))), algoInfo, 1), true))
-        else
-          Ok(views.html.algos.template(handleParamSections[AlgoInfo](algoInfo.paramsections, algoInfo, 1), false))
-      } getOrElse {
-        NotFound(s"AlgoInfo ID ${algo.infoid} not found")
-      }
-  }
-
-  def getAlgoTemplateJs(appid: Int, engineid: Int, algoid: Int) = WithAlgo(appid, engineid, algoid) { (user, app, engine, algo) =>
-    implicit request =>
-      algoInfos.get(algo.infoid) map { algoInfo =>
-        Ok(views.js.algos.template(
-          algoInfo.id,
-          algoInfo.paramsections.map(collectParams(algoInfo, _)).foldLeft(Set[Param]())(_ ++ _).toSeq,
-          algoInfo.paramsections.map(collectParams(algoInfo, _, true)).foldLeft(Set[Param]())(_ ++ _).toSeq))
-      } getOrElse {
-        NotFound(s"AlgoInfo ID ${algo.infoid} not found")
-      }
-  }
-
-  def getMetricInfoTemplateHtml(engineinfoid: String, metricinfoid: String) = WithUser { user =>
-    implicit request =>
-      offlineEvalMetricInfos.get(metricinfoid) map { metricInfo =>
-        if (metricInfo.paramsections.isEmpty)
-          Ok(views.html.metrics.template(handleParamSections[OfflineEvalMetricInfo](Seq(ParamSection(
-            name = "Parameter Settings",
-            description = Some("No extra setting is required for this metric."))), metricInfo, 1), true))
-        else
-          Ok(views.html.metrics.template(handleParamSections[OfflineEvalMetricInfo](metricInfo.paramsections, metricInfo, 1), false))
-      } getOrElse {
-        NotFound(s"OfflineEvalMetricInfo ID ${metricinfoid} not found")
-      }
-  }
-
-  def getSplitterInfoTemplateHtml(engineinfoid: String, splitterinfoid: String) = WithUser { user =>
-    implicit request =>
-      offlineEvalSplitterInfos.get(splitterinfoid) map { splitterInfo =>
-        if (splitterInfo.paramsections.isEmpty)
-          Ok(views.html.splitters.template(handleParamSections[OfflineEvalSplitterInfo](Seq(ParamSection(
-            name = "Parameter Settings",
-            description = Some("No extra setting is required for this splitter."))), splitterInfo, 1), true))
-        else
-          Ok(views.html.splitters.template(handleParamSections[OfflineEvalSplitterInfo](splitterInfo.paramsections, splitterInfo, 1), false))
-      } getOrElse {
-        NotFound(s"OfflineEvalSplitterInfo ID ${splitterinfoid} not found")
-      }
-  }
-
-  def collectParams[T <: Info](info: T, paramsection: ParamSection, tuning: Boolean = false): Set[Param] = {
-    if (tuning)
-      if (paramsection.sectiontype == "tuning")
-        paramsection.params.map(_.map(info.params(_)).toSet).getOrElse(Set()) ++
-          paramsection.subsections.map(_.map(collectParams(info, _, false)).reduce(_ ++ _)).getOrElse(Set())
-      else
-        paramsection.subsections.map(_.map(collectParams(info, _, tuning)).reduce(_ ++ _)).getOrElse(Set())
-    else
-      paramsection.params.map(_.map(info.params(_)).toSet).getOrElse(Set()) ++
-        paramsection.subsections.map(_.map(collectParams(info, _, tuning)).reduce(_ ++ _)).getOrElse(Set())
-  }
-
-  def handleParam[T <: Info](param: Param, info: T, tuning: Boolean = false): String = {
-    val content = param.ui.uitype match {
-      case "selection" =>
-        uiSelection[T](info, param.id, param.name, param.description, param.ui.selections.map(_.map(s => (s.name, s.value))).get, Some(param.defaultvalue.toString))
-      case "slider" =>
-        uiSlider[T](info, param.id, param.name, param.description)
-      case _ =>
-        if (tuning)
-          uiTextPair[T](info, param.id + "Min", param.id + "Max", param.name, param.description)
-        else
-          uiText[T](info, param.id, param.name, param.description, Some(param.defaultvalue.toString))
-    }
-    content.toString
-  }
-
-  def handleParamSections[T <: Info](paramsections: Seq[ParamSection], info: T, level: Int, tuning: Boolean = false): String = {
-    paramsections map { paramsection =>
-      if (paramsection.sectiontype == "tuning")
-        views.html.algos.sectionmanualauto(
-          paramsection.name,
-          handleParamSectionContent[T](paramsection, info, level),
-          handleParamSectionContent[T](paramsection, info, level, true))
-      else if (level > 1)
-        uiSection2[T](info, paramsection.name, paramsection.description, handleParamSectionContent[T](paramsection, info, level, tuning))
-      else
-        uiSection1[T](info, paramsection.name, paramsection.description, handleParamSectionContent[T](paramsection, info, level, tuning))
-    } mkString ""
-  }
-
-  def handleParamSectionContent[T <: Info](paramsection: ParamSection, info: T, level: Int, tuning: Boolean = false) = {
-    paramsection.params.map(_.map(p => handleParam[T](info.params(p), info, tuning)).mkString).getOrElse("") +
-      paramsection.subsections.map(handleParamSections[T](_, info, level + 1, tuning)).getOrElse("")
-  }
-
-  def uiText[T <: Info](info: T, id: String, name: String, description: Option[String], defaultValue: Option[String] = None) = {
-    info match {
-      case _: AlgoInfo =>
-        views.html.algos.text(id, name, description)
-      case _: EngineInfo =>
-        views.html.engines.text(id, name, description)
-      case _: OfflineEvalMetricInfo =>
-        views.html.metrics.text(id, name, description, defaultValue)
-      case _: OfflineEvalSplitterInfo =>
-        views.html.splitters.text(id, name, description, defaultValue)
-    }
-  }
-
-  def uiTextPair[T <: Info](info: T, id1: String, id2: String, name: String, description: Option[String]) = {
-    views.html.algos.textpair(id1, id2, name, description)
-  }
-
-  def uiSlider[T <: Info](info: T, id: String, name: String, description: Option[String]) = {
-    views.html.engines.slider(id, name, description)
-  }
-
-  def uiSelection[T <: Info](info: T, id: String, name: String, description: Option[String], selections: Seq[(String, String)], defaultValue: Option[String] = None) = {
-    info match {
-      case _: AlgoInfo =>
-        views.html.algos.selection(id, name, description, selections)
-      case _: EngineInfo =>
-        views.html.engines.selection(id, name, description, selections)
-      case _: OfflineEvalMetricInfo =>
-        views.html.metrics.selection(id, name, description, selections, defaultValue)
-      case _: OfflineEvalSplitterInfo =>
-        views.html.splitters.selection(id, name, description, selections, defaultValue)
-    }
-  }
-
-  def uiSection1[T <: Info](info: T, name: String, description: Option[String], content: String) = {
-    info match {
-      case _: AlgoInfo =>
-        views.html.algos.section1(name, description, content)
-      case _: EngineInfo =>
-        views.html.engines.section1(name, description, content)
-      case _: OfflineEvalMetricInfo =>
-        views.html.metrics.section1(name, description, content)
-      case _: OfflineEvalSplitterInfo =>
-        views.html.splitters.section1(name, description, content)
-    }
-  }
-
-  def uiSection2[T <: Info](info: T, name: String, description: Option[String], content: String) = {
-    info match {
-      case _: AlgoInfo =>
-        views.html.algos.section2(name, description, content)
-      case _: EngineInfo =>
-        views.html.engines.section2(name, description, content)
-      // OfflineEvalMetricInfo doesn't support section2
-      // OfflineEvalSplitterInfo doesn't support section2
-    }
-  }
-}
diff --git a/servers/admin/app/controllers/Forms.scala b/servers/admin/app/controllers/Forms.scala
deleted file mode 100644
index cafe158..0000000
--- a/servers/admin/app/controllers/Forms.scala
+++ /dev/null
@@ -1,95 +0,0 @@
-package controllers
-
-import io.prediction.commons.settings.{ AlgoInfo, AlgoInfos, EngineInfo, EngineInfos, Param }
-
-import play.api.data._
-import play.api.data.Forms._
-import play.api.data.validation._
-import play.api.data.format._
-
-object Forms {
-  def mapOfStringToAny: Mapping[Map[String, Any]] = of[Map[String, Any]]
-  def seqOfMapOfStringToAny: Mapping[Seq[Map[String, Any]]] = of[Seq[Map[String, Any]]]
-
-  private val infotypeKey = "infotype"
-  private val scopeKey = "scope"
-
-  private def scoped(scope: Option[String], scopes: Option[Set[String]], result: Either[Seq[FormError], Map[String, Any]]): Either[Seq[FormError], Map[String, Any]] = {
-    val resultOrEmpty = result match {
-      case Right(s) => Right(s)
-      case Left(s) => Right(Map[String, Any]())
-    }
-
-    (scope, scopes) match {
-      case (Some(s), Some(ss)) => if (ss(s)) result else resultOrEmpty
-      case _ => result
-    }
-  }
-
-  implicit def mapOfStringToAnyFormat: Formatter[Map[String, Any]] = new Formatter[Map[String, Any]] {
-    def bind(key: String, data: Map[String, String]) = {
-      data.get(infotypeKey) map { infotype =>
-        data.get(key) map { id =>
-          bindParams(key, infotypeKey, infotype, id, data, None)
-        } getOrElse Left(Seq(FormError(key, "error.required", Nil)))
-      } getOrElse Left(Seq(FormError(infotypeKey, "error.required", Nil)))
-    }
-
-    def unbind(key: String, value: Map[String, Any]) = Map(key -> value(key).toString)
-  }
-
-  implicit def seqOfMapOfStringToAnyFormat: Formatter[Seq[Map[String, Any]]] = new Formatter[Seq[Map[String, Any]]] {
-    def bind(key: String, data: Map[String, String]) = {
-      // Get available indexes of infotypeKey first.
-      val results = RepeatedMapping.indexes(infotypeKey, data) map { i =>
-        val infotype = data.get(infotypeKey + "[" + i + "]").get
-        data.get(key + "[" + i + "]") map { id =>
-          bindParams(key, infotypeKey, infotype, id, data, Some(i))
-        } getOrElse Left(Seq(FormError(key + "[" + i + "]", "error.required", Nil)))
-      }
-
-      if (results.forall(_.isRight)) {
-        Right(results.map(_.right.get))
-      } else {
-        Left(results.collect { case Left(errors) => errors }.flatten)
-      }
-    }
-
-    def unbind(key: String, value: Seq[Map[String, Any]]) = {
-      (for ((v, i) <- value.zipWithIndex) yield Map(key + "[" + i + "]" -> v(key).toString)).reduce(_ ++ _)
-    }
-  }
-
-  private def bindParams(key: String, infotypeKey: String, infotype: String, infoid: String, data: Map[String, String], index: Option[Int]): Either[Seq[FormError], Map[String, Any]] = {
-    val indexedKey = index map { key + "[" + _ + "]" } getOrElse key
-    val indexedInfotypeKey = index map { infotypeKey + "[" + _ + "]" } getOrElse infotypeKey
-    val infoParams = infotype match {
-      case "algo" => Some(Application.algoInfos.get(infoid) map { _.params })
-      case "engine" => Some(Application.engineInfos.get(infoid) map { _.params })
-      case "offlineevalmetric" => Some(Application.offlineEvalMetricInfos.get(infoid) map { _.params })
-      case "offlineevalsplitter" => Some(Application.offlineEvalSplitterInfos.get(infoid) map { _.params })
-      case _ => None
-    }
-
-    infoParams map { someParams =>
-      someParams map { params =>
-        val allErrorsOrItems: Seq[Either[Seq[FormError], Map[String, Any]]] = params.toSeq map { param =>
-          val indexedParamKey = index map { param._1 + "[" + _ + "]" } getOrElse param._1
-          param._2.constraint.paramtype match {
-            case "integer" => scoped(data.get(scopeKey), param._2.scopes, Formats.intFormat.bind(indexedParamKey, data).right.map(d => Map[String, Any](param._1 -> d)))
-            case "long" => scoped(data.get(scopeKey), param._2.scopes, Formats.longFormat.bind(indexedParamKey, data).right.map(d => Map[String, Any](param._1 -> d)))
-            case "boolean" => scoped(data.get(scopeKey), param._2.scopes, Formats.booleanFormat.bind(indexedParamKey, data).right.map(d => Map[String, Any](param._1 -> d)))
-            case "string" => scoped(data.get(scopeKey), param._2.scopes, Formats.stringFormat.bind(indexedParamKey, data).right.map(d => Map[String, Any](param._1 -> d)))
-            case "double" => scoped(data.get(scopeKey), param._2.scopes, Formats.doubleFormat.bind(indexedParamKey, data).right.map(d => Map[String, Any](param._1 -> d)))
-            case _ => scoped(data.get(scopeKey), param._2.scopes, Left(Seq(FormError(indexedParamKey, "error.invalidconstraint", Nil))))
-          }
-        }
-        if (allErrorsOrItems.forall(_.isRight)) {
-          Right(((Map[String, Any](key -> infoid, infotypeKey -> infotype) /: allErrorsOrItems.map(_.right.get))((a, b) => a ++ b)))
-        } else {
-          Left(allErrorsOrItems.collect { case Left(errors) => errors }.flatten)
-        }
-      } getOrElse Left(Seq(FormError(indexedKey, "error.invalid", Nil)))
-    } getOrElse Left(Seq(FormError(indexedInfotypeKey, "error.invalid", Nil)))
-  }
-}
diff --git a/servers/admin/app/controllers/Helper.scala b/servers/admin/app/controllers/Helper.scala
deleted file mode 100644
index 7409203..0000000
--- a/servers/admin/app/controllers/Helper.scala
+++ /dev/null
@@ -1,602 +0,0 @@
-package controllers
-
-import play.api.Logger
-
-import Application.{ users, apps, engines, engineInfos, algos, algoInfos }
-import Application.{ offlineEvalMetricInfos, offlineEvals, offlineEvalMetrics, offlineEvalResults }
-import Application.{ offlineEvalSplitters, offlineTunes, paramGens }
-import Application.{ appDataUsers, appDataItems, appDataU2IActions }
-import Application.{ trainingSetUsers, trainingSetItems, trainingSetU2IActions }
-import Application.{ validationSetUsers, validationSetItems, validationSetU2IActions }
-import Application.{ testSetUsers, testSetItems, testSetU2IActions }
-import Application.{ itemRecScores, itemSimScores }
-import Application.{ trainingItemRecScores, trainingItemSimScores }
-import Application.settingsSchedulerUrl
-
-import io.prediction.commons.settings.{ Algo, Engine }
-import io.prediction.commons.settings.{ OfflineEval, OfflineTune, OfflineEvalMetric, OfflineEvalSplitter }
-import io.prediction.commons.settings.{ AlgoInfo, OfflineEvalMetricInfo, OfflineEvalSplitterInfo }
-
-import play.api.libs.concurrent.Execution.Implicits._
-import play.api.libs.ws.WS
-import play.api.mvc.Controller
-import play.api.libs.json.{ JsNull, JsArray, Json, JsValue, Writes, JsObject }
-import play.api.http
-
-import com.github.nscala_time.time.Imports._
-
-/** helper functions */
-object Helper extends Controller {
-
-  /** Check if the offlineEval is simeval */
-  def isSimEval(eval: OfflineEval): Boolean = (eval.tuneid == None)
-
-  /** check if this simeval is pending */
-  def isPendingSimEval(eval: OfflineEval): Boolean = isSimEval(eval) && (eval.createtime != None) && (eval.endtime == None)
-
-  /** Check if this offline tune is pending */
-  def isPendingOfflineTune(tune: OfflineTune): Boolean = (tune.createtime != None) && (tune.endtime == None)
-
-  /** Check if algo is available */
-  def isAvailableAlgo(algo: Algo): Boolean = !((algo.status == "deployed") || (algo.status == "simeval"))
-
-  def isSimEvalAlgo(algo: Algo): Boolean = (algo.status == "simeval")
-
-  /** Return sim evals of this engine */
-  def getSimEvalsByEngineid(engineid: Int): Iterator[OfflineEval] = offlineEvals.getByEngineid(engineid).filter(isSimEval(_))
-
-  def getSimEvalStatus(eval: OfflineEval): String = {
-    val status = (eval.createtime, eval.starttime, eval.endtime) match {
-      case (Some(x), Some(y), Some(z)) => "completed"
-      case (Some(x), Some(y), None) => "running"
-      case (Some(x), None, Some(z)) => "internal error"
-      case (Some(x), None, None) => "pending"
-      case (None, _, _) => "canceled"
-    }
-    status
-  }
-
-  def getOfflineTuneStatus(tune: OfflineTune): String = {
-    val status: String = (tune.createtime, tune.starttime, tune.endtime) match {
-      case (Some(x), Some(y), Some(z)) => "completed"
-      case (Some(x), Some(y), None) => "running"
-      case (Some(x), None, Some(z)) => "internal error"
-      case (Some(x), None, None) => "pending"
-      case (None, _, _) => "canceled"
-    }
-    status
-  }
-  /**
-   * Convert algo data to JsObject
-   *   {
-   *     "id" : <algo id>,
-   *     "algoname" : <algo name>,
-   *     "appid" : <app id>,
-   *     "engineid" : <engine id>,
-   *     "algoinfoid" : <algo info id>,
-   *     "algoinfoname" : <algo info name>,
-   *     "status" : <algo status>,
-   *     "createdtime" : <algo creation time>,
-   *     "updatedtime" : <algo last updated time>
-   *   }
-   * @note status: ready, deployed, tuning, tuned, simeval
-   * @param algo the algo
-   * @param appid the App ID
-   * @param algoinfo AlgoInfo
-   */
-  def algoToJson(algo: Algo, appid: Int, algoinfoOpt: Option[AlgoInfo], withParam: Boolean = false): JsObject = {
-    val infoname = algoinfoOpt.map(_.name).getOrElse[String](s"algoinfo ${algo.infoid} not found")
-
-    if (withParam)
-      Json.obj(
-        "id" -> algo.id,
-        "algoname" -> algo.name,
-        "appid" -> appid,
-        "engineid" -> algo.engineid,
-        "algoinfoid" -> algo.infoid,
-        "algoinfoname" -> infoname,
-        "settingsstring" -> algoParamToString(algo, algoinfoOpt)
-      )
-    else
-      Json.obj(
-        "id" -> algo.id,
-        "algoname" -> algo.name,
-        "appid" -> appid,
-        "engineid" -> algo.engineid,
-        "algoinfoid" -> algo.infoid,
-        "algoinfoname" -> infoname,
-        "status" -> algo.status,
-        "createdtime" -> dateTimeToString(algo.createtime),
-        "updatedtime" -> dateTimeToString(algo.updatetime)
-      )
-  }
-
-  def offlineEvalMetricToJson(metric: OfflineEvalMetric, metricinfoOpt: Option[OfflineEvalMetricInfo], withParam: Boolean = false): JsObject = {
-    val infoname = metricinfoOpt.map(_.name).getOrElse[String](s"offlineevalmetricinfo ${metric.infoid} not found")
-    if (withParam)
-      Json.obj(
-        "id" -> metric.id,
-        "metricsinfoid" -> metric.infoid,
-        "metricsname" -> infoname,
-        "settingsstring" -> offlineEvalMetricParamToString(metric, metricinfoOpt)
-      )
-    else
-      Json.obj(
-        "id" -> metric.id,
-        "metricsinfoid" -> metric.infoid,
-        "metricsname" -> infoname
-      )
-  }
-
-  def algoParamToString(algo: Algo, algoinfoOpt: Option[AlgoInfo]): String = {
-    algoinfoOpt.map { algoInfo =>
-      algoInfo.paramorder.map { paramid =>
-        algoInfo.params(paramid).name + " = " +
-          algo.params.getOrElse(paramid, algoInfo.params(paramid).defaultvalue)
-      }.mkString(", ")
-    }.getOrElse(s"algoinfo ${algo.infoid} not found")
-  }
-
-  def offlineEvalMetricParamToString(metric: OfflineEvalMetric, metricinfoOpt: Option[OfflineEvalMetricInfo]): String = {
-    metricinfoOpt.map { metricInfo =>
-      metricInfo.paramorder.map { paramid =>
-        metricInfo.params(paramid).name + " = " +
-          metric.params.getOrElse(paramid, metricInfo.params(paramid).defaultvalue)
-      }.mkString(", ")
-    }.getOrElse(s"offlineevalmetricinfo ${metric.infoid} not found")
-  }
-
-  def offlineEvalSplitterParamToString(splitter: OfflineEvalSplitter, splitterinfoOpt: Option[OfflineEvalSplitterInfo]): String = {
-    splitterinfoOpt.map { splitterInfo =>
-      splitterInfo.paramorder.map { paramid =>
-        val param = splitterInfo.params(paramid)
-
-        val value = splitter.settings.getOrElse(paramid, splitterInfo.params(paramid).defaultvalue)
-        val displayValue = param.ui.uitype match {
-          // if selection, display the name of the selection instead of value.
-          case "selection" => {
-            val names: Map[String, String] = param.ui.selections.map(_.map(s => (s.value, s.name)).toMap[String, String]).getOrElse(Map[String, String]())
-            names.getOrElse(value.toString, value.toString)
-          }
-          case _ => value
-        }
-        splitterInfo.params(paramid).name + ": " + displayValue
-      }.mkString(", ")
-    }.getOrElse(s"OfflineEvalSplitterInfo ${splitter.infoid} not found")
-  }
-
-  val timeFormat = DateTimeFormat.forPattern("yyyy-MM-dd hh:mm:ss a z")
-
-  def dateTimeToString(t: DateTime, zoneName: String = "UTC"): String =
-    timeFormat.print(t.withZone(DateTimeZone.forID(zoneName)))
-
-  /**
-   * Common function to create Offline Evaluation for sim eval or auto tune
-   * @param engine Engine
-   * @param algoList List of Algo
-   * @param metricList List of OfflineEvalMetric
-   * @param splitter OfflineEvalSplitter
-   * @param evalIteration number of iteration
-   * @param tuneid specify offline tune id if this Offine Eval is for auto tune
-   * @param the created OfflineEval ID
-   */
-  def createOfflineEval(engine: Engine, algoList: List[Algo], metricList: List[OfflineEvalMetric], splitter: OfflineEvalSplitter, evalIteration: Int, tuneid: Option[Int] = None): Int = {
-
-    // insert offlineeval record without create time
-    val newOfflineEval = OfflineEval(
-      id = 0,
-      engineid = engine.id,
-      name = "",
-      iterations = evalIteration,
-      tuneid = tuneid,
-      createtime = None, // NOTE: no createtime yet
-      starttime = None,
-      endtime = None
-    )
-
-    val evalid = offlineEvals.insert(newOfflineEval)
-    Logger.info("Create offline eval ID " + evalid)
-
-    // duplicate algo with evalid
-    for (algo <- algoList) {
-      // duplicate algo for sim eval
-      val algoid = algos.insert(algo.copy(
-        id = 0,
-        offlineevalid = Option(evalid),
-        status = "simeval"
-      ))
-      Logger.info("Create sim eval algo ID " + algoid)
-    }
-
-    for (metric <- metricList) {
-      val metricid = offlineEvalMetrics.insert(metric.copy(
-        id = 0,
-        evalid = evalid
-      ))
-      Logger.info("Create metric ID " + metricid)
-    }
-
-    // create splitter record
-    val splitterid = offlineEvalSplitters.insert(splitter.copy(
-      evalid = evalid,
-      name = ("sim-eval-" + evalid + "-splitter")
-    ))
-    Logger.info("Create offline eval splitter ID " + splitterid)
-
-    // after all algo and metric info is stored.
-    // update offlineeval record with createtime, so scheduler can know it's ready to be picked up
-    offlineEvals.update(newOfflineEval.copy(
-      id = evalid,
-      name = ("sim-eval-" + evalid),
-      createtime = Option(DateTime.now)
-    ))
-
-    evalid
-  }
-
-  /**
-   * Delete appdata DB of this appid
-   */
-  def deleteAppData(appid: Int) = {
-    Logger.info("Delete appdata for app ID " + appid)
-    appDataUsers.deleteByAppid(appid)
-    appDataItems.deleteByAppid(appid)
-    appDataU2IActions.deleteByAppid(appid)
-  }
-
-  /**
-   * Delete training set data of this evalid
-   */
-  def deleteTrainingSetData(evalid: Int) = {
-    Logger.info("Delete training set for offline eval ID " + evalid)
-    trainingSetUsers.deleteByAppid(evalid)
-    trainingSetItems.deleteByAppid(evalid)
-    trainingSetU2IActions.deleteByAppid(evalid)
-  }
-
-  /**
-   * Delete validation set data of this evalid
-   */
-  def deleteValidationSetData(evalid: Int) = {
-    Logger.info("Delete validation set for offline eval ID " + evalid)
-    validationSetUsers.deleteByAppid(evalid)
-    validationSetItems.deleteByAppid(evalid)
-    validationSetU2IActions.deleteByAppid(evalid)
-  }
-
-  /**
-   * Delete test set data of this evalid
-   */
-  def deleteTestSetData(evalid: Int) = {
-    Logger.info("Delete test set for offline eval ID " + evalid)
-    testSetUsers.deleteByAppid(evalid)
-    testSetItems.deleteByAppid(evalid)
-    testSetU2IActions.deleteByAppid(evalid)
-  }
-
-  /**
-   * Delete modeldata of this algoid
-   */
-  def deleteModelData(algoid: Int) = {
-    val algoOpt = algos.get(algoid)
-    algoOpt map { algo =>
-      algoInfos.get(algo.infoid) map { algoInfo =>
-        if (algo.status == "simeval") {
-          Logger.info("Delete training model data for algo ID " + algoid)
-          algoInfo.engineinfoid match {
-            case "itemrec" | "itemrank" => trainingItemRecScores.deleteByAlgoid(algoid)
-            case "itemsim" => trainingItemSimScores.deleteByAlgoid(algoid)
-            case _ => throw new RuntimeException("Try to delete algo of unsupported engine type: " + algoInfo.engineinfoid)
-          }
-        } else {
-          Logger.info("Delete model data for algo ID " + algoid)
-          algoInfo.engineinfoid match {
-            case "itemrec" | "itemrank" => itemRecScores.deleteByAlgoid(algoid)
-            case "itemsim" => itemSimScores.deleteByAlgoid(algoid)
-            case _ => throw new RuntimeException("Try to delete algo of unsupported engine type: " + algoInfo.engineinfoid)
-          }
-        }
-      } getOrElse { throw new RuntimeException("Try to delete algo of non-existing algotype: " + algo.infoid) }
-    }
-  }
-
-  /**
-   * Delete this app and the assoicated engines and appdata
-   * @param appid the appid
-   * @param userid the userid
-   * @param keepSettings keepSettings flag. If this is true, keep all settings record (ie. only delete the appdata, modeldata)
-   */
-  def deleteApp(appid: Int, userid: Int, keepSettings: Boolean) = {
-
-    val appEngines = engines.getByAppid(appid)
-
-    appEngines foreach { eng =>
-      deleteEngine(eng.id, appid, keepSettings)
-    }
-
-    deleteAppData(appid)
-
-    if (!keepSettings) {
-      Logger.info("Delete app ID " + appid)
-      apps.deleteByIdAndUserid(appid, userid)
-    }
-  }
-
-  /**
-   * Delete engine and the associated algos and simevals.
-   */
-  def deleteEngine(engineid: Int, appid: Int, keepSettings: Boolean) = {
-
-    // delete non-sim eval algos, "simeval" algo is deleted when delete sim eval later
-    val engineAlgos = algos.getByEngineid(engineid).filter(!isSimEvalAlgo(_))
-
-    engineAlgos foreach { algo =>
-      deleteAlgo(algo.id, keepSettings)
-    }
-
-    val simEvals = getSimEvalsByEngineid(engineid)
-
-    simEvals foreach { eval =>
-      deleteOfflineEval(eval.id, keepSettings)
-    }
-
-    if (!keepSettings) {
-      Logger.info("Delete engine ID " + engineid)
-      engines.deleteByIdAndAppid(engineid, appid)
-    }
-  }
-
-  /**
-   * Delete non-simeval algo and associated modeldata, offlineTune
-   */
-  def deleteAlgo(algoid: Int, keepSettings: Boolean) = {
-    deleteModelData(algoid)
-
-    algos.get(algoid) map { algo =>
-      algo.offlinetuneid map { tuneid =>
-        deleteOfflineTune(tuneid, keepSettings)
-      }
-    }
-
-    if (!keepSettings) {
-      Logger.info("Delete algo ID " + algoid)
-      algos.delete(algoid)
-    }
-  }
-
-  /** Delete "simeval" algo and assoicated modeldata */
-  def deleteSimEvalAlgo(algoid: Int, keepSettings: Boolean) = {
-    deleteModelData(algoid)
-
-    if (!keepSettings) {
-      Logger.info("Delete simeval algo ID " + algoid)
-      algos.delete(algoid)
-    }
-  }
-
-  /**
-   * Delete offline tune and associated trainig/validation/test set data, evaluated algos, metrics, eval results, and splitters
-   */
-  def deleteOfflineEval(evalid: Int, keepSettings: Boolean) = {
-
-    deleteTrainingSetData(evalid)
-    deleteValidationSetData(evalid)
-    deleteTestSetData(evalid)
-
-    val evalAlgos = algos.getByOfflineEvalid(evalid)
-
-    evalAlgos foreach { algo =>
-      deleteSimEvalAlgo(algo.id, keepSettings)
-    }
-
-    if (!keepSettings) {
-      val evalMetrics = offlineEvalMetrics.getByEvalid(evalid)
-
-      evalMetrics foreach { metric =>
-        Logger.info("Delete metric ID " + metric.id)
-        offlineEvalMetrics.delete(metric.id)
-      }
-
-      Logger.info("Delete offline eval results of offline eval ID " + evalid)
-      offlineEvalResults.deleteByEvalid(evalid)
-
-      val evalSplitters = offlineEvalSplitters.getByEvalid(evalid)
-      evalSplitters foreach { splitter =>
-        Logger.info("Delete Offline Eval Splitter ID " + splitter.id)
-        offlineEvalSplitters.delete(splitter.id)
-      }
-    }
-
-    if (!keepSettings) {
-      Logger.info("Delete offline eval ID " + evalid)
-      offlineEvals.delete(evalid)
-    }
-
-  }
-
-  /**
-   * Delete offline tune and associated param gens and offline evals
-   */
-  def deleteOfflineTune(tuneid: Int, keepSettings: Boolean) = {
-
-    // delete paramGen
-    if (!keepSettings) {
-      val tuneParamGens = paramGens.getByTuneid(tuneid)
-      tuneParamGens foreach { gen =>
-        Logger.info("Delete ParamGen ID " + gen.id)
-        paramGens.delete(gen.id)
-      }
-    }
-
-    // delete OfflineEval
-    val tuneOfflineEvals = offlineEvals.getByTuneid(tuneid)
-
-    tuneOfflineEvals foreach { eval =>
-      deleteOfflineEval(eval.id, keepSettings)
-    }
-
-    if (!keepSettings) {
-      Logger.info("Delete offline tune ID " + tuneid)
-      offlineTunes.delete(tuneid)
-    }
-  }
-
-  def hadoopRequiredByApp(appid: Int): Boolean = {
-    apps.get(appid) map { app =>
-      engines.getByAppid(app.id).foldLeft(false) { (b, a) => b || hadoopRequiredByEngine(a.id) }
-    } getOrElse false
-  }
-
-  def hadoopRequiredByEngine(engineid: Int): Boolean = {
-    engines.get(engineid) map { engine =>
-      algos.getByEngineid(engine.id).foldLeft(false) { (b, a) => (b || hadoopRequiredByAlgo(a.id)) }
-    } getOrElse false
-  }
-
-  def hadoopRequiredByAlgo(algoid: Int): Boolean = {
-    algos.get(algoid) map { algo =>
-      algoInfos.get(algo.infoid) map { algoinfo =>
-        algoinfo.techreq.contains("Hadoop")
-      } getOrElse false
-    } getOrElse false
-  }
-
-  def hadoopRequiredByOfflineEval(evalid: Int): Boolean = {
-    offlineEvals.get(evalid) map { oe =>
-      algos.getByOfflineEvalid(oe.id).foldLeft(false) { (b, a) => (b || hadoopRequiredByAlgo(a.id)) }
-    } getOrElse false
-  }
-
-  /**
-   * Request scheduler to stop and delete sim eval
-   * @return Future[SimpleResult]
-   */
-  def stopAndDeleteSimEvalScheduler(appid: Int, engineid: Int, evalid: Int) = {
-
-    /** Stop any possible running jobs */
-    val stop = WS.url(s"${settingsSchedulerUrl}/apps/${appid}/engines/${engineid}/offlineevals/${evalid}/stop").get()
-    /** Clean up intermediate data files */
-    val deleteHadoop = if (hadoopRequiredByOfflineEval(evalid)) "?hadoop=1" else ""
-    val delete = WS.url(s"${settingsSchedulerUrl}/apps/${appid}/engines/${engineid}/offlineevals/${evalid}/delete${deleteHadoop}").get()
-    /** Synchronize on both scheduler actions */
-    val remove = concurrent.Future.reduce(Seq(stop, delete)) { (a, b) =>
-      if (a.status != http.Status.OK) // keep the 1st error
-        a
-      else
-        b
-    }
-
-    /** Handle any error that might occur within the Future */
-    val complete = remove map { r =>
-      if (r.status == http.Status.OK)
-        Ok(Json.obj("message" -> s"Offline evaluation ID ${evalid} has been deleted"))
-      else
-        InternalServerError(Json.obj("message" -> (r.json \ "message").as[String]))
-    } recover {
-      case e: Exception => InternalServerError(Json.obj("message" ->
-        ("Failed to delete simulated evaluation. Please check if the scheduler server is running properly. " + e.getMessage())))
-    }
-
-    complete
-  }
-
-  /**
-   * Request scheduler to stop and delete offline Tune
-   * @return Future[SimpleResult]
-   */
-  def stopAndDeleteOfflineTuneScheduler(appid: Int, engineid: Int, tuneid: Int) = {
-
-    val stop = WS.url(s"${settingsSchedulerUrl}/apps/${appid}/engines/${engineid}/offlinetunes/${tuneid}/stop").get()
-
-    val deletes = offlineEvals.getByTuneid(tuneid) map { eval =>
-      val deleteHadoop = if (hadoopRequiredByOfflineEval(eval.id)) "?hadoop=1" else ""
-      WS.url(s"${settingsSchedulerUrl}/apps/${appid}/engines/${engineid}/offlineevals/${eval.id}/delete${deleteHadoop}").get()
-    }
-
-    val remove = concurrent.Future.reduce(Seq(stop) ++ deletes) { (a, b) =>
-      if (a.status != http.Status.OK) // keep the 1st error
-        a
-      else
-        b
-    }
-
-    val complete = remove map { r =>
-      if (r.status == http.Status.OK)
-        Ok(Json.obj("message" -> s"Offline Tune ID ${tuneid} has been deleted"))
-      else
-        InternalServerError(Json.obj("message" -> (r.json \ "message").as[String]))
-    } recover {
-      case e: Exception => InternalServerError(Json.obj("message" ->
-        ("Failed to delete autotuning algorithm. Please check if the scheduler server is running properly. " + e.getMessage())))
-    }
-
-    complete
-
-  }
-
-  /**
-   * Request scheduler to delete algo file
-   * @return Future[SimpleResult]
-   */
-  def deleteAlgoScheduler(appid: Int, engineid: Int, id: Int) = {
-    val deleteHadoop = if (hadoopRequiredByAlgo(id)) "?hadoop=1" else ""
-    val delete = WS.url(s"${settingsSchedulerUrl}/apps/${appid}/engines/${engineid}/algos/${id}/delete${deleteHadoop}").get()
-
-    delete map { r =>
-      if (r.status == http.Status.OK)
-        Ok
-      else
-        InternalServerError(Json.obj("message" -> (r.json \ "message").as[String]))
-    } recover {
-      case e: Exception => InternalServerError(Json.obj("message" ->
-        ("Failed to delete algorithm. Please check if the scheduler server is running properly. " + e.getMessage())))
-    }
-  }
-
-  /**
-   * Request scheduler to delete engine file
-   * @return Future[SimpleResult]
-   */
-  def deleteEngineScheduler(appid: Int, engineid: Int) = {
-    val deleteHadoop = if (hadoopRequiredByEngine(engineid)) "?hadoop=1" else ""
-    val delete = WS.url(s"${settingsSchedulerUrl}/apps/${appid}/engines/${engineid}/delete${deleteHadoop}").get()
-
-    delete map { r =>
-      if (r.status == http.Status.OK)
-        Ok
-      else
-        InternalServerError(Json.obj("message" -> (r.json \ "message").as[String]))
-    } recover {
-      case e: Exception => InternalServerError(Json.obj("message" ->
-        ("Failed to delete engine. Please check if the scheduler server is running properly. " + e.getMessage())))
-    }
-  }
-
-  /**
-   * Request scheduler to delete app file
-   * @return Future[SimpleResult]
-   */
-  def deleteAppScheduler(appid: Int) = {
-    val deleteHadoop = if (hadoopRequiredByApp(appid)) "?hadoop=1" else ""
-    val delete = WS.url(s"${settingsSchedulerUrl}/apps/${appid}/delete${deleteHadoop}").get()
-
-    delete map { r =>
-      if (r.status == http.Status.OK)
-        Ok
-      else
-        InternalServerError(Json.obj("message" -> (r.json \ "message").as[String]))
-    } recover {
-      case e: Exception => InternalServerError(Json.obj("message" ->
-        ("Failed to delete app. Please check if the scheduler server is running properly. " + e.getMessage())))
-    }
-  }
-
-  def displayParams(algoInfo: AlgoInfo, params: Map[String, Any]): String = {
-    // return default value if the param doesn't exist in algo's params field
-    // (eg. new param added later).
-    algoInfo.name + ": " + (algoInfo.paramorder map { paramName =>
-      algoInfo.params(paramName).name + " = " +
-        params.getOrElse(paramName, algoInfo.params(paramName).defaultvalue)
-    } mkString (", "))
-  }
-}
diff --git a/servers/admin/app/views/Web/index.scala.html b/servers/admin/app/views/Web/index.scala.html
deleted file mode 100644
index 5e2d2af..0000000
--- a/servers/admin/app/views/Web/index.scala.html
+++ /dev/null
@@ -1,972 +0,0 @@
-<!DOCTYPE html>
-<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
-<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
-<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
-<!--[if gt IE 8]><!-->
-<html class="no-js">
-<!--<![endif]-->
-<head>
-<meta charset="utf-8">
-<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
-<title>PredictionIO Admin Web</title>
-<meta name="description" content="">
-<meta name="viewport" content="width=device-width">
-
-<link rel="stylesheet" href="assets/stylesheets/vendors/bootstrap.min.css">
-<link rel="stylesheet" href="assets/stylesheets/vendors/darkstrap.css">
-<link rel="stylesheet" href="assets/stylesheets/main.css?v=201304091">
-<link rel="stylesheet" href="assets/stylesheets/vendors/jquery-ui-1.9.2.custom.min.css">
-<script type="text/javascript" src="assets/javascripts/vendors/modernizr-2.6.2-respond-1.1.0.min.js"></script>
-<link rel="stylesheet" href="assets/stylesheets/vendors/toastr-1.2.2.min.css">
-<link rel="stylesheet" href="assets/stylesheets/vendors/toggle-switch.css">
-
-<script type="text/template" id="auth_template">
-        <% if (data.username) { %>
-            <div id="navAuth" class="btn-group pull-right">
-                <a class="btn btn-inverse btn-small dropdown-toggle" data-toggle="dropdown" href="#"><i class="icon-user icon-white"></i> <%= data.username %> <span class="caret"></span></a>
-                <ul class="dropdown-menu">
-                    <!-- TODO
-                    <li><a href="#">Edit Account</a></li>
-                    <li><a href="#">Admin Settings</a></li>
-                    <li class="divider"></li>
-                    -->
-                    <li><a href="?#signout"><i class="i"></i> Logout</a></li>
-                </ul>
-            </div>
-        <% } %>
-</script>
-<script type="text/template" id="signin_template">
-    <div class="row-fluid">
-        <div class="span12">
-            <div id="signinContainer" class="center">
-                <form id="signinForm" class="form-horizontal">
-                    <div class="modal modal-visible">
-                        <div class="modal-header">
-                            <h4>PredictionIO Admin Panel</h4>
-                        </div>
-                        <div class="modal-body">
-                            <div class="control-group">
-                                <label class="control-label" for="email">Email</label>
-                                <div class="controls">
-                                    <input type="text" name="email" required="required" placeholder="your email">
-                                </div>
-                            </div>
-                            <div class="control-group">
-                                <label class="control-label" for="password">Password</label>
-                                <div class="controls">
-                                    <input type="password" name="password" required="required" placeholder="your password">
-                                </div>
-                            </div>
-                            <div class="control-group">
-                                <div class="controls">
-                                    <label class="checkbox"> <input name="remember" type="checkbox">
-                                        Remember me
-                                    </label>
-                                </div>
-                            </div>
-                            <div class="pull-right">
-                                 <span id="signinFormError" class="displayNone text-warning">error</span>
-                            </div>
-                        </div>
-                        <div class="modal-footer">
-
-                            <button type="submit" class="btn btn-primary input-medium">Sign In</button>
-                        </div>
-                    </div>
-                </form>
-                <div>
-                    <!-- TODO
-                    <a href="#">Forget Password?</a>
-                    -->
-                </div>
-            </div>
-        </div>
-    </div>
-</script>
-
-<script type="text/template" id="appsDashboard_template">
-	<div class="row-fluid topMargin">
-		<div class="span10 offset1">
-			<div class="modal modal-visible modal-inverse">
-				<div class="modal-header">
-					<h5>Applications</h5>
-				</div>
-				<div class="modal-container">
-					<section class="modal-content">
-						<div class="modal-item-box">
-							<div id="appList">
-								<!-- App list template -->
-							</div>
-							<div id="appCreatePanel" class="displayNone modal-item">
-								<div class="row-fluid">
-									<div class="span5">
-										<form class="navbar-form">
-											<div class="input-append">
-												<input id="addAppInput" type="text"
-													placeholder="Name your app. E.g. MyMobileApp">
-												<button id="createAppBtn" class="btn" type="button">Add</button>
-											</div>
-											<span id="addAppInputError" class="displayNone text-error">Something
-												may have gone wrong</span>
-										</form>
-									</div>
-								</div>
-							</div>
-						</div>
-						<!-- End of App -->
-						<a href="#" id="showAddAppBtn" class="btn btn-small pull-right">Add
-							an App</a>
-					</section>
-
-				</div>
-			</div>
-		</div>
-	</div>
-</script>
-
-<script type="text/template" id="app_template">
-    <div class="modal-item">
-        <div class="clearfix">
-            <div class="pull-left">
-                <h5>
-                    <a class="toggleAppDetailsAction" href="#"><%= data.appname %></a>
-                </h5>
-            </div>
-            <div class="modal-item-panel pull-right">
-                <a href="#" class="actionbtn toggleAppDetailsAction"><i
-                    class="icon-cog icon-white"></i> Develop</a>
-            </div>
-        </div>
-        <div class="app-info displayNone">
-            <div class="appdetails">
-                <!--  app details template -->
-            </div>
-            <div class="appenginelist">
-                <!--  app engine template -->
-            </div>
-            <p>
-                [ <a href="#" class="eraseAllDataAction"><span
-                    class="text-warning">Reset and Erase All Data</span></a> ]
-
-                [ <a href="#"
-                    class="removeAppAction"><span class="text-warning">Remove
-                        this App</span></a> ]
- <!-- TODO
-                [ <a href="javascript:alert('This feature will be available soon.');" ><span
-                    class="text-warning">Reset and Erase All Data</span></a> ]
-
-                [ <a href="javascript:alert('This feature will be available soon.');"><span class="text-warning">Remove this App</span></a> ]
--->
-            </p>
-        </div>
-    </div>
-</script>
-<script type="text/template" id="appdetails_template">
-                                    <div class="row-fluid">
-                                        <div class="span8">
-                                            <p>
-                                                Last Updated: <%= data.updatedtime %> <a class="detailsRefreshAction" href="#"><i class="icon-refresh"></i></a>
-                                                <br /> Number of Users: <%= data.userscount %>
-                                                <br /> Number of Items: <%= data.itemscount %>
-                                                <br /> Number of U2I Actions: <%= data.u2icount %>
-                                            </p>
-<!--
-                                            <strong>API Endpoint</strong> &nbsp;[<a href="#">?</a>]
-                                            <input class="span12" type="text" readonly required="" value="<%= data.apiurl %>" name="apiurl">
--->
-                                            <strong>App Key</strong> &nbsp;<!-- TODO [<a href="#">?</a>] -->
-                                            <input class="span12" type="text" readonly required="" value="<%= data.appkey %>" name="appkey">
-                                            <div class="bottomMargin"></div>
-
-                                            <div class="clearfix">
-                                                <strong>Prediction Engines</strong>
-                                                <a href="?appid=<%= data.id %>#addEngine" class="pull-right btn btn-small">Add an Engine &raquo;</a>
-                                            </div>
-
-                                        </div>
-                                    </div>
-</script>
-<script type="text/template" id="appenginelist_template">
-                                    <div class="row-fluid">
-                                        <div class="span8">
-                                            <table class="table bottomMargin-large">
-                                                <thead>
-                                                    <tr>
-                                                        <th>Engine Name</th>
-                                                        <th>Type</th>
-                                                        <th></th>
-                                                    </tr>
-                                                </thead>
-                                                <tbody id="appdetails_engines">
-                                                <% _.each(data.enginelist, function(engine) { %>
-                                                    <tr>
-                                                        <td><%= engine.enginename %></td>
-                                                        <td><%= engine.engineinfoid %></td>
-                                                        <td><a href="?appid=<%= data.id %>&engineid=<%= engine.id %>&engineinfoid=<%= engine.engineinfoid %>#engine" class="btn btn-small">Manage</a></td>
-                                                    </tr>
-                                                <% }); %>
-
-                                                </tbody>
-                                            </table>
-                                        </div>
-                                    </div>
-</script>
-<script type="text/template" id="breadcrumb_template">
-        <ul class="breadcrumb">
-            <% if(data.appname != null) { %>
-                <li><strong><a href="#appsDashboard"><%= data.appname %></a></strong>
-            <% } %>
-            <% if(data.enginename != null) { %>
-                <span class="divider">/</span></li>
-                <li class="active"><%= data.enginename %></li>
-            <% } %>
-        </ul>
-</script>
-
-<script type="text/template" id="app_addEngine_template">
-<div class="row-fluid">
-    <div class="span10 offset1">
-        <div id="breadcrumb_ContentHolder"></div>
-        <div class="page-header"><h4>Create an Engine</h4></div>
-            <div id="createEngine" class="boxContainer clearfix bottomMargin-large">
-                <% _.each(data, function(enginetype, index) { %>
-                    <% if(index % 2 == 0) { %>
-                    <div class="row-fluid">
-                    <% } %>
-                        <div class="span6 boxBlock">
-                            <div class="boxtitle">
-                                <strong><i class="icon-cog icon-white"></i> <%= enginetype.engineinfoname%></strong>
-                            </div>
-                            <div class="boxContent">
-                                <%= enginetype.description%>
-                            </div>
-                            <div class="boxPanel clearfix">
-                                <form>
-                                    <div class="textRight">
-                                        <span class="createEngineError text-error displayNone">Error text here</span>
-                                    </div>
-                                    <div class="pull-right">
-                                        <div class="input-append">
-                                            <input type="hidden" name="engineinfoid" value="<%= enginetype.id%>"/>
-                                            <input class="btn-input" name="enginename" type="text" placeholder="type engine name..."/>
-                                            <button class="btn btn-inverse" type="submit">Create</button>
-                                        </div>
-                                    </div>
-                                </form>
-                            </div>
-                        </div>
-                    <% if(index % 2 != 0) { %>
-                    </div>
-                    <% } %>
-
-                <% }); %>
-            </div>
-        </div>
-    </div>
-</div>
-
-</script>
-
-<script type="text/template" id="engineTabAlgorithms_template">
-                    <div class="row-fluid bottomMargin">
-                        <div class="span8">
-                            <div class="boxContainer">
-                                <div class="boxBlock">
-                                    <div class="boxtitle">
-                                        <i class="icon-fire icon-white"></i> Deployed Algorithm <small>
-                                            - running on live system</small>
-                                    </div>
-                                    <div class="boxContent">
-                                        <div id="engine_deployedAlgo_ContentHolder"></div>
-                                    </div>
-                                </div>
-                            </div>
-                        </div>
-                    </div>
-
-                    <div class="boxContainer">
-                        <div class="boxBlock">
-                            <div class="boxContent">
-                                <div class="row-fluid">
-                                    <div class="span8">
-                                        <h4>Available Algorithms</h4>
-<!-- TODO
-                                        <a href="#" disabled id="availableAlgoDeployBtn" class="btn btn-small btn-primary">
-                                            Deploy <i class="icon-play icon-white"></i>
-                                        </a>
--->
-                                        &nbsp;
-                                        <a href="#" disabled id="availableSimEvalBtn" class="btn btn-small btn-primary">
-                                            Run Simulated Evaluation <i class="icon-signal icon-white"></i>
-                                        </a>
-                                        &nbsp;
-                                        <a href="#engineAddAlgorithm" class="btn btn-info btn-small">Add an Algorithm &raquo;</a>
-                                        <div id="engine_availableAlgoList_ContentHolder">
-                                            <!-- template here -->
-                                        </div>
-                                    </div>
-                                    <div class="span4">
-                                        <div id="engine_simevalList_ContentHolder">
-                                            <!-- template here -->
-                                        </div>
-                                    </div>
-                                </div>
-                            </div>
-                        </div>
-                    </div>
-</script>
-<script type="text/template" id="engine_simevalList_template">
-                                        <h4>
-                                            Simulated Evaluation <i class="icon-signal icon-white"></i>
-                                        </h4>
-                                        <table
-                                            class="table table-bordered table-condensed smallContent table-hover">
-                                            <thead>
-                                                <tr>
-                                                    <th>Created Date</th>
-                                                    <th>Algo(s)</th>
-                                                    <th></th>
-                                                </tr>
-                                            </thead>
-                                            <tbody>
-                                                <!-- template here -->
-                                            </tbody>
-                                        </table>
-</script>
-<script type="text/template" id="engine_simeval_template">
-    <td><%= data.createtime %></td>
-    <td>
-        <%
-            var algoArray = [];
-            _.each(data.algolist, function(algo, index) {
-                algoArray.push(algo.algoname);
-            });
-        %>
-        <%= algoArray.join(', ') %>
-    </td>
-    <td>
-        <div class="btn-group dropup">
-            <button data-toggle="dropdown"
-                class="btn btn-mini btn-inverse dropdown-toggle">
-                Actions <span class="caret"></span>
-            </button>
-            <ul class="dropdown-menu pull-right">
-                <li><a href="#simEvalReport/<%= encodeURIComponent(data.id) %>">View Report</a></li>
-                <li><a class="simevalDeleteBtn" href="javascript:void(0);">Stop and Delete</a></li>
-            </ul>
-        </div>
-    </td>
-</script>
-
-<script type="text/template" id="engine_deployedAlgo_template">
-<table class="table">
-	<thead>
-		<tr>
-			<th>Algo Name</th>
-			<th>Algorithm</th>
-			<th>Status</th>
-<!-- TODO
-			<th>Running Since</th>
--->
-		</tr>
-	</thead>
-	<tbody>
-        <% _.each(data.algolist, function(algo, index) { %>
-		<tr>
-			<td><%= algo.algoname %></td>
-			<td><%= algo.algoinfoname %></td>
-			<td span="2">
-                <% if(index == 0) { %>
-				<div class="btn-group">
-					<button data-toggle="dropdown"
-						class="btn btn-mini btn-inverse dropdown-toggle">
-						<%= data.status %> <span class="caret"></span>
-					</button>
-					<ul class="dropdown-menu pull-right">
-                        <!-- TODO
-						<li><a href="#"><i class="icon-signal"></i> View Report</a></li>
-						<li><a href="#"><i class="icon-pencil"></i> Edit Deploy
-								Settings</a></li>
-						<li class="divider"></li>
-                        -->
-                        <li><a id="algoTrainNowBtn" href="javascript:void(0);">Train Data Model Now</a></li>
-						<li><a id="algoUndeployBtn" href="#">Undeploy</a></li>
-					</ul>
-				</div>
-                <% } %>
-			</td>
-<!-- TODO
-			<td span="2" class="smallContent">
-                <% if(index == 0) { %>
-                    <%= data.updatedtime %>
-                <% } %>
-            </td>
--->
-		</tr>
-        <% }); %>
-	</tbody>
-</table>
-</script>
-
-<script type="text/template" id="engine_availableAlgoList_template">
-                                        <table class="table table-hover">
-                                            <thead>
-                                                <tr>
-                                                    <th></th>
-                                                    <th>Algo Name</th>
-                                                    <th>Algorithm</th>
-                                                    <th>Status</th>
-                                                    <th>Last Updated</th>
-                                                </tr>
-                                            </thead>
-                                            <tbody>
-                                                <!-- template here -->
-                                            </tbody>
-                                        </table>
-</script>
-
-<script type="text/template" id="engine_availableAlgo_template">
-                                                    <td>
-                                                        <% if ( data.status == "ready") {%>
-                                                        <input type="checkbox" name="avaalgoSelect" value="<%= data.id %>" />
-                                                        <% } %>
-                                                    </td>
-                                                    <td><%= data.algoname %></td>
-                                                    <td><%= data.algoinfoname %></td>
-                                                    <td>
-                                                        <% if ( data.status == "ready") {%>
-                                                        <div class="btn-group dropup">
-                                                            <button data-toggle="dropdown"
-                                                                class="btn btn-mini btn-inverse dropdown-toggle">
-                                                                Ready to Deploy<span class="caret"></span>
-                                                            </button>
-                                                            <ul class="dropdown-menu pull-right">
-                                                                <li><a class="algoDeployBtn" href="#">Deploy</a></li>
-                                                                <li><a href="#algoSettings/<%= data.algoinfoid %>/<%= data.algoname %>/<%= encodeURIComponent(data.id) %>">View/Edit Algorithm Settings</a></li>
-                                                                <li><a href="#simEvalSettings/<%= encodeURIComponent(data.id) %>">Run Simulated Evaluation</a></li>
-                                                                <li class="divider"></li>
-                                                                <li><a class="algoDeleteBtn" href="#">Delete</a></li>
-                                                            </ul>
-                                                        </div>
-                                                        <% } else { %>
-                                                        <div class="btn-group dropup">
-                                                            <button data-toggle="dropdown"
-                                                                class="btn btn-mini btn-inverse dropdown-toggle">
-                                                                <% if ( data.status == "tuning") {%>
-                                                                    <em>Auto-tuning...</em><span class="caret"></span>
-                                                                <% } else { %>
-                                                                    Auto-tuning Completed<span class="caret"></span>
-                                                                <% } %>
-                                                            </button>
-                                                            <ul class="dropdown-menu pull-right">
-                                                                <li><a href="#algoAutotuningReport/<%= encodeURIComponent(data.id) %>">View Tuning Report</a></li>
-                                                                <li class="divider"></li>
-                                                                <li><a class="algoDeleteBtn" href="#">Delete</a></li>
-                                                            </ul>
-                                                        </div>
-                                                        <% } %>
-                                                    </td>
-                                                    <td class="smallContent"><%= data.updatedtime %></td>
-</script>
-<script type="text/template" id="engine_addAlgorithm_template">
-    <div class="row-fluid bottomMargin">
-        <div class="span12">
-            <div class="boxContainer">
-                <div class="boxBlock">
-                    <div class="boxtitle">Available Algorithms for <%= data.engineinfoname %></div>
-                    <div class="boxContent">
-                        <table class="table">
-                            <thead>
-                                <tr>
-                                    <th>Algorithm</th>
-                                    <th>Description</th>
-                                    <th>Requirement</th>
-                                    <th>Data Requirement</th>
-                                    <th></th>
-                                </tr>
-                            </thead>
-                            <tbody>
-                                <% _.each(data.algotypelist, function(algotype) { %>
-                                <tr>
-                                    <td><%= algotype.algoinfoname %></td>
-                                    <td><%= algotype.description %></td>
-                                    <td><%= algotype.req %></td>
-                                    <td><%= algotype.datareq %></td>
-                                    <td>
-                                        <form>
-                                        <div class="input-append">
-                                            <input type="hidden" name="algoinfoid" value="<%= algotype.id%>"/>
-                                            <input class="btn-input span9" name="algoname" type="text" placeholder="type algo name..."/>
-                                            <button class="btn btn-primary" type="submit">Add</button>
-                                        </div>
-                                        <div class="addAlgoError text-error displayNone">Error text here</div>
-                                        </form>
-                                     </td>
-                                </tr>
-                                <% }); %>
-                            </tbody>
-                        </table>
-                    </div>
-                </div>
-            </div>
-        </div>
-    </div>
-</script>
-<script type="text/template" id="engineStatus_template">
-        <div class="row-fluid bottomMargin">
-            <div class="span12">
-                Engine Status: &nbsp;
-                    <% if (data.enginestatus == "noappdata") { %>
-                        <span class="label label-warning"><i class="icon-warning-sign icon-white"></i> Not Running: No Data. Please import some data.</span>
-                    <% } else if (data.enginestatus == "nodeployedalgo") { %>
-                        <span class="label label-warning"><i class="icon-warning-sign icon-white"></i> Not Running: Please deploy an algorithm.</span>
-                    <% } else if (data.enginestatus == "nomodeldata") { %>
-                        <span class="label label-warning"><i class="icon-warning-sign icon-white"></i> Not Running: Waiting for the the first-time data model training.</span>
-                    <% } else if (data.enginestatus == "nomodeldatanoscheduler") { %>
-                        <span class="label label-warning"><i class="icon-warning-sign icon-white"></i> Not Running: Waiting for the the first-time data model training. (Scheduler is unreachable)</span>
-                    <% } else if (data.enginestatus == "firsttraining") { %>
-                        <span class="label label-warning"><i class="icon-warning-sign icon-white"></i> Not Running: Training the first data model.</span>
-                    <% } else if (data.enginestatus == "training") { %>
-                        <span class="label label-info">Running (Last Successful Training: <%= data.lasttraintime %>) (training data model) <i class="icon-ok icon-white"></i></span>
-                    <% } else if (data.enginestatus == "runningnoscheduler") { %>
-                        <span class="label label-warning"><i class="icon-warning-sign icon-white"></i> Running (Last Successful Training: <%= data.lasttraintime %>) (Scheduler is unreachable)</span>
-                    <% } else if (data.enginestatus == "running") { %>
-                        <span class="label label-info">Running (Last Successful Training: <%= data.lasttraintime %>) <i class="icon-ok icon-white"></i></span>
-                    <% } else { %>
-                        <span class="label label-warning"><i class="icon-warning-sign icon-white"></i> Not Running: Undetermined error</span>
-                    <% } %>
-                &nbsp;&nbsp;<a href="javascript:void(0);" id="engineStatusReloadBtn" title="refresh engine status"><i class="icon-refresh"></i></a>
-            </div>
-        </div>
-</script>
-<script type="text/template" id="engine_template">
-<div class="row-fluid">
-    <div class="span10 offset1">
-        <div class="alert alert-block alert-error displayNone">
-            <button type="button" class="close" data-dismiss="alert">&times;</button>
-            <strong>Warning!</strong> Error placeholder here.... It should be
-            hidden by default. For now, please click the 'x' button.
-        </div>
-        <!--  breadcrumb -->
-        <div id="breadcrumb_ContentHolder"></div>
-
-        <div id="engineStatus_ContentHolder"></div>
-
-        <div id="engineTab" class="row-fluid">
-            <div class="span12">
-                <div class="pull-right">
-                    <div class="btn-group">
-                        <button data-toggle="dropdown" class="btn btn-inverse btn-small dropdown-toggle">Engine Control <span class="caret"></span></button>
-                        <ul class="dropdown-menu">
-                            <li><a id="deleteEngineBtn" href="#">Delete this Engine</a></li>
-                        </ul>
-                    </div>
-                </div>
-                <ul class="nav nav-tabs" id="engineTab">
-                    <li><a id="engineTabSettingsBtn" href="#engineTabSettings">Engine</a></li>
-                    <li><a id="engineTabAlgorithmsBtn" href="#engineTabAlgorithms">Algorithms</a></li>
-                    <li id="engineExtraTabTitle" class="displayNone"><a onclick="return false;" id="engineExtraTabBtn" href="#engineExtraTab">-</a></li>
-                </ul>
-
-            </div>
-        </div>
-        <div class="tab-content">
-            <div class="tab-pane" id="engineTabSettings">
-                <h4>Prediction Settings</h4>
-                <div id="engineTabSettingsContentHolder">
-                    <!-- engine settings template -->
-                </div>
-            </div>
-            <div class="tab-pane" id="engineTabAlgorithms">
-                <div id="engineTabAlgorithmsContentHolder">
-                    <!-- engine algorithms tab template -->
-                </div>
-            </div>
-            <div class="tab-pane" id="engineExtraTab">
-                <div id="engineExtraTabContentHolder">
-                </div>
-            </div>
-        </div>
-    </div>
-</div>
-</script>
-<script type="text/template" id="engine_algoAutotuningReport_template">
-<%
-    var algo = {};
-    var metric = {}
-    if (data.algo) {
-        algo = data.algo;
-    }
-    if (data.metric) {
-        metric = data.metric;
-    }
-%>
-<div class="row-fluid">
-    <div class="span12">
-        <form class="form-horizontal">
-            <div class="modal modal-visible">
-                <div class="modal-header">
-                    <h4>Algorithm Autotuning Report for <%= algo.algoname%></h4>
-                </div>
-                <div class="modal-body">
-                    <div class="bottomMargin">
-                        <p>Auto-tuning Status: <%= data.status %></p>
-                        <p>Start Time: <%= data.starttime %></p>
-                        <p>End Time: <%= data.endtime %></p>
-
-                        <h5 class="topMargin">Targeted Algorithm</h5>
-                        <span>Algo Name: <%= algo.algoname %></span>
-                        <span class="leftMargin">Algo Type: <%= algo.algoinfoname %></span>
-
-                        <h5 class="topMargin">Data Split Settings</h5>
-                        <span>Train Set: <%= data.splittrain %>%</span>
-                        <span class="leftMargin">Validation Set: <%= data.splitvalidation %>%</span>
-                        <span class="leftMargin">Test Set: <%= data.splittest %>%</span>
-                        <div>
-                            <%= data.splittersettingsstring %>
-                        </div>
-                        <h5 class="topMargin">Metric</h5>
-                        <span>Name: <%= metric.metricsname %> (<%= metric.settingsstring %>)</span>
-                        <span class="leftMargin">Number of Iteration: <%= data.evaliteration %></span>
-                    </div>
-
-                    <h4 class="topMargin-large">Average Results</h4>
-                    <table class="table bottomMargin-large">
-                        <thead>
-                            <tr>
-                                <th>Param Settings</th>
-                                <th>Score</th>
-                                <th></th>
-                            </tr>
-                        </thead>
-                        <tbody>
-                            <% _.each(data.metricscorelist, function(m, index) { %>
-                            <tr>
-                                <td><%= m.algoinfoname %>: <%= m.settingsstring %></td>
-                                <td><%= m.score %></td>
-                                <td>
-                                    <!-- NOTE: index 0 is baseline algo -->
-                                <% if(index != 0) { %>
-                                    <a href="#" data-autotuneid="<%= m.algoautotuneid %>" class="algoAutotuneSelectBtn btn btn-primary btn-small">Use It</a>
-                                <% } %>
-                                </td>
-                            </tr>
-                            <% }); %>
-                        </tbody>
-                    </table>
-
-                    <% _.each(data.metricscoreiterationlist, function(iterationscorelist, index) { %>
-                        <h6>Results in Iteration <%= index+1 %></h6>
-                        <table class="table">
-                            <thead>
-                                <tr>
-                                    <th>Param Settings</th>
-                                    <th>Score</th>
-                                    <th></th>
-                                </tr>
-                            </thead>
-                            <tbody>
-                                <% _.each(iterationscorelist, function(m) { %>
-                                <tr>
-                                    <td><%= m.algoinfoname %>: <%= m.settingsstring %></td>
-                                    <td><%= m.score %></td>
-                                    <td></td>
-                                </tr>
-                                <% }); %>
-                            </tbody>
-                        </table>
-                    <% }); %>
-
-                </div>
-            </div>
-        </form>
-    </div>
-</div>
-</script>
-<script type="text/template" id="engine_simEvalReport_template">
-<div class="row-fluid">
-    <div class="span12">
-        <form class="form-horizontal">
-            <div class="modal modal-visible">
-                <div class="modal-header">
-                    <h4>Simulated Evaluation Report</h4>
-                </div>
-                <div class="modal-body">
-                    <div class="bottomMargin">
-                        <p>Simulated Evaluation Status: <%= data.status %></p>
-                        <p>Start Time: <%= data.starttime %></p>
-                        <p>End Time: <%= data.endtime %></p>
-
-                        <h5>Data Split Settings:</h5>
-                        <span>Train Set: <%= data.splittrain %>%</span>
-                        <!-- 3-part split
-                        <span class="leftMargin">Validation Set: <%= data.splitvalidation %>%</span>
-                        -->
-                        <span class="leftMargin">Test Set: <%= data.splittest %>%</span>
-                        <div>
-                            <%= data.splittersettingsstring %>
-                        </div>
-                    </div>
-                    <h5>Algorithms</h5>
-                    <p>Settings of algorithms at the time of evaluation.</p>
-                    <div class="well">
-                        <ul>
-                            <% _.each(data.algolist, function(algo) { %>
-                            <li><%= algo.algoname %>
-                                <p><%= algo.algoinfoname %> (<%= algo.settingsstring %>)</p>
-                            </li>
-                            <% }); %>
-                        </ul>
-                    </div>
-
-                    <h4>Average Results</h4>
-                    <% // create result matrix
-                        var result = {};
-                        _.each(data.algolist, function(algo) {
-                            result[algo.id] = {};
-                        });
-                        _.each(data.metricscorelist, function(s) {
-                            result[s.algoid][s.metricsid] = s.score;
-                        });
-                    %>
-                    <table class="table bottomMargin-large">
-                        <thead>
-                            <tr>
-                                <th>Algorithm ID</th>
-                                <% _.each(data.metricslist, function(metrics) { %>
-                                <th><%= metrics.metricsname%> (<%= metrics.settingsstring%>)</th>
-                                <% }); %>
-                            </tr>
-                        </thead>
-                        <tbody>
-                            <% _.each(data.algolist, function(algo) { %>
-                            <tr>
-                                <td><%= algo.algoname %></td>
-                                <% _.each(data.metricslist, function(metrics) { %>
-                                    <td><%= result[algo.id][metrics.id] %></td>
-                                <% }); %>
-                            </tr>
-                            <% }); %>
-                        </tbody>
-                    </table>
-
-                    <% _.each(data.metricscoreiterationlist, function(iterationscorelist, index) { %>
-                        <h6>Results in Iteration <%= index+1 %></h6>
-                        <% // create result matrix
-                            var result = {};
-                            _.each(data.algolist, function(algo) {
-                                result[algo.id] = {};
-                            });
-                            _.each(iterationscorelist, function(s) {
-                                result[s.algoid][s.metricsid] = s.score;
-                            });
-                        %>
-                        <table class="table">
-                            <thead>
-                                <tr>
-                                    <th>Algorithm ID</th>
-                                    <% _.each(data.metricslist, function(metrics) { %>
-                                    <th><%= metrics.metricsname%> (<%= metrics.settingsstring%>)</th>
-                                    <% }); %>
-                                </tr>
-                            </thead>
-                            <tbody>
-                                <% _.each(data.algolist, function(algo) { %>
-                                <tr>
-                                    <td><%= algo.algoname %></td>
-                                    <% _.each(data.metricslist, function(metrics) { %>
-                                        <td><%= result[algo.id][metrics.id] %></td>
-                                    <% }); %>
-                                </tr>
-                                <% }); %>
-                            </tbody>
-                        </table>
-                    <% }); %>
-                </div>
-            </div>
-        </form>
-    </div>
-</div>
-</script>
-
-<script type="text/template" id="engine_simEvalSettingsMetrics_template">
-
-                                            <li class="bottomMargin">
-                                                <div class="bottomMargin">
-                                                    <select name="infoid[<%= data.index %>]" class="span6 changeMetricsSelect">
-                                                        <% _.each(data.metricslist, function(metrics) { %>
-                                                            <% if ( metrics.id == this.defaultmetric ) { %>
-                                                            <option value="<%= metrics.id %>" selected><%= metrics.description %> (<%= metrics.name %>)</option>
-                                                            <% } else { %>
-                                                            <option value="<%= metrics.id %>"><%= metrics.description %> (<%= metrics.name %>)</option>
-                                                            <% } %>
-                                                        <% }, data); %>
-                                                    </select>
-                                                    <span>&nbsp;&nbsp;&nbsp;&nbsp;[<a href="#" class="deleteMetricsBtn"> remove </a>]
-                                                    </span>
-                                                </div>
-                                                <div id="metricSetting_Holder">
-                                                </div>
-                                            </li>
-</script>
-
-<script type="text/template" id="engine_simEvalSettings_template">
-                        <div class="row-fluid">
-                           <div class="span10 offset1">
-                                <form id="simEvalSettingsForm" class="form-horizontal">
-                                <div class="modal modal-visible">
-                                    <div class="modal-header">
-                                        <h4>Simulated Evaluation</h4>
-                                    </div>
-                                    <div class="modal-body">
-                                        <h5>Algorithms to be Evaluated</h5>
-                                        <div class="well">
-                                            <ul>
-                                                <% _.each(data.algoList, function(algo, index) { %>
-                                                    <li><%= algo.algoname %><input type="hidden" value="<%= algo.id %>" name="algoids[<%= index %>]"/></li>
-                                                <% }); %>
-                                            </ul>
-                                        </div>
-
-                                        <h5 class="topMargin-large">Metrics <small><!-- TODO [<a href="#">?</a>] --> </small></h5>
-                                        <p>
-                                            The above algorithms will be evaluated against the following metrics.
-                                        </p>
-
-                                        <ul id="metrics_list_ContentHolder">
-
-                                        </ul>
-                                        <a href="#" id="addMetricsBtn" class="btn btn-small btn-inverse">Add Another Metric</a>
-
-                                        <h5 class="topMargin-large">Data Split</h5>
-                                        <p class="bottomMargin">Adjust the slider to specify how you want to split data into Train Set and Test Set.</p>
-                                        <!-- 3-part split
-                                        <table id="dataSplitBar" width="70%" cellspacing="0" cellpadding="0" border="0">
-                                            <tr>
-                                                <td class="selection" width="55%"><span>Train Set</span></td>
-                                                <td class="selection" width="20%"><span>Validation Set</span></td>
-                                                <td class="selection" width="15%"><span>Test Set</span></td>
-                                                <td width="10%"></td>
-                                            </tr>
-                                        </table>
-                                        -->
-                                        <table id="dataSplitBar" width="70%" cellspacing="0" cellpadding="0" border="0">
-                                            <tr>
-                                                <td class="selection" width="60%"><span>Train Set</span></td>
-                                                <td class="selection" width="20%"><span>Test Set</span></td>
-                                                <td width="20%"></td>
-                                            </tr>
-                                        </table>
-                                        <div class="topMargin">
-                                            <!-- 3-part split
-                                            <span>Train: </span><input class="span1" readonly type="text" id="splittrain" name="splittrain" value="55">%
-                                            <span class="leftMargin">Validation: </span><input class="span1" readonly type="text" id="splitvalidation" name="splitvalidation" value="20">%
-                                            <span class="leftMargin">Test: </span><input class="span1" readonly type="text" id="splittest" name="splittest" value="15">%
-                                            -->
-                                            <span>Train: </span><input class="span1" readonly type="text" id="splittrain" name="splittrain" value="60">%
-                                            <span class="leftMargin">Test: </span><input class="span1" readonly type="text" id="splittest" name="splittest" value="20">%
-                                        </div>
-
-                                        <div class="topMargin-large" id="splitterSetting_Holder">
-                                        </div>
-                                        <h5 class="topMargin-large">Iteration</h5>
-                                        <p>You may want to repeat the evaluation for a few times with different sampling. An average score will be reported.</p>
-                                        <div class="topMargin">
-                                            <span>Number of Iteration:  </span><input class="span1" type="text" name="evaliteration" value="3">
-                                        </div>
-
-                                    </div>
-                                    <div class="modal-footer">
-                                        <button type="submit" class="btn btn-primary input-medium">Run Now</button>
-                                    </div>
-                                </div>
-                                </form>
-                            </div>
-                        </div>
-</script>
-
-</head>
-
-<body>
-	<!--[if lt IE 7]>
-            <p class="chromeframe">You are using an <strong>outdated</strong> browser. Please upgrade your browser or <a href="http://www.google.com/chromeframe/?redirect=true">activate Google Chrome Frame</a> to improve your experience.</p>
-    <![endif]-->
-
-	<div class="wrapper">
-		<!-- sticky footer -->
-		<div id="headbar" class="navbar navbar-inverse navbar-fixed-top">
-			<div class="navbar-inner">
-				<div class="container-fluid">
-					<a class="btn btn-navbar" data-toggle="collapse"
-						data-target=".nav-collapse"> <span class="icon-bar"></span> <span
-						class="icon-bar"></span> <span class="icon-bar"></span>
-					</a> <a class="brand" href="?#appsDashboard"><img width="130px"
-						src="assets/images/predictionio.png" /></a>
-					<div id="navBar" class="nav-collapse collapse">
-						<ul class="nav">
-							<!-- <li><a href="#about">Processing Tasks <span class="badge badge-info">0</span></a></li> -->
-							<li class="dropdown"><a href="#" class="dropdown-toggle"
-								data-toggle="dropdown">Help <b class="caret"></b></a>
-								<ul class="dropdown-menu">
-									<li><a href="http://docs.prediction.io" target="_blank">PredictionIO Docs</a></li>
-									<li><a href="http://prediction.io/download">Download SDKs</a></li>
-									<li><a href="https://github.com/PredictionIO">View Source Code</a></li>
-									<li class="divider"></li>
-									<li class="nav-header">Support</li>
-									<li><a href="https://groups.google.com/#predictionio-user">Google Group</a></li>
-									<li><a href="http://www.twitter.com/predictionio">Twitter</a></li>
-								</ul></li>
-						</ul>
-						<div id="AuthHolder"></div>
-					</div>
-					<!--/.nav-collapse -->
-				</div>
-			</div>
-		</div>
-		<div id="mainarea" class="container-fluid">
-			<div id="ContentHolder"></div>
-		</div>
-		<div id="dialog_template" class="hide" title="Confirm?">
-		  <div>
-		      <span id="dialog_text">Are you sure?</span>
-		  </div>
-		</div>
-		<div class="push"></div>
-		<!-- sticky footer -->
-	</div>
-
-	<div class="footer">
-		<hr />
-		<footer>
-			<p>PredictionIO Community Edition core is released under the
-				AGPL License, SDKs under Apache License and documentation under
-				Creative Common.</p>
-			<p>
-				<a href="http://groups.google.com/group/predictionio-user" target="_blank">Contact Us</a> | <a href="http://predictionio.atlassian.net/" target="_blank">Report Bugs</a> | <a href="https://github.com/PredictionIO/" target="_blank">Contribute
-					Codes</a>
-			</p>
-		</footer>
-	</div>
-
-	<script
-		src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
-	<script>
-		window.jQuery
-				|| document
-						.write('<script type="text/javascript" src="assets/javascripts/vendors/jquery-1.8.3.min.js"><\/script>')
-	</script>
-	<script type="text/javascript"
-		src="assets/javascripts/vendors/jquery-ui-1.9.2.custom.min.js"></script>
-	<script type="text/javascript"
-		src="assets/javascripts/vendors/bootstrap.min.js"></script>
-	<script type="text/javascript"
-		src="assets/javascripts/vendors/underscore-min.js"></script>
-	<script type="text/javascript"
-		src="assets/javascripts/vendors/json2.js"></script>
-	<script type="text/javascript"
-		src="assets/javascripts/vendors/backbone-min.js"></script>
-	<script type="text/javascript" src="assets/javascripts/core.js?v=20130320-1"></script>
-    <script type="text/javascript" src="assets/javascripts/vendors/toastr-1.2.2.min.js"></script>
-    <script type="text/javascript" src="assets/javascripts/vendors/colResizable-1.3.min.js"></script>
-</body>
-</html>
diff --git a/servers/admin/app/views/algos/section1.scala.html b/servers/admin/app/views/algos/section1.scala.html
deleted file mode 100644
index 2fdd893..0000000
--- a/servers/admin/app/views/algos/section1.scala.html
+++ /dev/null
@@ -1,12 +0,0 @@
-@(name: String, description: Option[String], content: String)
-                                    <div class="boxBlock">
-                                        <div class="boxtitle">
-                                           @name
-                                        </div>
-                                        <div class="boxContent">
-                                            @Html(description.map(d => s"<p>$d</p>").getOrElse(""))
-                                            <div class="form-horizontal">
-@Html(content)
-                                            </div>
-                                        </div>
-                                    </div>
\ No newline at end of file
diff --git a/servers/admin/app/views/algos/section2.scala.html b/servers/admin/app/views/algos/section2.scala.html
deleted file mode 100644
index acafc77..0000000
--- a/servers/admin/app/views/algos/section2.scala.html
+++ /dev/null
@@ -1,4 +0,0 @@
-@(name: String, description: Option[String], content: String)
-                                                <h5>@name</h5>
-                                                @Html(description.map(d => s"<p>$d</p>").getOrElse(""))
-@Html(content)
diff --git a/servers/admin/app/views/algos/sectionmanualauto.scala.html b/servers/admin/app/views/algos/sectionmanualauto.scala.html
deleted file mode 100644
index c399bf8..0000000
--- a/servers/admin/app/views/algos/sectionmanualauto.scala.html
+++ /dev/null
@@ -1,28 +0,0 @@
-@(name: String, manualSection: String, autoSection: String)
-                                                <h5>@name</h5>
-                                                <span>* Auto Tuning is an experimental option.<span>
-                                                <div class="bottomMargin switch candy blue" style="width: 250px;">
-                                                    <input id="tuneManual" name="tune" value="manual" type="radio" checked>
-                                                    <label for="tuneManual" onclick="">Manual Tuning</label>
-                                                    <input id="tuneAuto" name="tune" value="auto" type="radio">
-                                                    <label for="tuneAuto" onclick="">Auto Tuning</label>
-                                                    <span class="slide-button"></span>
-                                                </div>
-
-                                                <div id="tuneManualPanel">
-@Html(manualSection)
-                                                </div>
-                                                <div id="tuneAutoPanel" class="hide">
-                                                    <!-- TODO: load tuneMethod based on algotype_id dynamically -->
-                                                    <div class="span12 bottomMargin-large">
-                                                        <p>Select an Autotuning Method:</p>
-                                                        <div>
-                                                            <select id="tuneMethod" name="tuneMethod">
-                                                                <option value="random">Random Search</option>
-                                                            </select>
-                                                        </div>
-                                                    </div>
-
-                                                    <h5>Please specify the Min and Max value range the system should consider during the auto tuning process</h5>
-@Html(autoSection)
-                                                </div>
diff --git a/servers/admin/app/views/algos/selection.scala.html b/servers/admin/app/views/algos/selection.scala.html
deleted file mode 100644
index 2872495..0000000
--- a/servers/admin/app/views/algos/selection.scala.html
+++ /dev/null
@@ -1,12 +0,0 @@
-@(id: String, name: String, description: Option[String], selections: Seq[(String, String)])
-                                                <div class="control-group">
-                                                    <label for="@id" class="control-label">@name</label>
-                                                    <div class="controls">
-                                                        <select name="@id" id="@id" class="span4">
-                                                        @for(s <- selections) {
-                                                            <option value="@s._2">@s._1</option>
-                                                        }
-                                                        </select>
-                                                        @Html(description.map("<span class=\"help-inline\">"+_+"</span>").getOrElse(""))
-                                                    </div>
-                                                </div>
diff --git a/servers/admin/app/views/algos/template.scala.html b/servers/admin/app/views/algos/template.scala.html
deleted file mode 100644
index 6a2192c..0000000
--- a/servers/admin/app/views/algos/template.scala.html
+++ /dev/null
@@ -1,24 +0,0 @@
-@(content: String, emptySection: Boolean)
-<script type="text/template" id="algoSettingsTemplate">
-                        <div class="row-fluid bottomMargin">
-                        <form id="algoSettingsForm">
-                           <div class="span12">
-                                <div class="boxContainer clearfix">
-@Html(content)
-@if(emptySection) {
-                                    <div class="pull-right">
-                                        <a href="#engineTabAlgorithms" class="btn btn-primary">Close</a>
-                                    </div>
-} else {
-                                    <div class="pull-right">
-                                        <a href="#engineTabAlgorithms" class="btn">Cancel</a>
-                                        <button class="btn btn-primary leftMargin" type="submit">Change</button>
-                                    </div>
-}
-                                </div>
-                            </div>
-                        </form>
-                        </div>
-</script>
-
-<div id="algoSettingsContentHolder"></div>
\ No newline at end of file
diff --git a/servers/admin/app/views/algos/template.scala.js b/servers/admin/app/views/algos/template.scala.js
deleted file mode 100644
index e19e37e..0000000
--- a/servers/admin/app/views/algos/template.scala.js
+++ /dev/null
@@ -1,102 +0,0 @@
-@(algoInfoId: String, params: Seq[io.prediction.commons.settings.Param], tuningParams: Seq[io.prediction.commons.settings.Param])
-
-var AlgoSettingsModel = Backbone.Model.extend({
-    /* Required params: app_id, engine_id, id (algo_id) */
-    urlRoot: function(){
-        //return '/modules/itemrec/settings/app/'+ this.get("app_id") +'/engine/' + this.get("engine_id") + '/@(algoInfoId)';
-        return '/apps/' + this.get("app_id") + '/engines/' + this.get("engine_id") + '/algo_settings';
-    }
-});
-
-var AlgoSettingsView = Backbone.View.extend({
-    el: '#algoSettingsContentHolder',
-    initialize : function() {
-        this.form_el = '#algoSettingsForm';
-        this.template = _.template($("#algoSettingsTemplate").html());
-        this.app_id = this.options.app_id;
-        this.engine_id = this.options.engine_id;
-        this.algo_id = this.options.algo_id;
-        this.algotype_id = this.options.algotype_id;
-        this.model = new AlgoSettingsModel({app_id: this.app_id, engine_id: this.engine_id, id: this.algo_id})
-        var self = this;
-        this.model.fetch({
-            success: function() {
-                self.render();
-            @for(p <- params) {
-                self.initValue('@p.id');
-            }
-                //
-                self.initValue('tune');
-                self.initValue('tuneMethod');
-            @for(p <- tuningParams) {
-                self.initValue('@(p.id)Min');
-                self.initValue('@(p.id)Max');
-            }
-                //
-                if (self.model.get('tune') == 'auto') {
-                    self.tuneAuto();
-                }
-
-            }
-        });
-    },
-    initValue: function(attrName){
-        var value = this.model.get(attrName);
-        this.$el.find('#'+attrName).val(value);
-    },
-    events: {
-        "submit #algoSettingsForm" : "formDataSubmit",
-        'click #tuneManual' : "tuneManual",
-        'click #tuneAuto' : "tuneAuto"
-    },
-    render : function() {
-        this.$el.html(this.template());
-        return this;
-    },
-    reloadData : function() { // Required Algorithm Module Function
-    },
-    tuneManual: function() {
-        $('#tuneAuto').removeAttr('checked');
-        $('#tuneManual').attr('checked', 'checked');
-        $('#tuneAutoPanel').slideUp();
-        $('#tuneManualPanel').slideDown();
-    },
-    tuneAuto: function() {
-        $('#tuneManual').removeAttr('checked');
-        $('#tuneAuto').attr('checked', 'checked');
-        $('#tuneManualPanel').slideUp();
-        $('#tuneAutoPanel').slideDown();
-    },
-    formDataSubmit: function() {
-        var data = formToJSON(this.$el.find(this.form_el)); // convert form names/values of fields into key/value pairs
-        data.infotype = "algo";
-        data.infoid = this.algotype_id;
-        var settingSaveInfo = notifyInfoSticky('Saving Settings...','');
-        this.model.save(data, {
-            wait: true,
-            success: function(model, res) {
-                notifyClear(settingSaveInfo);
-                window.location.hash = 'engineTabAlgorithms';
-            },
-            error: function(model, res){
-                notifyClear(settingSaveInfo);
-                notifyErrorResponse(res);
-            }
-        });
-        return false;
-    },
-    close : function() {  // Required Algorithm Module Function
-        this.remove();
-        this.off();
-        // handle other unbinding needs, here
-        _.each(this.subViews, function(subView){
-            if (subView.close){
-                subView.close();
-            }
-        });
-    }
-});
-
-createAlgorithmView = function(app_id, engine_id, algo_id, algotype_id) { // Required Algorithm Module Function
-    return new AlgoSettingsView({app_id: app_id, engine_id: engine_id, algo_id: algo_id, algotype_id: algotype_id});
-};
diff --git a/servers/admin/app/views/algos/text.scala.html b/servers/admin/app/views/algos/text.scala.html
deleted file mode 100644
index 2bdae52..0000000
--- a/servers/admin/app/views/algos/text.scala.html
+++ /dev/null
@@ -1,8 +0,0 @@
-@(id: String, name: String, description: Option[String])
-                                                    <div class="control-group">
-                                                        <label for="@id" class="control-label">@name</label>
-                                                        <div class="controls">
-                                                            <input name="@id" id="@id" class="span2" type="text">
-                                                            @Html(description.map("<span class=\"help-inline\">"+_+"</span>").getOrElse(""))
-                                                        </div>
-                                                    </div>
diff --git a/servers/admin/app/views/algos/textpair.scala.html b/servers/admin/app/views/algos/textpair.scala.html
deleted file mode 100644
index 4224c4c..0000000
--- a/servers/admin/app/views/algos/textpair.scala.html
+++ /dev/null
@@ -1,9 +0,0 @@
-@(id1: String, id2: String, name: String, description: Option[String])
-                                                    <div class="control-group">
-                                                        <label class="control-label">@name</label>
-                                                        <div class="controls">
-                                                            Min: <input name="@id1" id="@id1" class="rightMargin span1" type="text">
-                                                            Max: <input name="@id2" id="@id2" class="span1" type="text">
-                                                            @Html(description.map("<span class=\"help-inline\">"+_+"</span>").getOrElse(""))
-                                                        </div>
-                                                    </div>
diff --git a/servers/admin/app/views/engines/section1.scala.html b/servers/admin/app/views/engines/section1.scala.html
deleted file mode 100644
index 2d4cf98..0000000
--- a/servers/admin/app/views/engines/section1.scala.html
+++ /dev/null
@@ -1,8 +0,0 @@
-@(name: String, description: Option[String], content: String)
-                        <div class="boxBlock">
-                            <div class="boxtitle">@name</div>
-                            <div class="boxContent">
-                                @Html(description.map(d => "<div class=\"row-fluid bottomMargin\">" + d + "</div>").getOrElse(""))
-@Html(content)
-                            </div>
-                        </div>
\ No newline at end of file
diff --git a/servers/admin/app/views/engines/section2.scala.html b/servers/admin/app/views/engines/section2.scala.html
deleted file mode 100644
index e69766f..0000000
--- a/servers/admin/app/views/engines/section2.scala.html
+++ /dev/null
@@ -1,8 +0,0 @@
-@(name: String, description: Option[String], content: String)
-                                <div class="row-fluid">
-                                    <h5>@name</h5>
-                                    <div class="span12">
-                                        @Html(description.map(d => s"<p>$d</p>").getOrElse(""))
-@Html(content)
-                                    </div>
-                                </div>
diff --git a/servers/admin/app/views/engines/selection.scala.html b/servers/admin/app/views/engines/selection.scala.html
deleted file mode 100644
index 8621c69..0000000
--- a/servers/admin/app/views/engines/selection.scala.html
+++ /dev/null
@@ -1,12 +0,0 @@
-@(id: String, name: String, description: Option[String], selections: Seq[(String, String)])
-                                <div class="control-group">
-                                    <label class="control-label">@name</label>
-                                    <div class="controls">
-                                        <select id="@id">
-                                        @for(s <- selections) {
-                                            <option value="@s._2">@s._1</option>
-                                        }
-                                        </select>
-                                        @Html(description.map("<span class=\"help-inline\">"+_+"</span>").getOrElse(""))
-                                    </div>
-                                </div>
diff --git a/servers/admin/app/views/engines/slider.scala.html b/servers/admin/app/views/engines/slider.scala.html
deleted file mode 100644
index fad0424..0000000
--- a/servers/admin/app/views/engines/slider.scala.html
+++ /dev/null
@@ -1,10 +0,0 @@
-@(id: String, name: String, description: Option[String])
-                                <div class="row-fluid bottomMargin">
-                                    <div class="span4">
-                                        <h5>
-                                            @name: <span id="slider-@(id)-val"></span>
-                                        </h5>
-                                        <div id="slider-@(id)"></div>
-                                    </div>
-                                    @Html(description.map("<div class=\"span6\"><br />"+_+"</div>").getOrElse(""))
-                                </div>
diff --git a/servers/admin/app/views/engines/template.scala.html b/servers/admin/app/views/engines/template.scala.html
deleted file mode 100644
index 30fa00d..0000000
--- a/servers/admin/app/views/engines/template.scala.html
+++ /dev/null
@@ -1,80 +0,0 @@
-@(content: String, emptySection: Boolean)
-<script type="text/template" id="engineItemTypeList_template">
-    <td><%= data.itemtype_id %> <input type="hidden" name="engineItemType[<%= data.index %>]" value="<%= data.itemtype_id %>" /></td>
-    <td><a class="removeItemTypeBtn" href="#">[ x ]</a></td>
-</script>
-<script type="text/template" id="engineTemplate">
-    <form>
-            <div class="row-fluid">
-                <div class="span9">
-                    <!-- Prediction Settings -->
-                    <div class="boxContainer">
-                        <div class="boxBlock">
-                            <div class="boxtitle">Item Types Settings</div>
-                            <div class="boxContent">
-                                <p>In your app, you may have more than one type of items,
-                                    e.g. photos, news and jobs. For better prediction accuracy, one
-                                    engine should handle only: One item type (e.g. News), or A set
-                                    of related item types (e.g. World News, Sport News,
-                                    Entertainment News) Please name the item type(s) to be
-                                    recommended by this engine. You will use these names in
-                                    API/SDKs.</p>
-                                <div class="bottomMargin">
-                                    <label class="checkbox">
-                                        <input id="engineAllItemTypes" <% if (data.allitemtypes == true){ %> checked <%} %> name="engineAllItemTypes" type="checkbox" /> Include ALL item types
-                                    </label>
-                                </div>
-                                <div class="row-fluid">
-                                    <div class="span5">
-                                        <table class="table table-condensed">
-                                            <thead>
-                                                <tr>
-                                                    <th>Selected Item Types</th>
-                                                    <th></th>
-                                                </tr>
-                                            </thead>
-                                            <tbody id="engineItemTypeList_ContentHolder">
-                                                <!-- engineItemTypeList_template here -->
-                                            </tbody>
-                                        </table>
-                                    </div>
-                                    <div class="span5 offset1">
-                                        <div class="input-append">
-                                            <input class="span8" id="engineAddItemTypeInput" type="text" placeholder="item type name"/>
-                                            <a href="#" id="engineAddItemTypeBtn" class="btn btn-primary">Add</a>
-                                        </div>
-                                    </div>
-                                </div>
-                            </div>
-                        </div>
-                        <div class="boxBlock">
-                          <div class="boxtitle">Training Schedule</div>
-                          <div class="boxContent">
-                            <p>
-                              You may configure this engine's training schedule in this section.
-                              The schedule can be specified by a valid "Cron-Expression", which is slightly different from the standard crontab.
-                              A description of "Cron-Expression" can be found <a href="http://quartz-scheduler.org/api/2.1.7/org/quartz/CronExpression.html">here</a>.
-                            </p>
-                            <div class="bottomMargin">
-                              <label class="checkbox">
-                                <input id="trainingdisabled" <% if (data.trainingdisabled == true) { %> checked <% } %> name="trainingdisabled" type="checkbox" /> Disable scheduled training
-                              </label>
-                            </div>
-                            <div class="control-group">
-                              <label for="trainingschedule" class="control-label">Training Schedule</label>
-                              <div class="controls">
-                                <input id="trainingschedule" name="trainingschedule" class="span2" type="text" value="<%= data.trainingschedule %>" />
-                                <span class="help-inline">If empty or invalid, "0 0 * * * ?" (train hourly at 0-minute and 0-second) is assumed.</span>
-                              </div>
-                            </div>
-                          </div>
-                        </div>
-@Html(content)
-                    </div>
-                    <!-- End of Prediction Settings -->
-                </div>
-            </div>
-    </form>
-</script>
-
-<div id="engineContentHolder"></div>
diff --git a/servers/admin/app/views/engines/template.scala.js b/servers/admin/app/views/engines/template.scala.js
deleted file mode 100644
index 1cf94b0..0000000
--- a/servers/admin/app/views/engines/template.scala.js
+++ /dev/null
@@ -1,228 +0,0 @@
-@(engineInfoId: String, params: Seq[io.prediction.commons.settings.Param])
-var EngineSettingsModel = Backbone.Model.extend({
-    /* Required params: app_id, id (engine_id) */
-    urlRoot: function(){
-        return '/apps/' + this.get("app_id") + '/engine_settings';
-    },
-    /* Override save for displaying saving status */
-    save: function(attributes, options) {
-        var settingSave = toastr.info('Saving Settings...','', {positionClass: 'toast-bottom-right'});
-        var result = Backbone.Model.prototype.save.call(this, attributes, options);
-        toastr.clear(settingSave);
-        return result;
-    }
-});
-
-var EngineSettingsView = Backbone.View.extend({
-    el: '#engineContentHolder',
-    initialize : function() {
-        this.subViews = []; // keep track of sub view
-        this.template = _.template($("#engineTemplate").html());
-        this.index = 0;
-        this.engine_id = this.options.engine_id;
-        this.app_id = this.options.app_id;
-        this.itemtypelist = {}; // storing itemtypes
-        var self = this;
-        this.model = new EngineSettingsModel({app_id: this.app_id, id: this.engine_id, infotype: "engine", infoid: this.options.engineinfo_id});
-        this.model.fetch({
-            success: function() {
-                self.render();
-
-                // load itemtypes to this.itemtypelist and display it
-                var currItemTypeList = self.model.get('itemtypelist');
-                if (currItemTypeList) {
-                    for (var i=0;i < currItemTypeList.length; i++) {
-                        var currItemtype_id = currItemTypeList[i];
-                        self.itemtypelist[currItemtype_id] = true;
-                        self.addItemTypeView(currItemtype_id);
-                    }
-                }
-
-            @for(p <- params) {
-                self.initValue('@p.id');
-            }
-            }
-        });
-    },
-    initValue: function(attrName){
-        var value = this.model.get(attrName);
-        this.$el.find('#'+attrName).val(value);
-    },
-    events : {
-        "click #engineAddItemTypeBtn" : "addItemType",
-        'keypress #engineAddItemTypeInput': 'onEnterAddItemType',
-        @for(p <- params) {
-            @if(p.ui.uitype != "slider") {
-        "change #@(p.id)": "@(p.id)Changed",
-            }
-        }
-        "change #trainingdisabled" : "trainingdisabledChanged",
-        "change #trainingschedule" : "trainingscheduleChanged",
-        "change #engineAllItemTypes" : "toggleAllItemTypes"
-    },
-    onEnterAddItemType : function(e) {
-        if (e.keyCode == 13) { // if it's ENTER
-            this.addItemType();
-            return false;
-        } else { // continue if it's not ENTER
-            return true;
-        }
-    },
-    addItemType : function() {
-        var inputObj = this.$el.find('#engineAddItemTypeInput');
-        var itemtype_id = inputObj.val();
-        // add itemtype
-        this.itemtypelist[itemtype_id] = true;
-        this.model.set({
-            itemtypelist: MapKeyToArray(this.itemtypelist),
-            allitemtypes: false
-        });
-        var self = this;
-        this.model.save({},{
-            success: function(model, res) {
-                self.addItemTypeView(itemtype_id);
-                inputObj.val(''); // clear input field
-                self.$el.find('#engineAllItemTypes').attr('checked', false); // unselect include all
-            }
-        });
-        return false;
-    },
-    addItemTypeView: function(itemtype_id){
-        var itemTypeView = new EngineSettingsItemTypeView({ itemtype_id: itemtype_id, index: this.index});
-        this.$el.find('#engineItemTypeList_ContentHolder').append(itemTypeView.render().el);
-        this.subViews.push(itemTypeView);
-        this.listenTo(itemTypeView, 'ItemTypeRemoved', this.itemtypeRemoved);
-        itemTypeView.listenTo(this, 'AllItemTypesSelected', itemTypeView.remove);
-        this.index += 1;
-    },
-    itemtypeRemoved: function(itemtype_id) {
-        if (itemtype_id in this.itemtypelist) {
-            delete this.itemtypelist[itemtype_id];
-            if ($.isEmptyObject(this.itemtypelist)) { // if no more selected item types
-                this.model.set({allitemtypes: true});
-                this.$el.find('#engineAllItemTypes').prop('checked', true);
-            }
-            this.model.set({itemtypelist: MapKeyToArray(this.itemtypelist)});
-            this.model.save();
-        }
-    },
-    toggleAllItemTypes: function() {
-        var inputObj = this.$el.find('#engineAllItemTypes');
-        var isAllItemTypes = inputObj.is(':checked');
-        if (isAllItemTypes == true) {   // select AllItemTypes
-            this.trigger('AllItemTypesSelected');
-            this.itemtypelist = {};
-            this.model.set({itemtypelist: MapKeyToArray(this.itemtypelist), allitemtypes: true});
-            this.model.save();
-        } else { //unselect AllItemTypes
-            createDialog('Item Type Required','You must select at least one item type for the engine.', {
-                  resizable: false,
-                  height:185,
-                  modal: false,
-                  buttons: {
-                    Okay: function() {
-                        $( this ).dialog( "close" );
-                    }
-                  }
-            });
-            inputObj.prop('checked', true); // disallow unselect ALlItemTypes manually
-        }
-    },
-    trainingdisabledChanged: function(e) {
-        var trainingdisabled = this.$el.find('#trainingdisabled').is(':checked');
-        this.model.set({trainingdisabled: trainingdisabled});
-        this.model.save();
-        return false;
-    },
-    trainingscheduleChanged: function(e) {
-        var trainingschedule = this.$el.find('#trainingschedule').val();
-        this.model.set({trainingschedule: trainingschedule});
-        this.model.save();
-        return false;
-    },
-    @for(p <- params) {
-        @if(p.ui.uitype != "slider") {
-    @(p.id)Changed: function(e) {
-        var @p.id = this.$el.find('#@p.id').val();
-        this.model.set({@p.id: @p.id});
-        this.model.save();
-        return false;
-    },
-        }
-    }
-    render : function() {
-        this.$el.html(this.template({'data': this.model.toJSON()}));
-        var self = this;
-        @for(p <- params) {
-            @if(p.ui.uitype == "slider") {
-        var @p.id = self.model.get('@p.id');
-
-        this.$el.find("#slider-@p.id").slider({
-            value : @p.id,
-            min : @p.ui.slidermin.get,
-            max : @p.ui.slidermax.get,
-            step : @p.ui.sliderstep.get,
-            slide : function(event, ui) {
-                self.model.set({@p.id: ui.value});
-                self.model.save({}, {success: function(){
-                    self.$el.find("#slider-@p.id-val").text(ui.value);
-                }});
-            }
-        });
-        this.$el.find("#slider-@p.id-val").text(@p.id);
-            }
-        }
-        return this;
-    },
-    reloadData : function() { // Required Engine Module Function
-    },
-    close : function() {  // Required Engine Module Function
-        try {
-            @for(p <- params) {
-                @if(p.ui.uitype == "slider") {
-            this.$el.find("#slider-@p.id").slider("destroy");
-                }
-            }
-        } catch(e){};
-
-        this.remove();
-        this.off();
-        // handle other unbinding needs, here
-        _.each(this.subViews, function(subView){
-            if (subView.close){
-                subView.close();
-            }
-        });
-    }
-});
-
-/* Required Param: itemtype_id, index*/
-var EngineSettingsItemTypeView = Backbone.View.extend({
-    tagName: 'tr',
-    initialize: function(){
-        this.template_el = '#engineItemTypeList_template';
-        this.template = _.template($(this.template_el).html()); // define template function
-        this.itemtype_id = this.options.itemtype_id;
-        this.index  = this.options.index;
-    },
-    events : {
-        "click .removeItemTypeBtn" : "removeItemType"
-    },
-    render: function(){
-        //this.$el.html( this.template({"data": this.model.toJSON()}) );
-        this.$el.html( this.template({"data": {
-            itemtype_id: this.itemtype_id,
-            index: this.index
-        }}) );
-        return this;
-    },
-    removeItemType: function() {
-        this.remove();
-        this.trigger('ItemTypeRemoved', this.itemtype_id);
-        return false;
-    }
-});
-
-var createEngineView = function(app_id, engine_id, engineinfo_id) { // Required Engine Module Function
-    return new EngineSettingsView({app_id: app_id, engine_id: engine_id, engineinfo_id: engineinfo_id});
-};
diff --git a/servers/admin/app/views/engines/text.scala.html b/servers/admin/app/views/engines/text.scala.html
deleted file mode 100644
index 162ec16..0000000
--- a/servers/admin/app/views/engines/text.scala.html
+++ /dev/null
@@ -1,8 +0,0 @@
-@(id: String, name: String, description: Option[String])
-                                <div class="control-group">
-                                    <label for="@id" class="control-label">@name</label>
-                                    <div class="controls">
-                                        <input id="@id" name="@id" class="span2" type="text">
-                                        @Html(description.map("<span class=\"help-inline\">"+_+"</span>").getOrElse(""))
-                                    </div>
-                                </div>
diff --git a/servers/admin/app/views/metrics/section1.scala.html b/servers/admin/app/views/metrics/section1.scala.html
deleted file mode 100644
index cd7c3fd..0000000
--- a/servers/admin/app/views/metrics/section1.scala.html
+++ /dev/null
@@ -1,6 +0,0 @@
-@(name: String, description: Option[String], content: String)
-<div>
-    <div class="form-inline">
-        @Html(content)
-    </div>
-</div>
diff --git a/servers/admin/app/views/metrics/selection.scala.html b/servers/admin/app/views/metrics/selection.scala.html
deleted file mode 100644
index 3ff388c..0000000
--- a/servers/admin/app/views/metrics/selection.scala.html
+++ /dev/null
@@ -1,8 +0,0 @@
-@(id: String, name: String, description: Option[String], selections: Seq[(String, String)], defaultValue: Option[String])
-<label for="@{id}[<%= data.index %>]">@{name} =</label>
-<select name="@{id}[<%= data.index %>]" id="@{id}[<%= data.index %>]" class="span2">
-    @for(s <- selections) {
-        <option value="@s._2" @{defaultValue.map(d => if (s._2 == d) "selected" else "").getOrElse("")}>@s._1</option>
-    }
-</select>
-<!--@Html(description.map("<span class=\"help-inline\">"+_+"</span>").getOrElse("")) -->
diff --git a/servers/admin/app/views/metrics/template.scala.html b/servers/admin/app/views/metrics/template.scala.html
deleted file mode 100644
index f3cdd00..0000000
--- a/servers/admin/app/views/metrics/template.scala.html
+++ /dev/null
@@ -1,4 +0,0 @@
-@(content: String, emptySection: Boolean)
-<!-- <script type="text/template" id="metricSettingsTemplate"> -->
-@Html(content)
-<!-- </script> -->
diff --git a/servers/admin/app/views/metrics/text.scala.html b/servers/admin/app/views/metrics/text.scala.html
deleted file mode 100644
index 4b87d0b..0000000
--- a/servers/admin/app/views/metrics/text.scala.html
+++ /dev/null
@@ -1,4 +0,0 @@
-@(id: String, name: String, description: Option[String], defaultValue: Option[String])
-<label>@{name} =</label>
-<input name="@{id}[<%= data.index %>]" id="@{id}[<%= data.index %>]" class="span1" type="text" @{defaultValue.map { "value="+_ }.getOrElse{""}}>
-<!-- @Html(description.map("<span class=\"help-inline\">"+_+"</span>").getOrElse("")) -->
diff --git a/servers/admin/app/views/splitters/section1.scala.html b/servers/admin/app/views/splitters/section1.scala.html
deleted file mode 100644
index f6d0092..0000000
--- a/servers/admin/app/views/splitters/section1.scala.html
+++ /dev/null
@@ -1,4 +0,0 @@
-@(name: String, description: Option[String], content: String)
-<div>
-    @Html(content)
-</div>
diff --git a/servers/admin/app/views/splitters/selection.scala.html b/servers/admin/app/views/splitters/selection.scala.html
deleted file mode 100644
index 7b0486e..0000000
--- a/servers/admin/app/views/splitters/selection.scala.html
+++ /dev/null
@@ -1,10 +0,0 @@
-@(id: String, name: String, description: Option[String], selections: Seq[(String, String)], defaultValue: Option[String])
-<span>@{name}:</span>
-<select id="@{id}[<%= data.index %>]" name="@{id}[<%= data.index %>]" class="span3">
-    @for(s <- selections) {
-        <option value="@s._2" @{defaultValue.map(d => if (s._2 == d) "selected" else "").getOrElse("")}>@s._1</option>
-    }
-</select>
-<p> 
-    <small>@{description.getOrElse("")}</small>
-</p>
diff --git a/servers/admin/app/views/splitters/template.scala.html b/servers/admin/app/views/splitters/template.scala.html
deleted file mode 100644
index 3b1ae96..0000000
--- a/servers/admin/app/views/splitters/template.scala.html
+++ /dev/null
@@ -1,5 +0,0 @@
-@(content: String, emptySection: Boolean)
-<!-- <script type="text/template" id="splitterSettingsTemplate"> -->
-<input name="infoid[<%= data.index %>]" type="hidden" value="<%= data.splitterinfoid %>">
-@Html(content)
-<!-- </script> -->
diff --git a/servers/admin/app/views/splitters/text.scala.html b/servers/admin/app/views/splitters/text.scala.html
deleted file mode 100644
index c5c3661..0000000
--- a/servers/admin/app/views/splitters/text.scala.html
+++ /dev/null
@@ -1,6 +0,0 @@
-@(id: String, name: String, description: Option[String], defaultValue: Option[String])
-<span>@{name}:</span>
-<input name="@{id}[<%= data.index %>]" id="@{id}[<%= data.index %>]" class="span1" type="text" @{defaultValue.map { "value="+_ }.getOrElse{""}}>
-<p> 
-    <small>@{description.getOrElse("")}</small>
-</p>
diff --git a/servers/admin/build.sbt b/servers/admin/build.sbt
deleted file mode 100644
index adf871d..0000000
--- a/servers/admin/build.sbt
+++ /dev/null
@@ -1,16 +0,0 @@
-name := "predictionio-admin"
-
-version := "0.7.3"
-
-organization := "io.prediction"
-
-libraryDependencies ++= Seq(
-  "io.prediction" %% "predictionio-commons" % version.value,
-  "io.prediction" %% "predictionio-output" % version.value,
-  "commons-codec" % "commons-codec" % "1.8")
-
-javaOptions in Test += "-Dconfig.file=conf/test.conf"
-
-play.Project.playScalaSettings
-
-scalariformSettings
diff --git a/servers/admin/conf/application.conf b/servers/admin/conf/application.conf
deleted file mode 100644
index 3517457..0000000
--- a/servers/admin/conf/application.conf
+++ /dev/null
@@ -1,78 +0,0 @@
-# This is the main configuration file for the application.
-# ~~~~~
-
-# Secret key
-# ~~~~~
-# The secret key is used to secure cryptographics functions.
-# If you deploy your application to several instances be sure to use the same key!
-application.secret="CR2H^VlZ3M3fu;/jDZ<_ZQI`nb[pQ7:TxyV/tACshUD;Udj^5b64F=/J08yTG1A2"
-
-# The application languages
-# ~~~~~
-application.langs="en"
-
-# Global object class
-# ~~~~~
-# Define the Global object class for this application.
-# Default to Global in the root package.
-# global=Global
-
-# Database configuration
-# ~~~~~
-# You can declare as many datasources as you want.
-# By convention, the default datasource is named `default`
-#
-# db.default.driver=org.h2.Driver
-# db.default.url="jdbc:h2:mem:play"
-# db.default.user=sa
-# db.default.password=
-
-# Evolutions
-# ~~~~~
-# You can disable evolutions if needed
-# evolutionplugin=disabled
-
-# Logger
-# ~~~~~
-# You can also configure logback (http://logback.qos.ch/), by providing a logger.xml file in the conf directory .
-
-# Root logger:
-logger.root=ERROR
-
-# Logger used by the framework:
-logger.play=INFO
-
-# Logger provided to your application:
-logger.application=DEBUG
-
-# PredictionIO Repository Base (For Development Only)
-io.prediction.base=../..
-
-# PredictionIO Commons Settings
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.host=localhost
-io.prediction.commons.settings.db.port=27017
-
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.host=localhost
-io.prediction.commons.appdata.db.port=27017
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.host=localhost
-io.prediction.commons.appdata.test.db.port=27017
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.host=localhost
-io.prediction.commons.appdata.training.db.port=27017
-
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.host=localhost
-io.prediction.commons.appdata.validation.db.port=27017
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.host=localhost
-io.prediction.commons.modeldata.db.port=27017
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.host=localhost
-io.prediction.commons.modeldata.training.db.port=27017
diff --git a/servers/admin/conf/routes b/servers/admin/conf/routes
deleted file mode 100644
index a4c0dc6..0000000
--- a/servers/admin/conf/routes
+++ /dev/null
@@ -1,82 +0,0 @@
-# Routes
-# This file defines all application routes (Higher priority routes first)
-# ~~~~
-
-GET     /                           controllers.Application.redirectToWeb
-GET     /web                        controllers.Application.redirectToWeb
-GET     /web/                        controllers.Application.showWeb
-GET     /web/assets/*file               controllers.Assets.at(path="/public", file)
-
-### During development, use enginebase controller instead to avoid cache problems
-# TODO: remove these new routes when work on PDIO-235
-GET     /web/enginebase/*file               controllers.Assets.at(path="/enginebase", file)
-# GET     /web/enginebase/*file                controllers.Application.enginebase(file)
-
-# TODO: use these new routes when work on PDIO-235
-#GET    /engineinfos/:engineinfoid/:filename   controllers.engineinfo.getFile(engineinfoid, filename)
-#GET    /algoinfos/:algoinfoid/:filename       controllers.algoinfo.getFile(algoinfoid, filename)
-
-
-POST    /signin                        controllers.Application.signin
-POST    /signout                       controllers.Application.signout
-
-# Admin User
-GET     /auth                          controllers.Application.getAuth
-
-# An App
-GET     /apps                          controllers.Application.getApplist
-GET     /apps/:id                      controllers.Application.getApp(id: Int)
-POST    /apps                          controllers.Application.createApp
-DELETE  /apps/:id                      controllers.Application.removeApp(id: Int)
-#PUT    /apps/:id                      controllers.Application.updateApp(id: Int)
-GET     /apps/:id/details              controllers.Application.getAppDetails(id: Int)
-POST    /apps/:id/erase_data           controllers.Application.eraseAppData(id: Int)
-
-# System Level
-GET     /engineinfos                   controllers.Application.getEngineInfoList
-GET     /engineinfos/:id/algoinfos     controllers.Application.getEngineInfoAlgoInfoList(id: String)
-GET     /engineinfos/:id/metricinfos   controllers.Application.getEngineInfoMetricInfoList(id: String)
-GET     /engineinfos/:id/splitterinfos controllers.Application.getEngineInfoSplitterInfoList(id: String)
-
-# An Engine of an App
-GET     /apps/:appid/engines          controllers.Application.getAppEnginelist(appid: Int)
-GET     /apps/:appid/engines/:id      controllers.Application.getEngine(appid: Int, id: Int)
-POST    /apps/:appid/engines          controllers.Application.createEngine(appid: Int)
-DELETE  /apps/:appid/engines/:id      controllers.Application.removeEngine(appid: Int, id: Int)
-
-GET     /apps/:appid/engines/:engineid/algos_available      controllers.Application.getAvailableAlgoList(appid: Int, engineid: Int)
-GET     /apps/:appid/engines/:engineid/algos_available/:id  controllers.Application.getAvailableAlgo(appid: Int, engineid: Int, id: Int)
-POST    /apps/:appid/engines/:engineid/algos_available      controllers.Application.createAvailableAlgo(appid: Int, engineid: Int)
-DELETE  /apps/:appid/engines/:engineid/algos_available/:id  controllers.Application.removeAvailableAlgo(appid: Int, engineid: Int, id: Int)
-
-GET     /apps/:appid/engines/:engineid/algos_deployed       controllers.Application.getDeployedAlgoList(appid: Int, engineid: Int)
-POST    /apps/:appid/engines/:engineid/algos_deploy         controllers.Application.algoDeploy(appid: Int, engineid: Int)
-POST    /apps/:appid/engines/:engineid/algos_undeploy       controllers.Application.algoUndeploy(appid: Int, engineid: Int)
-POST    /apps/:appid/engines/:engineid/algos_trainnow       controllers.Application.algoTrainNow(appid: Int, engineid: Int)
-
-GET     /apps/:appid/engines/:engineid/simevals             controllers.Application.getSimEvalList(appid: Int, engineid: Int)
-POST    /apps/:appid/engines/:engineid/simevals             controllers.Application.createSimEval(appid: Int, engineid: Int)
-DELETE  /apps/:appid/engines/:engineid/simevals/:id         controllers.Application.removeSimEval(appid: Int, engineid: Int, id: Int)
-GET     /apps/:appid/engines/:engineid/simevals/:id/report  controllers.Application.getSimEvalReport(appid: Int, engineid: Int, id: Int)
-
-GET     /apps/:appid/engines/:engineid/algos_available/:algoid/autotune_report   controllers.Application.getAlgoAutotuningReport(appid: Int, engineid: Int, algoid: Int)
-POST    /apps/:appid/engines/:engineid/algos_available/:algoid/autotune_apply    controllers.Application.algoAutotuningSelect(appid: Int, engineid: Int, algoid: Int)
-
-# Engine Module
-GET     /apps/:appid/engine_settings/:engineid         controllers.Application.getEngineSettings(appid: Int, engineid: Int)
-PUT     /apps/:appid/engine_settings/:engineid         controllers.Application.updateEngineSettings(appid: Int, engineid: Int)
-
-GET     /apps/:appid/engines/:engineid/template.html   controllers.Application.getEngineTemplateHtml(appid: Int, engineid: Int)
-GET     /apps/:appid/engines/:engineid/template.js     controllers.Application.getEngineTemplateJs(appid: Int, engineid: Int)
-
-# Algo Module
-GET     /apps/:appid/engines/:engineid/algo_settings/:algoid    controllers.Application.getAlgoSettings(appid: Int, engineid: Int, algoid: Int)
-PUT     /apps/:appid/engines/:engineid/algo_settings/:algoid    controllers.Application.updateAlgoSettings(appid: Int, engineid: Int, algoid: Int)
-
-GET     /apps/:appid/engines/:engineid/algos/:algoid/template.html   controllers.Application.getAlgoTemplateHtml(appid: Int, engineid: Int, algoid: Int)
-GET     /apps/:appid/engines/:engineid/algos/:algoid/template.js     controllers.Application.getAlgoTemplateJs(appid: Int, engineid: Int, algoid: Int)
-
-# Metric Info template
-GET     /engineinfos/:engineinfoid/metricinfos/:metricinfoid/template.html    controllers.Application.getMetricInfoTemplateHtml(engineinfoid: String, metricinfoid: String)
-GET     /engineinfos/:engineinfoid/splitterinfos/:splitterinfoid/template.html    controllers.Application.getSplitterInfoTemplateHtml(engineinfoid: String, splitterinfoid: String)
-
diff --git a/servers/admin/conf/test.conf b/servers/admin/conf/test.conf
deleted file mode 100644
index 5c0a210..0000000
--- a/servers/admin/conf/test.conf
+++ /dev/null
@@ -1,81 +0,0 @@
-# This is the main configuration file for the application.
-# ~~~~~
-
-# Secret key
-# ~~~~~
-# The secret key is used to secure cryptographics functions.
-# If you deploy your application to several instances be sure to use the same key!
-application.secret="LXWfyDJiEh];Q]w;6W[97aRF;[TR[2Q0yZCrZP0pbpUC2KpNFov1w5u@bpl=4/Ck"
-
-# The application languages
-# ~~~~~
-application.langs="en"
-
-# Global object class
-# ~~~~~
-# Define the Global object class for this application.
-# Default to Global in the root package.
-# global=Global
-
-# Database configuration
-# ~~~~~
-# You can declare as many datasources as you want.
-# By convention, the default datasource is named `default`
-#
-# db.default.driver=org.h2.Driver
-# db.default.url="jdbc:h2:mem:play"
-# db.default.user=sa
-# db.default.password=
-
-# Evolutions
-# ~~~~~
-# You can disable evolutions if needed
-# evolutionplugin=disabled
-
-# Logger
-# ~~~~~
-# You can also configure logback (http://logback.qos.ch/), by providing a logger.xml file in the conf directory .
-
-# Root logger:
-logger.root=ERROR
-
-# Logger used by the framework:
-logger.play=INFO
-
-# Logger provided to your application:
-logger.application=DEBUG
-
-# PredictionIO Repository Base (For Development Only)
-io.prediction.base=../..
-
-# PredictionIO Commons Settings
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.host=localhost
-io.prediction.commons.settings.db.port=27017
-io.prediction.commons.settings.db.name=test_admin_predictionio
-
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.host=localhost
-io.prediction.commons.appdata.db.port=27017
-io.prediction.commons.appdata.db.name=test_admin_predictionio_appdata
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.host=localhost
-io.prediction.commons.appdata.test.db.port=27017
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.host=localhost
-io.prediction.commons.appdata.training.db.port=27017
-
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.host=localhost
-io.prediction.commons.appdata.validation.db.port=27017
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.host=localhost
-io.prediction.commons.modeldata.db.port=27017
-io.prediction.commons.modeldata.db.name=test_admin_predictionio_modeldata
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.host=localhost
-io.prediction.commons.modeldata.training.db.port=27017
diff --git a/servers/admin/project/build.properties b/servers/admin/project/build.properties
deleted file mode 100644
index 0974fce..0000000
--- a/servers/admin/project/build.properties
+++ /dev/null
@@ -1 +0,0 @@
-sbt.version=0.13.0
diff --git a/servers/admin/project/plugins.sbt b/servers/admin/project/plugins.sbt
deleted file mode 100644
index 16ba183..0000000
--- a/servers/admin/project/plugins.sbt
+++ /dev/null
@@ -1,10 +0,0 @@
-// Comment to get more information during initialization
-logLevel := Level.Warn
-
-// The Typesafe repository
-resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
-
-// Use the Play sbt plugin for Play projects
-addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.2.2")
-
-addSbtPlugin("com.typesafe.sbt" % "sbt-scalariform" % "1.2.1")
diff --git a/servers/admin/public/images/favicon.png b/servers/admin/public/images/favicon.png
deleted file mode 100644
index c7d92d2..0000000
--- a/servers/admin/public/images/favicon.png
+++ /dev/null
Binary files differ
diff --git a/servers/admin/public/images/predictionio.png b/servers/admin/public/images/predictionio.png
deleted file mode 100644
index 90e15b6..0000000
--- a/servers/admin/public/images/predictionio.png
+++ /dev/null
Binary files differ
diff --git a/servers/admin/public/javascripts/core.js b/servers/admin/public/javascripts/core.js
deleted file mode 100644
index 31ab50b..0000000
--- a/servers/admin/public/javascripts/core.js
+++ /dev/null
@@ -1,1604 +0,0 @@
-var ADMIN_API_PATH = '/';
-function getAPIUrl(path) {
-    return ADMIN_API_PATH + path;
-}
-
-/* TO BE DISCUSSED: whether we want to use default 'id' or mongo's '_id'
- * Backbone.Model.prototype.idAttribute = "_id";
- */
-
-/* Function to convert form's name/value pairs to JSON */
-function formToJSON(formObj) {
-    var arr = formObj.serializeArray();
-    var data = _(arr).reduce(function(acc, field) {
-        acc[field.name] = field.value;
-        return acc;
-    }, {});
-    return data;
-}
-function getUrlParam(key) {
-    var result = new RegExp(key + "=([^&]*)", "i").exec(window.location.search);
-    return result && decodeURIComponent(result[1]) || "";
-}
-/* URI encode keys of map, separated by , */
-function encodeURIComponentMapKey(jmap) {
-      var array = [];
-      for (var key in jmap)
-          array.push(encodeURIComponent(key));
-      return array.join(',');
-}
-function MapKeyToArray(mapObj) {
-    var array = [];
-    for (var key in mapObj) {
-        if (mapObj.hasOwnProperty(key)) {
-            array.push(key);
-        }
-    }
-    return array;
-}
-/* Global Dialogbox function */
-function createDialog(title, content, params) {
-    $('#dialog_template').attr('title',title).find('#dialog_text').text(content).end().dialog(params);
-}
-
-function createDialogErrorResponse(res) {
-    var message = "HTTP " + res.status + ". ";
-    try { // show error message if fail
-        var resData = $.parseJSON(res.responseText);
-        message = message + resData.message;
-    } catch (err) {
-        message = message + "An error has occured.";
-    }
-    createDialog("", message, {
-        width: 400,
-        modal: true
-    });
-}
-
-/* Notification functions */
-function notifyInfo(message, title, optionsOverride) {
-    return toastr.info(message, title, optionsOverride);
-}
-
-function notifySuccess(message, title, optionsOverride) {
-    return toastr.success(message, title, optionsOverride);
-}
-
-function notifyError(message, title, optionsOverride) {
-    return toastr.error(message, title, optionsOverride);
-}
-
-function notifyErrorSticky(message, title) {
-    return toastr.error(message, title, {positionClass: 'toast-bottom-right', timeOut: 0, extendedTimeOut: 0});
-}
-
-function notifyInfoDefault(message, title) {
-    return toastr.info(message, title, {positionClass: 'toast-bottom-right', timeOut: 4000});
-}
-
-function notifyInfoSticky(message, title) {
-    return toastr.info(message, title, {positionClass: 'toast-bottom-right', timeOut: 0, extendedTimeOut: 0, fadeOut: 1});
-}
-
-function notifyClear(element) {
-    return toastr.clear(element);
-}
-
-function notifyErrorResponse(res) {
-    var message = "HTTP " + res.status + ". ";
-    try { // show error message if fail
-        var resData = $.parseJSON(res.responseText);
-        message = message + resData.message;
-    } catch (err) {
-        message = message + "An error has occured.";
-    }
-    notifyErrorSticky(message, "");
-}
-
-$(function() {
-    // TODO: prevent "a href='#'" behavior
-
-    var core_router = new CoreRouter();
-    Backbone.history.start();
-});
-
-/*
- *  Default Close Methods for Backbone Views
- *  Add custom closing codes to 'beforeClose' method in your View class
- *  Push subviews to this.subViews = [] so that they will be closed automatically (e.g. this.subViews.push(subView);)
- */
-Backbone.View.prototype.close = function() {
-    if (this.beforeClose) {  // for custom closing codes
-        this.beforeClose();
-    }
-    this.remove();
-    this.off();
-    if (this.subViews) {  // for closing subviews
-        _.each(this.subViews, function(subView){
-            if (subView.close){
-                subView.close();
-            }
-        });
-    }
-}
-
-/* abstract function for engine and algo modules */
-var createAlgorithmView = function() { return null; };
-var createEngineView = function(appid, engineid) { return null; };
-
-var CoreRouter = Backbone.Router.extend({
-    initialize : function() {
-        this.target_el = '#ContentHolder';
-        this.currentView = null;
-        this.auth_el = '#AuthHolder';
-        this.authView = new AuthView();
-        $(this.auth_el).html(this.authView.render().el);
-    },
-    routes : {
-        signin : 'signinPage',
-        signout : 'signout',
-        appsDashboard : 'appsDashboardPage',
-        engine : 'engineTabSettings',
-        engineTabSettings : 'engineTabSettings',
-        engineTabAlgorithms : 'engineTabAlgorithms',
-        engineAddAlgorithm : 'engineExtraTabAddAlgorithm',
-        addEngine : 'addEnginePage',
-        'algoSettings/:algoinfoid/:algoName/:algoid' : 'engineExtraTabAlgorithmSettings',
-        'algoAutotuningReport/:algoid' : 'engineExtraTabAlgoAutotuningReport',
-        'simEvalSettings/:algoidlist' : 'engineExtraTabSimEvalSettings',
-        'simEvalReport/:id' : 'engineExtraTabSimEvalReport',
-        '*actions' : 'defaultRoute' // default -- exception
-    },
-    defaultRoute : function(action) { // exception
-        var path = window.location.protocol + '//' + window.location.host + window.location.pathname + '#appsDashboard';
-        window.location = path;
-    },
-    signinPage : function() {
-        this.authView.clearAuth();
-        if (this.currentView) {this.currentView.close();}
-        this.currentView = new SigninView();
-        $(this.target_el).html(this.currentView.render().el);
-    },
-    signout: function() {
-        $.post(getAPIUrl('signout')).success(function() {
-            window.location.hash = 'signin';
-        }).error(function(res){
-            alert("An error has occured. HTTP Status Code: " + res.status);
-        });
-        return false;
-    },
-    appsDashboardPage : function() {
-        this.authView.ensureAuth();
-        if (this.currentView) {this.currentView.close();}
-        this.currentView = new AppsDashboardView();
-        $(this.target_el).html(this.currentView.render().el);
-    },
-    engineTabSettings : function() {
-        this.authView.ensureAuth();
-        if (!this.currentView || !this.currentView.isEngineView) { // if not currently Engine view
-            if (this.currentView) {this.currentView.close();}
-            this.currentView = new EngineView();
-            $(this.target_el).html(this.currentView.render().el);
-        }
-        this.currentView.showTabSettings();
-        return false;
-    },
-    engineTabAlgorithms : function() {
-        this.authView.ensureAuth();
-        if (!this.currentView || !this.currentView.isEngineView) { // if not currently Engine view
-            if (this.currentView) {this.currentView.close();}
-            this.currentView = new EngineView();
-            $(this.target_el).html(this.currentView.render().el);
-        }
-        this.currentView.showTabAlgorithms();
-        return false;
-    },
-    engineExtraTabAddAlgorithm : function() {
-        this.authView.ensureAuth();
-        if (!this.currentView || !this.currentView.isEngineView) { // if not currently Engine view
-            if (this.currentView) {this.currentView.close();}
-            this.currentView = new EngineView();
-            $(this.target_el).html(this.currentView.render().el);
-        }
-        this.currentView.showExtraTabAddAlgorithm();
-        return false;
-    },
-    addEnginePage : function() {
-        this.authView.ensureAuth();
-        if (this.currentView) {this.currentView.close();}
-        this.currentView = new AddEngineView();
-        $(this.target_el).html(this.currentView.el);
-    },
-    engineExtraTabAlgorithmSettings: function(algoinfoid, algoName, algoid) {
-        this.authView.ensureAuth();
-        if (!this.currentView || !this.currentView.isEngineView) { // if not currently Engine view
-            if (this.currentView) {this.currentView.close();}
-            this.currentView = new EngineView();
-            $(this.target_el).html(this.currentView.render().el);
-        }
-        this.currentView.showExtraTabAlgorithmSettings(algoinfoid, algoName, algoid);
-    },
-    engineExtraTabAlgoAutotuningReport: function(algoid) {
-        this.authView.ensureAuth();
-        if (!this.currentView || !this.currentView.isEngineView) { // if not currently Engine view
-            if (this.currentView) {this.currentView.close();}
-            this.currentView = new EngineView();
-            $(this.target_el).html(this.currentView.render().el);
-        }
-        this.currentView.showExtraTabAlgoAutotuningReport(algoid);
-    },
-    engineExtraTabSimEvalReport : function(simeval_id) {
-        this.authView.ensureAuth();
-        if (!this.currentView || !this.currentView.isEngineView) { // if not currently Engine view
-            if (this.currentView) {this.currentView.close();}
-            this.currentView = new EngineView();
-            $(this.target_el).html(this.currentView.render().el);
-        }
-        this.currentView.showExtraTabSimEvalReport(simeval_id);
-    },
-    engineExtraTabSimEvalSettings : function(algoidlist) {
-        // TODO: encodeURIComponent each element in the comma-separated algoidlist
-        this.authView.ensureAuth();
-        if (!this.currentView || !this.currentView.isEngineView) { // if not currently Engine view
-            if (this.currentView) {this.currentView.close();}
-            this.currentView = new EngineView();
-            $(this.target_el).html(this.currentView.render().el);
-        }
-        this.currentView.showExtraTabSimEvalSettings(algoidlist);
-    }
-});
-
-var AuthModel = Backbone.Model.extend({
-    urlRoot : getAPIUrl('auth')
-});
-var AuthView = Backbone.View.extend({
-    initialize: function(){
-        this.template_el = '#auth_template';
-        this.template = _.template($(this.template_el).html()); // define template function
-        this.isEnsureAuth = false;
-        this.model = new AuthModel(); // assign auth data model
-        this.model.bind('change', this.render, this);
-        this.reloadAuth();
-    },
-    render: function(){
-        this.$el.html( this.template({"data": this.model.toJSON()}) );
-        // for v0.2 processing task
-        // this.navAuthViewObj = new NavTaskView();
-        return this;
-    },
-    reloadAuth: function() {
-        var self = this; // for accessing "this" in callback func
-        self.model.clear({ silent: true }); // clear previous auth model data
-        this.model.fetch({
-            error: function() {
-                if (self.isEnsureAuth) { // if auth required but auth fails, redirect to #signin
-                    self.isEnsureAuth = false;
-                    window.location.hash = 'signin';
-                }
-                self.render(); // show no auth view
-            }
-        });
-    },
-    ensureAuth: function() {
-        this.isEnsureAuth = true;
-        this.reloadAuth();
-    },
-    clearAuth: function() {
-        this.model.clear();
-    }
-})
-
-
-var BreadcrumbView = Backbone.View.extend({
-    initialize : function() {
-        this.template_el = '#breadcrumb_template';
-        this.template = _.template($(this.template_el).html()); // define template function
-        this.appid = getUrlParam("appid");
-        this.engineid = getUrlParam("engineid");
-        this.engineinfoid = getUrlParam("engineinfoid");
-    },
-    render : function() {
-        var data = {};
-        $.ajaxSetup({async:false});
-        if (this.appid) {
-            data['appid'] = this.appid;
-            var appModel = new AppModel({id: this.appid});
-            appModel.fetch({
-                success: function() {
-                    data['appname'] = appModel.get('appname');
-                }
-            });
-        }
-        if (this.engineid) {
-            data['engineid'] = this.engineid;
-            var engineModel = new EngineModel({appid: this.appid, id: this.engineid});
-            engineModel.fetch({
-                success: function() {
-                    data['enginename'] = engineModel.get('enginename');
-                }
-            });
-
-        }
-        if (this.engineinfoid)
-            data['engineinfoid'] = this.engineinfoid;
-        $.ajaxSetup({async:true});
-
-        this.$el.slideUp().html(this.template({"data": data})).slideDown();
-        return this;
-    }
-});
-
-
-
-var SigninView = Backbone.View.extend({
-    initialize : function() {
-        this.template_el = '#signin_template';
-        this.error_el = '#signinFormError'; // read error template dom
-        this.form_el = '#signinForm';
-        this.template = _.template($(this.template_el).html()); // define template function
-    },
-    events : {
-        "submit" : "auth" // bind form submit to auth function
-    },
-    render : function() {
-        this.$el.html(this.template());
-        return this;
-    },
-    auth : function() {
-        $(this.error_el).slideUp().html(""); // reset/clear all error msg
-        var data = formToJSON(this.$el.find(this.form_el)); // convert form names/values of fields into key/value pairs
-        // post to server
-        var self = this; // for accessing "this" in callback function
-        $.post(getAPIUrl('signin'), data).success(function() {
-                window.location.hash = 'appsDashboard';
-        }).error(function(res){
-            try { // show error message if fail
-                var resData = $.parseJSON(res.responseText);
-                $(self.error_el).html(resData.message).slideDown("fast");
-            } catch (err) {
-                alert("An error has occured. HTTP Status Code: "
-                        + res.status);
-            }
-        });
-        return false;
-    }
-})
-
-var AppsDashboardView = Backbone.View.extend({
-    initialize: function(){
-        this.template_el = '#appsDashboard_template';
-        this.template = _.template($(this.template_el).html());
-        this.subViews = [];
-        this.appListView = new AppListView();
-        this.subViews.push(this.appListView); // for auto subview closing
-        this.listenTo(this.appListView, 'NoApp', this.showAddApp); // show AddApp area if there's no existing app
-    },
-    render : function() {
-        this.$el.html(this.template());
-        this.$el.find('#appList').html(this.appListView.render().el);
-        return this;
-    },
-    events: {
-        "click #showAddAppBtn": "showAddApp",
-        "click #createAppBtn": "createApp"
-    },
-    showAddApp: function() {
-        this.$el.find("#appCreatePanel").slideDown("fast");
-        this.$el.find("#showAddAppBtn").attr("disabled", "true");
-        return false;
-    },
-    hideAddApp: function() {
-        var self = this;
-        this.$el.find("#appCreatePanel").slideUp("fast", function(){
-            self.$el.find("#addAppInputError").hide().html(""); // reset error message
-            self.$el.find("#addAppInput").val(""); // clearn input value
-            self.$el.find("#showAddAppBtn").removeAttr("disabled");
-        });
-        return false;
-    },
-    createApp: function() {
-        this.$el.find("#addAppInputError").html(""); // reset error msg
-        var appName = this.$el.find("#addAppInput").val();
-        var self= this;
-        this.appListView.collection.create({
-            "appname": appName
-        }, {
-            wait: true, // wait for server to return the new app info
-            success: function() {
-                self.hideAddApp();
-            },
-            error: function(model, res) {
-                try { // show error message if fail
-                    var resData = $.parseJSON(res.responseText);
-                    $("#addAppInputError").html(resData.message).slideDown("fast");
-                } catch(err) {
-                    alert("An error has occured. HTTP Status Code: " + res.status);
-                }
-            }
-        });
-        return this;
-    }
-});
-
-var AppModel = Backbone.Model.extend({
-    urlRoot: getAPIUrl('apps')
-});
-var AppListModel = Backbone.Collection.extend({
-    model: AppModel,
-    url: getAPIUrl('apps')
-});
-var AppListView = Backbone.View.extend({
-    initialize: function(){
-        this.subViews = [];
-        this.collection = new AppListModel();
-        this.collection.bind('add', this.addOne, this);
-        this.collection.bind('reset', this.render, this);
-        this.collection.fetch();
-    },
-    render: function(eventData) {
-        if (eventData) {
-            this.$el.html(""); // clear previous html
-            _.each(eventData.models, function(appModel){
-                this.addOne(appModel); // debug: console.log(app.attributes['id']);
-            }, this);
-            if (eventData.models.length == 0) {
-                this.trigger('NoApp');
-            }
-        }
-        return this;
-    },
-    addOne: function(appModel) {
-        var appView = new AppView({ model:appModel}); // create app view
-        this.subViews.push(appView); // for auto subview closing
-        $(appView.render().el).css("display", "none").appendTo(this.$el).slideDown("fast");
-    }
-});
-
-var AppView = Backbone.View.extend({
-    /*
-     * Required Param: model
-     */
-    initialize: function(){
-        this.id = this.model.get("id"); // app id
-        this.template_el = "#app_template";
-        this.template = _.template($(this.template_el).html());
-        this.subViews = [];
-        this.showdetails = false;
-    },
-    events: {
-        "click .toggleAppDetailsAction":  "toggleDetails",
-        "click .eraseAllDataAction":  "eraseAllData",
-        "click .removeAppAction":  "removeApp"
-    },
-    render : function() {
-        this.$el.html(this.template({"data": this.model.toJSON()}));
-        return this;
-    },
-    toggleDetails: function() {
-        if (this.showdetails) {
-            this.showdetails = false;
-            this.hideDetails();
-        } else {
-            this.showdetails = true;
-            this.showDetails();
-        }
-        return false;
-    },
-    showDetails: function() {
-        // show app details
-        this.appDetailsView = new AppDetailsView({"id": this.id});
-        this.subViews.push(this.appDetailsView);
-        this.$el.find(".appdetails").html( this.appDetailsView.render().el );
-        // show app engine list
-        this.appEnginelistView = new AppEnginelistView({"id": this.id});
-        this.subViews.push(this.appEnginelistView);
-        this.$el.find(".appenginelist").html( this.appEnginelistView.render().el );
-
-        this.$el.find(".app-info").slideDown("fast"); // make app details area visible
-    },
-    hideDetails: function() {
-        var self = this;
-        this.$el.find(".app-info").slideUp("fast", function(){ // make app details area hidden
-            self.appDetailsView.close();
-            self.appEnginelistView.close();
-        });
-    },
-    eraseAllData: function() {
-        var self = this;
-        createDialog('Erase All Data?','All data of this application will be permanently erased and cannot be recovered. Are you sure?', {
-              resizable: false,
-              height:185,
-              modal: true,
-              buttons: {
-                "Erase All Data": function() {
-                    var erasingInfo = notifyInfoSticky('Erasing All Application Data...','');
-                    $.post(getAPIUrl("apps/"+self.id+"/erase_data"), function() {
-                        self.appDetailsView.model.fetch(); // refresh data
-                        notifyClear(erasingInfo);
-                        notifyInfoDefault('Data Erased.','');
-                    }).error(function(res) {
-                        notifyClear(erasingInfo);
-                        notifyErrorResponse(res);
-                    });
-                    $( this ).dialog( "close" );
-                },
-                Cancel: function() {
-                    $( this ).dialog( "close" );
-                }
-              }
-        });
-        return false;
-    },
-    removeApp: function() {
-        var self = this;
-        createDialog('Remove Application?','This application and all its data will be permanently deleted and cannot be recovered. Are you sure?', {
-              resizable: false,
-              height:185,
-              modal: true,
-              buttons: {
-                "Delete Application": function() {
-                    var deletingInfo = notifyInfoSticky('Deleting Application...','');
-                    self.model.destroy({
-                        success: function(model, res) {
-                            notifyClear(deletingInfo);
-                            notifyInfoDefault('Application Deleted.','');
-                            self.close();
-                        },
-                        error: function(model, res) {
-                            notifyClear(deletingInfo);
-                            notifyErrorResponse(res);
-                        }
-                    });
-                    $( this ).dialog( "close" );
-                },
-                Cancel: function() {
-                    $( this ).dialog( "close" );
-                }
-              }
-        });
-        return false;
-    }
-});
-
-var AppDetailsModel = Backbone.Model.extend({
-    url: function() {
-        return getAPIUrl('apps/' + this.id + "/details");
-    }
-});
-var AppDetailsView = Backbone.View.extend({
-    /*
-     * Required Param: id  (app id)
-     */
-    initialize: function(){
-        this.id = this.options.id; // app id
-        this.model = new AppDetailsModel({"id": this.id});
-        this.template = _.template($("#appdetails_template").html());
-
-        this.model.bind('change', this.render, this);
-        this.model.fetch();
-    },
-    events: {
-        "click .detailsRefreshAction":  "refresh"
-    },
-    //
-    render: function() {
-        this.$el.html(this.template({"data": this.model.toJSON()}));
-        return this;
-    },
-    refresh: function() {
-        this.model.fetch();
-        return false;
-    }
-});
-
-
-var AppEnginelistModel = Backbone.Model.extend({
-    url: function() {
-        return getAPIUrl('apps/' + this.id + '/engines');
-    }
-});
-var AppEnginelistView = Backbone.View.extend({
-    /*
-     * Required Param: id  (app id)
-     */
-    initialize: function(){
-        this.id = this.options.id; // app id
-        this.model = new AppEnginelistModel({"id": this.id});
-        this.template = _.template($("#appenginelist_template").html());
-
-        this.model.bind('change', this.render, this);
-        this.model.fetch();
-    },
-    render: function() {
-        this.$el.html(this.template({"data": this.model.toJSON()}));
-        return this;
-    },
-});
-
-var EngineStatusView = Backbone.View.extend({
-    initialize : function() {
-        this.template_el = '#engineStatus_template';
-        this.template = _.template($(this.template_el).html()); // define template function
-        this.appid = getUrlParam("appid");
-        this.engineid = getUrlParam("engineid");
-        this.engineinfoid = getUrlParam("engineinfoid");
-        this.model = new EngineModel({appid: this.appid, id: this.engineid});
-    },
-    events: {
-        "click #engineStatusReloadBtn" : "render"
-    },
-    render : function() {
-        this.poll(this);
-        return this;
-    },
-    poll: function(view) {
-        view.model.fetch({
-            success: function() {
-                view.$el.html(view.template({"data": view.model.toJSON()}));
-                setTimeout(function() {view.poll(view);}, 2000);
-            }
-        });
-        return view;
-    }
-});
-
-var EngineView = Backbone.View.extend({
-    initialize : function() {
-        this.subViews = [];
-        this.template_el = '#engine_template';
-        this.template = _.template($(this.template_el).html());
-        // TODO: Error checking for IDs
-        this.appid = getUrlParam("appid");
-        this.engineid = getUrlParam("engineid");
-        this.engineinfoid = getUrlParam("engineinfoid");
-        this.tabSettingsView == null;
-        this.tabAlgorithmsView == null;
-        this.tabExtraTabView == null;
-
-        this.breadcrumbView = new BreadcrumbView();
-        this.engineStatusView = new EngineStatusView();
-        this.subViews.push(this.breadcrumbView);
-        this.subViews.push(this.engineStatusView);
-    },
-    events: {
-        "click #deleteEngineBtn":  "deleteEngine"
-    },
-    render : function() {
-        this.$el.html(this.template());
-        this.$el.find('#breadcrumb_ContentHolder').html(this.breadcrumbView.render().el);
-        this.$el.find('#engineStatus_ContentHolder').html(this.engineStatusView.render().el);
-        return this;
-    },
-    isEngineView : function() {
-        return true;
-    },
-    closeExtraTab : function() {
-        if (this.tabExtraTabView) {
-            // remove data split slider for EngineSimEvalSetting page
-            if (this.tabExtraTabView.isEngineSimEvalSettingsView) {
-                $("#dataSplitBar").colResizable({disable:true});
-            }
-            this.tabExtraTabView.close();
-            this.$el.find('#engineExtraTabTitle').hide();
-            this.$el.find("#engineExtraTabContentHolder").html("");
-        }
-
-    },
-    showTabSettings : function() {
-        this.closeExtraTab();
-        this.$el.find("#engineTabSettingsBtn").tab('show');
-        if (!this.tabSettingsView) {
-            $.ajaxSetup({async:false}); // make jquery sync temporary to ensure it's loaded before we move on
-            //this.$el.find("#engineTabSettingsContentHolder").load("enginebase/Engines/" + this.engineinfoid + "/engine.template.html");
-            //$.getScript("enginebase/Engines/" + this.engineinfoid + "/engine.js");
-            this.$el.find("#engineTabSettingsContentHolder").load("/apps/" + this.appid + "/engines/" + this.engineid + "/template.html");
-            $.getScript("/apps/" + this.appid + "/engines/" + this.engineid + "/template.js");
-            $.ajaxSetup({async:true});
-            // engine template and js should be ready by now
-            this.tabSettingsView = createEngineView(this.appid, this.engineid, this.engineinfoid);
-            this.subViews.push(this.tabSettingsView);
-        } else {
-            this.tabSettingsView.reloadData();
-        }
-        return false;
-    },
-    showTabAlgorithms : function() {
-        this.closeExtraTab();
-        this.$el.find("#engineTabAlgorithmsBtn").tab('show');
-
-        if (!this.tabAlgorithmsView) {
-            this.tabAlgorithmsView = new EngineAlgorithmsView();
-            this.engineStatusView.listenTo(this.tabAlgorithmsView, 'engineStatusUpdate', this.engineStatusView.render); // listen to engineStatusUpdate event
-            this.subViews.push(this.tabAlgorithmsView);
-            this.$el.find("#engineTabAlgorithmsContentHolder").html(this.tabAlgorithmsView.render().el);
-        } else {
-            this.tabAlgorithmsView.reloadData();
-        }
-        return false;
-    },
-    showExtraTabAddAlgorithm : function() {
-        this.closeExtraTab();
-        this.$el.find('#engineExtraTabBtn').html("Add an Algorithm").tab('show');
-        this.$el.find('#engineExtraTabTitle').show();
-
-        this.tabExtraTabView = new EngineAddAlgorithmView();
-        this.subViews.push(this.tabExtraTabView);
-        this.$el.find("#engineExtraTabContentHolder").html(this.tabExtraTabView.render().el);
-    },
-    showExtraTabAlgorithmSettings : function(algoinfoid, algoName, algoid) {
-        this.closeExtraTab();
-        this.$el.find('#engineExtraTabBtn').html("Algorithm Settings: "+algoName).tab('show');
-        this.$el.find('#engineExtraTabTitle').show();
-
-        $.ajaxSetup({async:false}); // make jquery sync temporary to ensure it's loaded before we move on
-        this.$el.find("#engineExtraTabContentHolder").load("/apps/" + this.appid + "/engines/" + this.engineid + "/algos/" + algoid + "/template.html");
-        $.getScript("/apps/" + this.appid + "/engines/" + this.engineid + "/algos/" + algoid + "/template.js");
-        $.ajaxSetup({async:true});
-        // algorithm template and js should be ready by now
-        this.tabExtraTabView = createAlgorithmView(this.appid, this.engineid, algoid, algoinfoid);
-        this.subViews.push(this.tabExtraTabView);
-    },
-    showExtraTabAlgoAutotuningReport : function(algoid) {
-        this.closeExtraTab();
-        this.$el.find('#engineExtraTabBtn').html("Algo Auto-tuning Report").tab('show');
-        this.$el.find('#engineExtraTabTitle').show();
-
-        this.tabExtraTabView = new EngineAlgoAutotuningReportView({id: algoid});
-        this.subViews.push(this.tabExtraTabView);
-        this.$el.find("#engineExtraTabContentHolder").html(this.tabExtraTabView.render().el);
-    },
-    showExtraTabSimEvalReport : function(simeval_id) {
-        this.closeExtraTab();
-        this.$el.find('#engineExtraTabBtn').html("Simulated Evaluation Report").tab('show');
-        this.$el.find('#engineExtraTabTitle').show();
-
-        this.tabExtraTabView = new EngineSimEvalReportView({id: simeval_id});
-        this.subViews.push(this.tabExtraTabView);
-        this.$el.find("#engineExtraTabContentHolder").html(this.tabExtraTabView.render().el);
-    },
-    showExtraTabSimEvalSettings : function(algoidlist) {
-        this.closeExtraTab();
-        this.$el.find('#engineExtraTabBtn').html("Simulated Evaluation Settings").tab('show');
-        this.$el.find('#engineExtraTabTitle').show();
-
-        this.tabExtraTabView = new EngineSimEvalSettingsView({algoidlist: algoidlist});
-        this.subViews.push(this.tabExtraTabView);
-
-        this.$el.find("#engineExtraTabContentHolder").html(this.tabExtraTabView.render().el).promise().done(function(){
-            $("#dataSplitBar").colResizable({
-                liveDrag: true,
-                draggingClass: "rangeDrag",
-                gripInnerHtml: "<div class='rangeGrip'></div>",
-                onDrag: onSimEvalDataSplitPercentChange,
-                minWidth: 12
-            });
-        });
-    },
-    deleteEngine : function() {
-        var self = this;
-        createDialog('Remove Engine?','This engine and all its data will be permanently deleted and cannot be recovered. Are you sure?', {
-              resizable: false,
-              height:185,
-              modal: true,
-              buttons: {
-                "Delete Engine": function() {
-                    var engineModel = new EngineModel({appid: self.appid, id: self.engineid});
-                    var erasingInfo = notifyInfoSticky('Removing engine. Please wait...','');
-                    engineModel.destroy({
-                        success: function() {
-                            notifyClear(erasingInfo);
-                            notifyInfoDefault('Engine removed.','');
-                            window.location = '/';
-                        },
-                        error: function(model, res) {
-                            notifyClear(erasingInfo);
-                            notifyErrorResponse(res);
-                        }
-                    });
-                    $( this ).dialog( "close" );
-                },
-                Cancel: function() {
-                    $( this ).dialog( "close" );
-                }
-              }
-        });
-        return false;
-    }
-});
-
-/* Data Split Slider onChange in EngineSimEvalSettings */
-var onSimEvalDataSplitPercentChange = function(e){
-    var columns = $(e.currentTarget).find("td");
-    var ranges = [], total = 0, i, w;
-    for(i = 0; i<columns.length; i++) {
-        // workaround, fix it later
-        if (i==0) {
-            w = columns.eq(i).width() - 9;
-        } else if (i==2) {
-            w = columns.eq(i).width() - 12;
-        } else {
-            w = columns.eq(i).width();
-        }
-        ranges.push(w);
-        total+=w;
-    }
-    for(i=0; i<columns.length; i++){
-        ranges[i] = 100*ranges[i]/total;
-    }
-    var trainPercent = Math.round(ranges[0]);
-    var testPercent = Math.round(ranges[1]);
-    var unusedPercent = 100 - trainPercent - testPercent;
-    $('#simEvalSettingsForm').find('#splittrain').val(trainPercent).end().find('#splittest').val(testPercent).end();
-};
-/*
-var onDataSplitPercentChange = function(e){
-    var columns = $(e.currentTarget).find("td");
-    var ranges = [], total = 0, i, w;
-    for(i = 0; i<columns.length; i++) {
-        // workaround, fix it later
-        if (i==0) {
-            w = columns.eq(i).width() - 35;
-        } else if (i==3) {
-            w = columns.eq(i).width() - 14;
-        } else {
-            w = columns.eq(i).width() -7;
-        }
-        ranges.push(w);
-        total+=w;
-    }
-    for(i=0; i<columns.length; i++){
-        ranges[i] = 100*ranges[i]/total;
-    }
-    var trainPercent = Math.round(ranges[0]);
-    var validationPercent = Math.round(ranges[1]);
-    var unusedPercent = Math.round(ranges[3]);
-    var testPercent = 100 - trainPercent - validationPercent - unusedPercent;
-    $('#simEvalSettingsForm').find('#splittrain').val(trainPercent).end().find('#splitvalidation').val(validationPercent).end().find('#splittest').val(testPercent).end();
-};
-*/
-
-
-var EngineTypeListModel = Backbone.Model.extend({
-    urlRoot: getAPIUrl('engineinfos')
-});
-var EngineModel = Backbone.Model.extend({
-    /* Required param: appid */
-    urlRoot: function(){
-        return getAPIUrl("apps/" +this.get("appid") + "/engines");
-    }
-});
-var AddEngineView = Backbone.View.extend({
-    initialize: function(){
-        this.subViews = [];
-        this.template_el = '#app_addEngine_template';
-        this.template = _.template($(this.template_el).html()); // define template function
-        this.appid = getUrlParam("appid");
-
-        this.model = new EngineTypeListModel();
-        this.model.bind('change', this.render, this);
-        this.model.fetch();
-
-        this.breadcrumbView = new BreadcrumbView();
-        this.subViews.push(this.breadcrumbView);
-    },
-    events: {
-        "submit":  "createEngine"
-    },
-    createEngine: function(e) {
-        $(e.target).find(".createEngineError").slideUp("fast").html(""); // clear error msg
-        var engineData = formToJSON($(e.target)); // convert targeted form fields' names/values into key/value pairs
-        engineData.appid = this.appid;
-        var engineModel = new EngineModel();
-        engineModel.save(engineData, {
-            success: function(model, resData) { // success, go to engine settings
-                window.location = '?appid=' + resData.appid + '&engineid=' + resData.id + '&engineinfoid=' + resData.engineinfoid + '#engine';
-            },
-            error: function(model, res) {
-                try { // show error message if fail
-                    var resData = $.parseJSON(res.responseText);
-                    $(e.target).find(".createEngineError").html(resData.message).slideDown("fast");
-                } catch(err) {
-                    alert("An error has occured. HTTP Status Code: " + res.status);
-                }
-            }
-
-        });
-        return false;
-    },
-    render: function() {
-        this.$el.html(this.template({"data": this.model.toJSON()}));
-        this.$el.find('#breadcrumb_ContentHolder').html(this.breadcrumbView.render().el);
-        return this;
-    },
-});
-
-
-var EngineAlgorithmsView = Backbone.View.extend({
-    initialize : function() {
-        this.subViews = [];
-        this.template_el = '#engineTabAlgorithms_template';
-        this.template = _.template($(this.template_el).html()); // define template function
-        this.appid = getUrlParam("appid");
-        this.engineid = getUrlParam("engineid");
-        this.engineinfoid = getUrlParam("engineinfoid");
-        this.availableAlgoListView = new EngineAlgorithmsAvailableAlgoListView();
-        this.listenTo(this.availableAlgoListView, 'changeSelected', this.changeAvailableAlgoSelected);
-        this.subViews.push(this.availableAlgoListView);
-
-        this.deployedAlgoView = new EngineAlgorithmsDeployedAlgoView();
-        this.subViews.push(this.deployedAlgoView);
-
-        this.simevalListView = new EngineAlgorithmsSimEvalListView();
-        this.subViews.push(this.simevalListView);
-
-        // Listen to deployDone, undeployDone events for refreshing display
-        this.listenTo(this.deployedAlgoView, 'undeployDone', this.engineStatusUpdate); // listen to undeploy, trigger engineStatusUpdate when it happens
-        this.listenTo(this.availableAlgoListView, 'deployDone', this.engineStatusUpdate); // listen to deploy, trigger engineStatusUpdate when it happens
-        this.availableAlgoListView.listenTo(this.deployedAlgoView, 'undeployDone', this.availableAlgoListView.undeployDone);
-        this.deployedAlgoView.listenTo(this.availableAlgoListView, 'deployDone', this.deployedAlgoView.deployDone);
-    },
-    events: {
-        "click #availableAlgoDeployBtn":  "availableAlgoDeploy",
-        "click #availableSimEvalBtn":  "availableAlgoSimEval"
-    },
-    render : function() {
-        //this.$el.html(this.template({"data": this.model.toJSON()}));
-        this.$el.html(this.template());
-        this.$el.find('#engine_availableAlgoList_ContentHolder').html(this.availableAlgoListView.el);
-        this.$el.find('#engine_deployedAlgo_ContentHolder').html(this.deployedAlgoView.render().el);
-        this.$el.find('#engine_simevalList_ContentHolder').html(this.simevalListView.el);
-
-        // Disable offline evaluation for anything other than ItemRec & ItemSim
-        if (this.engineinfoid != "itemrec" && this.engineinfoid != "itemsim") {
-            this.$el.find('#availableSimEvalBtn').hide();
-        }
-
-        return this;
-    },
-    reloadData : function() {
-        this.availableAlgoListView.reloadData();
-        this.simevalListView.reloadData();
-        this.deployedAlgoView.reloadData();
-    },
-    engineStatusUpdate: function() {
-        this.trigger('engineStatusUpdate');
-    },
-    changeAvailableAlgoSelected: function(selectedAlgos) {
-        if ($.isEmptyObject(selectedAlgos)) {
-            this.$el.find('#availableAlgoDeployBtn').attr('disabled', true);
-            this.$el.find('#availableSimEvalBtn').attr('disabled', true);
-        } else {
-            this.$el.find('#availableAlgoDeployBtn').removeAttr('disabled');
-            this.$el.find('#availableSimEvalBtn').removeAttr('disabled');
-        }
-    },
-    availableAlgoDeploy : function() {
-        if (this.availableAlgoListView.hasSelectedAnyAlgo()){
-            alert("Deploying multiple algorithms is not supported yet.");
-            //this.availableAlgoListView.deploySelectedAlgos();  // uncomment this when deploy multi is ready
-        }
-        return false;
-    },
-    availableAlgoSimEval : function() {
-        if (this.availableAlgoListView.hasSelectedAnyAlgo()){
-            window.location.hash = 'simEvalSettings/'+ encodeURIComponentMapKey(this.availableAlgoListView.selectedAlgos);
-        }
-        return false;
-    }
-});
-
-/* Required param: appid, engineid */
-var DeployedAlgoModel = Backbone.Model.extend({
-    urlRoot: function() {
-        var path ='apps/' + this.get('appid') + '/engines/' + this.get('engineid') +'/algos_deployed';
-        return getAPIUrl(path);
-    }
-});
-var EngineAlgorithmsDeployedAlgoView = Backbone.View.extend({
-    initialize : function() {
-        this.template_el = '#engine_deployedAlgo_template';
-        this.template = _.template($(this.template_el).html()); // define template function
-        this.appid = getUrlParam("appid");
-        this.engineid = getUrlParam("engineid");
-        this.engineinfoid = getUrlParam("engineinfoid")
-        this.model = new DeployedAlgoModel({appid: this.appid, engineid: this.engineid});
-        this.model.bind('change', this.render, this);
-        this.model.fetch();
-    },
-    events: {
-        'click #algoUndeployBtn': 'undeploy',
-        'click #algoTrainNowBtn': 'trainnow',
-    },
-    render : function() {
-        this.$el.html(this.template({"data": this.model.toJSON()}));
-        return this;
-    },
-    undeploy: function() {
-        var self = this;
-        var path ='apps/' + this.appid + '/engines/' + this.engineid +'/algos_undeploy';
-        $.post(getAPIUrl(path), function() {
-            var appid = self.model.get('appid');
-            var engineid = self.model.get('engineid');
-            self.model.clear(); // empty display
-            self.model.set({appid: appid, engineid: engineid}); // put these back
-            self.trigger('undeployDone');
-        }).error(function(res) {
-            alert("An error has occured:" + res.status);
-        });
-        return false;
-    },
-    trainnow: function() {
-        var self = this;
-        var path ='apps/' + this.appid + '/engines/' + this.engineid +'/algos_trainnow';
-        var info = notifyInfo('Requesting to train data model immediately...', '', {positionClass: 'toast-bottom-right', fadeOut: 1});
-        $.post(getAPIUrl(path), function(res) {
-            notifyClear(info);
-            notifySuccess(res.message, '', {positionClass: 'toast-bottom-right', timeOut: 2800});
-        }).error(function(res) {
-            try { // show error message if fail
-                var resData = $.parseJSON(res.responseText);
-                notifyClear(info);
-                notifyErrorSticky("HTTP " + res.status + ": " + resData.message, '');
-            } catch(err) {
-                alert("An error has occured. HTTP Status Code: " + res.status);
-            }
-        });
-    },
-    deployDone: function() {
-        this.model.fetch();
-    },
-    reloadData: function() {
-        this.model.fetch();
-    }
-});
-
-/* Required param: appid, engineid */
-var AvailableAlgoModel = Backbone.Model.extend({
-    urlRoot: function() {
-        var path ='apps/' + this.get('appid') + '/engines/' + this.get('engineid') +'/algos_available';
-        return getAPIUrl(path);
-    }
-});
-/* Required param: appid, engineid */
-var AvailableAlgoListCollection = Backbone.Collection.extend({
-    model: AvailableAlgoModel,
-    initialize: function(models, options) {
-        this.url = getAPIUrl('apps/' + options.appid + '/engines/' + options.engineid +'/algos_available');
-    }
-});
-var EngineAlgorithmsAvailableAlgoListView = Backbone.View.extend({
-    initialize : function() {
-        this.subViews = [];
-        this.selectedAlgos = {};
-        this.appid = getUrlParam("appid");
-        this.engineid = getUrlParam("engineid");
-        this.engineinfoid = getUrlParam("engineinfoid");
-
-        this.template_el = '#engine_availableAlgoList_template';
-        this.template = _.template($(this.template_el).html());
-        this.$el.html(this.template());
-
-        this.collection = new AvailableAlgoListCollection([], {appid: this.appid, engineid: this.engineid});
-        this.collection.bind('add', this.addOne, this);
-        this.collection.bind('reset', this.render, this);
-        this.collection.fetch();
-    },
-    render: function(eventData) {
-        this.$el.find('tbody').html(""); // clear previous items in table
-        _.each(eventData.models, function(model){
-            this.addOne(model); // debug: console.log(app.attributes['id']);
-        }, this);
-        return this;
-    },
-    addOne: function(model) {
-        var avaAlgoView = new EngineAlgorithmsAvailableAlgoView({ model:model});
-        this.listenTo(avaAlgoView, 'select', this.algoSelect);
-        this.listenTo(avaAlgoView, 'unselect', this.algoUnselect);
-        this.listenTo(avaAlgoView, 'deploy', this.deploySingleAlgo);
-        this.subViews.push(avaAlgoView);
-        this.$el.find('tbody').append( avaAlgoView.render().el );
-    },
-    algoSelect: function(algoid) {
-        this.selectedAlgos[algoid] = true;
-        this.trigger('changeSelected', this.selectedAlgos);
-    },
-    algoUnselect: function(algoid) {
-        if (this.selectedAlgos[algoid]) {
-            delete this.selectedAlgos[algoid];
-            this.trigger('changeSelected', this.selectedAlgos);
-        }
-    },
-    deploySingleAlgo: function(algoid) {
-        this.deploy([algoid]);
-    },
-    deploySelectedAlgos: function() {
-        if(!$.isEmptyObject(this.selectedAlgos)) { // if selectedAlgos is not empty
-            this.deploy(MapKeyToArray(this.selectedAlgos));
-        }
-    },
-    deploy: function(algoidlist) { // common func for deploying single/multiple algo(s)
-        var self = this;
-        var path ='apps/' + this.appid + '/engines/' + this.engineid +'/algos_deploy';
-        $.ajax({
-            type: "POST",
-            url: getAPIUrl(path),
-            data: JSON.stringify({algoidlist: algoidlist}),
-            contentType: "application/json; charset=utf-8",
-            success: function() {
-                self.collection.fetch();
-                self.trigger('deployDone');
-            }
-        }).error(function(res) {
-            alert("An error has occured:" + res.status);
-        });
-    },
-    undeployDone: function() {
-        this.collection.fetch();
-    },
-    hasSelectedAnyAlgo: function() { // determine if user has selected the checkbox of any available algo
-        if ($.isEmptyObject(this.selectedAlgos)) {
-            return false;
-        } else {
-            return true;
-        }
-    },
-    reloadData: function(){
-        this.selectedAlgos = {}
-        this.trigger('changeSelected', this.selectedAlgos);
-        this.collection.fetch();
-    }
-});
-/* required: model */
-var EngineAlgorithmsAvailableAlgoView = Backbone.View.extend({
-    tagName: 'tr',
-    initialize : function() {
-        this.template_el = '#engine_availableAlgo_template';
-        this.template = _.template($(this.template_el).html()); // define template function
-        this.appid = getUrlParam("appid");
-        this.engineid = getUrlParam("engineid");
-        this.engineinfoid = getUrlParam("engineinfoid");
-        //this.model.bind('change', this.render, this);
-        //this.model.fetch();
-    },
-    events: {
-        //'':'customFunction'
-        "change input[type='checkbox']":  "selectToggle",
-        "click .algoDeployBtn": "deploy",
-        "click .algoDeleteBtn": "delete"
-    },
-    render : function() {
-        this.$el.html(this.template({"data": this.model.toJSON()}));
-
-        // Disable offline evaluation for anything other than ItemRec & ItemSim
-        if (this.engineinfoid != "itemrec" && this.engineinfoid != "itemsim") {
-            this.$el.find("a[href*='#simEvalSettings']").hide();
-        }
-
-        return this;
-    },
-    selectToggle: function(e) {
-        if (e.currentTarget.checked == true) {
-            this.trigger('select', this.model.get('id'));
-        } else {
-            this.trigger('unselect', this.model.get('id'));
-        }
-    },
-    deploy: function(e) {
-        this.trigger('deploy', this.model.get('id'));
-        return false;
-    },
-    delete: function() {
-        var self = this;
-        var erasingInfo = notifyInfoSticky('Removing algorithm. Please wait...','');
-        this.model.destroy({
-            success: function(model, res) {
-                notifyClear(erasingInfo);
-                notifyInfoDefault('Algorithm removed.','');
-                self.close();
-            },
-            error: function(model, res) {
-                notifyClear(erasingInfo);
-                notifyErrorResponse(res);
-            },
-        });
-        return false;
-    }
-});
-
-/* Required param: appid, engineid */
-var SimEvalModel = Backbone.Model.extend({
-    urlRoot: function() {
-        var path ='apps/' + this.get('appid') + '/engines/' + this.get('engineid') +'/simevals';
-        return getAPIUrl(path);
-    }
-});
-/* Required param: appid, engineid */
-var SimEvalListCollection = Backbone.Collection.extend({
-    model: SimEvalModel,
-    initialize: function(models, options) {
-        this.url = getAPIUrl('apps/' + options.appid + '/engines/' + options.engineid +'/simevals');
-    }
-});
-var EngineAlgorithmsSimEvalListView = Backbone.View.extend({
-    initialize : function() {
-        this.subViews = [];
-        this.appid = getUrlParam("appid");
-        this.engineid = getUrlParam("engineid");
-        this.engineinfoid = getUrlParam("engineinfoid");
-
-        this.template_el = '#engine_simevalList_template';
-        this.template = _.template($(this.template_el).html());
-        this.$el.html(this.template());
-
-        this.collection = new SimEvalListCollection([], {appid: this.appid, engineid: this.engineid});
-        this.collection.bind('add', this.addOne, this);
-        this.collection.bind('reset', this.render, this);
-        this.collection.fetch();
-    },
-    render: function(eventData) {
-        this.$el.find('tbody').html(""); // clear previous items in table
-        _.each(eventData.models, function(model){
-            this.addOne(model); // debug: console.log(app.attributes['id']);
-        }, this);
-        return this;
-    },
-    addOne: function(model) {
-        var simevalView = new EngineAlgorithmsSimEvalView({ model:model});
-        this.subViews.push(simevalView);
-        this.$el.find('tbody').append( simevalView.render().el );
-    },
-    reloadData: function(){
-        this.collection.fetch();
-    }
-});
-/* required: model */
-var EngineAlgorithmsSimEvalView = Backbone.View.extend({
-    tagName: 'tr',
-    initialize : function() {
-        this.template_el = '#engine_simeval_template';
-        this.template = _.template($(this.template_el).html()); // define template function
-        this.appid = getUrlParam("appid");
-        this.engineid = getUrlParam("engineid");
-        this.engineinfoid = getUrlParam("engineinfoid");
-        //this.model.bind('change', this.render, this);
-        //this.model.fetch();
-    },
-    events: {
-        "click .simevalDeleteBtn":  "delete",
-    },
-    render : function() {
-        this.$el.html(this.template({"data": this.model.toJSON()}));
-        return this;
-    },
-    delete: function() {
-        var self = this;
-        var erasingInfo = notifyInfoSticky('Removing simulated evaluation. Please wait...','');
-        this.model.destroy({
-            success: function(model, res) {
-                notifyClear(erasingInfo);
-                notifyInfoDefault('Simulated evaluation removed.','');
-                self.close();
-            },
-            error: function(model, res) {
-                notifyClear(erasingInfo);
-                notifyErrorResponse(res);
-            }
-        });
-    }
-});
-
-
-var EnginetypeAlgorithmListModel = Backbone.Model.extend({
-    url: function() {
-        return getAPIUrl('engineinfos/' + this.id + '/algoinfos');
-    }
-});
-var EngineAddAlgorithmView = Backbone.View.extend({
-    initialize : function() {
-        this.template_el = '#engine_addAlgorithm_template';
-        this.template = _.template($(this.template_el).html()); // define template function
-        this.appid = getUrlParam("appid");
-        this.engineid = getUrlParam("engineid");
-        this.engineinfoid = getUrlParam("engineinfoid");
-        this.model = new EnginetypeAlgorithmListModel({"id": this.engineinfoid});
-        this.model.bind('change', this.render, this);
-        this.model.fetch();
-    },
-    render : function() {
-        this.$el.html(this.template({"data": this.model.toJSON()}));
-        return this;
-    },
-    events: {
-        "submit":  "addAlgorithm"
-    },
-    addAlgorithm: function(e) {
-        $(e.target).find(".addAlgoError").slideUp("fast").html(""); // clear error msg
-        var algoData = formToJSON($(e.target)); // convert targeted form fields' names/values into key/value pairs
-        algoData.appid = this.appid;
-        algoData.engineid = this.engineid;
-        var algoModel = new AvailableAlgoModel();
-        algoModel.save(algoData, {
-            success: function(model, resData) { // success, go to algo settings
-                window.location.hash = 'algoSettings/' + decodeURIComponent(resData.algoinfoid) + '/'+ decodeURIComponent(resData.algoname) + '/' + decodeURIComponent(resData.id);
-            },
-            error: function(model, res) {
-                try { // show error message if fail
-                    var resData = $.parseJSON(res.responseText);
-                    $(e.target).find(".addAlgoError").html(resData.message).slideDown("fast");
-                } catch(err) {
-                    alert("An error has occured. HTTP Status Code: " + res.status);
-                }
-            }
-        });
-        return false;
-    }
-});
-
-var EngineAlgoAutotuningReportModel = Backbone.Model.extend({
-    initialize: function(model, options) {
-        //this.urlRoot = getAPIUrl('apps/' + options.appid + '/engines/' + options.engineid +'/algoautotuning_report'); # TODO: remove
-        this.url = getAPIUrl('apps/' + options.appid + '/engines/' + options.engineid +'/algos_available/' + this.id + '/autotune_report');
-    }
-});
-var EngineAlgoAutotuningReportView = Backbone.View.extend({
-    initialize : function() {
-        this.template_el = '#engine_algoAutotuningReport_template';
-        this.template = _.template($(this.template_el).html()); // define template function
-        this.algoid = this.options.id;
-        this.appid = getUrlParam("appid");
-        this.engineid = getUrlParam("engineid");
-        this.engineinfoid = getUrlParam("engineinfoid");
-        this.model = new EngineAlgoAutotuningReportModel({"id": this.algoid}, {appid: this.appid, engineid: this.engineid});
-        this.model.bind('change', this.render, this);
-        this.model.fetch();
-    },
-    events: {
-        "click .algoAutotuneSelectBtn":  "selectAutotune"
-    },
-    render : function() {
-        this.$el.html(this.template({"data": this.model.toJSON()}));
-        console.log(this.model.toJSON());
-        return this;
-    },
-    selectAutotune: function(e) {
-        var tunedalgoid = $(e.target).data('autotuneid');
-        var path ='apps/' + this.appid + '/engines/' + this.engineid +'/algos_available/' + this.algoid + '/autotune_apply';
-        $.ajax({
-            type: "POST",
-            url: getAPIUrl(path),
-            data: JSON.stringify({tunedalgoid: tunedalgoid}),
-            contentType: "application/json; charset=utf-8",
-            success: function() {
-                window.location.hash = 'engineTabAlgorithms';
-            }
-        }).error(function(res) {
-            alert("An error has occured:" + res.status);
-        });
-        return false;
-    }
-});
-
-var EngineSimEvalReportModel = Backbone.Model.extend({
-    initialize: function(model, options) {
-        //this.urlRoot = getAPIUrl('app/' + options.appid + '/engine/' + options.engineid +'/simeval_report');
-        this.url = getAPIUrl('apps/' + options.appid + '/engines/' + options.engineid +'/simevals/' + this.id + '/report');
-    }
-});
-/* Required Param: id  (simulated eval report id) */
-var EngineSimEvalReportView = Backbone.View.extend({
-    initialize : function() {
-        this.template_el = '#engine_simEvalReport_template';
-        this.template = _.template($(this.template_el).html()); // define template function
-        this.simeval_id = this.options.id;
-        this.appid = getUrlParam("appid");
-        this.engineid = getUrlParam("engineid");
-        this.engineinfoid = getUrlParam("engineinfoid");
-        this.model = new EngineSimEvalReportModel({"id": this.simeval_id}, {appid: this.appid, engineid: this.engineid});
-        this.model.bind('change', this.render, this);
-        this.model.fetch();
-    },
-    render : function() {
-        this.$el.html(this.template({"data": this.model.toJSON()}));
-        return this;
-    }
-});
-
-
-
-
-var EnginetypeMetricsTypeListModel = Backbone.Model.extend({
-    url: function() {
-        return getAPIUrl('engineinfos/' + this.id + "/metricinfos");
-    }
-});
-var EnginetypeSplitterTypeListModel = Backbone.Model.extend({
-    url: function() {
-        return getAPIUrl('engineinfos/' + this.id + "/splitterinfos");
-    }
-});
-
-/* Required Param: algoidlist  (algo ids to be evaluated) */
-var EngineSimEvalSettingsView = Backbone.View.extend({
-    initialize : function() {
-        this.isEngineSimEvalSettingsView = true;
-        this.subViews = [];
-        this.template_el = '#engine_simEvalSettings_template';
-        this.template = _.template($(this.template_el).html()); // define template function
-        this.simeval_id = this.options.id;
-        this.algoidlist = this.options.algoidlist;
-        this.form_el = '#simEvalSettingsForm';
-        this.appid = getUrlParam("appid");
-        this.engineid = getUrlParam("engineid");
-        this.engineinfoid = getUrlParam("engineinfoid");
-        this.indexCount = 0;
-        this.infotype = [];
-//      this.model = new EngineSimEvalSettingsModel({"id": this.simeval_id});
-//      this.model.bind('change', this.render, this);
-//      this.model.fetch();
-    },
-    events: {
-        'submit':  'save',
-        'click #addMetricsBtn': 'addMetrics'
-    },
-    render : function() {
-        $.ajaxSetup({async:false});  // ensure sync, necessary for Data Split Slider
-        //this.$el.html(this.template({"data": this.model.toJSON()}));
-        // construct algo id list
-        var self = this;
-
-        // construct algo name list (this.algoName_list) from inputted algo id list
-        var algoArrayRaw = this.algoidlist.split(',');
-        this.algoList = algoArrayRaw.map(function(algoid_encoded){
-            var algoid = decodeURIComponent(algoid_encoded);
-            var algoModel = new AvailableAlgoModel({appid: self.appid, engineid: self.engineid, id: algoid});
-            algoModel.fetch();
-            return {algoname: algoModel.get('algoname'), id: algoModel.get('id')};
-        });
-
-        // render metrics options
-        metricstypeListModel = new EnginetypeMetricsTypeListModel({id: this.engineinfoid});
-        metricstypeListModel.fetch({
-                success: function(model, res) {
-                    self.metricslist = res.metricslist;
-                    self.defaultmetric = res.defaultmetric;
-                    self.$el.html(self.template({data: { algoList: self.algoList }}));
-                    self.addOne();
-                }
-        });
-
-        // render splitter options
-        splittertypeListModel = new EnginetypeSplitterTypeListModel({id: this.engineinfoid});
-        splittertypeListModel.fetch({
-                success: function(model, res) {
-                    self.splitterlist = res.splitterlist;
-                    self.defaultsplitter = res.defaultsplitter;
-                    self.addSplitter(self.defaultsplitter); // note: only support using default splitter now
-                }
-        });
-
-        $.ajaxSetup({async:true}); // end of ensure sync, necessary for Data Split Slider
-        return this;
-    },
-    addMetrics: function() {
-        this.addOne();
-        return false;
-    },
-    addOne: function() {
-        var metricsView = new EngineSimEvalSettingsMetricsView({
-            data: {
-                index: this.indexCount,
-                metricslist: this.metricslist,
-                defaultmetric: this.defaultmetric,
-                engineinfoid: this.engineinfoid
-            }
-        });
-        this.infotype[this.indexCount] = "offlineevalmetric";
-        this.indexCount += 1; // increase count
-        this.subViews.push(metricsView);
-        this.$el.find('#metrics_list_ContentHolder').append(metricsView.render().el);
-    },
-    addSplitter: function(splitterinfoid) {
-        var splitterSettingView = new SplitterSettingView({
-            data: {
-                index: this.indexCount,
-                engineinfoid: this.engineinfoid,
-                splitterinfoid: splitterinfoid
-            }
-        });
-        this.infotype[this.indexCount] = "offlineevalsplitter";
-        this.indexCount += 1; // increase count
-        this.subViews.push(splitterSettingView);
-        this.$el.find('#splitterSetting_Holder').html(splitterSettingView.render().el);
-    },
-    save: function() {
-        $(this.error_el).slideUp().html(""); // reset/clear all error msg
-        var data = formToJSON(this.$el.find(this.form_el)); // convert form names/values of fields into key/value pairs
-        var simEvalModel = new SimEvalModel({appid: this.appid, engineid: this.engineid, infotype: this.infotype});
-        var self = this;
-        simEvalModel.save(data, {
-            wait: true,
-            success: function(model, res) {
-                window.location.hash = 'engineTabAlgorithms';
-            },
-            error: function(model, res){
-                notifyErrorResponse(res);
-                /*
-                alert("An error has occured. HTTP Status Code: "
-                        + res.status);*/
-            }
-        });
-        return false;
-    }
-});
-
-var EngineSimEvalSettingsMetricsView = Backbone.View.extend({
-    initialize : function() {
-        this.template_el = '#engine_simEvalSettingsMetrics_template';
-        this.template = _.template($(this.template_el).html());
-        this.data = this.options.data;
-        this.subViews = [];
-    },
-    events: {
-        'click .deleteMetricsBtn': 'delete',
-        'change .changeMetricsSelect': 'selectionChanged'
-    },
-    render : function() {
-        //this.$el.html(this.template({"data": this.model.toJSON()}));
-        this.$el.html(this.template({data: this.data}));
-        this.showSetting(this.data.defaultmetric); // show setting of default metric
-        return this;
-    },
-    delete: function() {
-        this.remove();
-        this.close();
-        return false;
-    },
-    showSetting: function(metricinfoid) {
-        var metricSettingView = new MetricSettingView({
-            data: {
-                index: this.data.index,
-                engineinfoid: this.data.engineinfoid,
-                metricinfoid: metricinfoid
-            }
-        });
-        this.subViews.push(metricSettingView);
-        this.$el.find('#metricSetting_Holder').html(metricSettingView.render().el);
-
-    },
-    selectionChanged: function(e) {
-        var value = $(e.currentTarget).val();
-        this.showSetting(value);
-    }
-});
-
-var MetricSettingView = Backbone.View.extend({
-    initialize: function() {
-        this.data = this.options.data;
-    },
-    render: function() {
-        var that = this;
-        //$.ajaxSetup({async:false}); // make jquery sync temporary to ensure it's loaded before we move on
-        $.get(getAPIUrl('engineinfos/' + this.data.engineinfoid  + '/metricinfos/' + this.data.metricinfoid + '/template.html'), function(template_html) {
-            var template = _.template(template_html);
-            that.$el.html(template({data: that.data}));
-        });
-        //$.ajaxSetup({async:true});
-        return this;
-    }
-})
-
-var SplitterSettingView = Backbone.View.extend({
-    initialize: function() {
-        this.data = this.options.data;
-    },
-    render: function() {
-        var that = this;
-        //$.ajaxSetup({async:false}); // make jquery sync temporary to ensure it's loaded before we move on
-        $.get(getAPIUrl('engineinfos/' + this.data.engineinfoid  + '/splitterinfos/' + this.data.splitterinfoid + '/template.html'), function(template_html) {
-            var template = _.template(template_html);
-            that.$el.html(template({data: that.data}));
-        });
-        //$.ajaxSetup({async:true});
-        return this;
-    }
-})
diff --git a/servers/admin/public/javascripts/vendors/backbone-min.js b/servers/admin/public/javascripts/vendors/backbone-min.js
deleted file mode 100644
index 05f53a7..0000000
--- a/servers/admin/public/javascripts/vendors/backbone-min.js
+++ /dev/null
@@ -1,42 +0,0 @@
-// Backbone.js 0.9.9
-
-// (c) 2010-2012 Jeremy Ashkenas, DocumentCloud Inc.
-// Backbone may be freely distributed under the MIT license.
-// For all details and documentation:
-// http://backbonejs.org
-(function(){var k=this,y=k.Backbone,h=[],z=h.push,r=h.slice,A=h.splice,g;g="undefined"!==typeof exports?exports:k.Backbone={};g.VERSION="0.9.9";var e=k._;!e&&"undefined"!==typeof require&&(e=require("underscore"));g.$=k.jQuery||k.Zepto||k.ender;g.noConflict=function(){k.Backbone=y;return this};g.emulateHTTP=!1;g.emulateJSON=!1;var s=/\s+/,n=function(a,b,c,d){if(!c)return!0;if("object"===typeof c)for(var f in c)a[b].apply(a,[f,c[f]].concat(d));else if(s.test(c)){c=c.split(s);f=0;for(var e=c.length;f<
-e;f++)a[b].apply(a,[c[f]].concat(d))}else return!0},t=function(a,b,c){var d,a=-1,f=b.length;switch(c.length){case 0:for(;++a<f;)(d=b[a]).callback.call(d.ctx);break;case 1:for(;++a<f;)(d=b[a]).callback.call(d.ctx,c[0]);break;case 2:for(;++a<f;)(d=b[a]).callback.call(d.ctx,c[0],c[1]);break;case 3:for(;++a<f;)(d=b[a]).callback.call(d.ctx,c[0],c[1],c[2]);break;default:for(;++a<f;)(d=b[a]).callback.apply(d.ctx,c)}},h=g.Events={on:function(a,b,c){if(!n(this,"on",a,[b,c])||!b)return this;this._events||(this._events=
-{});(this._events[a]||(this._events[a]=[])).push({callback:b,context:c,ctx:c||this});return this},once:function(a,b,c){if(!n(this,"once",a,[b,c])||!b)return this;var d=this,f=e.once(function(){d.off(a,f);b.apply(this,arguments)});f._callback=b;this.on(a,f,c);return this},off:function(a,b,c){var d,f,l,g,i,m,h,j;if(!this._events||!n(this,"off",a,[b,c]))return this;if(!a&&!b&&!c)return this._events={},this;g=a?[a]:e.keys(this._events);i=0;for(m=g.length;i<m;i++)if(a=g[i],d=this._events[a]){l=[];if(b||
-c){h=0;for(j=d.length;h<j;h++)f=d[h],(b&&b!==(f.callback._callback||f.callback)||c&&c!==f.context)&&l.push(f)}this._events[a]=l}return this},trigger:function(a){if(!this._events)return this;var b=r.call(arguments,1);if(!n(this,"trigger",a,b))return this;var c=this._events[a],d=this._events.all;c&&t(this,c,b);d&&t(this,d,arguments);return this},listenTo:function(a,b,c){var d=this._listeners||(this._listeners={}),f=a._listenerId||(a._listenerId=e.uniqueId("l"));d[f]=a;a.on(b,c||this,this);return this},
-stopListening:function(a,b,c){var d=this._listeners;if(d){if(a)a.off(b,c,this),!b&&!c&&delete d[a._listenerId];else{for(var f in d)d[f].off(null,null,this);this._listeners={}}return this}}};h.bind=h.on;h.unbind=h.off;e.extend(g,h);var o=g.Model=function(a,b){var c,d=a||{};this.cid=e.uniqueId("c");this.changed={};this.attributes={};this._changes=[];b&&b.collection&&(this.collection=b.collection);b&&b.parse&&(d=this.parse(d));(c=e.result(this,"defaults"))&&e.defaults(d,c);this.set(d,{silent:!0});this._currentAttributes=
-e.clone(this.attributes);this._previousAttributes=e.clone(this.attributes);this.initialize.apply(this,arguments)};e.extend(o.prototype,h,{changed:null,idAttribute:"id",initialize:function(){},toJSON:function(){return e.clone(this.attributes)},sync:function(){return g.sync.apply(this,arguments)},get:function(a){return this.attributes[a]},escape:function(a){return e.escape(this.get(a))},has:function(a){return null!=this.get(a)},set:function(a,b,c){var d,f;if(null==a)return this;e.isObject(a)?(f=a,c=
-b):(f={})[a]=b;var a=c&&c.silent,l=c&&c.unset;if(!this._validate(f,c))return!1;this.idAttribute in f&&(this.id=f[this.idAttribute]);var g=this.attributes;for(d in f)b=f[d],l?delete g[d]:g[d]=b,this._changes.push(d,b);this._hasComputed=!1;a||this.change(c);return this},unset:function(a,b){return this.set(a,void 0,e.extend({},b,{unset:!0}))},clear:function(a){var b={},c;for(c in this.attributes)b[c]=void 0;return this.set(b,e.extend({},a,{unset:!0}))},fetch:function(a){a=a?e.clone(a):{};void 0===a.parse&&
-(a.parse=!0);var b=this,c=a.success;a.success=function(d){if(!b.set(b.parse(d),a))return false;c&&c(b,d,a)};return this.sync("read",this,a)},save:function(a,b,c){var d,f,g;null==a||e.isObject(a)?(d=a,c=b):null!=a&&((d={})[a]=b);c=c?e.clone(c):{};if(c.wait){if(d&&!this._validate(d,c))return!1;f=e.clone(this.attributes)}a=e.extend({},c,{silent:!0});if(d&&!this.set(d,c.wait?a:c)||!d&&!this._validate(null,c))return!1;var q=this,i=c.success;c.success=function(a){g=true;var b=q.parse(a);c.wait&&(b=e.extend(d||
-{},b));if(!q.set(b,c))return false;i&&i(q,a,c)};b=this.isNew()?"create":c.patch?"patch":"update";"patch"==b&&(c.attrs=d);b=this.sync(b,this,c);!g&&c.wait&&(this.clear(a),this.set(f,a));return b},destroy:function(a){var a=a?e.clone(a):{},b=this,c=a.success,d=function(){b.trigger("destroy",b,b.collection,a)};a.success=function(f){(a.wait||b.isNew())&&d();c&&c(b,f,a)};if(this.isNew())return a.success(),!1;var f=this.sync("delete",this,a);a.wait||d();return f},url:function(){var a=e.result(this,"urlRoot")||
-e.result(this.collection,"url")||u();return this.isNew()?a:a+("/"===a.charAt(a.length-1)?"":"/")+encodeURIComponent(this.id)},parse:function(a){return a},clone:function(){return new this.constructor(this.attributes)},isNew:function(){return null==this.id},change:function(a){var b=this._changing;this._changing=!0;var c=this._computeChanges(!0);this._pending=!!c.length;for(var d=c.length-2;0<=d;d-=2)this.trigger("change:"+c[d],this,c[d+1],a);if(b)return this;for(;this._pending;)this._pending=!1,this.trigger("change",
-this,a),this._previousAttributes=e.clone(this.attributes);this._changing=!1;return this},hasChanged:function(a){this._hasComputed||this._computeChanges();return null==a?!e.isEmpty(this.changed):e.has(this.changed,a)},changedAttributes:function(a){if(!a)return this.hasChanged()?e.clone(this.changed):!1;var b,c=!1,d=this._previousAttributes,f;for(f in a)if(!e.isEqual(d[f],b=a[f]))(c||(c={}))[f]=b;return c},_computeChanges:function(a){this.changed={};for(var b={},c=[],d=this._currentAttributes,f=this._changes,
-e=f.length-2;0<=e;e-=2){var g=f[e],i=f[e+1];b[g]||(b[g]=!0,d[g]!==i&&(this.changed[g]=i,a&&(c.push(g,i),d[g]=i)))}a&&(this._changes=[]);this._hasComputed=!0;return c},previous:function(a){return null==a||!this._previousAttributes?null:this._previousAttributes[a]},previousAttributes:function(){return e.clone(this._previousAttributes)},_validate:function(a,b){if(!this.validate)return!0;var a=e.extend({},this.attributes,a),c=this.validate(a,b);if(!c)return!0;b&&b.error&&b.error(this,c,b);this.trigger("error",
-this,c,b);return!1}});var p=g.Collection=function(a,b){b||(b={});b.model&&(this.model=b.model);void 0!==b.comparator&&(this.comparator=b.comparator);this._reset();this.initialize.apply(this,arguments);a&&this.reset(a,e.extend({silent:!0},b))};e.extend(p.prototype,h,{model:o,initialize:function(){},toJSON:function(a){return this.map(function(b){return b.toJSON(a)})},sync:function(){return g.sync.apply(this,arguments)},add:function(a,b){var c,d,f,g,h=b&&b.at,i=null==(b&&b.sort)?!0:b.sort,a=e.isArray(a)?
-a.slice():[a];for(c=a.length-1;0<=c;c--)(d=this._prepareModel(a[c],b))?(a[c]=d,(f=null!=d.id&&this._byId[d.id])||this._byCid[d.cid]?(b&&(b.merge&&f)&&(f.set(d.attributes,b),g=i),a.splice(c,1)):(d.on("all",this._onModelEvent,this),this._byCid[d.cid]=d,null!=d.id&&(this._byId[d.id]=d))):(this.trigger("error",this,a[c],b),a.splice(c,1));a.length&&(g=i);this.length+=a.length;c=[null!=h?h:this.models.length,0];z.apply(c,a);A.apply(this.models,c);g&&(this.comparator&&null==h)&&this.sort({silent:!0});if(b&&
-b.silent)return this;for(;d=a.shift();)d.trigger("add",d,this,b);return this},remove:function(a,b){var c,d,f,g;b||(b={});a=e.isArray(a)?a.slice():[a];c=0;for(d=a.length;c<d;c++)if(g=this.get(a[c]))delete this._byId[g.id],delete this._byCid[g.cid],f=this.indexOf(g),this.models.splice(f,1),this.length--,b.silent||(b.index=f,g.trigger("remove",g,this,b)),this._removeReference(g);return this},push:function(a,b){a=this._prepareModel(a,b);this.add(a,e.extend({at:this.length},b));return a},pop:function(a){var b=
-this.at(this.length-1);this.remove(b,a);return b},unshift:function(a,b){a=this._prepareModel(a,b);this.add(a,e.extend({at:0},b));return a},shift:function(a){var b=this.at(0);this.remove(b,a);return b},slice:function(a,b){return this.models.slice(a,b)},get:function(a){return null==a?void 0:this._byId[null!=a.id?a.id:a]||this._byCid[a.cid||a]},at:function(a){return this.models[a]},where:function(a){return e.isEmpty(a)?[]:this.filter(function(b){for(var c in a)if(a[c]!==b.get(c))return!1;return!0})},
-sort:function(a){if(!this.comparator)throw Error("Cannot sort a set without a comparator");e.isString(this.comparator)||1===this.comparator.length?this.models=this.sortBy(this.comparator,this):this.models.sort(e.bind(this.comparator,this));(!a||!a.silent)&&this.trigger("sort",this,a);return this},pluck:function(a){return e.invoke(this.models,"get",a)},update:function(a,b){var c,d,f,g,h=[],i=[],m={},j=this.model.prototype.idAttribute,b=e.extend({add:!0,merge:!0,remove:!0},b);b.parse&&(a=this.parse(a));
-e.isArray(a)||(a=a?[a]:[]);if(b.add&&!b.remove)return this.add(a,b);d=0;for(f=a.length;d<f;d++)c=a[d],g=this.get(c.id||c.cid||c[j]),b.remove&&g&&(m[g.cid]=!0),(b.add&&!g||b.merge&&g)&&h.push(c);if(b.remove){d=0;for(f=this.models.length;d<f;d++)c=this.models[d],m[c.cid]||i.push(c)}i.length&&this.remove(i,b);h.length&&this.add(h,b);return this},reset:function(a,b){b||(b={});b.parse&&(a=this.parse(a));for(var c=0,d=this.models.length;c<d;c++)this._removeReference(this.models[c]);b.previousModels=this.models;
-this._reset();a&&this.add(a,e.extend({silent:!0},b));b.silent||this.trigger("reset",this,b);return this},fetch:function(a){a=a?e.clone(a):{};void 0===a.parse&&(a.parse=!0);var b=this,c=a.success;a.success=function(d){b[a.update?"update":"reset"](d,a);c&&c(b,d,a)};return this.sync("read",this,a)},create:function(a,b){var c=this,b=b?e.clone(b):{},a=this._prepareModel(a,b);if(!a)return!1;b.wait||c.add(a,b);var d=b.success;b.success=function(a,b,e){e.wait&&c.add(a,e);d&&d(a,b,e)};a.save(null,b);return a},
-parse:function(a){return a},clone:function(){return new this.constructor(this.models)},chain:function(){return e(this.models).chain()},_reset:function(){this.length=0;this.models=[];this._byId={};this._byCid={}},_prepareModel:function(a,b){if(a instanceof o)return a.collection||(a.collection=this),a;b||(b={});b.collection=this;var c=new this.model(a,b);return!c._validate(a,b)?!1:c},_removeReference:function(a){this===a.collection&&delete a.collection;a.off("all",this._onModelEvent,this)},_onModelEvent:function(a,
-b,c,d){("add"===a||"remove"===a)&&c!==this||("destroy"===a&&this.remove(b,d),b&&a==="change:"+b.idAttribute&&(delete this._byId[b.previous(b.idAttribute)],null!=b.id&&(this._byId[b.id]=b)),this.trigger.apply(this,arguments))}});e.each("forEach each map collect reduce foldl inject reduceRight foldr find detect filter select reject every all some any include contains invoke max min sortedIndex toArray size first head take initial rest tail last without indexOf shuffle lastIndexOf isEmpty".split(" "),
-function(a){p.prototype[a]=function(){var b=r.call(arguments);b.unshift(this.models);return e[a].apply(e,b)}});e.each(["groupBy","countBy","sortBy"],function(a){p.prototype[a]=function(b,c){var d=e.isFunction(b)?b:function(a){return a.get(b)};return e[a](this.models,d,c)}});var v=g.Router=function(a){a||(a={});a.routes&&(this.routes=a.routes);this._bindRoutes();this.initialize.apply(this,arguments)},B=/\((.*?)\)/g,C=/:\w+/g,D=/\*\w+/g,E=/[\-{}\[\]+?.,\\\^$|#\s]/g;e.extend(v.prototype,h,{initialize:function(){},
-route:function(a,b,c){e.isRegExp(a)||(a=this._routeToRegExp(a));c||(c=this[b]);g.history.route(a,e.bind(function(d){d=this._extractParameters(a,d);c&&c.apply(this,d);this.trigger.apply(this,["route:"+b].concat(d));g.history.trigger("route",this,b,d)},this));return this},navigate:function(a,b){g.history.navigate(a,b);return this},_bindRoutes:function(){if(this.routes)for(var a,b=e.keys(this.routes);null!=(a=b.pop());)this.route(a,this.routes[a])},_routeToRegExp:function(a){a=a.replace(E,"\\$&").replace(B,
-"(?:$1)?").replace(C,"([^/]+)").replace(D,"(.*?)");return RegExp("^"+a+"$")},_extractParameters:function(a,b){return a.exec(b).slice(1)}});var j=g.History=function(){this.handlers=[];e.bindAll(this,"checkUrl");"undefined"!==typeof window&&(this.location=window.location,this.history=window.history)},w=/^[#\/]|\s+$/g,F=/^\/+|\/+$/g,G=/msie [\w.]+/,H=/\/$/;j.started=!1;e.extend(j.prototype,h,{interval:50,getHash:function(a){return(a=(a||this).location.href.match(/#(.*)$/))?a[1]:""},getFragment:function(a,
-b){if(null==a)if(this._hasPushState||!this._wantsHashChange||b){var a=this.location.pathname,c=this.root.replace(H,"");a.indexOf(c)||(a=a.substr(c.length))}else a=this.getHash();return a.replace(w,"")},start:function(a){if(j.started)throw Error("Backbone.history has already been started");j.started=!0;this.options=e.extend({},{root:"/"},this.options,a);this.root=this.options.root;this._wantsHashChange=!1!==this.options.hashChange;this._wantsPushState=!!this.options.pushState;this._hasPushState=!(!this.options.pushState||
-!this.history||!this.history.pushState);var a=this.getFragment(),b=document.documentMode,b=G.exec(navigator.userAgent.toLowerCase())&&(!b||7>=b);this.root=("/"+this.root+"/").replace(F,"/");b&&this._wantsHashChange&&(this.iframe=g.$('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo("body")[0].contentWindow,this.navigate(a));this._hasPushState?g.$(window).bind("popstate",this.checkUrl):this._wantsHashChange&&"onhashchange"in window&&!b?g.$(window).bind("hashchange",this.checkUrl):this._wantsHashChange&&
-(this._checkUrlInterval=setInterval(this.checkUrl,this.interval));this.fragment=a;a=this.location;b=a.pathname.replace(/[^\/]$/,"$&/")===this.root;if(this._wantsHashChange&&this._wantsPushState&&!this._hasPushState&&!b)return this.fragment=this.getFragment(null,!0),this.location.replace(this.root+this.location.search+"#"+this.fragment),!0;this._wantsPushState&&(this._hasPushState&&b&&a.hash)&&(this.fragment=this.getHash().replace(w,""),this.history.replaceState({},document.title,this.root+this.fragment+
-a.search));if(!this.options.silent)return this.loadUrl()},stop:function(){g.$(window).unbind("popstate",this.checkUrl).unbind("hashchange",this.checkUrl);clearInterval(this._checkUrlInterval);j.started=!1},route:function(a,b){this.handlers.unshift({route:a,callback:b})},checkUrl:function(){var a=this.getFragment();a===this.fragment&&this.iframe&&(a=this.getFragment(this.getHash(this.iframe)));if(a===this.fragment)return!1;this.iframe&&this.navigate(a);this.loadUrl()||this.loadUrl(this.getHash())},
-loadUrl:function(a){var b=this.fragment=this.getFragment(a);return e.any(this.handlers,function(a){if(a.route.test(b))return a.callback(b),!0})},navigate:function(a,b){if(!j.started)return!1;if(!b||!0===b)b={trigger:b};a=this.getFragment(a||"");if(this.fragment!==a){this.fragment=a;var c=this.root+a;if(this._hasPushState)this.history[b.replace?"replaceState":"pushState"]({},document.title,c);else if(this._wantsHashChange)this._updateHash(this.location,a,b.replace),this.iframe&&a!==this.getFragment(this.getHash(this.iframe))&&
-(b.replace||this.iframe.document.open().close(),this._updateHash(this.iframe.location,a,b.replace));else return this.location.assign(c);b.trigger&&this.loadUrl(a)}},_updateHash:function(a,b,c){c?(c=a.href.replace(/(javascript:|#).*$/,""),a.replace(c+"#"+b)):a.hash="#"+b}});g.history=new j;var x=g.View=function(a){this.cid=e.uniqueId("view");this._configure(a||{});this._ensureElement();this.initialize.apply(this,arguments);this.delegateEvents()},I=/^(\S+)\s*(.*)$/,J="model collection el id attributes className tagName events".split(" ");
-e.extend(x.prototype,h,{tagName:"div",$:function(a){return this.$el.find(a)},initialize:function(){},render:function(){return this},remove:function(){this.$el.remove();this.stopListening();return this},make:function(a,b,c){a=document.createElement(a);b&&g.$(a).attr(b);null!=c&&g.$(a).html(c);return a},setElement:function(a,b){this.$el&&this.undelegateEvents();this.$el=a instanceof g.$?a:g.$(a);this.el=this.$el[0];!1!==b&&this.delegateEvents();return this},delegateEvents:function(a){if(a||(a=e.result(this,
-"events"))){this.undelegateEvents();for(var b in a){var c=a[b];e.isFunction(c)||(c=this[a[b]]);if(!c)throw Error('Method "'+a[b]+'" does not exist');var d=b.match(I),f=d[1],d=d[2],c=e.bind(c,this),f=f+(".delegateEvents"+this.cid);""===d?this.$el.bind(f,c):this.$el.delegate(d,f,c)}}},undelegateEvents:function(){this.$el.unbind(".delegateEvents"+this.cid)},_configure:function(a){this.options&&(a=e.extend({},e.result(this,"options"),a));e.extend(this,e.pick(a,J));this.options=a},_ensureElement:function(){if(this.el)this.setElement(e.result(this,
-"el"),!1);else{var a=e.extend({},e.result(this,"attributes"));this.id&&(a.id=e.result(this,"id"));this.className&&(a["class"]=e.result(this,"className"));this.setElement(this.make(e.result(this,"tagName"),a),!1)}}});var K={create:"POST",update:"PUT",patch:"PATCH","delete":"DELETE",read:"GET"};g.sync=function(a,b,c){var d=K[a];e.defaults(c||(c={}),{emulateHTTP:g.emulateHTTP,emulateJSON:g.emulateJSON});var f={type:d,dataType:"json"};c.url||(f.url=e.result(b,"url")||u());if(null==c.data&&b&&("create"===
-a||"update"===a||"patch"===a))f.contentType="application/json",f.data=JSON.stringify(c.attrs||b.toJSON(c));c.emulateJSON&&(f.contentType="application/x-www-form-urlencoded",f.data=f.data?{model:f.data}:{});if(c.emulateHTTP&&("PUT"===d||"DELETE"===d||"PATCH"===d)){f.type="POST";c.emulateJSON&&(f.data._method=d);var h=c.beforeSend;c.beforeSend=function(a){a.setRequestHeader("X-HTTP-Method-Override",d);if(h)return h.apply(this,arguments)}}"GET"!==f.type&&!c.emulateJSON&&(f.processData=!1);var j=c.success;
-c.success=function(a,d,e){j&&j(a,d,e);b.trigger("sync",b,a,c)};var i=c.error;c.error=function(a){i&&i(b,a,c);b.trigger("error",b,a,c)};a=g.ajax(e.extend(f,c));b.trigger("request",b,a,c);return a};g.ajax=function(){return g.$.ajax.apply(g.$,arguments)};o.extend=p.extend=v.extend=x.extend=j.extend=function(a,b){var c=this,d;d=a&&e.has(a,"constructor")?a.constructor:function(){c.apply(this,arguments)};e.extend(d,c,b);var f=function(){this.constructor=d};f.prototype=c.prototype;d.prototype=new f;a&&e.extend(d.prototype,
-a);d.__super__=c.prototype;return d};var u=function(){throw Error('A "url" property or function must be specified');}}).call(this);
diff --git a/servers/admin/public/javascripts/vendors/bootstrap.js b/servers/admin/public/javascripts/vendors/bootstrap.js
deleted file mode 100755
index c753bd6..0000000
--- a/servers/admin/public/javascripts/vendors/bootstrap.js
+++ /dev/null
@@ -1,2025 +0,0 @@
-/* ===================================================
- * bootstrap-transition.js v2.2.1
- * http://twitter.github.com/bootstrap/javascript.html#transitions
- * ===================================================
- * Copyright 2012 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================================================== */
-
-
-!function ($) {
-
-  "use strict"; // jshint ;_;
-
-
-  /* CSS TRANSITION SUPPORT (http://www.modernizr.com/)
-   * ======================================================= */
-
-  $(function () {
-
-    $.support.transition = (function () {
-
-      var transitionEnd = (function () {
-
-        var el = document.createElement('bootstrap')
-          , transEndEventNames = {
-               'WebkitTransition' : 'webkitTransitionEnd'
-            ,  'MozTransition'    : 'transitionend'
-            ,  'OTransition'      : 'oTransitionEnd otransitionend'
-            ,  'transition'       : 'transitionend'
-            }
-          , name
-
-        for (name in transEndEventNames){
-          if (el.style[name] !== undefined) {
-            return transEndEventNames[name]
-          }
-        }
-
-      }())
-
-      return transitionEnd && {
-        end: transitionEnd
-      }
-
-    })()
-
-  })
-
-}(window.jQuery);/* ==========================================================
- * bootstrap-alert.js v2.2.1
- * http://twitter.github.com/bootstrap/javascript.html#alerts
- * ==========================================================
- * Copyright 2012 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================================================== */
-
-
-!function ($) {
-
-  "use strict"; // jshint ;_;
-
-
- /* ALERT CLASS DEFINITION
-  * ====================== */
-
-  var dismiss = '[data-dismiss="alert"]'
-    , Alert = function (el) {
-        $(el).on('click', dismiss, this.close)
-      }
-
-  Alert.prototype.close = function (e) {
-    var $this = $(this)
-      , selector = $this.attr('data-target')
-      , $parent
-
-    if (!selector) {
-      selector = $this.attr('href')
-      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
-    }
-
-    $parent = $(selector)
-
-    e && e.preventDefault()
-
-    $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent())
-
-    $parent.trigger(e = $.Event('close'))
-
-    if (e.isDefaultPrevented()) return
-
-    $parent.removeClass('in')
-
-    function removeElement() {
-      $parent
-        .trigger('closed')
-        .remove()
-    }
-
-    $.support.transition && $parent.hasClass('fade') ?
-      $parent.on($.support.transition.end, removeElement) :
-      removeElement()
-  }
-
-
- /* ALERT PLUGIN DEFINITION
-  * ======================= */
-
-  $.fn.alert = function (option) {
-    return this.each(function () {
-      var $this = $(this)
-        , data = $this.data('alert')
-      if (!data) $this.data('alert', (data = new Alert(this)))
-      if (typeof option == 'string') data[option].call($this)
-    })
-  }
-
-  $.fn.alert.Constructor = Alert
-
-
- /* ALERT DATA-API
-  * ============== */
-
-  $(document).on('click.alert.data-api', dismiss, Alert.prototype.close)
-
-}(window.jQuery);/* ============================================================
- * bootstrap-button.js v2.2.1
- * http://twitter.github.com/bootstrap/javascript.html#buttons
- * ============================================================
- * Copyright 2012 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============================================================ */
-
-
-!function ($) {
-
-  "use strict"; // jshint ;_;
-
-
- /* BUTTON PUBLIC CLASS DEFINITION
-  * ============================== */
-
-  var Button = function (element, options) {
-    this.$element = $(element)
-    this.options = $.extend({}, $.fn.button.defaults, options)
-  }
-
-  Button.prototype.setState = function (state) {
-    var d = 'disabled'
-      , $el = this.$element
-      , data = $el.data()
-      , val = $el.is('input') ? 'val' : 'html'
-
-    state = state + 'Text'
-    data.resetText || $el.data('resetText', $el[val]())
-
-    $el[val](data[state] || this.options[state])
-
-    // push to event loop to allow forms to submit
-    setTimeout(function () {
-      state == 'loadingText' ?
-        $el.addClass(d).attr(d, d) :
-        $el.removeClass(d).removeAttr(d)
-    }, 0)
-  }
-
-  Button.prototype.toggle = function () {
-    var $parent = this.$element.closest('[data-toggle="buttons-radio"]')
-
-    $parent && $parent
-      .find('.active')
-      .removeClass('active')
-
-    this.$element.toggleClass('active')
-  }
-
-
- /* BUTTON PLUGIN DEFINITION
-  * ======================== */
-
-  $.fn.button = function (option) {
-    return this.each(function () {
-      var $this = $(this)
-        , data = $this.data('button')
-        , options = typeof option == 'object' && option
-      if (!data) $this.data('button', (data = new Button(this, options)))
-      if (option == 'toggle') data.toggle()
-      else if (option) data.setState(option)
-    })
-  }
-
-  $.fn.button.defaults = {
-    loadingText: 'loading...'
-  }
-
-  $.fn.button.Constructor = Button
-
-
- /* BUTTON DATA-API
-  * =============== */
-
-  $(document).on('click.button.data-api', '[data-toggle^=button]', function (e) {
-    var $btn = $(e.target)
-    if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
-    $btn.button('toggle')
-  })
-
-}(window.jQuery);/* ==========================================================
- * bootstrap-carousel.js v2.2.1
- * http://twitter.github.com/bootstrap/javascript.html#carousel
- * ==========================================================
- * Copyright 2012 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================================================== */
-
-
-!function ($) {
-
-  "use strict"; // jshint ;_;
-
-
- /* CAROUSEL CLASS DEFINITION
-  * ========================= */
-
-  var Carousel = function (element, options) {
-    this.$element = $(element)
-    this.options = options
-    this.options.slide && this.slide(this.options.slide)
-    this.options.pause == 'hover' && this.$element
-      .on('mouseenter', $.proxy(this.pause, this))
-      .on('mouseleave', $.proxy(this.cycle, this))
-  }
-
-  Carousel.prototype = {
-
-    cycle: function (e) {
-      if (!e) this.paused = false
-      this.options.interval
-        && !this.paused
-        && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
-      return this
-    }
-
-  , to: function (pos) {
-      var $active = this.$element.find('.item.active')
-        , children = $active.parent().children()
-        , activePos = children.index($active)
-        , that = this
-
-      if (pos > (children.length - 1) || pos < 0) return
-
-      if (this.sliding) {
-        return this.$element.one('slid', function () {
-          that.to(pos)
-        })
-      }
-
-      if (activePos == pos) {
-        return this.pause().cycle()
-      }
-
-      return this.slide(pos > activePos ? 'next' : 'prev', $(children[pos]))
-    }
-
-  , pause: function (e) {
-      if (!e) this.paused = true
-      if (this.$element.find('.next, .prev').length && $.support.transition.end) {
-        this.$element.trigger($.support.transition.end)
-        this.cycle()
-      }
-      clearInterval(this.interval)
-      this.interval = null
-      return this
-    }
-
-  , next: function () {
-      if (this.sliding) return
-      return this.slide('next')
-    }
-
-  , prev: function () {
-      if (this.sliding) return
-      return this.slide('prev')
-    }
-
-  , slide: function (type, next) {
-      var $active = this.$element.find('.item.active')
-        , $next = next || $active[type]()
-        , isCycling = this.interval
-        , direction = type == 'next' ? 'left' : 'right'
-        , fallback  = type == 'next' ? 'first' : 'last'
-        , that = this
-        , e
-
-      this.sliding = true
-
-      isCycling && this.pause()
-
-      $next = $next.length ? $next : this.$element.find('.item')[fallback]()
-
-      e = $.Event('slide', {
-        relatedTarget: $next[0]
-      })
-
-      if ($next.hasClass('active')) return
-
-      if ($.support.transition && this.$element.hasClass('slide')) {
-        this.$element.trigger(e)
-        if (e.isDefaultPrevented()) return
-        $next.addClass(type)
-        $next[0].offsetWidth // force reflow
-        $active.addClass(direction)
-        $next.addClass(direction)
-        this.$element.one($.support.transition.end, function () {
-          $next.removeClass([type, direction].join(' ')).addClass('active')
-          $active.removeClass(['active', direction].join(' '))
-          that.sliding = false
-          setTimeout(function () { that.$element.trigger('slid') }, 0)
-        })
-      } else {
-        this.$element.trigger(e)
-        if (e.isDefaultPrevented()) return
-        $active.removeClass('active')
-        $next.addClass('active')
-        this.sliding = false
-        this.$element.trigger('slid')
-      }
-
-      isCycling && this.cycle()
-
-      return this
-    }
-
-  }
-
-
- /* CAROUSEL PLUGIN DEFINITION
-  * ========================== */
-
-  $.fn.carousel = function (option) {
-    return this.each(function () {
-      var $this = $(this)
-        , data = $this.data('carousel')
-        , options = $.extend({}, $.fn.carousel.defaults, typeof option == 'object' && option)
-        , action = typeof option == 'string' ? option : options.slide
-      if (!data) $this.data('carousel', (data = new Carousel(this, options)))
-      if (typeof option == 'number') data.to(option)
-      else if (action) data[action]()
-      else if (options.interval) data.cycle()
-    })
-  }
-
-  $.fn.carousel.defaults = {
-    interval: 5000
-  , pause: 'hover'
-  }
-
-  $.fn.carousel.Constructor = Carousel
-
-
- /* CAROUSEL DATA-API
-  * ================= */
-
-  $(document).on('click.carousel.data-api', '[data-slide]', function (e) {
-    var $this = $(this), href
-      , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
-      , options = $.extend({}, $target.data(), $this.data())
-    $target.carousel(options)
-    e.preventDefault()
-  })
-
-}(window.jQuery);/* =============================================================
- * bootstrap-collapse.js v2.2.1
- * http://twitter.github.com/bootstrap/javascript.html#collapse
- * =============================================================
- * Copyright 2012 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============================================================ */
-
-
-!function ($) {
-
-  "use strict"; // jshint ;_;
-
-
- /* COLLAPSE PUBLIC CLASS DEFINITION
-  * ================================ */
-
-  var Collapse = function (element, options) {
-    this.$element = $(element)
-    this.options = $.extend({}, $.fn.collapse.defaults, options)
-
-    if (this.options.parent) {
-      this.$parent = $(this.options.parent)
-    }
-
-    this.options.toggle && this.toggle()
-  }
-
-  Collapse.prototype = {
-
-    constructor: Collapse
-
-  , dimension: function () {
-      var hasWidth = this.$element.hasClass('width')
-      return hasWidth ? 'width' : 'height'
-    }
-
-  , show: function () {
-      var dimension
-        , scroll
-        , actives
-        , hasData
-
-      if (this.transitioning) return
-
-      dimension = this.dimension()
-      scroll = $.camelCase(['scroll', dimension].join('-'))
-      actives = this.$parent && this.$parent.find('> .accordion-group > .in')
-
-      if (actives && actives.length) {
-        hasData = actives.data('collapse')
-        if (hasData && hasData.transitioning) return
-        actives.collapse('hide')
-        hasData || actives.data('collapse', null)
-      }
-
-      this.$element[dimension](0)
-      this.transition('addClass', $.Event('show'), 'shown')
-      $.support.transition && this.$element[dimension](this.$element[0][scroll])
-    }
-
-  , hide: function () {
-      var dimension
-      if (this.transitioning) return
-      dimension = this.dimension()
-      this.reset(this.$element[dimension]())
-      this.transition('removeClass', $.Event('hide'), 'hidden')
-      this.$element[dimension](0)
-    }
-
-  , reset: function (size) {
-      var dimension = this.dimension()
-
-      this.$element
-        .removeClass('collapse')
-        [dimension](size || 'auto')
-        [0].offsetWidth
-
-      this.$element[size !== null ? 'addClass' : 'removeClass']('collapse')
-
-      return this
-    }
-
-  , transition: function (method, startEvent, completeEvent) {
-      var that = this
-        , complete = function () {
-            if (startEvent.type == 'show') that.reset()
-            that.transitioning = 0
-            that.$element.trigger(completeEvent)
-          }
-
-      this.$element.trigger(startEvent)
-
-      if (startEvent.isDefaultPrevented()) return
-
-      this.transitioning = 1
-
-      this.$element[method]('in')
-
-      $.support.transition && this.$element.hasClass('collapse') ?
-        this.$element.one($.support.transition.end, complete) :
-        complete()
-    }
-
-  , toggle: function () {
-      this[this.$element.hasClass('in') ? 'hide' : 'show']()
-    }
-
-  }
-
-
- /* COLLAPSIBLE PLUGIN DEFINITION
-  * ============================== */
-
-  $.fn.collapse = function (option) {
-    return this.each(function () {
-      var $this = $(this)
-        , data = $this.data('collapse')
-        , options = typeof option == 'object' && option
-      if (!data) $this.data('collapse', (data = new Collapse(this, options)))
-      if (typeof option == 'string') data[option]()
-    })
-  }
-
-  $.fn.collapse.defaults = {
-    toggle: true
-  }
-
-  $.fn.collapse.Constructor = Collapse
-
-
- /* COLLAPSIBLE DATA-API
-  * ==================== */
-
-  $(document).on('click.collapse.data-api', '[data-toggle=collapse]', function (e) {
-    var $this = $(this), href
-      , target = $this.attr('data-target')
-        || e.preventDefault()
-        || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
-      , option = $(target).data('collapse') ? 'toggle' : $this.data()
-    $this[$(target).hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
-    $(target).collapse(option)
-  })
-
-}(window.jQuery);/* ============================================================
- * bootstrap-dropdown.js v2.2.1
- * http://twitter.github.com/bootstrap/javascript.html#dropdowns
- * ============================================================
- * Copyright 2012 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============================================================ */
-
-
-!function ($) {
-
-  "use strict"; // jshint ;_;
-
-
- /* DROPDOWN CLASS DEFINITION
-  * ========================= */
-
-  var toggle = '[data-toggle=dropdown]'
-    , Dropdown = function (element) {
-        var $el = $(element).on('click.dropdown.data-api', this.toggle)
-        $('html').on('click.dropdown.data-api', function () {
-          $el.parent().removeClass('open')
-        })
-      }
-
-  Dropdown.prototype = {
-
-    constructor: Dropdown
-
-  , toggle: function (e) {
-      var $this = $(this)
-        , $parent
-        , isActive
-
-      if ($this.is('.disabled, :disabled')) return
-
-      $parent = getParent($this)
-
-      isActive = $parent.hasClass('open')
-
-      clearMenus()
-
-      if (!isActive) {
-        $parent.toggleClass('open')
-        $this.focus()
-      }
-
-      return false
-    }
-
-  , keydown: function (e) {
-      var $this
-        , $items
-        , $active
-        , $parent
-        , isActive
-        , index
-
-      if (!/(38|40|27)/.test(e.keyCode)) return
-
-      $this = $(this)
-
-      e.preventDefault()
-      e.stopPropagation()
-
-      if ($this.is('.disabled, :disabled')) return
-
-      $parent = getParent($this)
-
-      isActive = $parent.hasClass('open')
-
-      if (!isActive || (isActive && e.keyCode == 27)) return $this.click()
-
-      $items = $('[role=menu] li:not(.divider) a', $parent)
-
-      if (!$items.length) return
-
-      index = $items.index($items.filter(':focus'))
-
-      if (e.keyCode == 38 && index > 0) index--                                        // up
-      if (e.keyCode == 40 && index < $items.length - 1) index++                        // down
-      if (!~index) index = 0
-
-      $items
-        .eq(index)
-        .focus()
-    }
-
-  }
-
-  function clearMenus() {
-    $(toggle).each(function () {
-      getParent($(this)).removeClass('open')
-    })
-  }
-
-  function getParent($this) {
-    var selector = $this.attr('data-target')
-      , $parent
-
-    if (!selector) {
-      selector = $this.attr('href')
-      selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
-    }
-
-    $parent = $(selector)
-    $parent.length || ($parent = $this.parent())
-
-    return $parent
-  }
-
-
-  /* DROPDOWN PLUGIN DEFINITION
-   * ========================== */
-
-  $.fn.dropdown = function (option) {
-    return this.each(function () {
-      var $this = $(this)
-        , data = $this.data('dropdown')
-      if (!data) $this.data('dropdown', (data = new Dropdown(this)))
-      if (typeof option == 'string') data[option].call($this)
-    })
-  }
-
-  $.fn.dropdown.Constructor = Dropdown
-
-
-  /* APPLY TO STANDARD DROPDOWN ELEMENTS
-   * =================================== */
-
-  $(document)
-    .on('click.dropdown.data-api touchstart.dropdown.data-api', clearMenus)
-    .on('click.dropdown touchstart.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
-    .on('click.dropdown.data-api touchstart.dropdown.data-api'  , toggle, Dropdown.prototype.toggle)
-    .on('keydown.dropdown.data-api touchstart.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)
-
-}(window.jQuery);/* =========================================================
- * bootstrap-modal.js v2.2.1
- * http://twitter.github.com/bootstrap/javascript.html#modals
- * =========================================================
- * Copyright 2012 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================================================= */
-
-
-!function ($) {
-
-  "use strict"; // jshint ;_;
-
-
- /* MODAL CLASS DEFINITION
-  * ====================== */
-
-  var Modal = function (element, options) {
-    this.options = options
-    this.$element = $(element)
-      .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this))
-    this.options.remote && this.$element.find('.modal-body').load(this.options.remote)
-  }
-
-  Modal.prototype = {
-
-      constructor: Modal
-
-    , toggle: function () {
-        return this[!this.isShown ? 'show' : 'hide']()
-      }
-
-    , show: function () {
-        var that = this
-          , e = $.Event('show')
-
-        this.$element.trigger(e)
-
-        if (this.isShown || e.isDefaultPrevented()) return
-
-        this.isShown = true
-
-        this.escape()
-
-        this.backdrop(function () {
-          var transition = $.support.transition && that.$element.hasClass('fade')
-
-          if (!that.$element.parent().length) {
-            that.$element.appendTo(document.body) //don't move modals dom position
-          }
-
-          that.$element
-            .show()
-
-          if (transition) {
-            that.$element[0].offsetWidth // force reflow
-          }
-
-          that.$element
-            .addClass('in')
-            .attr('aria-hidden', false)
-
-          that.enforceFocus()
-
-          transition ?
-            that.$element.one($.support.transition.end, function () { that.$element.focus().trigger('shown') }) :
-            that.$element.focus().trigger('shown')
-
-        })
-      }
-
-    , hide: function (e) {
-        e && e.preventDefault()
-
-        var that = this
-
-        e = $.Event('hide')
-
-        this.$element.trigger(e)
-
-        if (!this.isShown || e.isDefaultPrevented()) return
-
-        this.isShown = false
-
-        this.escape()
-
-        $(document).off('focusin.modal')
-
-        this.$element
-          .removeClass('in')
-          .attr('aria-hidden', true)
-
-        $.support.transition && this.$element.hasClass('fade') ?
-          this.hideWithTransition() :
-          this.hideModal()
-      }
-
-    , enforceFocus: function () {
-        var that = this
-        $(document).on('focusin.modal', function (e) {
-          if (that.$element[0] !== e.target && !that.$element.has(e.target).length) {
-            that.$element.focus()
-          }
-        })
-      }
-
-    , escape: function () {
-        var that = this
-        if (this.isShown && this.options.keyboard) {
-          this.$element.on('keyup.dismiss.modal', function ( e ) {
-            e.which == 27 && that.hide()
-          })
-        } else if (!this.isShown) {
-          this.$element.off('keyup.dismiss.modal')
-        }
-      }
-
-    , hideWithTransition: function () {
-        var that = this
-          , timeout = setTimeout(function () {
-              that.$element.off($.support.transition.end)
-              that.hideModal()
-            }, 500)
-
-        this.$element.one($.support.transition.end, function () {
-          clearTimeout(timeout)
-          that.hideModal()
-        })
-      }
-
-    , hideModal: function (that) {
-        this.$element
-          .hide()
-          .trigger('hidden')
-
-        this.backdrop()
-      }
-
-    , removeBackdrop: function () {
-        this.$backdrop.remove()
-        this.$backdrop = null
-      }
-
-    , backdrop: function (callback) {
-        var that = this
-          , animate = this.$element.hasClass('fade') ? 'fade' : ''
-
-        if (this.isShown && this.options.backdrop) {
-          var doAnimate = $.support.transition && animate
-
-          this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
-            .appendTo(document.body)
-
-          this.$backdrop.click(
-            this.options.backdrop == 'static' ?
-              $.proxy(this.$element[0].focus, this.$element[0])
-            : $.proxy(this.hide, this)
-          )
-
-          if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
-
-          this.$backdrop.addClass('in')
-
-          doAnimate ?
-            this.$backdrop.one($.support.transition.end, callback) :
-            callback()
-
-        } else if (!this.isShown && this.$backdrop) {
-          this.$backdrop.removeClass('in')
-
-          $.support.transition && this.$element.hasClass('fade')?
-            this.$backdrop.one($.support.transition.end, $.proxy(this.removeBackdrop, this)) :
-            this.removeBackdrop()
-
-        } else if (callback) {
-          callback()
-        }
-      }
-  }
-
-
- /* MODAL PLUGIN DEFINITION
-  * ======================= */
-
-  $.fn.modal = function (option) {
-    return this.each(function () {
-      var $this = $(this)
-        , data = $this.data('modal')
-        , options = $.extend({}, $.fn.modal.defaults, $this.data(), typeof option == 'object' && option)
-      if (!data) $this.data('modal', (data = new Modal(this, options)))
-      if (typeof option == 'string') data[option]()
-      else if (options.show) data.show()
-    })
-  }
-
-  $.fn.modal.defaults = {
-      backdrop: true
-    , keyboard: true
-    , show: true
-  }
-
-  $.fn.modal.Constructor = Modal
-
-
- /* MODAL DATA-API
-  * ============== */
-
-  $(document).on('click.modal.data-api', '[data-toggle="modal"]', function (e) {
-    var $this = $(this)
-      , href = $this.attr('href')
-      , $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7
-      , option = $target.data('modal') ? 'toggle' : $.extend({ remote:!/#/.test(href) && href }, $target.data(), $this.data())
-
-    e.preventDefault()
-
-    $target
-      .modal(option)
-      .one('hide', function () {
-        $this.focus()
-      })
-  })
-
-}(window.jQuery);
-/* ===========================================================
- * bootstrap-tooltip.js v2.2.1
- * http://twitter.github.com/bootstrap/javascript.html#tooltips
- * Inspired by the original jQuery.tipsy by Jason Frame
- * ===========================================================
- * Copyright 2012 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================================================== */
-
-
-!function ($) {
-
-  "use strict"; // jshint ;_;
-
-
- /* TOOLTIP PUBLIC CLASS DEFINITION
-  * =============================== */
-
-  var Tooltip = function (element, options) {
-    this.init('tooltip', element, options)
-  }
-
-  Tooltip.prototype = {
-
-    constructor: Tooltip
-
-  , init: function (type, element, options) {
-      var eventIn
-        , eventOut
-
-      this.type = type
-      this.$element = $(element)
-      this.options = this.getOptions(options)
-      this.enabled = true
-
-      if (this.options.trigger == 'click') {
-        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
-      } else if (this.options.trigger != 'manual') {
-        eventIn = this.options.trigger == 'hover' ? 'mouseenter' : 'focus'
-        eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur'
-        this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
-        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
-      }
-
-      this.options.selector ?
-        (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
-        this.fixTitle()
-    }
-
-  , getOptions: function (options) {
-      options = $.extend({}, $.fn[this.type].defaults, options, this.$element.data())
-
-      if (options.delay && typeof options.delay == 'number') {
-        options.delay = {
-          show: options.delay
-        , hide: options.delay
-        }
-      }
-
-      return options
-    }
-
-  , enter: function (e) {
-      var self = $(e.currentTarget)[this.type](this._options).data(this.type)
-
-      if (!self.options.delay || !self.options.delay.show) return self.show()
-
-      clearTimeout(this.timeout)
-      self.hoverState = 'in'
-      this.timeout = setTimeout(function() {
-        if (self.hoverState == 'in') self.show()
-      }, self.options.delay.show)
-    }
-
-  , leave: function (e) {
-      var self = $(e.currentTarget)[this.type](this._options).data(this.type)
-
-      if (this.timeout) clearTimeout(this.timeout)
-      if (!self.options.delay || !self.options.delay.hide) return self.hide()
-
-      self.hoverState = 'out'
-      this.timeout = setTimeout(function() {
-        if (self.hoverState == 'out') self.hide()
-      }, self.options.delay.hide)
-    }
-
-  , show: function () {
-      var $tip
-        , inside
-        , pos
-        , actualWidth
-        , actualHeight
-        , placement
-        , tp
-
-      if (this.hasContent() && this.enabled) {
-        $tip = this.tip()
-        this.setContent()
-
-        if (this.options.animation) {
-          $tip.addClass('fade')
-        }
-
-        placement = typeof this.options.placement == 'function' ?
-          this.options.placement.call(this, $tip[0], this.$element[0]) :
-          this.options.placement
-
-        inside = /in/.test(placement)
-
-        $tip
-          .detach()
-          .css({ top: 0, left: 0, display: 'block' })
-          .insertAfter(this.$element)
-
-        pos = this.getPosition(inside)
-
-        actualWidth = $tip[0].offsetWidth
-        actualHeight = $tip[0].offsetHeight
-
-        switch (inside ? placement.split(' ')[1] : placement) {
-          case 'bottom':
-            tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}
-            break
-          case 'top':
-            tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}
-            break
-          case 'left':
-            tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}
-            break
-          case 'right':
-            tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
-            break
-        }
-
-        $tip
-          .offset(tp)
-          .addClass(placement)
-          .addClass('in')
-      }
-    }
-
-  , setContent: function () {
-      var $tip = this.tip()
-        , title = this.getTitle()
-
-      $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
-      $tip.removeClass('fade in top bottom left right')
-    }
-
-  , hide: function () {
-      var that = this
-        , $tip = this.tip()
-
-      $tip.removeClass('in')
-
-      function removeWithAnimation() {
-        var timeout = setTimeout(function () {
-          $tip.off($.support.transition.end).detach()
-        }, 500)
-
-        $tip.one($.support.transition.end, function () {
-          clearTimeout(timeout)
-          $tip.detach()
-        })
-      }
-
-      $.support.transition && this.$tip.hasClass('fade') ?
-        removeWithAnimation() :
-        $tip.detach()
-
-      return this
-    }
-
-  , fixTitle: function () {
-      var $e = this.$element
-      if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
-        $e.attr('data-original-title', $e.attr('title') || '').removeAttr('title')
-      }
-    }
-
-  , hasContent: function () {
-      return this.getTitle()
-    }
-
-  , getPosition: function (inside) {
-      return $.extend({}, (inside ? {top: 0, left: 0} : this.$element.offset()), {
-        width: this.$element[0].offsetWidth
-      , height: this.$element[0].offsetHeight
-      })
-    }
-
-  , getTitle: function () {
-      var title
-        , $e = this.$element
-        , o = this.options
-
-      title = $e.attr('data-original-title')
-        || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
-
-      return title
-    }
-
-  , tip: function () {
-      return this.$tip = this.$tip || $(this.options.template)
-    }
-
-  , validate: function () {
-      if (!this.$element[0].parentNode) {
-        this.hide()
-        this.$element = null
-        this.options = null
-      }
-    }
-
-  , enable: function () {
-      this.enabled = true
-    }
-
-  , disable: function () {
-      this.enabled = false
-    }
-
-  , toggleEnabled: function () {
-      this.enabled = !this.enabled
-    }
-
-  , toggle: function (e) {
-      var self = $(e.currentTarget)[this.type](this._options).data(this.type)
-      self[self.tip().hasClass('in') ? 'hide' : 'show']()
-    }
-
-  , destroy: function () {
-      this.hide().$element.off('.' + this.type).removeData(this.type)
-    }
-
-  }
-
-
- /* TOOLTIP PLUGIN DEFINITION
-  * ========================= */
-
-  $.fn.tooltip = function ( option ) {
-    return this.each(function () {
-      var $this = $(this)
-        , data = $this.data('tooltip')
-        , options = typeof option == 'object' && option
-      if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))
-      if (typeof option == 'string') data[option]()
-    })
-  }
-
-  $.fn.tooltip.Constructor = Tooltip
-
-  $.fn.tooltip.defaults = {
-    animation: true
-  , placement: 'top'
-  , selector: false
-  , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
-  , trigger: 'hover'
-  , title: ''
-  , delay: 0
-  , html: false
-  }
-
-}(window.jQuery);/* ===========================================================
- * bootstrap-popover.js v2.2.1
- * http://twitter.github.com/bootstrap/javascript.html#popovers
- * ===========================================================
- * Copyright 2012 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * =========================================================== */
-
-
-!function ($) {
-
-  "use strict"; // jshint ;_;
-
-
- /* POPOVER PUBLIC CLASS DEFINITION
-  * =============================== */
-
-  var Popover = function (element, options) {
-    this.init('popover', element, options)
-  }
-
-
-  /* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js
-     ========================================== */
-
-  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, {
-
-    constructor: Popover
-
-  , setContent: function () {
-      var $tip = this.tip()
-        , title = this.getTitle()
-        , content = this.getContent()
-
-      $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
-      $tip.find('.popover-content > *')[this.options.html ? 'html' : 'text'](content)
-
-      $tip.removeClass('fade top bottom left right in')
-    }
-
-  , hasContent: function () {
-      return this.getTitle() || this.getContent()
-    }
-
-  , getContent: function () {
-      var content
-        , $e = this.$element
-        , o = this.options
-
-      content = $e.attr('data-content')
-        || (typeof o.content == 'function' ? o.content.call($e[0]) :  o.content)
-
-      return content
-    }
-
-  , tip: function () {
-      if (!this.$tip) {
-        this.$tip = $(this.options.template)
-      }
-      return this.$tip
-    }
-
-  , destroy: function () {
-      this.hide().$element.off('.' + this.type).removeData(this.type)
-    }
-
-  })
-
-
- /* POPOVER PLUGIN DEFINITION
-  * ======================= */
-
-  $.fn.popover = function (option) {
-    return this.each(function () {
-      var $this = $(this)
-        , data = $this.data('popover')
-        , options = typeof option == 'object' && option
-      if (!data) $this.data('popover', (data = new Popover(this, options)))
-      if (typeof option == 'string') data[option]()
-    })
-  }
-
-  $.fn.popover.Constructor = Popover
-
-  $.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, {
-    placement: 'right'
-  , trigger: 'click'
-  , content: ''
-  , template: '<div class="popover"><div class="arrow"></div><div class="popover-inner"><h3 class="popover-title"></h3><div class="popover-content"><p></p></div></div></div>'
-  })
-
-}(window.jQuery);/* =============================================================
- * bootstrap-scrollspy.js v2.2.1
- * http://twitter.github.com/bootstrap/javascript.html#scrollspy
- * =============================================================
- * Copyright 2012 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============================================================== */
-
-
-!function ($) {
-
-  "use strict"; // jshint ;_;
-
-
- /* SCROLLSPY CLASS DEFINITION
-  * ========================== */
-
-  function ScrollSpy(element, options) {
-    var process = $.proxy(this.process, this)
-      , $element = $(element).is('body') ? $(window) : $(element)
-      , href
-    this.options = $.extend({}, $.fn.scrollspy.defaults, options)
-    this.$scrollElement = $element.on('scroll.scroll-spy.data-api', process)
-    this.selector = (this.options.target
-      || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
-      || '') + ' .nav li > a'
-    this.$body = $('body')
-    this.refresh()
-    this.process()
-  }
-
-  ScrollSpy.prototype = {
-
-      constructor: ScrollSpy
-
-    , refresh: function () {
-        var self = this
-          , $targets
-
-        this.offsets = $([])
-        this.targets = $([])
-
-        $targets = this.$body
-          .find(this.selector)
-          .map(function () {
-            var $el = $(this)
-              , href = $el.data('target') || $el.attr('href')
-              , $href = /^#\w/.test(href) && $(href)
-            return ( $href
-              && $href.length
-              && [[ $href.position().top, href ]] ) || null
-          })
-          .sort(function (a, b) { return a[0] - b[0] })
-          .each(function () {
-            self.offsets.push(this[0])
-            self.targets.push(this[1])
-          })
-      }
-
-    , process: function () {
-        var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
-          , scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight
-          , maxScroll = scrollHeight - this.$scrollElement.height()
-          , offsets = this.offsets
-          , targets = this.targets
-          , activeTarget = this.activeTarget
-          , i
-
-        if (scrollTop >= maxScroll) {
-          return activeTarget != (i = targets.last()[0])
-            && this.activate ( i )
-        }
-
-        for (i = offsets.length; i--;) {
-          activeTarget != targets[i]
-            && scrollTop >= offsets[i]
-            && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
-            && this.activate( targets[i] )
-        }
-      }
-
-    , activate: function (target) {
-        var active
-          , selector
-
-        this.activeTarget = target
-
-        $(this.selector)
-          .parent('.active')
-          .removeClass('active')
-
-        selector = this.selector
-          + '[data-target="' + target + '"],'
-          + this.selector + '[href="' + target + '"]'
-
-        active = $(selector)
-          .parent('li')
-          .addClass('active')
-
-        if (active.parent('.dropdown-menu').length)  {
-          active = active.closest('li.dropdown').addClass('active')
-        }
-
-        active.trigger('activate')
-      }
-
-  }
-
-
- /* SCROLLSPY PLUGIN DEFINITION
-  * =========================== */
-
-  $.fn.scrollspy = function (option) {
-    return this.each(function () {
-      var $this = $(this)
-        , data = $this.data('scrollspy')
-        , options = typeof option == 'object' && option
-      if (!data) $this.data('scrollspy', (data = new ScrollSpy(this, options)))
-      if (typeof option == 'string') data[option]()
-    })
-  }
-
-  $.fn.scrollspy.Constructor = ScrollSpy
-
-  $.fn.scrollspy.defaults = {
-    offset: 10
-  }
-
-
- /* SCROLLSPY DATA-API
-  * ================== */
-
-  $(window).on('load', function () {
-    $('[data-spy="scroll"]').each(function () {
-      var $spy = $(this)
-      $spy.scrollspy($spy.data())
-    })
-  })
-
-}(window.jQuery);/* ========================================================
- * bootstrap-tab.js v2.2.1
- * http://twitter.github.com/bootstrap/javascript.html#tabs
- * ========================================================
- * Copyright 2012 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ======================================================== */
-
-
-!function ($) {
-
-  "use strict"; // jshint ;_;
-
-
- /* TAB CLASS DEFINITION
-  * ==================== */
-
-  var Tab = function (element) {
-    this.element = $(element)
-  }
-
-  Tab.prototype = {
-
-    constructor: Tab
-
-  , show: function () {
-      var $this = this.element
-        , $ul = $this.closest('ul:not(.dropdown-menu)')
-        , selector = $this.attr('data-target')
-        , previous
-        , $target
-        , e
-
-      if (!selector) {
-        selector = $this.attr('href')
-        selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
-      }
-
-      if ( $this.parent('li').hasClass('active') ) return
-
-      previous = $ul.find('.active:last a')[0]
-
-      e = $.Event('show', {
-        relatedTarget: previous
-      })
-
-      $this.trigger(e)
-
-      if (e.isDefaultPrevented()) return
-
-      $target = $(selector)
-
-      this.activate($this.parent('li'), $ul)
-      this.activate($target, $target.parent(), function () {
-        $this.trigger({
-          type: 'shown'
-        , relatedTarget: previous
-        })
-      })
-    }
-
-  , activate: function ( element, container, callback) {
-      var $active = container.find('> .active')
-        , transition = callback
-            && $.support.transition
-            && $active.hasClass('fade')
-
-      function next() {
-        $active
-          .removeClass('active')
-          .find('> .dropdown-menu > .active')
-          .removeClass('active')
-
-        element.addClass('active')
-
-        if (transition) {
-          element[0].offsetWidth // reflow for transition
-          element.addClass('in')
-        } else {
-          element.removeClass('fade')
-        }
-
-        if ( element.parent('.dropdown-menu') ) {
-          element.closest('li.dropdown').addClass('active')
-        }
-
-        callback && callback()
-      }
-
-      transition ?
-        $active.one($.support.transition.end, next) :
-        next()
-
-      $active.removeClass('in')
-    }
-  }
-
-
- /* TAB PLUGIN DEFINITION
-  * ===================== */
-
-  $.fn.tab = function ( option ) {
-    return this.each(function () {
-      var $this = $(this)
-        , data = $this.data('tab')
-      if (!data) $this.data('tab', (data = new Tab(this)))
-      if (typeof option == 'string') data[option]()
-    })
-  }
-
-  $.fn.tab.Constructor = Tab
-
-
- /* TAB DATA-API
-  * ============ */
-
-  $(document).on('click.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
-    e.preventDefault()
-    $(this).tab('show')
-  })
-
-}(window.jQuery);/* =============================================================
- * bootstrap-typeahead.js v2.2.1
- * http://twitter.github.com/bootstrap/javascript.html#typeahead
- * =============================================================
- * Copyright 2012 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============================================================ */
-
-
-!function($){
-
-  "use strict"; // jshint ;_;
-
-
- /* TYPEAHEAD PUBLIC CLASS DEFINITION
-  * ================================= */
-
-  var Typeahead = function (element, options) {
-    this.$element = $(element)
-    this.options = $.extend({}, $.fn.typeahead.defaults, options)
-    this.matcher = this.options.matcher || this.matcher
-    this.sorter = this.options.sorter || this.sorter
-    this.highlighter = this.options.highlighter || this.highlighter
-    this.updater = this.options.updater || this.updater
-    this.$menu = $(this.options.menu).appendTo('body')
-    this.source = this.options.source
-    this.shown = false
-    this.listen()
-  }
-
-  Typeahead.prototype = {
-
-    constructor: Typeahead
-
-  , select: function () {
-      var val = this.$menu.find('.active').attr('data-value')
-      this.$element
-        .val(this.updater(val))
-        .change()
-      return this.hide()
-    }
-
-  , updater: function (item) {
-      return item
-    }
-
-  , show: function () {
-      var pos = $.extend({}, this.$element.offset(), {
-        height: this.$element[0].offsetHeight
-      })
-
-      this.$menu.css({
-        top: pos.top + pos.height
-      , left: pos.left
-      })
-
-      this.$menu.show()
-      this.shown = true
-      return this
-    }
-
-  , hide: function () {
-      this.$menu.hide()
-      this.shown = false
-      return this
-    }
-
-  , lookup: function (event) {
-      var items
-
-      this.query = this.$element.val()
-
-      if (!this.query || this.query.length < this.options.minLength) {
-        return this.shown ? this.hide() : this
-      }
-
-      items = $.isFunction(this.source) ? this.source(this.query, $.proxy(this.process, this)) : this.source
-
-      return items ? this.process(items) : this
-    }
-
-  , process: function (items) {
-      var that = this
-
-      items = $.grep(items, function (item) {
-        return that.matcher(item)
-      })
-
-      items = this.sorter(items)
-
-      if (!items.length) {
-        return this.shown ? this.hide() : this
-      }
-
-      return this.render(items.slice(0, this.options.items)).show()
-    }
-
-  , matcher: function (item) {
-      return ~item.toLowerCase().indexOf(this.query.toLowerCase())
-    }
-
-  , sorter: function (items) {
-      var beginswith = []
-        , caseSensitive = []
-        , caseInsensitive = []
-        , item
-
-      while (item = items.shift()) {
-        if (!item.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item)
-        else if (~item.indexOf(this.query)) caseSensitive.push(item)
-        else caseInsensitive.push(item)
-      }
-
-      return beginswith.concat(caseSensitive, caseInsensitive)
-    }
-
-  , highlighter: function (item) {
-      var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&')
-      return item.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) {
-        return '<strong>' + match + '</strong>'
-      })
-    }
-
-  , render: function (items) {
-      var that = this
-
-      items = $(items).map(function (i, item) {
-        i = $(that.options.item).attr('data-value', item)
-        i.find('a').html(that.highlighter(item))
-        return i[0]
-      })
-
-      items.first().addClass('active')
-      this.$menu.html(items)
-      return this
-    }
-
-  , next: function (event) {
-      var active = this.$menu.find('.active').removeClass('active')
-        , next = active.next()
-
-      if (!next.length) {
-        next = $(this.$menu.find('li')[0])
-      }
-
-      next.addClass('active')
-    }
-
-  , prev: function (event) {
-      var active = this.$menu.find('.active').removeClass('active')
-        , prev = active.prev()
-
-      if (!prev.length) {
-        prev = this.$menu.find('li').last()
-      }
-
-      prev.addClass('active')
-    }
-
-  , listen: function () {
-      this.$element
-        .on('blur',     $.proxy(this.blur, this))
-        .on('keypress', $.proxy(this.keypress, this))
-        .on('keyup',    $.proxy(this.keyup, this))
-
-      if (this.eventSupported('keydown')) {
-        this.$element.on('keydown', $.proxy(this.keydown, this))
-      }
-
-      this.$menu
-        .on('click', $.proxy(this.click, this))
-        .on('mouseenter', 'li', $.proxy(this.mouseenter, this))
-    }
-
-  , eventSupported: function(eventName) {
-      var isSupported = eventName in this.$element
-      if (!isSupported) {
-        this.$element.setAttribute(eventName, 'return;')
-        isSupported = typeof this.$element[eventName] === 'function'
-      }
-      return isSupported
-    }
-
-  , move: function (e) {
-      if (!this.shown) return
-
-      switch(e.keyCode) {
-        case 9: // tab
-        case 13: // enter
-        case 27: // escape
-          e.preventDefault()
-          break
-
-        case 38: // up arrow
-          e.preventDefault()
-          this.prev()
-          break
-
-        case 40: // down arrow
-          e.preventDefault()
-          this.next()
-          break
-      }
-
-      e.stopPropagation()
-    }
-
-  , keydown: function (e) {
-      this.suppressKeyPressRepeat = !~$.inArray(e.keyCode, [40,38,9,13,27])
-      this.move(e)
-    }
-
-  , keypress: function (e) {
-      if (this.suppressKeyPressRepeat) return
-      this.move(e)
-    }
-
-  , keyup: function (e) {
-      switch(e.keyCode) {
-        case 40: // down arrow
-        case 38: // up arrow
-        case 16: // shift
-        case 17: // ctrl
-        case 18: // alt
-          break
-
-        case 9: // tab
-        case 13: // enter
-          if (!this.shown) return
-          this.select()
-          break
-
-        case 27: // escape
-          if (!this.shown) return
-          this.hide()
-          break
-
-        default:
-          this.lookup()
-      }
-
-      e.stopPropagation()
-      e.preventDefault()
-  }
-
-  , blur: function (e) {
-      var that = this
-      setTimeout(function () { that.hide() }, 150)
-    }
-
-  , click: function (e) {
-      e.stopPropagation()
-      e.preventDefault()
-      this.select()
-    }
-
-  , mouseenter: function (e) {
-      this.$menu.find('.active').removeClass('active')
-      $(e.currentTarget).addClass('active')
-    }
-
-  }
-
-
-  /* TYPEAHEAD PLUGIN DEFINITION
-   * =========================== */
-
-  $.fn.typeahead = function (option) {
-    return this.each(function () {
-      var $this = $(this)
-        , data = $this.data('typeahead')
-        , options = typeof option == 'object' && option
-      if (!data) $this.data('typeahead', (data = new Typeahead(this, options)))
-      if (typeof option == 'string') data[option]()
-    })
-  }
-
-  $.fn.typeahead.defaults = {
-    source: []
-  , items: 8
-  , menu: '<ul class="typeahead dropdown-menu"></ul>'
-  , item: '<li><a href="#"></a></li>'
-  , minLength: 1
-  }
-
-  $.fn.typeahead.Constructor = Typeahead
-
-
- /*   TYPEAHEAD DATA-API
-  * ================== */
-
-  $(document).on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) {
-    var $this = $(this)
-    if ($this.data('typeahead')) return
-    e.preventDefault()
-    $this.typeahead($this.data())
-  })
-
-}(window.jQuery);
-/* ==========================================================
- * bootstrap-affix.js v2.2.1
- * http://twitter.github.com/bootstrap/javascript.html#affix
- * ==========================================================
- * Copyright 2012 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================================================== */
-
-
-!function ($) {
-
-  "use strict"; // jshint ;_;
-
-
- /* AFFIX CLASS DEFINITION
-  * ====================== */
-
-  var Affix = function (element, options) {
-    this.options = $.extend({}, $.fn.affix.defaults, options)
-    this.$window = $(window)
-      .on('scroll.affix.data-api', $.proxy(this.checkPosition, this))
-      .on('click.affix.data-api',  $.proxy(function () { setTimeout($.proxy(this.checkPosition, this), 1) }, this))
-    this.$element = $(element)
-    this.checkPosition()
-  }
-
-  Affix.prototype.checkPosition = function () {
-    if (!this.$element.is(':visible')) return
-
-    var scrollHeight = $(document).height()
-      , scrollTop = this.$window.scrollTop()
-      , position = this.$element.offset()
-      , offset = this.options.offset
-      , offsetBottom = offset.bottom
-      , offsetTop = offset.top
-      , reset = 'affix affix-top affix-bottom'
-      , affix
-
-    if (typeof offset != 'object') offsetBottom = offsetTop = offset
-    if (typeof offsetTop == 'function') offsetTop = offset.top()
-    if (typeof offsetBottom == 'function') offsetBottom = offset.bottom()
-
-    affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ?
-      false    : offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ?
-      'bottom' : offsetTop != null && scrollTop <= offsetTop ?
-      'top'    : false
-
-    if (this.affixed === affix) return
-
-    this.affixed = affix
-    this.unpin = affix == 'bottom' ? position.top - scrollTop : null
-
-    this.$element.removeClass(reset).addClass('affix' + (affix ? '-' + affix : ''))
-  }
-
-
- /* AFFIX PLUGIN DEFINITION
-  * ======================= */
-
-  $.fn.affix = function (option) {
-    return this.each(function () {
-      var $this = $(this)
-        , data = $this.data('affix')
-        , options = typeof option == 'object' && option
-      if (!data) $this.data('affix', (data = new Affix(this, options)))
-      if (typeof option == 'string') data[option]()
-    })
-  }
-
-  $.fn.affix.Constructor = Affix
-
-  $.fn.affix.defaults = {
-    offset: 0
-  }
-
-
- /* AFFIX DATA-API
-  * ============== */
-
-  $(window).on('load', function () {
-    $('[data-spy="affix"]').each(function () {
-      var $spy = $(this)
-        , data = $spy.data()
-
-      data.offset = data.offset || {}
-
-      data.offsetBottom && (data.offset.bottom = data.offsetBottom)
-      data.offsetTop && (data.offset.top = data.offsetTop)
-
-      $spy.affix(data)
-    })
-  })
-
-
-}(window.jQuery);
\ No newline at end of file
diff --git a/servers/admin/public/javascripts/vendors/bootstrap.min.js b/servers/admin/public/javascripts/vendors/bootstrap.min.js
deleted file mode 100755
index 55da8c3..0000000
--- a/servers/admin/public/javascripts/vendors/bootstrap.min.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/*!
-* Bootstrap.js by @fat & @mdo
-* Copyright 2012 Twitter, Inc.
-* http://www.apache.org/licenses/LICENSE-2.0.txt
-*/
-!function(e){"use strict";e(function(){e.support.transition=function(){var e=function(){var e=document.createElement("bootstrap"),t={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},n;for(n in t)if(e.style[n]!==undefined)return t[n]}();return e&&{end:e}}()})}(window.jQuery),!function(e){"use strict";var t='[data-dismiss="alert"]',n=function(n){e(n).on("click",t,this.close)};n.prototype.close=function(t){function s(){i.trigger("closed").remove()}var n=e(this),r=n.attr("data-target"),i;r||(r=n.attr("href"),r=r&&r.replace(/.*(?=#[^\s]*$)/,"")),i=e(r),t&&t.preventDefault(),i.length||(i=n.hasClass("alert")?n:n.parent()),i.trigger(t=e.Event("close"));if(t.isDefaultPrevented())return;i.removeClass("in"),e.support.transition&&i.hasClass("fade")?i.on(e.support.transition.end,s):s()},e.fn.alert=function(t){return this.each(function(){var r=e(this),i=r.data("alert");i||r.data("alert",i=new n(this)),typeof t=="string"&&i[t].call(r)})},e.fn.alert.Constructor=n,e(document).on("click.alert.data-api",t,n.prototype.close)}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.button.defaults,n)};t.prototype.setState=function(e){var t="disabled",n=this.$element,r=n.data(),i=n.is("input")?"val":"html";e+="Text",r.resetText||n.data("resetText",n[i]()),n[i](r[e]||this.options[e]),setTimeout(function(){e=="loadingText"?n.addClass(t).attr(t,t):n.removeClass(t).removeAttr(t)},0)},t.prototype.toggle=function(){var e=this.$element.closest('[data-toggle="buttons-radio"]');e&&e.find(".active").removeClass("active"),this.$element.toggleClass("active")},e.fn.button=function(n){return this.each(function(){var r=e(this),i=r.data("button"),s=typeof n=="object"&&n;i||r.data("button",i=new t(this,s)),n=="toggle"?i.toggle():n&&i.setState(n)})},e.fn.button.defaults={loadingText:"loading..."},e.fn.button.Constructor=t,e(document).on("click.button.data-api","[data-toggle^=button]",function(t){var n=e(t.target);n.hasClass("btn")||(n=n.closest(".btn")),n.button("toggle")})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=n,this.options.slide&&this.slide(this.options.slide),this.options.pause=="hover"&&this.$element.on("mouseenter",e.proxy(this.pause,this)).on("mouseleave",e.proxy(this.cycle,this))};t.prototype={cycle:function(t){return t||(this.paused=!1),this.options.interval&&!this.paused&&(this.interval=setInterval(e.proxy(this.next,this),this.options.interval)),this},to:function(t){var n=this.$element.find(".item.active"),r=n.parent().children(),i=r.index(n),s=this;if(t>r.length-1||t<0)return;return this.sliding?this.$element.one("slid",function(){s.to(t)}):i==t?this.pause().cycle():this.slide(t>i?"next":"prev",e(r[t]))},pause:function(t){return t||(this.paused=!0),this.$element.find(".next, .prev").length&&e.support.transition.end&&(this.$element.trigger(e.support.transition.end),this.cycle()),clearInterval(this.interval),this.interval=null,this},next:function(){if(this.sliding)return;return this.slide("next")},prev:function(){if(this.sliding)return;return this.slide("prev")},slide:function(t,n){var r=this.$element.find(".item.active"),i=n||r[t](),s=this.interval,o=t=="next"?"left":"right",u=t=="next"?"first":"last",a=this,f;this.sliding=!0,s&&this.pause(),i=i.length?i:this.$element.find(".item")[u](),f=e.Event("slide",{relatedTarget:i[0]});if(i.hasClass("active"))return;if(e.support.transition&&this.$element.hasClass("slide")){this.$element.trigger(f);if(f.isDefaultPrevented())return;i.addClass(t),i[0].offsetWidth,r.addClass(o),i.addClass(o),this.$element.one(e.support.transition.end,function(){i.removeClass([t,o].join(" ")).addClass("active"),r.removeClass(["active",o].join(" ")),a.sliding=!1,setTimeout(function(){a.$element.trigger("slid")},0)})}else{this.$element.trigger(f);if(f.isDefaultPrevented())return;r.removeClass("active"),i.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return s&&this.cycle(),this}},e.fn.carousel=function(n){return this.each(function(){var r=e(this),i=r.data("carousel"),s=e.extend({},e.fn.carousel.defaults,typeof n=="object"&&n),o=typeof n=="string"?n:s.slide;i||r.data("carousel",i=new t(this,s)),typeof n=="number"?i.to(n):o?i[o]():s.interval&&i.cycle()})},e.fn.carousel.defaults={interval:5e3,pause:"hover"},e.fn.carousel.Constructor=t,e(document).on("click.carousel.data-api","[data-slide]",function(t){var n=e(this),r,i=e(n.attr("data-target")||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,"")),s=e.extend({},i.data(),n.data());i.carousel(s),t.preventDefault()})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.collapse.defaults,n),this.options.parent&&(this.$parent=e(this.options.parent)),this.options.toggle&&this.toggle()};t.prototype={constructor:t,dimension:function(){var e=this.$element.hasClass("width");return e?"width":"height"},show:function(){var t,n,r,i;if(this.transitioning)return;t=this.dimension(),n=e.camelCase(["scroll",t].join("-")),r=this.$parent&&this.$parent.find("> .accordion-group > .in");if(r&&r.length){i=r.data("collapse");if(i&&i.transitioning)return;r.collapse("hide"),i||r.data("collapse",null)}this.$element[t](0),this.transition("addClass",e.Event("show"),"shown"),e.support.transition&&this.$element[t](this.$element[0][n])},hide:function(){var t;if(this.transitioning)return;t=this.dimension(),this.reset(this.$element[t]()),this.transition("removeClass",e.Event("hide"),"hidden"),this.$element[t](0)},reset:function(e){var t=this.dimension();return this.$element.removeClass("collapse")[t](e||"auto")[0].offsetWidth,this.$element[e!==null?"addClass":"removeClass"]("collapse"),this},transition:function(t,n,r){var i=this,s=function(){n.type=="show"&&i.reset(),i.transitioning=0,i.$element.trigger(r)};this.$element.trigger(n);if(n.isDefaultPrevented())return;this.transitioning=1,this.$element[t]("in"),e.support.transition&&this.$element.hasClass("collapse")?this.$element.one(e.support.transition.end,s):s()},toggle:function(){this[this.$element.hasClass("in")?"hide":"show"]()}},e.fn.collapse=function(n){return this.each(function(){var r=e(this),i=r.data("collapse"),s=typeof n=="object"&&n;i||r.data("collapse",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.collapse.defaults={toggle:!0},e.fn.collapse.Constructor=t,e(document).on("click.collapse.data-api","[data-toggle=collapse]",function(t){var n=e(this),r,i=n.attr("data-target")||t.preventDefault()||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,""),s=e(i).data("collapse")?"toggle":n.data();n[e(i).hasClass("in")?"addClass":"removeClass"]("collapsed"),e(i).collapse(s)})}(window.jQuery),!function(e){"use strict";function r(){e(t).each(function(){i(e(this)).removeClass("open")})}function i(t){var n=t.attr("data-target"),r;return n||(n=t.attr("href"),n=n&&/#/.test(n)&&n.replace(/.*(?=#[^\s]*$)/,"")),r=e(n),r.length||(r=t.parent()),r}var t="[data-toggle=dropdown]",n=function(t){var n=e(t).on("click.dropdown.data-api",this.toggle);e("html").on("click.dropdown.data-api",function(){n.parent().removeClass("open")})};n.prototype={constructor:n,toggle:function(t){var n=e(this),s,o;if(n.is(".disabled, :disabled"))return;return s=i(n),o=s.hasClass("open"),r(),o||(s.toggleClass("open"),n.focus()),!1},keydown:function(t){var n,r,s,o,u,a;if(!/(38|40|27)/.test(t.keyCode))return;n=e(this),t.preventDefault(),t.stopPropagation();if(n.is(".disabled, :disabled"))return;o=i(n),u=o.hasClass("open");if(!u||u&&t.keyCode==27)return n.click();r=e("[role=menu] li:not(.divider) a",o);if(!r.length)return;a=r.index(r.filter(":focus")),t.keyCode==38&&a>0&&a--,t.keyCode==40&&a<r.length-1&&a++,~a||(a=0),r.eq(a).focus()}},e.fn.dropdown=function(t){return this.each(function(){var r=e(this),i=r.data("dropdown");i||r.data("dropdown",i=new n(this)),typeof t=="string"&&i[t].call(r)})},e.fn.dropdown.Constructor=n,e(document).on("click.dropdown.data-api touchstart.dropdown.data-api",r).on("click.dropdown touchstart.dropdown.data-api",".dropdown form",function(e){e.stopPropagation()}).on("click.dropdown.data-api touchstart.dropdown.data-api",t,n.prototype.toggle).on("keydown.dropdown.data-api touchstart.dropdown.data-api",t+", [role=menu]",n.prototype.keydown)}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.options=n,this.$element=e(t).delegate('[data-dismiss="modal"]',"click.dismiss.modal",e.proxy(this.hide,this)),this.options.remote&&this.$element.find(".modal-body").load(this.options.remote)};t.prototype={constructor:t,toggle:function(){return this[this.isShown?"hide":"show"]()},show:function(){var t=this,n=e.Event("show");this.$element.trigger(n);if(this.isShown||n.isDefaultPrevented())return;this.isShown=!0,this.escape(),this.backdrop(function(){var n=e.support.transition&&t.$element.hasClass("fade");t.$element.parent().length||t.$element.appendTo(document.body),t.$element.show(),n&&t.$element[0].offsetWidth,t.$element.addClass("in").attr("aria-hidden",!1),t.enforceFocus(),n?t.$element.one(e.support.transition.end,function(){t.$element.focus().trigger("shown")}):t.$element.focus().trigger("shown")})},hide:function(t){t&&t.preventDefault();var n=this;t=e.Event("hide"),this.$element.trigger(t);if(!this.isShown||t.isDefaultPrevented())return;this.isShown=!1,this.escape(),e(document).off("focusin.modal"),this.$element.removeClass("in").attr("aria-hidden",!0),e.support.transition&&this.$element.hasClass("fade")?this.hideWithTransition():this.hideModal()},enforceFocus:function(){var t=this;e(document).on("focusin.modal",function(e){t.$element[0]!==e.target&&!t.$element.has(e.target).length&&t.$element.focus()})},escape:function(){var e=this;this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.modal",function(t){t.which==27&&e.hide()}):this.isShown||this.$element.off("keyup.dismiss.modal")},hideWithTransition:function(){var t=this,n=setTimeout(function(){t.$element.off(e.support.transition.end),t.hideModal()},500);this.$element.one(e.support.transition.end,function(){clearTimeout(n),t.hideModal()})},hideModal:function(e){this.$element.hide().trigger("hidden"),this.backdrop()},removeBackdrop:function(){this.$backdrop.remove(),this.$backdrop=null},backdrop:function(t){var n=this,r=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var i=e.support.transition&&r;this.$backdrop=e('<div class="modal-backdrop '+r+'" />').appendTo(document.body),this.$backdrop.click(this.options.backdrop=="static"?e.proxy(this.$element[0].focus,this.$element[0]):e.proxy(this.hide,this)),i&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),i?this.$backdrop.one(e.support.transition.end,t):t()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),e.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(e.support.transition.end,e.proxy(this.removeBackdrop,this)):this.removeBackdrop()):t&&t()}},e.fn.modal=function(n){return this.each(function(){var r=e(this),i=r.data("modal"),s=e.extend({},e.fn.modal.defaults,r.data(),typeof n=="object"&&n);i||r.data("modal",i=new t(this,s)),typeof n=="string"?i[n]():s.show&&i.show()})},e.fn.modal.defaults={backdrop:!0,keyboard:!0,show:!0},e.fn.modal.Constructor=t,e(document).on("click.modal.data-api",'[data-toggle="modal"]',function(t){var n=e(this),r=n.attr("href"),i=e(n.attr("data-target")||r&&r.replace(/.*(?=#[^\s]+$)/,"")),s=i.data("modal")?"toggle":e.extend({remote:!/#/.test(r)&&r},i.data(),n.data());t.preventDefault(),i.modal(s).one("hide",function(){n.focus()})})}(window.jQuery),!function(e){"use strict";var t=function(e,t){this.init("tooltip",e,t)};t.prototype={constructor:t,init:function(t,n,r){var i,s;this.type=t,this.$element=e(n),this.options=this.getOptions(r),this.enabled=!0,this.options.trigger=="click"?this.$element.on("click."+this.type,this.options.selector,e.proxy(this.toggle,this)):this.options.trigger!="manual"&&(i=this.options.trigger=="hover"?"mouseenter":"focus",s=this.options.trigger=="hover"?"mouseleave":"blur",this.$element.on(i+"."+this.type,this.options.selector,e.proxy(this.enter,this)),this.$element.on(s+"."+this.type,this.options.selector,e.proxy(this.leave,this))),this.options.selector?this._options=e.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},getOptions:function(t){return t=e.extend({},e.fn[this.type].defaults,t,this.$element.data()),t.delay&&typeof t.delay=="number"&&(t.delay={show:t.delay,hide:t.delay}),t},enter:function(t){var n=e(t.currentTarget)[this.type](this._options).data(this.type);if(!n.options.delay||!n.options.delay.show)return n.show();clearTimeout(this.timeout),n.hoverState="in",this.timeout=setTimeout(function(){n.hoverState=="in"&&n.show()},n.options.delay.show)},leave:function(t){var n=e(t.currentTarget)[this.type](this._options).data(this.type);this.timeout&&clearTimeout(this.timeout);if(!n.options.delay||!n.options.delay.hide)return n.hide();n.hoverState="out",this.timeout=setTimeout(function(){n.hoverState=="out"&&n.hide()},n.options.delay.hide)},show:function(){var e,t,n,r,i,s,o;if(this.hasContent()&&this.enabled){e=this.tip(),this.setContent(),this.options.animation&&e.addClass("fade"),s=typeof this.options.placement=="function"?this.options.placement.call(this,e[0],this.$element[0]):this.options.placement,t=/in/.test(s),e.detach().css({top:0,left:0,display:"block"}).insertAfter(this.$element),n=this.getPosition(t),r=e[0].offsetWidth,i=e[0].offsetHeight;switch(t?s.split(" ")[1]:s){case"bottom":o={top:n.top+n.height,left:n.left+n.width/2-r/2};break;case"top":o={top:n.top-i,left:n.left+n.width/2-r/2};break;case"left":o={top:n.top+n.height/2-i/2,left:n.left-r};break;case"right":o={top:n.top+n.height/2-i/2,left:n.left+n.width}}e.offset(o).addClass(s).addClass("in")}},setContent:function(){var e=this.tip(),t=this.getTitle();e.find(".tooltip-inner")[this.options.html?"html":"text"](t),e.removeClass("fade in top bottom left right")},hide:function(){function r(){var t=setTimeout(function(){n.off(e.support.transition.end).detach()},500);n.one(e.support.transition.end,function(){clearTimeout(t),n.detach()})}var t=this,n=this.tip();return n.removeClass("in"),e.support.transition&&this.$tip.hasClass("fade")?r():n.detach(),this},fixTitle:function(){var e=this.$element;(e.attr("title")||typeof e.attr("data-original-title")!="string")&&e.attr("data-original-title",e.attr("title")||"").removeAttr("title")},hasContent:function(){return this.getTitle()},getPosition:function(t){return e.extend({},t?{top:0,left:0}:this.$element.offset(),{width:this.$element[0].offsetWidth,height:this.$element[0].offsetHeight})},getTitle:function(){var e,t=this.$element,n=this.options;return e=t.attr("data-original-title")||(typeof n.title=="function"?n.title.call(t[0]):n.title),e},tip:function(){return this.$tip=this.$tip||e(this.options.template)},validate:function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},enable:function(){this.enabled=!0},disable:function(){this.enabled=!1},toggleEnabled:function(){this.enabled=!this.enabled},toggle:function(t){var n=e(t.currentTarget)[this.type](this._options).data(this.type);n[n.tip().hasClass("in")?"hide":"show"]()},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}},e.fn.tooltip=function(n){return this.each(function(){var r=e(this),i=r.data("tooltip"),s=typeof n=="object"&&n;i||r.data("tooltip",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.tooltip.Constructor=t,e.fn.tooltip.defaults={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover",title:"",delay:0,html:!1}}(window.jQuery),!function(e){"use strict";var t=function(e,t){this.init("popover",e,t)};t.prototype=e.extend({},e.fn.tooltip.Constructor.prototype,{constructor:t,setContent:function(){var e=this.tip(),t=this.getTitle(),n=this.getContent();e.find(".popover-title")[this.options.html?"html":"text"](t),e.find(".popover-content > *")[this.options.html?"html":"text"](n),e.removeClass("fade top bottom left right in")},hasContent:function(){return this.getTitle()||this.getContent()},getContent:function(){var e,t=this.$element,n=this.options;return e=t.attr("data-content")||(typeof n.content=="function"?n.content.call(t[0]):n.content),e},tip:function(){return this.$tip||(this.$tip=e(this.options.template)),this.$tip},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}}),e.fn.popover=function(n){return this.each(function(){var r=e(this),i=r.data("popover"),s=typeof n=="object"&&n;i||r.data("popover",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.popover.Constructor=t,e.fn.popover.defaults=e.extend({},e.fn.tooltip.defaults,{placement:"right",trigger:"click",content:"",template:'<div class="popover"><div class="arrow"></div><div class="popover-inner"><h3 class="popover-title"></h3><div class="popover-content"><p></p></div></div></div>'})}(window.jQuery),!function(e){"use strict";function t(t,n){var r=e.proxy(this.process,this),i=e(t).is("body")?e(window):e(t),s;this.options=e.extend({},e.fn.scrollspy.defaults,n),this.$scrollElement=i.on("scroll.scroll-spy.data-api",r),this.selector=(this.options.target||(s=e(t).attr("href"))&&s.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.$body=e("body"),this.refresh(),this.process()}t.prototype={constructor:t,refresh:function(){var t=this,n;this.offsets=e([]),this.targets=e([]),n=this.$body.find(this.selector).map(function(){var t=e(this),n=t.data("target")||t.attr("href"),r=/^#\w/.test(n)&&e(n);return r&&r.length&&[[r.position().top,n]]||null}).sort(function(e,t){return e[0]-t[0]}).each(function(){t.offsets.push(this[0]),t.targets.push(this[1])})},process:function(){var e=this.$scrollElement.scrollTop()+this.options.offset,t=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,n=t-this.$scrollElement.height(),r=this.offsets,i=this.targets,s=this.activeTarget,o;if(e>=n)return s!=(o=i.last()[0])&&this.activate(o);for(o=r.length;o--;)s!=i[o]&&e>=r[o]&&(!r[o+1]||e<=r[o+1])&&this.activate(i[o])},activate:function(t){var n,r;this.activeTarget=t,e(this.selector).parent(".active").removeClass("active"),r=this.selector+'[data-target="'+t+'"],'+this.selector+'[href="'+t+'"]',n=e(r).parent("li").addClass("active"),n.parent(".dropdown-menu").length&&(n=n.closest("li.dropdown").addClass("active")),n.trigger("activate")}},e.fn.scrollspy=function(n){return this.each(function(){var r=e(this),i=r.data("scrollspy"),s=typeof n=="object"&&n;i||r.data("scrollspy",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.scrollspy.Constructor=t,e.fn.scrollspy.defaults={offset:10},e(window).on("load",function(){e('[data-spy="scroll"]').each(function(){var t=e(this);t.scrollspy(t.data())})})}(window.jQuery),!function(e){"use strict";var t=function(t){this.element=e(t)};t.prototype={constructor:t,show:function(){var t=this.element,n=t.closest("ul:not(.dropdown-menu)"),r=t.attr("data-target"),i,s,o;r||(r=t.attr("href"),r=r&&r.replace(/.*(?=#[^\s]*$)/,""));if(t.parent("li").hasClass("active"))return;i=n.find(".active:last a")[0],o=e.Event("show",{relatedTarget:i}),t.trigger(o);if(o.isDefaultPrevented())return;s=e(r),this.activate(t.parent("li"),n),this.activate(s,s.parent(),function(){t.trigger({type:"shown",relatedTarget:i})})},activate:function(t,n,r){function o(){i.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),t.addClass("active"),s?(t[0].offsetWidth,t.addClass("in")):t.removeClass("fade"),t.parent(".dropdown-menu")&&t.closest("li.dropdown").addClass("active"),r&&r()}var i=n.find("> .active"),s=r&&e.support.transition&&i.hasClass("fade");s?i.one(e.support.transition.end,o):o(),i.removeClass("in")}},e.fn.tab=function(n){return this.each(function(){var r=e(this),i=r.data("tab");i||r.data("tab",i=new t(this)),typeof n=="string"&&i[n]()})},e.fn.tab.Constructor=t,e(document).on("click.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(t){t.preventDefault(),e(this).tab("show")})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.typeahead.defaults,n),this.matcher=this.options.matcher||this.matcher,this.sorter=this.options.sorter||this.sorter,this.highlighter=this.options.highlighter||this.highlighter,this.updater=this.options.updater||this.updater,this.$menu=e(this.options.menu).appendTo("body"),this.source=this.options.source,this.shown=!1,this.listen()};t.prototype={constructor:t,select:function(){var e=this.$menu.find(".active").attr("data-value");return this.$element.val(this.updater(e)).change(),this.hide()},updater:function(e){return e},show:function(){var t=e.extend({},this.$element.offset(),{height:this.$element[0].offsetHeight});return this.$menu.css({top:t.top+t.height,left:t.left}),this.$menu.show(),this.shown=!0,this},hide:function(){return this.$menu.hide(),this.shown=!1,this},lookup:function(t){var n;return this.query=this.$element.val(),!this.query||this.query.length<this.options.minLength?this.shown?this.hide():this:(n=e.isFunction(this.source)?this.source(this.query,e.proxy(this.process,this)):this.source,n?this.process(n):this)},process:function(t){var n=this;return t=e.grep(t,function(e){return n.matcher(e)}),t=this.sorter(t),t.length?this.render(t.slice(0,this.options.items)).show():this.shown?this.hide():this},matcher:function(e){return~e.toLowerCase().indexOf(this.query.toLowerCase())},sorter:function(e){var t=[],n=[],r=[],i;while(i=e.shift())i.toLowerCase().indexOf(this.query.toLowerCase())?~i.indexOf(this.query)?n.push(i):r.push(i):t.push(i);return t.concat(n,r)},highlighter:function(e){var t=this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&");return e.replace(new RegExp("("+t+")","ig"),function(e,t){return"<strong>"+t+"</strong>"})},render:function(t){var n=this;return t=e(t).map(function(t,r){return t=e(n.options.item).attr("data-value",r),t.find("a").html(n.highlighter(r)),t[0]}),t.first().addClass("active"),this.$menu.html(t),this},next:function(t){var n=this.$menu.find(".active").removeClass("active"),r=n.next();r.length||(r=e(this.$menu.find("li")[0])),r.addClass("active")},prev:function(e){var t=this.$menu.find(".active").removeClass("active"),n=t.prev();n.length||(n=this.$menu.find("li").last()),n.addClass("active")},listen:function(){this.$element.on("blur",e.proxy(this.blur,this)).on("keypress",e.proxy(this.keypress,this)).on("keyup",e.proxy(this.keyup,this)),this.eventSupported("keydown")&&this.$element.on("keydown",e.proxy(this.keydown,this)),this.$menu.on("click",e.proxy(this.click,this)).on("mouseenter","li",e.proxy(this.mouseenter,this))},eventSupported:function(e){var t=e in this.$element;return t||(this.$element.setAttribute(e,"return;"),t=typeof this.$element[e]=="function"),t},move:function(e){if(!this.shown)return;switch(e.keyCode){case 9:case 13:case 27:e.preventDefault();break;case 38:e.preventDefault(),this.prev();break;case 40:e.preventDefault(),this.next()}e.stopPropagation()},keydown:function(t){this.suppressKeyPressRepeat=!~e.inArray(t.keyCode,[40,38,9,13,27]),this.move(t)},keypress:function(e){if(this.suppressKeyPressRepeat)return;this.move(e)},keyup:function(e){switch(e.keyCode){case 40:case 38:case 16:case 17:case 18:break;case 9:case 13:if(!this.shown)return;this.select();break;case 27:if(!this.shown)return;this.hide();break;default:this.lookup()}e.stopPropagation(),e.preventDefault()},blur:function(e){var t=this;setTimeout(function(){t.hide()},150)},click:function(e){e.stopPropagation(),e.preventDefault(),this.select()},mouseenter:function(t){this.$menu.find(".active").removeClass("active"),e(t.currentTarget).addClass("active")}},e.fn.typeahead=function(n){return this.each(function(){var r=e(this),i=r.data("typeahead"),s=typeof n=="object"&&n;i||r.data("typeahead",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.typeahead.defaults={source:[],items:8,menu:'<ul class="typeahead dropdown-menu"></ul>',item:'<li><a href="#"></a></li>',minLength:1},e.fn.typeahead.Constructor=t,e(document).on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(t){var n=e(this);if(n.data("typeahead"))return;t.preventDefault(),n.typeahead(n.data())})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.options=e.extend({},e.fn.affix.defaults,n),this.$window=e(window).on("scroll.affix.data-api",e.proxy(this.checkPosition,this)).on("click.affix.data-api",e.proxy(function(){setTimeout(e.proxy(this.checkPosition,this),1)},this)),this.$element=e(t),this.checkPosition()};t.prototype.checkPosition=function(){if(!this.$element.is(":visible"))return;var t=e(document).height(),n=this.$window.scrollTop(),r=this.$element.offset(),i=this.options.offset,s=i.bottom,o=i.top,u="affix affix-top affix-bottom",a;typeof i!="object"&&(s=o=i),typeof o=="function"&&(o=i.top()),typeof s=="function"&&(s=i.bottom()),a=this.unpin!=null&&n+this.unpin<=r.top?!1:s!=null&&r.top+this.$element.height()>=t-s?"bottom":o!=null&&n<=o?"top":!1;if(this.affixed===a)return;this.affixed=a,this.unpin=a=="bottom"?r.top-n:null,this.$element.removeClass(u).addClass("affix"+(a?"-"+a:""))},e.fn.affix=function(n){return this.each(function(){var r=e(this),i=r.data("affix"),s=typeof n=="object"&&n;i||r.data("affix",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.affix.Constructor=t,e.fn.affix.defaults={offset:0},e(window).on("load",function(){e('[data-spy="affix"]').each(function(){var t=e(this),n=t.data();n.offset=n.offset||{},n.offsetBottom&&(n.offset.bottom=n.offsetBottom),n.offsetTop&&(n.offset.top=n.offsetTop),t.affix(n)})})}(window.jQuery);
\ No newline at end of file
diff --git a/servers/admin/public/javascripts/vendors/colResizable-1.3.min.js b/servers/admin/public/javascripts/vendors/colResizable-1.3.min.js
deleted file mode 100755
index 406f7b3..0000000
--- a/servers/admin/public/javascripts/vendors/colResizable-1.3.min.js
+++ /dev/null
@@ -1,2 +0,0 @@
-//colResizable - by Alvaro Prieto Lauroba - MIT & GPL

-(function(a){function h(b){var c=a(this).data(q),d=m[c.t],e=d.g[c.i];e.ox=b.pageX;e.l=e[I]()[H];i[D](E+q,f)[D](F+q,g);P[z](x+"*{cursor:"+d.opt.dragCursor+K+J);e[B](d.opt.draggingClass);l=e;if(d.c[c.i].l)for(b=0;b<d.ln;b++)c=d.c[b],c.l=j,c.w=c[u]();return j}function g(b){i.unbind(E+q).unbind(F+q);a("head :last-child").remove();if(l){l[A](l.t.opt.draggingClass);var f=l.t,g=f.opt.onResize;l.x&&(e(f,l.i,1),d(f),g&&(b[G]=f[0],g(b)));f.p&&O&&c(f);l=k}}function f(a){if(l){var b=l.t,c=a.pageX-l.ox+l.l,f=b.opt.minWidth,g=l.i,h=1.5*b.cs+f+b.b,i=g==b.ln-1?b.w-h:b.g[g+1][I]()[H]-b.cs-f,f=g?b.g[g-1][I]()[H]+b.cs+f:h,c=s.max(f,s.min(i,c));l.x=c;l.css(H,c+p);if(b.opt.liveDrag&&(e(b,g),d(b),c=b.opt.onDrag))a[G]=b[0],c(a)}return j}function e(a,b,c){var d=l.x-l.l,e=a.c[b],f=a.c[b+1],g=e.w+d,d=f.w-d;e[u](g+p);f[u](d+p);a.cg.eq(b)[u](g+p);a.cg.eq(b+1)[u](d+p);if(c)e.w=g,f.w=d}function d(a){a.gc[u](a.w);for(var b=0;b<a.ln;b++){var c=a.c[b];a.g[b].css({left:c.offset().left-a.offset()[H]+c.outerWidth()+a.cs/2+p,height:a.opt.headerOnly?a.c[0].outerHeight():a.outerHeight()})}}function c(a,b){var c,d=0,e=0,f=[];if(b)if(a.cg[C](u),a.opt.flush)O[a.id]="";else{for(c=O[a.id].split(";");e<a.ln;e++)f[y](100*c[e]/c[a.ln]+"%"),b.eq(e).css(u,f[e]);for(e=0;e<a.ln;e++)a.cg.eq(e).css(u,f[e])}else{O[a.id]="";for(e in a.c)c=a.c[e][u](),O[a.id]+=c+";",d+=c;O[a.id]+=d}}function b(b){var e=">thead>tr>",f='"></div>',g=">tbody>tr:first>",i=">tr:first>",j="td",k="th",l=b.find(e+k+","+e+j);l.length||(l=b.find(g+k+","+i+k+","+g+j+","+i+j));b.cg=b.find("col");b.ln=l.length;b.p&&O&&O[b.id]&&c(b,l);l.each(function(c){var d=a(this),e=a(b.gc[z](w+"CRG"+f)[0].lastChild);e.t=b;e.i=c;e.c=d;d.w=d[u]();b.g[y](e);b.c[y](d);d[u](d.w)[C](u);if(c<b.ln-1)e.mousedown(h)[z](b.opt.gripInnerHtml)[z](w+q+'" style="cursor:'+b.opt.hoverCursor+f);else e[B]("CRL")[A]("CRG");e.data(q,{i:c,t:b[v](o)})});b.cg[C](u);d(b);b.find("td, th").not(l).not(N+"th, table td").each(function(){a(this)[C](u)})}var i=a(document),j=!1,k=null,l=k,m=[],n=0,o="id",p="px",q="CRZ",r=parseInt,s=Math,t=a.browser.msie,u="width",v="attr",w='<div class="',x="<style type='text/css'>",y="push",z="append",A="removeClass",B="addClass",C="removeAttr",D="bind",E="mousemove.",F="mouseup.",G="currentTarget",H="left",I="position",J="}</style>",K="!important;",L=":0px"+K,M="resize",N="table",O,P=a("head")[z](x+".CRZ{table-layout:fixed;}.CRZ td,.CRZ th{padding-"+H+L+"padding-right"+L+"overflow:hidden}.CRC{height:0px;"+I+":relative;}.CRG{margin-left:-5px;"+I+":absolute;z-index:5;}.CRG .CRZ{"+I+":absolute;background-color:red;filter:alpha(opacity=1);opacity:0;width:10px;height:100%;top:0px}.CRL{"+I+":absolute;width:1px}.CRD{ border-left:1px dotted black"+J);try{O=sessionStorage}catch(Q){}a(window)[D](M+"."+q,function(){for(a in m){var a=m[a],b,c=0;a[A](q);if(a.w!=a[u]()){a.w=a[u]();for(b=0;b<a.ln;b++)c+=a.c[b].w;for(b=0;b<a.ln;b++)a.c[b].css(u,s.round(1e3*a.c[b].w/c)/10+"%").l=1}d(a[B](q))}});a.fn.extend({colResizable:function(c){c=a.extend({draggingClass:"CRD",gripInnerHtml:"",liveDrag:j,minWidth:15,headerOnly:j,hoverCursor:"e-"+M,dragCursor:"e-"+M,postbackSafe:j,flush:j,marginLeft:k,marginRight:k,disable:j,onDrag:k,onResize:k},c);return this.each(function(){var d=c,e=a(this);if(d.disable){if(e=e[v](o),(d=m[e])&&d.is(N))d[A](q).gc.remove(),delete m[e]}else{var f=e.id=e[v](o)||q+n++;e.p=d.postbackSafe;if(e.is(N)&&!m[f])e[B](q)[v](o,f).before(w+'CRC"/>'),e.opt=d,e.g=[],e.c=[],e.w=e[u](),e.gc=e.prev(),d.marginLeft&&e.gc.css("marginLeft",d.marginLeft),d.marginRight&&e.gc.css("marginRight",d.marginRight),e.cs=r(t?this.cellSpacing||this.currentStyle.borderSpacing:e.css("border-spacing"))||2,e.b=r(t?this.border||this.currentStyle.borderLeftWidth:e.css("border-"+H+"-"+u))||1,m[f]=e,b(e)}})}})})(jQuery)
\ No newline at end of file
diff --git a/servers/admin/public/javascripts/vendors/jquery-1.8.3.min.js b/servers/admin/public/javascripts/vendors/jquery-1.8.3.min.js
deleted file mode 100755
index 83589da..0000000
--- a/servers/admin/public/javascripts/vendors/jquery-1.8.3.min.js
+++ /dev/null
@@ -1,2 +0,0 @@
-/*! jQuery v1.8.3 jquery.com | jquery.org/license */

-(function(e,t){function _(e){var t=M[e]={};return v.each(e.split(y),function(e,n){t[n]=!0}),t}function H(e,n,r){if(r===t&&e.nodeType===1){var i="data-"+n.replace(P,"-$1").toLowerCase();r=e.getAttribute(i);if(typeof r=="string"){try{r=r==="true"?!0:r==="false"?!1:r==="null"?null:+r+""===r?+r:D.test(r)?v.parseJSON(r):r}catch(s){}v.data(e,n,r)}else r=t}return r}function B(e){var t;for(t in e){if(t==="data"&&v.isEmptyObject(e[t]))continue;if(t!=="toJSON")return!1}return!0}function et(){return!1}function tt(){return!0}function ut(e){return!e||!e.parentNode||e.parentNode.nodeType===11}function at(e,t){do e=e[t];while(e&&e.nodeType!==1);return e}function ft(e,t,n){t=t||0;if(v.isFunction(t))return v.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return v.grep(e,function(e,r){return e===t===n});if(typeof t=="string"){var r=v.grep(e,function(e){return e.nodeType===1});if(it.test(t))return v.filter(t,r,!n);t=v.filter(t,r)}return v.grep(e,function(e,r){return v.inArray(e,t)>=0===n})}function lt(e){var t=ct.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function At(e,t){if(t.nodeType!==1||!v.hasData(e))return;var n,r,i,s=v._data(e),o=v._data(t,s),u=s.events;if(u){delete o.handle,o.events={};for(n in u)for(r=0,i=u[n].length;r<i;r++)v.event.add(t,n,u[n][r])}o.data&&(o.data=v.extend({},o.data))}function Ot(e,t){var n;if(t.nodeType!==1)return;t.clearAttributes&&t.clearAttributes(),t.mergeAttributes&&t.mergeAttributes(e),n=t.nodeName.toLowerCase(),n==="object"?(t.parentNode&&(t.outerHTML=e.outerHTML),v.support.html5Clone&&e.innerHTML&&!v.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):n==="input"&&Et.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):n==="option"?t.selected=e.defaultSelected:n==="input"||n==="textarea"?t.defaultValue=e.defaultValue:n==="script"&&t.text!==e.text&&(t.text=e.text),t.removeAttribute(v.expando)}function Mt(e){return typeof e.getElementsByTagName!="undefined"?e.getElementsByTagName("*"):typeof e.querySelectorAll!="undefined"?e.querySelectorAll("*"):[]}function _t(e){Et.test(e.type)&&(e.defaultChecked=e.checked)}function Qt(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=Jt.length;while(i--){t=Jt[i]+n;if(t in e)return t}return r}function Gt(e,t){return e=t||e,v.css(e,"display")==="none"||!v.contains(e.ownerDocument,e)}function Yt(e,t){var n,r,i=[],s=0,o=e.length;for(;s<o;s++){n=e[s];if(!n.style)continue;i[s]=v._data(n,"olddisplay"),t?(!i[s]&&n.style.display==="none"&&(n.style.display=""),n.style.display===""&&Gt(n)&&(i[s]=v._data(n,"olddisplay",nn(n.nodeName)))):(r=Dt(n,"display"),!i[s]&&r!=="none"&&v._data(n,"olddisplay",r))}for(s=0;s<o;s++){n=e[s];if(!n.style)continue;if(!t||n.style.display==="none"||n.style.display==="")n.style.display=t?i[s]||"":"none"}return e}function Zt(e,t,n){var r=Rt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function en(e,t,n,r){var i=n===(r?"border":"content")?4:t==="width"?1:0,s=0;for(;i<4;i+=2)n==="margin"&&(s+=v.css(e,n+$t[i],!0)),r?(n==="content"&&(s-=parseFloat(Dt(e,"padding"+$t[i]))||0),n!=="margin"&&(s-=parseFloat(Dt(e,"border"+$t[i]+"Width"))||0)):(s+=parseFloat(Dt(e,"padding"+$t[i]))||0,n!=="padding"&&(s+=parseFloat(Dt(e,"border"+$t[i]+"Width"))||0));return s}function tn(e,t,n){var r=t==="width"?e.offsetWidth:e.offsetHeight,i=!0,s=v.support.boxSizing&&v.css(e,"boxSizing")==="border-box";if(r<=0||r==null){r=Dt(e,t);if(r<0||r==null)r=e.style[t];if(Ut.test(r))return r;i=s&&(v.support.boxSizingReliable||r===e.style[t]),r=parseFloat(r)||0}return r+en(e,t,n||(s?"border":"content"),i)+"px"}function nn(e){if(Wt[e])return Wt[e];var t=v("<"+e+">").appendTo(i.body),n=t.css("display");t.remove();if(n==="none"||n===""){Pt=i.body.appendChild(Pt||v.extend(i.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!Ht||!Pt.createElement)Ht=(Pt.contentWindow||Pt.contentDocument).document,Ht.write("<!doctype html><html><body>"),Ht.close();t=Ht.body.appendChild(Ht.createElement(e)),n=Dt(t,"display"),i.body.removeChild(Pt)}return Wt[e]=n,n}function fn(e,t,n,r){var i;if(v.isArray(t))v.each(t,function(t,i){n||sn.test(e)?r(e,i):fn(e+"["+(typeof i=="object"?t:"")+"]",i,n,r)});else if(!n&&v.type(t)==="object")for(i in t)fn(e+"["+i+"]",t[i],n,r);else r(e,t)}function Cn(e){return function(t,n){typeof t!="string"&&(n=t,t="*");var r,i,s,o=t.toLowerCase().split(y),u=0,a=o.length;if(v.isFunction(n))for(;u<a;u++)r=o[u],s=/^\+/.test(r),s&&(r=r.substr(1)||"*"),i=e[r]=e[r]||[],i[s?"unshift":"push"](n)}}function kn(e,n,r,i,s,o){s=s||n.dataTypes[0],o=o||{},o[s]=!0;var u,a=e[s],f=0,l=a?a.length:0,c=e===Sn;for(;f<l&&(c||!u);f++)u=a[f](n,r,i),typeof u=="string"&&(!c||o[u]?u=t:(n.dataTypes.unshift(u),u=kn(e,n,r,i,u,o)));return(c||!u)&&!o["*"]&&(u=kn(e,n,r,i,"*",o)),u}function Ln(e,n){var r,i,s=v.ajaxSettings.flatOptions||{};for(r in n)n[r]!==t&&((s[r]?e:i||(i={}))[r]=n[r]);i&&v.extend(!0,e,i)}function An(e,n,r){var i,s,o,u,a=e.contents,f=e.dataTypes,l=e.responseFields;for(s in l)s in r&&(n[l[s]]=r[s]);while(f[0]==="*")f.shift(),i===t&&(i=e.mimeType||n.getResponseHeader("content-type"));if(i)for(s in a)if(a[s]&&a[s].test(i)){f.unshift(s);break}if(f[0]in r)o=f[0];else{for(s in r){if(!f[0]||e.converters[s+" "+f[0]]){o=s;break}u||(u=s)}o=o||u}if(o)return o!==f[0]&&f.unshift(o),r[o]}function On(e,t){var n,r,i,s,o=e.dataTypes.slice(),u=o[0],a={},f=0;e.dataFilter&&(t=e.dataFilter(t,e.dataType));if(o[1])for(n in e.converters)a[n.toLowerCase()]=e.converters[n];for(;i=o[++f];)if(i!=="*"){if(u!=="*"&&u!==i){n=a[u+" "+i]||a["* "+i];if(!n)for(r in a){s=r.split(" ");if(s[1]===i){n=a[u+" "+s[0]]||a["* "+s[0]];if(n){n===!0?n=a[r]:a[r]!==!0&&(i=s[0],o.splice(f--,0,i));break}}}if(n!==!0)if(n&&e["throws"])t=n(t);else try{t=n(t)}catch(l){return{state:"parsererror",error:n?l:"No conversion from "+u+" to "+i}}}u=i}return{state:"success",data:t}}function Fn(){try{return new e.XMLHttpRequest}catch(t){}}function In(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}function $n(){return setTimeout(function(){qn=t},0),qn=v.now()}function Jn(e,t){v.each(t,function(t,n){var r=(Vn[t]||[]).concat(Vn["*"]),i=0,s=r.length;for(;i<s;i++)if(r[i].call(e,t,n))return})}function Kn(e,t,n){var r,i=0,s=0,o=Xn.length,u=v.Deferred().always(function(){delete a.elem}),a=function(){var t=qn||$n(),n=Math.max(0,f.startTime+f.duration-t),r=n/f.duration||0,i=1-r,s=0,o=f.tweens.length;for(;s<o;s++)f.tweens[s].run(i);return u.notifyWith(e,[f,i,n]),i<1&&o?n:(u.resolveWith(e,[f]),!1)},f=u.promise({elem:e,props:v.extend({},t),opts:v.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:qn||$n(),duration:n.duration,tweens:[],createTween:function(t,n,r){var i=v.Tween(e,f.opts,t,n,f.opts.specialEasing[t]||f.opts.easing);return f.tweens.push(i),i},stop:function(t){var n=0,r=t?f.tweens.length:0;for(;n<r;n++)f.tweens[n].run(1);return t?u.resolveWith(e,[f,t]):u.rejectWith(e,[f,t]),this}}),l=f.props;Qn(l,f.opts.specialEasing);for(;i<o;i++){r=Xn[i].call(f,e,l,f.opts);if(r)return r}return Jn(f,l),v.isFunction(f.opts.start)&&f.opts.start.call(e,f),v.fx.timer(v.extend(a,{anim:f,queue:f.opts.queue,elem:e})),f.progress(f.opts.progress).done(f.opts.done,f.opts.complete).fail(f.opts.fail).always(f.opts.always)}function Qn(e,t){var n,r,i,s,o;for(n in e){r=v.camelCase(n),i=t[r],s=e[n],v.isArray(s)&&(i=s[1],s=e[n]=s[0]),n!==r&&(e[r]=s,delete e[n]),o=v.cssHooks[r];if(o&&"expand"in o){s=o.expand(s),delete e[r];for(n in s)n in e||(e[n]=s[n],t[n]=i)}else t[r]=i}}function Gn(e,t,n){var r,i,s,o,u,a,f,l,c,h=this,p=e.style,d={},m=[],g=e.nodeType&&Gt(e);n.queue||(l=v._queueHooks(e,"fx"),l.unqueued==null&&(l.unqueued=0,c=l.empty.fire,l.empty.fire=function(){l.unqueued||c()}),l.unqueued++,h.always(function(){h.always(function(){l.unqueued--,v.queue(e,"fx").length||l.empty.fire()})})),e.nodeType===1&&("height"in t||"width"in t)&&(n.overflow=[p.overflow,p.overflowX,p.overflowY],v.css(e,"display")==="inline"&&v.css(e,"float")==="none"&&(!v.support.inlineBlockNeedsLayout||nn(e.nodeName)==="inline"?p.display="inline-block":p.zoom=1)),n.overflow&&(p.overflow="hidden",v.support.shrinkWrapBlocks||h.done(function(){p.overflow=n.overflow[0],p.overflowX=n.overflow[1],p.overflowY=n.overflow[2]}));for(r in t){s=t[r];if(Un.exec(s)){delete t[r],a=a||s==="toggle";if(s===(g?"hide":"show"))continue;m.push(r)}}o=m.length;if(o){u=v._data(e,"fxshow")||v._data(e,"fxshow",{}),"hidden"in u&&(g=u.hidden),a&&(u.hidden=!g),g?v(e).show():h.done(function(){v(e).hide()}),h.done(function(){var t;v.removeData(e,"fxshow",!0);for(t in d)v.style(e,t,d[t])});for(r=0;r<o;r++)i=m[r],f=h.createTween(i,g?u[i]:0),d[i]=u[i]||v.style(e,i),i in u||(u[i]=f.start,g&&(f.end=f.start,f.start=i==="width"||i==="height"?1:0))}}function Yn(e,t,n,r,i){return new Yn.prototype.init(e,t,n,r,i)}function Zn(e,t){var n,r={height:e},i=0;t=t?1:0;for(;i<4;i+=2-t)n=$t[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}function tr(e){return v.isWindow(e)?e:e.nodeType===9?e.defaultView||e.parentWindow:!1}var n,r,i=e.document,s=e.location,o=e.navigator,u=e.jQuery,a=e.$,f=Array.prototype.push,l=Array.prototype.slice,c=Array.prototype.indexOf,h=Object.prototype.toString,p=Object.prototype.hasOwnProperty,d=String.prototype.trim,v=function(e,t){return new v.fn.init(e,t,n)},m=/[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,g=/\S/,y=/\s+/,b=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,w=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,E=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,S=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,T=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,N=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,C=/^-ms-/,k=/-([\da-z])/gi,L=function(e,t){return(t+"").toUpperCase()},A=function(){i.addEventListener?(i.removeEventListener("DOMContentLoaded",A,!1),v.ready()):i.readyState==="complete"&&(i.detachEvent("onreadystatechange",A),v.ready())},O={};v.fn=v.prototype={constructor:v,init:function(e,n,r){var s,o,u,a;if(!e)return this;if(e.nodeType)return this.context=this[0]=e,this.length=1,this;if(typeof e=="string"){e.charAt(0)==="<"&&e.charAt(e.length-1)===">"&&e.length>=3?s=[null,e,null]:s=w.exec(e);if(s&&(s[1]||!n)){if(s[1])return n=n instanceof v?n[0]:n,a=n&&n.nodeType?n.ownerDocument||n:i,e=v.parseHTML(s[1],a,!0),E.test(s[1])&&v.isPlainObject(n)&&this.attr.call(e,n,!0),v.merge(this,e);o=i.getElementById(s[2]);if(o&&o.parentNode){if(o.id!==s[2])return r.find(e);this.length=1,this[0]=o}return this.context=i,this.selector=e,this}return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e)}return v.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),v.makeArray(e,this))},selector:"",jquery:"1.8.3",length:0,size:function(){return this.length},toArray:function(){return l.call(this)},get:function(e){return e==null?this.toArray():e<0?this[this.length+e]:this[e]},pushStack:function(e,t,n){var r=v.merge(this.constructor(),e);return r.prevObject=this,r.context=this.context,t==="find"?r.selector=this.selector+(this.selector?" ":"")+n:t&&(r.selector=this.selector+"."+t+"("+n+")"),r},each:function(e,t){return v.each(this,e,t)},ready:function(e){return v.ready.promise().done(e),this},eq:function(e){return e=+e,e===-1?this.slice(e):this.slice(e,e+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(l.apply(this,arguments),"slice",l.call(arguments).join(","))},map:function(e){return this.pushStack(v.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:[].sort,splice:[].splice},v.fn.init.prototype=v.fn,v.extend=v.fn.extend=function(){var e,n,r,i,s,o,u=arguments[0]||{},a=1,f=arguments.length,l=!1;typeof u=="boolean"&&(l=u,u=arguments[1]||{},a=2),typeof u!="object"&&!v.isFunction(u)&&(u={}),f===a&&(u=this,--a);for(;a<f;a++)if((e=arguments[a])!=null)for(n in e){r=u[n],i=e[n];if(u===i)continue;l&&i&&(v.isPlainObject(i)||(s=v.isArray(i)))?(s?(s=!1,o=r&&v.isArray(r)?r:[]):o=r&&v.isPlainObject(r)?r:{},u[n]=v.extend(l,o,i)):i!==t&&(u[n]=i)}return u},v.extend({noConflict:function(t){return e.$===v&&(e.$=a),t&&e.jQuery===v&&(e.jQuery=u),v},isReady:!1,readyWait:1,holdReady:function(e){e?v.readyWait++:v.ready(!0)},ready:function(e){if(e===!0?--v.readyWait:v.isReady)return;if(!i.body)return setTimeout(v.ready,1);v.isReady=!0;if(e!==!0&&--v.readyWait>0)return;r.resolveWith(i,[v]),v.fn.trigger&&v(i).trigger("ready").off("ready")},isFunction:function(e){return v.type(e)==="function"},isArray:Array.isArray||function(e){return v.type(e)==="array"},isWindow:function(e){return e!=null&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return e==null?String(e):O[h.call(e)]||"object"},isPlainObject:function(e){if(!e||v.type(e)!=="object"||e.nodeType||v.isWindow(e))return!1;try{if(e.constructor&&!p.call(e,"constructor")&&!p.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||p.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw new Error(e)},parseHTML:function(e,t,n){var r;return!e||typeof e!="string"?null:(typeof t=="boolean"&&(n=t,t=0),t=t||i,(r=E.exec(e))?[t.createElement(r[1])]:(r=v.buildFragment([e],t,n?null:[]),v.merge([],(r.cacheable?v.clone(r.fragment):r.fragment).childNodes)))},parseJSON:function(t){if(!t||typeof t!="string")return null;t=v.trim(t);if(e.JSON&&e.JSON.parse)return e.JSON.parse(t);if(S.test(t.replace(T,"@").replace(N,"]").replace(x,"")))return(new Function("return "+t))();v.error("Invalid JSON: "+t)},parseXML:function(n){var r,i;if(!n||typeof n!="string")return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(s){r=t}return(!r||!r.documentElement||r.getElementsByTagName("parsererror").length)&&v.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&g.test(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(C,"ms-").replace(k,L)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,n,r){var i,s=0,o=e.length,u=o===t||v.isFunction(e);if(r){if(u){for(i in e)if(n.apply(e[i],r)===!1)break}else for(;s<o;)if(n.apply(e[s++],r)===!1)break}else if(u){for(i in e)if(n.call(e[i],i,e[i])===!1)break}else for(;s<o;)if(n.call(e[s],s,e[s++])===!1)break;return e},trim:d&&!d.call("\ufeff\u00a0")?function(e){return e==null?"":d.call(e)}:function(e){return e==null?"":(e+"").replace(b,"")},makeArray:function(e,t){var n,r=t||[];return e!=null&&(n=v.type(e),e.length==null||n==="string"||n==="function"||n==="regexp"||v.isWindow(e)?f.call(r,e):v.merge(r,e)),r},inArray:function(e,t,n){var r;if(t){if(c)return c.call(t,e,n);r=t.length,n=n?n<0?Math.max(0,r+n):n:0;for(;n<r;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,s=0;if(typeof r=="number")for(;s<r;s++)e[i++]=n[s];else while(n[s]!==t)e[i++]=n[s++];return e.length=i,e},grep:function(e,t,n){var r,i=[],s=0,o=e.length;n=!!n;for(;s<o;s++)r=!!t(e[s],s),n!==r&&i.push(e[s]);return i},map:function(e,n,r){var i,s,o=[],u=0,a=e.length,f=e instanceof v||a!==t&&typeof a=="number"&&(a>0&&e[0]&&e[a-1]||a===0||v.isArray(e));if(f)for(;u<a;u++)i=n(e[u],u,r),i!=null&&(o[o.length]=i);else for(s in e)i=n(e[s],s,r),i!=null&&(o[o.length]=i);return o.concat.apply([],o)},guid:1,proxy:function(e,n){var r,i,s;return typeof n=="string"&&(r=e[n],n=e,e=r),v.isFunction(e)?(i=l.call(arguments,2),s=function(){return e.apply(n,i.concat(l.call(arguments)))},s.guid=e.guid=e.guid||v.guid++,s):t},access:function(e,n,r,i,s,o,u){var a,f=r==null,l=0,c=e.length;if(r&&typeof r=="object"){for(l in r)v.access(e,n,l,r[l],1,o,i);s=1}else if(i!==t){a=u===t&&v.isFunction(i),f&&(a?(a=n,n=function(e,t,n){return a.call(v(e),n)}):(n.call(e,i),n=null));if(n)for(;l<c;l++)n(e[l],r,a?i.call(e[l],l,n(e[l],r)):i,u);s=1}return s?e:f?n.call(e):c?n(e[0],r):o},now:function(){return(new Date).getTime()}}),v.ready.promise=function(t){if(!r){r=v.Deferred();if(i.readyState==="complete")setTimeout(v.ready,1);else if(i.addEventListener)i.addEventListener("DOMContentLoaded",A,!1),e.addEventListener("load",v.ready,!1);else{i.attachEvent("onreadystatechange",A),e.attachEvent("onload",v.ready);var n=!1;try{n=e.frameElement==null&&i.documentElement}catch(s){}n&&n.doScroll&&function o(){if(!v.isReady){try{n.doScroll("left")}catch(e){return setTimeout(o,50)}v.ready()}}()}}return r.promise(t)},v.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(e,t){O["[object "+t+"]"]=t.toLowerCase()}),n=v(i);var M={};v.Callbacks=function(e){e=typeof e=="string"?M[e]||_(e):v.extend({},e);var n,r,i,s,o,u,a=[],f=!e.once&&[],l=function(t){n=e.memory&&t,r=!0,u=s||0,s=0,o=a.length,i=!0;for(;a&&u<o;u++)if(a[u].apply(t[0],t[1])===!1&&e.stopOnFalse){n=!1;break}i=!1,a&&(f?f.length&&l(f.shift()):n?a=[]:c.disable())},c={add:function(){if(a){var t=a.length;(function r(t){v.each(t,function(t,n){var i=v.type(n);i==="function"?(!e.unique||!c.has(n))&&a.push(n):n&&n.length&&i!=="string"&&r(n)})})(arguments),i?o=a.length:n&&(s=t,l(n))}return this},remove:function(){return a&&v.each(arguments,function(e,t){var n;while((n=v.inArray(t,a,n))>-1)a.splice(n,1),i&&(n<=o&&o--,n<=u&&u--)}),this},has:function(e){return v.inArray(e,a)>-1},empty:function(){return a=[],this},disable:function(){return a=f=n=t,this},disabled:function(){return!a},lock:function(){return f=t,n||c.disable(),this},locked:function(){return!f},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],a&&(!r||f)&&(i?f.push(t):l(t)),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!r}};return c},v.extend({Deferred:function(e){var t=[["resolve","done",v.Callbacks("once memory"),"resolved"],["reject","fail",v.Callbacks("once memory"),"rejected"],["notify","progress",v.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return v.Deferred(function(n){v.each(t,function(t,r){var s=r[0],o=e[t];i[r[1]](v.isFunction(o)?function(){var e=o.apply(this,arguments);e&&v.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[s+"With"](this===i?n:this,[e])}:n[s])}),e=null}).promise()},promise:function(e){return e!=null?v.extend(e,r):r}},i={};return r.pipe=r.then,v.each(t,function(e,s){var o=s[2],u=s[3];r[s[1]]=o.add,u&&o.add(function(){n=u},t[e^1][2].disable,t[2][2].lock),i[s[0]]=o.fire,i[s[0]+"With"]=o.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=l.call(arguments),r=n.length,i=r!==1||e&&v.isFunction(e.promise)?r:0,s=i===1?e:v.Deferred(),o=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?l.call(arguments):r,n===u?s.notifyWith(t,n):--i||s.resolveWith(t,n)}},u,a,f;if(r>1){u=new Array(r),a=new Array(r),f=new Array(r);for(;t<r;t++)n[t]&&v.isFunction(n[t].promise)?n[t].promise().done(o(t,f,n)).fail(s.reject).progress(o(t,a,u)):--i}return i||s.resolveWith(f,n),s.promise()}}),v.support=function(){var t,n,r,s,o,u,a,f,l,c,h,p=i.createElement("div");p.setAttribute("className","t"),p.innerHTML="  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",n=p.getElementsByTagName("*"),r=p.getElementsByTagName("a")[0];if(!n||!r||!n.length)return{};s=i.createElement("select"),o=s.appendChild(i.createElement("option")),u=p.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:r.getAttribute("href")==="/a",opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,checkOn:u.value==="on",optSelected:o.selected,getSetAttribute:p.className!=="t",enctype:!!i.createElement("form").enctype,html5Clone:i.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",boxModel:i.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},u.checked=!0,t.noCloneChecked=u.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!o.disabled;try{delete p.test}catch(d){t.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",h=function(){t.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick"),p.detachEvent("onclick",h)),u=i.createElement("input"),u.value="t",u.setAttribute("type","radio"),t.radioValue=u.value==="t",u.setAttribute("checked","checked"),u.setAttribute("name","t"),p.appendChild(u),a=i.createDocumentFragment(),a.appendChild(p.lastChild),t.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,t.appendChecked=u.checked,a.removeChild(u),a.appendChild(p);if(p.attachEvent)for(l in{submit:!0,change:!0,focusin:!0})f="on"+l,c=f in p,c||(p.setAttribute(f,"return;"),c=typeof p[f]=="function"),t[l+"Bubbles"]=c;return v(function(){var n,r,s,o,u="padding:0;margin:0;border:0;display:block;overflow:hidden;",a=i.getElementsByTagName("body")[0];if(!a)return;n=i.createElement("div"),n.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",a.insertBefore(n,a.firstChild),r=i.createElement("div"),n.appendChild(r),r.innerHTML="<table><tr><td></td><td>t</td></tr></table>",s=r.getElementsByTagName("td"),s[0].style.cssText="padding:0;margin:0;border:0;display:none",c=s[0].offsetHeight===0,s[0].style.display="",s[1].style.display="none",t.reliableHiddenOffsets=c&&s[0].offsetHeight===0,r.innerHTML="",r.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",t.boxSizing=r.offsetWidth===4,t.doesNotIncludeMarginInBodyOffset=a.offsetTop!==1,e.getComputedStyle&&(t.pixelPosition=(e.getComputedStyle(r,null)||{}).top!=="1%",t.boxSizingReliable=(e.getComputedStyle(r,null)||{width:"4px"}).width==="4px",o=i.createElement("div"),o.style.cssText=r.style.cssText=u,o.style.marginRight=o.style.width="0",r.style.width="1px",r.appendChild(o),t.reliableMarginRight=!parseFloat((e.getComputedStyle(o,null)||{}).marginRight)),typeof r.style.zoom!="undefined"&&(r.innerHTML="",r.style.cssText=u+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=r.offsetWidth===3,r.style.display="block",r.style.overflow="visible",r.innerHTML="<div></div>",r.firstChild.style.width="5px",t.shrinkWrapBlocks=r.offsetWidth!==3,n.style.zoom=1),a.removeChild(n),n=r=s=o=null}),a.removeChild(p),n=r=s=o=u=a=p=null,t}();var D=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;v.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(v.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?v.cache[e[v.expando]]:e[v.expando],!!e&&!B(e)},data:function(e,n,r,i){if(!v.acceptData(e))return;var s,o,u=v.expando,a=typeof n=="string",f=e.nodeType,l=f?v.cache:e,c=f?e[u]:e[u]&&u;if((!c||!l[c]||!i&&!l[c].data)&&a&&r===t)return;c||(f?e[u]=c=v.deletedIds.pop()||v.guid++:c=u),l[c]||(l[c]={},f||(l[c].toJSON=v.noop));if(typeof n=="object"||typeof n=="function")i?l[c]=v.extend(l[c],n):l[c].data=v.extend(l[c].data,n);return s=l[c],i||(s.data||(s.data={}),s=s.data),r!==t&&(s[v.camelCase(n)]=r),a?(o=s[n],o==null&&(o=s[v.camelCase(n)])):o=s,o},removeData:function(e,t,n){if(!v.acceptData(e))return;var r,i,s,o=e.nodeType,u=o?v.cache:e,a=o?e[v.expando]:v.expando;if(!u[a])return;if(t){r=n?u[a]:u[a].data;if(r){v.isArray(t)||(t in r?t=[t]:(t=v.camelCase(t),t in r?t=[t]:t=t.split(" ")));for(i=0,s=t.length;i<s;i++)delete r[t[i]];if(!(n?B:v.isEmptyObject)(r))return}}if(!n){delete u[a].data;if(!B(u[a]))return}o?v.cleanData([e],!0):v.support.deleteExpando||u!=u.window?delete u[a]:u[a]=null},_data:function(e,t,n){return v.data(e,t,n,!0)},acceptData:function(e){var t=e.nodeName&&v.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),v.fn.extend({data:function(e,n){var r,i,s,o,u,a=this[0],f=0,l=null;if(e===t){if(this.length){l=v.data(a);if(a.nodeType===1&&!v._data(a,"parsedAttrs")){s=a.attributes;for(u=s.length;f<u;f++)o=s[f].name,o.indexOf("data-")||(o=v.camelCase(o.substring(5)),H(a,o,l[o]));v._data(a,"parsedAttrs",!0)}}return l}return typeof e=="object"?this.each(function(){v.data(this,e)}):(r=e.split(".",2),r[1]=r[1]?"."+r[1]:"",i=r[1]+"!",v.access(this,function(n){if(n===t)return l=this.triggerHandler("getData"+i,[r[0]]),l===t&&a&&(l=v.data(a,e),l=H(a,e,l)),l===t&&r[1]?this.data(r[0]):l;r[1]=n,this.each(function(){var t=v(this);t.triggerHandler("setData"+i,r),v.data(this,e,n),t.triggerHandler("changeData"+i,r)})},null,n,arguments.length>1,null,!1))},removeData:function(e){return this.each(function(){v.removeData(this,e)})}}),v.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=v._data(e,t),n&&(!r||v.isArray(n)?r=v._data(e,t,v.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=v.queue(e,t),r=n.length,i=n.shift(),s=v._queueHooks(e,t),o=function(){v.dequeue(e,t)};i==="inprogress"&&(i=n.shift(),r--),i&&(t==="fx"&&n.unshift("inprogress"),delete s.stop,i.call(e,o,s)),!r&&s&&s.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return v._data(e,n)||v._data(e,n,{empty:v.Callbacks("once memory").add(function(){v.removeData(e,t+"queue",!0),v.removeData(e,n,!0)})})}}),v.fn.extend({queue:function(e,n){var r=2;return typeof e!="string"&&(n=e,e="fx",r--),arguments.length<r?v.queue(this[0],e):n===t?this:this.each(function(){var t=v.queue(this,e,n);v._queueHooks(this,e),e==="fx"&&t[0]!=="inprogress"&&v.dequeue(this,e)})},dequeue:function(e){return this.each(function(){v.dequeue(this,e)})},delay:function(e,t){return e=v.fx?v.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,s=v.Deferred(),o=this,u=this.length,a=function(){--i||s.resolveWith(o,[o])};typeof e!="string"&&(n=e,e=t),e=e||"fx";while(u--)r=v._data(o[u],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(a));return a(),s.promise(n)}});var j,F,I,q=/[\t\r\n]/g,R=/\r/g,U=/^(?:button|input)$/i,z=/^(?:button|input|object|select|textarea)$/i,W=/^a(?:rea|)$/i,X=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,V=v.support.getSetAttribute;v.fn.extend({attr:function(e,t){return v.access(this,v.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){v.removeAttr(this,e)})},prop:function(e,t){return v.access(this,v.prop,e,t,arguments.length>1)},removeProp:function(e){return e=v.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,s,o,u;if(v.isFunction(e))return this.each(function(t){v(this).addClass(e.call(this,t,this.className))});if(e&&typeof e=="string"){t=e.split(y);for(n=0,r=this.length;n<r;n++){i=this[n];if(i.nodeType===1)if(!i.className&&t.length===1)i.className=e;else{s=" "+i.className+" ";for(o=0,u=t.length;o<u;o++)s.indexOf(" "+t[o]+" ")<0&&(s+=t[o]+" ");i.className=v.trim(s)}}}return this},removeClass:function(e){var n,r,i,s,o,u,a;if(v.isFunction(e))return this.each(function(t){v(this).removeClass(e.call(this,t,this.className))});if(e&&typeof e=="string"||e===t){n=(e||"").split(y);for(u=0,a=this.length;u<a;u++){i=this[u];if(i.nodeType===1&&i.className){r=(" "+i.className+" ").replace(q," ");for(s=0,o=n.length;s<o;s++)while(r.indexOf(" "+n[s]+" ")>=0)r=r.replace(" "+n[s]+" "," ");i.className=e?v.trim(r):""}}}return this},toggleClass:function(e,t){var n=typeof e,r=typeof t=="boolean";return v.isFunction(e)?this.each(function(n){v(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if(n==="string"){var i,s=0,o=v(this),u=t,a=e.split(y);while(i=a[s++])u=r?u:!o.hasClass(i),o[u?"addClass":"removeClass"](i)}else if(n==="undefined"||n==="boolean")this.className&&v._data(this,"__className__",this.className),this.className=this.className||e===!1?"":v._data(this,"__className__")||""})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;n<r;n++)if(this[n].nodeType===1&&(" "+this[n].className+" ").replace(q," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,s=this[0];if(!arguments.length){if(s)return n=v.valHooks[s.type]||v.valHooks[s.nodeName.toLowerCase()],n&&"get"in n&&(r=n.get(s,"value"))!==t?r:(r=s.value,typeof r=="string"?r.replace(R,""):r==null?"":r);return}return i=v.isFunction(e),this.each(function(r){var s,o=v(this);if(this.nodeType!==1)return;i?s=e.call(this,r,o.val()):s=e,s==null?s="":typeof s=="number"?s+="":v.isArray(s)&&(s=v.map(s,function(e){return e==null?"":e+""})),n=v.valHooks[this.type]||v.valHooks[this.nodeName.toLowerCase()];if(!n||!("set"in n)||n.set(this,s,"value")===t)this.value=s})}}),v.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,s=e.type==="select-one"||i<0,o=s?null:[],u=s?i+1:r.length,a=i<0?u:s?i:0;for(;a<u;a++){n=r[a];if((n.selected||a===i)&&(v.support.optDisabled?!n.disabled:n.getAttribute("disabled")===null)&&(!n.parentNode.disabled||!v.nodeName(n.parentNode,"optgroup"))){t=v(n).val();if(s)return t;o.push(t)}}return o},set:function(e,t){var n=v.makeArray(t);return v(e).find("option").each(function(){this.selected=v.inArray(v(this).val(),n)>=0}),n.length||(e.selectedIndex=-1),n}}},attrFn:{},attr:function(e,n,r,i){var s,o,u,a=e.nodeType;if(!e||a===3||a===8||a===2)return;if(i&&v.isFunction(v.fn[n]))return v(e)[n](r);if(typeof e.getAttribute=="undefined")return v.prop(e,n,r);u=a!==1||!v.isXMLDoc(e),u&&(n=n.toLowerCase(),o=v.attrHooks[n]||(X.test(n)?F:j));if(r!==t){if(r===null){v.removeAttr(e,n);return}return o&&"set"in o&&u&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r)}return o&&"get"in o&&u&&(s=o.get(e,n))!==null?s:(s=e.getAttribute(n),s===null?t:s)},removeAttr:function(e,t){var n,r,i,s,o=0;if(t&&e.nodeType===1){r=t.split(y);for(;o<r.length;o++)i=r[o],i&&(n=v.propFix[i]||i,s=X.test(i),s||v.attr(e,i,""),e.removeAttribute(V?i:n),s&&n in e&&(e[n]=!1))}},attrHooks:{type:{set:function(e,t){if(U.test(e.nodeName)&&e.parentNode)v.error("type property can't be changed");else if(!v.support.radioValue&&t==="radio"&&v.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}},value:{get:function(e,t){return j&&v.nodeName(e,"button")?j.get(e,t):t in e?e.value:null},set:function(e,t,n){if(j&&v.nodeName(e,"button"))return j.set(e,t,n);e.value=t}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(e,n,r){var i,s,o,u=e.nodeType;if(!e||u===3||u===8||u===2)return;return o=u!==1||!v.isXMLDoc(e),o&&(n=v.propFix[n]||n,s=v.propHooks[n]),r!==t?s&&"set"in s&&(i=s.set(e,r,n))!==t?i:e[n]=r:s&&"get"in s&&(i=s.get(e,n))!==null?i:e[n]},propHooks:{tabIndex:{get:function(e){var n=e.getAttributeNode("tabindex");return n&&n.specified?parseInt(n.value,10):z.test(e.nodeName)||W.test(e.nodeName)&&e.href?0:t}}}}),F={get:function(e,n){var r,i=v.prop(e,n);return i===!0||typeof i!="boolean"&&(r=e.getAttributeNode(n))&&r.nodeValue!==!1?n.toLowerCase():t},set:function(e,t,n){var r;return t===!1?v.removeAttr(e,n):(r=v.propFix[n]||n,r in e&&(e[r]=!0),e.setAttribute(n,n.toLowerCase())),n}},V||(I={name:!0,id:!0,coords:!0},j=v.valHooks.button={get:function(e,n){var r;return r=e.getAttributeNode(n),r&&(I[n]?r.value!=="":r.specified)?r.value:t},set:function(e,t,n){var r=e.getAttributeNode(n);return r||(r=i.createAttribute(n),e.setAttributeNode(r)),r.value=t+""}},v.each(["width","height"],function(e,t){v.attrHooks[t]=v.extend(v.attrHooks[t],{set:function(e,n){if(n==="")return e.setAttribute(t,"auto"),n}})}),v.attrHooks.contenteditable={get:j.get,set:function(e,t,n){t===""&&(t="false"),j.set(e,t,n)}}),v.support.hrefNormalized||v.each(["href","src","width","height"],function(e,n){v.attrHooks[n]=v.extend(v.attrHooks[n],{get:function(e){var r=e.getAttribute(n,2);return r===null?t:r}})}),v.support.style||(v.attrHooks.style={get:function(e){return e.style.cssText.toLowerCase()||t},set:function(e,t){return e.style.cssText=t+""}}),v.support.optSelected||(v.propHooks.selected=v.extend(v.propHooks.selected,{get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}})),v.support.enctype||(v.propFix.enctype="encoding"),v.support.checkOn||v.each(["radio","checkbox"],function(){v.valHooks[this]={get:function(e){return e.getAttribute("value")===null?"on":e.value}}}),v.each(["radio","checkbox"],function(){v.valHooks[this]=v.extend(v.valHooks[this],{set:function(e,t){if(v.isArray(t))return e.checked=v.inArray(v(e).val(),t)>=0}})});var $=/^(?:textarea|input|select)$/i,J=/^([^\.]*|)(?:\.(.+)|)$/,K=/(?:^|\s)hover(\.\S+|)\b/,Q=/^key/,G=/^(?:mouse|contextmenu)|click/,Y=/^(?:focusinfocus|focusoutblur)$/,Z=function(e){return v.event.special.hover?e:e.replace(K,"mouseenter$1 mouseleave$1")};v.event={add:function(e,n,r,i,s){var o,u,a,f,l,c,h,p,d,m,g;if(e.nodeType===3||e.nodeType===8||!n||!r||!(o=v._data(e)))return;r.handler&&(d=r,r=d.handler,s=d.selector),r.guid||(r.guid=v.guid++),a=o.events,a||(o.events=a={}),u=o.handle,u||(o.handle=u=function(e){return typeof v=="undefined"||!!e&&v.event.triggered===e.type?t:v.event.dispatch.apply(u.elem,arguments)},u.elem=e),n=v.trim(Z(n)).split(" ");for(f=0;f<n.length;f++){l=J.exec(n[f])||[],c=l[1],h=(l[2]||"").split(".").sort(),g=v.event.special[c]||{},c=(s?g.delegateType:g.bindType)||c,g=v.event.special[c]||{},p=v.extend({type:c,origType:l[1],data:i,handler:r,guid:r.guid,selector:s,needsContext:s&&v.expr.match.needsContext.test(s),namespace:h.join(".")},d),m=a[c];if(!m){m=a[c]=[],m.delegateCount=0;if(!g.setup||g.setup.call(e,i,h,u)===!1)e.addEventListener?e.addEventListener(c,u,!1):e.attachEvent&&e.attachEvent("on"+c,u)}g.add&&(g.add.call(e,p),p.handler.guid||(p.handler.guid=r.guid)),s?m.splice(m.delegateCount++,0,p):m.push(p),v.event.global[c]=!0}e=null},global:{},remove:function(e,t,n,r,i){var s,o,u,a,f,l,c,h,p,d,m,g=v.hasData(e)&&v._data(e);if(!g||!(h=g.events))return;t=v.trim(Z(t||"")).split(" ");for(s=0;s<t.length;s++){o=J.exec(t[s])||[],u=a=o[1],f=o[2];if(!u){for(u in h)v.event.remove(e,u+t[s],n,r,!0);continue}p=v.event.special[u]||{},u=(r?p.delegateType:p.bindType)||u,d=h[u]||[],l=d.length,f=f?new RegExp("(^|\\.)"+f.split(".").sort().join("\\.(?:.*\\.|)")+"(\\.|$)"):null;for(c=0;c<d.length;c++)m=d[c],(i||a===m.origType)&&(!n||n.guid===m.guid)&&(!f||f.test(m.namespace))&&(!r||r===m.selector||r==="**"&&m.selector)&&(d.splice(c--,1),m.selector&&d.delegateCount--,p.remove&&p.remove.call(e,m));d.length===0&&l!==d.length&&((!p.teardown||p.teardown.call(e,f,g.handle)===!1)&&v.removeEvent(e,u,g.handle),delete h[u])}v.isEmptyObject(h)&&(delete g.handle,v.removeData(e,"events",!0))},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(n,r,s,o){if(!s||s.nodeType!==3&&s.nodeType!==8){var u,a,f,l,c,h,p,d,m,g,y=n.type||n,b=[];if(Y.test(y+v.event.triggered))return;y.indexOf("!")>=0&&(y=y.slice(0,-1),a=!0),y.indexOf(".")>=0&&(b=y.split("."),y=b.shift(),b.sort());if((!s||v.event.customEvent[y])&&!v.event.global[y])return;n=typeof n=="object"?n[v.expando]?n:new v.Event(y,n):new v.Event(y),n.type=y,n.isTrigger=!0,n.exclusive=a,n.namespace=b.join("."),n.namespace_re=n.namespace?new RegExp("(^|\\.)"+b.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,h=y.indexOf(":")<0?"on"+y:"";if(!s){u=v.cache;for(f in u)u[f].events&&u[f].events[y]&&v.event.trigger(n,r,u[f].handle.elem,!0);return}n.result=t,n.target||(n.target=s),r=r!=null?v.makeArray(r):[],r.unshift(n),p=v.event.special[y]||{};if(p.trigger&&p.trigger.apply(s,r)===!1)return;m=[[s,p.bindType||y]];if(!o&&!p.noBubble&&!v.isWindow(s)){g=p.delegateType||y,l=Y.test(g+y)?s:s.parentNode;for(c=s;l;l=l.parentNode)m.push([l,g]),c=l;c===(s.ownerDocument||i)&&m.push([c.defaultView||c.parentWindow||e,g])}for(f=0;f<m.length&&!n.isPropagationStopped();f++)l=m[f][0],n.type=m[f][1],d=(v._data(l,"events")||{})[n.type]&&v._data(l,"handle"),d&&d.apply(l,r),d=h&&l[h],d&&v.acceptData(l)&&d.apply&&d.apply(l,r)===!1&&n.preventDefault();return n.type=y,!o&&!n.isDefaultPrevented()&&(!p._default||p._default.apply(s.ownerDocument,r)===!1)&&(y!=="click"||!v.nodeName(s,"a"))&&v.acceptData(s)&&h&&s[y]&&(y!=="focus"&&y!=="blur"||n.target.offsetWidth!==0)&&!v.isWindow(s)&&(c=s[h],c&&(s[h]=null),v.event.triggered=y,s[y](),v.event.triggered=t,c&&(s[h]=c)),n.result}return},dispatch:function(n){n=v.event.fix(n||e.event);var r,i,s,o,u,a,f,c,h,p,d=(v._data(this,"events")||{})[n.type]||[],m=d.delegateCount,g=l.call(arguments),y=!n.exclusive&&!n.namespace,b=v.event.special[n.type]||{},w=[];g[0]=n,n.delegateTarget=this;if(b.preDispatch&&b.preDispatch.call(this,n)===!1)return;if(m&&(!n.button||n.type!=="click"))for(s=n.target;s!=this;s=s.parentNode||this)if(s.disabled!==!0||n.type!=="click"){u={},f=[];for(r=0;r<m;r++)c=d[r],h=c.selector,u[h]===t&&(u[h]=c.needsContext?v(h,this).index(s)>=0:v.find(h,this,null,[s]).length),u[h]&&f.push(c);f.length&&w.push({elem:s,matches:f})}d.length>m&&w.push({elem:this,matches:d.slice(m)});for(r=0;r<w.length&&!n.isPropagationStopped();r++){a=w[r],n.currentTarget=a.elem;for(i=0;i<a.matches.length&&!n.isImmediatePropagationStopped();i++){c=a.matches[i];if(y||!n.namespace&&!c.namespace||n.namespace_re&&n.namespace_re.test(c.namespace))n.data=c.data,n.handleObj=c,o=((v.event.special[c.origType]||{}).handle||c.handler).apply(a.elem,g),o!==t&&(n.result=o,o===!1&&(n.preventDefault(),n.stopPropagation()))}}return b.postDispatch&&b.postDispatch.call(this,n),n.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return e.which==null&&(e.which=t.charCode!=null?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,s,o,u=n.button,a=n.fromElement;return e.pageX==null&&n.clientX!=null&&(r=e.target.ownerDocument||i,s=r.documentElement,o=r.body,e.pageX=n.clientX+(s&&s.scrollLeft||o&&o.scrollLeft||0)-(s&&s.clientLeft||o&&o.clientLeft||0),e.pageY=n.clientY+(s&&s.scrollTop||o&&o.scrollTop||0)-(s&&s.clientTop||o&&o.clientTop||0)),!e.relatedTarget&&a&&(e.relatedTarget=a===e.target?n.toElement:a),!e.which&&u!==t&&(e.which=u&1?1:u&2?3:u&4?2:0),e}},fix:function(e){if(e[v.expando])return e;var t,n,r=e,s=v.event.fixHooks[e.type]||{},o=s.props?this.props.concat(s.props):this.props;e=v.Event(r);for(t=o.length;t;)n=o[--t],e[n]=r[n];return e.target||(e.target=r.srcElement||i),e.target.nodeType===3&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,r):e},special:{load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(e,t,n){v.isWindow(this)&&(this.onbeforeunload=n)},teardown:function(e,t){this.onbeforeunload===t&&(this.onbeforeunload=null)}}},simulate:function(e,t,n,r){var i=v.extend(new v.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?v.event.trigger(i,null,t):v.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},v.event.handle=v.event.dispatch,v.removeEvent=i.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]=="undefined"&&(e[r]=null),e.detachEvent(r,n))},v.Event=function(e,t){if(!(this instanceof v.Event))return new v.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?tt:et):this.type=e,t&&v.extend(this,t),this.timeStamp=e&&e.timeStamp||v.now(),this[v.expando]=!0},v.Event.prototype={preventDefault:function(){this.isDefaultPrevented=tt;var e=this.originalEvent;if(!e)return;e.preventDefault?e.preventDefault():e.returnValue=!1},stopPropagation:function(){this.isPropagationStopped=tt;var e=this.originalEvent;if(!e)return;e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=tt,this.stopPropagation()},isDefaultPrevented:et,isPropagationStopped:et,isImmediatePropagationStopped:et},v.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){v.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,s=e.handleObj,o=s.selector;if(!i||i!==r&&!v.contains(r,i))e.type=s.origType,n=s.handler.apply(this,arguments),e.type=t;return n}}}),v.support.submitBubbles||(v.event.special.submit={setup:function(){if(v.nodeName(this,"form"))return!1;v.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=v.nodeName(n,"input")||v.nodeName(n,"button")?n.form:t;r&&!v._data(r,"_submit_attached")&&(v.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),v._data(r,"_submit_attached",!0))})},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&v.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){if(v.nodeName(this,"form"))return!1;v.event.remove(this,"._submit")}}),v.support.changeBubbles||(v.event.special.change={setup:function(){if($.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")v.event.add(this,"propertychange._change",function(e){e.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),v.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),v.event.simulate("change",this,e,!0)});return!1}v.event.add(this,"beforeactivate._change",function(e){var t=e.target;$.test(t.nodeName)&&!v._data(t,"_change_attached")&&(v.event.add(t,"change._change",function(e){this.parentNode&&!e.isSimulated&&!e.isTrigger&&v.event.simulate("change",this.parentNode,e,!0)}),v._data(t,"_change_attached",!0))})},handle:function(e){var t=e.target;if(this!==t||e.isSimulated||e.isTrigger||t.type!=="radio"&&t.type!=="checkbox")return e.handleObj.handler.apply(this,arguments)},teardown:function(){return v.event.remove(this,"._change"),!$.test(this.nodeName)}}),v.support.focusinBubbles||v.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){v.event.simulate(t,e.target,v.event.fix(e),!0)};v.event.special[t]={setup:function(){n++===0&&i.addEventListener(e,r,!0)},teardown:function(){--n===0&&i.removeEventListener(e,r,!0)}}}),v.fn.extend({on:function(e,n,r,i,s){var o,u;if(typeof e=="object"){typeof n!="string"&&(r=r||n,n=t);for(u in e)this.on(u,n,r,e[u],s);return this}r==null&&i==null?(i=n,r=n=t):i==null&&(typeof n=="string"?(i=r,r=t):(i=r,r=n,n=t));if(i===!1)i=et;else if(!i)return this;return s===1&&(o=i,i=function(e){return v().off(e),o.apply(this,arguments)},i.guid=o.guid||(o.guid=v.guid++)),this.each(function(){v.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,s;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,v(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if(typeof e=="object"){for(s in e)this.off(s,n,e[s]);return this}if(n===!1||typeof n=="function")r=n,n=t;return r===!1&&(r=et),this.each(function(){v.event.remove(this,e,r,n)})},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},live:function(e,t,n){return v(this.context).on(e,this.selector,t,n),this},die:function(e,t){return v(this.context).off(e,this.selector||"**",t),this},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return arguments.length===1?this.off(e,"**"):this.off(t,e||"**",n)},trigger:function(e,t){return this.each(function(){v.event.trigger(e,t,this)})},triggerHandler:function(e,t){if(this[0])return v.event.trigger(e,t,this[0],!0)},toggle:function(e){var t=arguments,n=e.guid||v.guid++,r=0,i=function(n){var i=(v._data(this,"lastToggle"+e.guid)||0)%r;return v._data(this,"lastToggle"+e.guid,i+1),n.preventDefault(),t[i].apply(this,arguments)||!1};i.guid=n;while(r<t.length)t[r++].guid=n;return this.click(i)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),v.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){v.fn[t]=function(e,n){return n==null&&(n=e,e=null),arguments.length>0?this.on(t,null,e,n):this.trigger(t)},Q.test(t)&&(v.event.fixHooks[t]=v.event.keyHooks),G.test(t)&&(v.event.fixHooks[t]=v.event.mouseHooks)}),function(e,t){function nt(e,t,n,r){n=n||[],t=t||g;var i,s,a,f,l=t.nodeType;if(!e||typeof e!="string")return n;if(l!==1&&l!==9)return[];a=o(t);if(!a&&!r)if(i=R.exec(e))if(f=i[1]){if(l===9){s=t.getElementById(f);if(!s||!s.parentNode)return n;if(s.id===f)return n.push(s),n}else if(t.ownerDocument&&(s=t.ownerDocument.getElementById(f))&&u(t,s)&&s.id===f)return n.push(s),n}else{if(i[2])return S.apply(n,x.call(t.getElementsByTagName(e),0)),n;if((f=i[3])&&Z&&t.getElementsByClassName)return S.apply(n,x.call(t.getElementsByClassName(f),0)),n}return vt(e.replace(j,"$1"),t,n,r,a)}function rt(e){return function(t){var n=t.nodeName.toLowerCase();return n==="input"&&t.type===e}}function it(e){return function(t){var n=t.nodeName.toLowerCase();return(n==="input"||n==="button")&&t.type===e}}function st(e){return N(function(t){return t=+t,N(function(n,r){var i,s=e([],n.length,t),o=s.length;while(o--)n[i=s[o]]&&(n[i]=!(r[i]=n[i]))})})}function ot(e,t,n){if(e===t)return n;var r=e.nextSibling;while(r){if(r===t)return-1;r=r.nextSibling}return 1}function ut(e,t){var n,r,s,o,u,a,f,l=L[d][e+" "];if(l)return t?0:l.slice(0);u=e,a=[],f=i.preFilter;while(u){if(!n||(r=F.exec(u)))r&&(u=u.slice(r[0].length)||u),a.push(s=[]);n=!1;if(r=I.exec(u))s.push(n=new m(r.shift())),u=u.slice(n.length),n.type=r[0].replace(j," ");for(o in i.filter)(r=J[o].exec(u))&&(!f[o]||(r=f[o](r)))&&(s.push(n=new m(r.shift())),u=u.slice(n.length),n.type=o,n.matches=r);if(!n)break}return t?u.length:u?nt.error(e):L(e,a).slice(0)}function at(e,t,r){var i=t.dir,s=r&&t.dir==="parentNode",o=w++;return t.first?function(t,n,r){while(t=t[i])if(s||t.nodeType===1)return e(t,n,r)}:function(t,r,u){if(!u){var a,f=b+" "+o+" ",l=f+n;while(t=t[i])if(s||t.nodeType===1){if((a=t[d])===l)return t.sizset;if(typeof a=="string"&&a.indexOf(f)===0){if(t.sizset)return t}else{t[d]=l;if(e(t,r,u))return t.sizset=!0,t;t.sizset=!1}}}else while(t=t[i])if(s||t.nodeType===1)if(e(t,r,u))return t}}function ft(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function lt(e,t,n,r,i){var s,o=[],u=0,a=e.length,f=t!=null;for(;u<a;u++)if(s=e[u])if(!n||n(s,r,i))o.push(s),f&&t.push(u);return o}function ct(e,t,n,r,i,s){return r&&!r[d]&&(r=ct(r)),i&&!i[d]&&(i=ct(i,s)),N(function(s,o,u,a){var f,l,c,h=[],p=[],d=o.length,v=s||dt(t||"*",u.nodeType?[u]:u,[]),m=e&&(s||!t)?lt(v,h,e,u,a):v,g=n?i||(s?e:d||r)?[]:o:m;n&&n(m,g,u,a);if(r){f=lt(g,p),r(f,[],u,a),l=f.length;while(l--)if(c=f[l])g[p[l]]=!(m[p[l]]=c)}if(s){if(i||e){if(i){f=[],l=g.length;while(l--)(c=g[l])&&f.push(m[l]=c);i(null,g=[],f,a)}l=g.length;while(l--)(c=g[l])&&(f=i?T.call(s,c):h[l])>-1&&(s[f]=!(o[f]=c))}}else g=lt(g===o?g.splice(d,g.length):g),i?i(null,o,g,a):S.apply(o,g)})}function ht(e){var t,n,r,s=e.length,o=i.relative[e[0].type],u=o||i.relative[" "],a=o?1:0,f=at(function(e){return e===t},u,!0),l=at(function(e){return T.call(t,e)>-1},u,!0),h=[function(e,n,r){return!o&&(r||n!==c)||((t=n).nodeType?f(e,n,r):l(e,n,r))}];for(;a<s;a++)if(n=i.relative[e[a].type])h=[at(ft(h),n)];else{n=i.filter[e[a].type].apply(null,e[a].matches);if(n[d]){r=++a;for(;r<s;r++)if(i.relative[e[r].type])break;return ct(a>1&&ft(h),a>1&&e.slice(0,a-1).join("").replace(j,"$1"),n,a<r&&ht(e.slice(a,r)),r<s&&ht(e=e.slice(r)),r<s&&e.join(""))}h.push(n)}return ft(h)}function pt(e,t){var r=t.length>0,s=e.length>0,o=function(u,a,f,l,h){var p,d,v,m=[],y=0,w="0",x=u&&[],T=h!=null,N=c,C=u||s&&i.find.TAG("*",h&&a.parentNode||a),k=b+=N==null?1:Math.E;T&&(c=a!==g&&a,n=o.el);for(;(p=C[w])!=null;w++){if(s&&p){for(d=0;v=e[d];d++)if(v(p,a,f)){l.push(p);break}T&&(b=k,n=++o.el)}r&&((p=!v&&p)&&y--,u&&x.push(p))}y+=w;if(r&&w!==y){for(d=0;v=t[d];d++)v(x,m,a,f);if(u){if(y>0)while(w--)!x[w]&&!m[w]&&(m[w]=E.call(l));m=lt(m)}S.apply(l,m),T&&!u&&m.length>0&&y+t.length>1&&nt.uniqueSort(l)}return T&&(b=k,c=N),x};return o.el=0,r?N(o):o}function dt(e,t,n){var r=0,i=t.length;for(;r<i;r++)nt(e,t[r],n);return n}function vt(e,t,n,r,s){var o,u,f,l,c,h=ut(e),p=h.length;if(!r&&h.length===1){u=h[0]=h[0].slice(0);if(u.length>2&&(f=u[0]).type==="ID"&&t.nodeType===9&&!s&&i.relative[u[1].type]){t=i.find.ID(f.matches[0].replace($,""),t,s)[0];if(!t)return n;e=e.slice(u.shift().length)}for(o=J.POS.test(e)?-1:u.length-1;o>=0;o--){f=u[o];if(i.relative[l=f.type])break;if(c=i.find[l])if(r=c(f.matches[0].replace($,""),z.test(u[0].type)&&t.parentNode||t,s)){u.splice(o,1),e=r.length&&u.join("");if(!e)return S.apply(n,x.call(r,0)),n;break}}}return a(e,h)(r,t,s,n,z.test(e)),n}function mt(){}var n,r,i,s,o,u,a,f,l,c,h=!0,p="undefined",d=("sizcache"+Math.random()).replace(".",""),m=String,g=e.document,y=g.documentElement,b=0,w=0,E=[].pop,S=[].push,x=[].slice,T=[].indexOf||function(e){var t=0,n=this.length;for(;t<n;t++)if(this[t]===e)return t;return-1},N=function(e,t){return e[d]=t==null||t,e},C=function(){var e={},t=[];return N(function(n,r){return t.push(n)>i.cacheLength&&delete e[t.shift()],e[n+" "]=r},e)},k=C(),L=C(),A=C(),O="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",_=M.replace("w","w#"),D="([*^$|!~]?=)",P="\\["+O+"*("+M+")"+O+"*(?:"+D+O+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+_+")|)|)"+O+"*\\]",H=":("+M+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+P+")|[^:]|\\\\.)*|.*))\\)|)",B=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+O+"*((?:-\\d)?\\d*)"+O+"*\\)|)(?=[^-]|$)",j=new RegExp("^"+O+"+|((?:^|[^\\\\])(?:\\\\.)*)"+O+"+$","g"),F=new RegExp("^"+O+"*,"+O+"*"),I=new RegExp("^"+O+"*([\\x20\\t\\r\\n\\f>+~])"+O+"*"),q=new RegExp(H),R=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,U=/^:not/,z=/[\x20\t\r\n\f]*[+~]/,W=/:not\($/,X=/h\d/i,V=/input|select|textarea|button/i,$=/\\(?!\\)/g,J={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),NAME:new RegExp("^\\[name=['\"]?("+M+")['\"]?\\]"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+H),POS:new RegExp(B,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+O+"*(even|odd|(([+-]|)(\\d*)n|)"+O+"*(?:([+-]|)"+O+"*(\\d+)|))"+O+"*\\)|)","i"),needsContext:new RegExp("^"+O+"*[>+~]|"+B,"i")},K=function(e){var t=g.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}},Q=K(function(e){return e.appendChild(g.createComment("")),!e.getElementsByTagName("*").length}),G=K(function(e){return e.innerHTML="<a href='#'></a>",e.firstChild&&typeof e.firstChild.getAttribute!==p&&e.firstChild.getAttribute("href")==="#"}),Y=K(function(e){e.innerHTML="<select></select>";var t=typeof e.lastChild.getAttribute("multiple");return t!=="boolean"&&t!=="string"}),Z=K(function(e){return e.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",!e.getElementsByClassName||!e.getElementsByClassName("e").length?!1:(e.lastChild.className="e",e.getElementsByClassName("e").length===2)}),et=K(function(e){e.id=d+0,e.innerHTML="<a name='"+d+"'></a><div name='"+d+"'></div>",y.insertBefore(e,y.firstChild);var t=g.getElementsByName&&g.getElementsByName(d).length===2+g.getElementsByName(d+0).length;return r=!g.getElementById(d),y.removeChild(e),t});try{x.call(y.childNodes,0)[0].nodeType}catch(tt){x=function(e){var t,n=[];for(;t=this[e];e++)n.push(t);return n}}nt.matches=function(e,t){return nt(e,null,null,t)},nt.matchesSelector=function(e,t){return nt(t,null,null,[e]).length>0},s=nt.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(i===1||i===9||i===11){if(typeof e.textContent=="string")return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=s(e)}else if(i===3||i===4)return e.nodeValue}else for(;t=e[r];r++)n+=s(t);return n},o=nt.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?t.nodeName!=="HTML":!1},u=nt.contains=y.contains?function(e,t){var n=e.nodeType===9?e.documentElement:e,r=t&&t.parentNode;return e===r||!!(r&&r.nodeType===1&&n.contains&&n.contains(r))}:y.compareDocumentPosition?function(e,t){return t&&!!(e.compareDocumentPosition(t)&16)}:function(e,t){while(t=t.parentNode)if(t===e)return!0;return!1},nt.attr=function(e,t){var n,r=o(e);return r||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):r||Y?e.getAttribute(t):(n=e.getAttributeNode(t),n?typeof e[t]=="boolean"?e[t]?t:null:n.specified?n.value:null:null)},i=nt.selectors={cacheLength:50,createPseudo:N,match:J,attrHandle:G?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},find:{ID:r?function(e,t,n){if(typeof t.getElementById!==p&&!n){var r=t.getElementById(e);return r&&r.parentNode?[r]:[]}}:function(e,n,r){if(typeof n.getElementById!==p&&!r){var i=n.getElementById(e);return i?i.id===e||typeof i.getAttributeNode!==p&&i.getAttributeNode("id").value===e?[i]:t:[]}},TAG:Q?function(e,t){if(typeof t.getElementsByTagName!==p)return t.getElementsByTagName(e)}:function(e,t){var n=t.getElementsByTagName(e);if(e==="*"){var r,i=[],s=0;for(;r=n[s];s++)r.nodeType===1&&i.push(r);return i}return n},NAME:et&&function(e,t){if(typeof t.getElementsByName!==p)return t.getElementsByName(name)},CLASS:Z&&function(e,t,n){if(typeof t.getElementsByClassName!==p&&!n)return t.getElementsByClassName(e)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace($,""),e[3]=(e[4]||e[5]||"").replace($,""),e[2]==="~="&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),e[1]==="nth"?(e[2]||nt.error(e[0]),e[3]=+(e[3]?e[4]+(e[5]||1):2*(e[2]==="even"||e[2]==="odd")),e[4]=+(e[6]+e[7]||e[2]==="odd")):e[2]&&nt.error(e[0]),e},PSEUDO:function(e){var t,n;if(J.CHILD.test(e[0]))return null;if(e[3])e[2]=e[3];else if(t=e[4])q.test(t)&&(n=ut(t,!0))&&(n=t.indexOf(")",t.length-n)-t.length)&&(t=t.slice(0,n),e[0]=e[0].slice(0,n)),e[2]=t;return e.slice(0,3)}},filter:{ID:r?function(e){return e=e.replace($,""),function(t){return t.getAttribute("id")===e}}:function(e){return e=e.replace($,""),function(t){var n=typeof t.getAttributeNode!==p&&t.getAttributeNode("id");return n&&n.value===e}},TAG:function(e){return e==="*"?function(){return!0}:(e=e.replace($,"").toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[d][e+" "];return t||(t=new RegExp("(^|"+O+")"+e+"("+O+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttribute!==p&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r,i){var s=nt.attr(r,e);return s==null?t==="!=":t?(s+="",t==="="?s===n:t==="!="?s!==n:t==="^="?n&&s.indexOf(n)===0:t==="*="?n&&s.indexOf(n)>-1:t==="$="?n&&s.substr(s.length-n.length)===n:t==="~="?(" "+s+" ").indexOf(n)>-1:t==="|="?s===n||s.substr(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r){return e==="nth"?function(e){var t,i,s=e.parentNode;if(n===1&&r===0)return!0;if(s){i=0;for(t=s.firstChild;t;t=t.nextSibling)if(t.nodeType===1){i++;if(e===t)break}}return i-=r,i===n||i%n===0&&i/n>=0}:function(t){var n=t;switch(e){case"only":case"first":while(n=n.previousSibling)if(n.nodeType===1)return!1;if(e==="first")return!0;n=t;case"last":while(n=n.nextSibling)if(n.nodeType===1)return!1;return!0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||nt.error("unsupported pseudo: "+e);return r[d]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?N(function(e,n){var i,s=r(e,t),o=s.length;while(o--)i=T.call(e,s[o]),e[i]=!(n[i]=s[o])}):function(e){return r(e,0,n)}):r}},pseudos:{not:N(function(e){var t=[],n=[],r=a(e.replace(j,"$1"));return r[d]?N(function(e,t,n,i){var s,o=r(e,null,i,[]),u=e.length;while(u--)if(s=o[u])e[u]=!(t[u]=s)}):function(e,i,s){return t[0]=e,r(t,null,s,n),!n.pop()}}),has:N(function(e){return function(t){return nt(e,t).length>0}}),contains:N(function(e){return function(t){return(t.textContent||t.innerText||s(t)).indexOf(e)>-1}}),enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return t==="input"&&!!e.checked||t==="option"&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},parent:function(e){return!i.pseudos.empty(e)},empty:function(e){var t;e=e.firstChild;while(e){if(e.nodeName>"@"||(t=e.nodeType)===3||t===4)return!1;e=e.nextSibling}return!0},header:function(e){return X.test(e.nodeName)},text:function(e){var t,n;return e.nodeName.toLowerCase()==="input"&&(t=e.type)==="text"&&((n=e.getAttribute("type"))==null||n.toLowerCase()===t)},radio:rt("radio"),checkbox:rt("checkbox"),file:rt("file"),password:rt("password"),image:rt("image"),submit:it("submit"),reset:it("reset"),button:function(e){var t=e.nodeName.toLowerCase();return t==="input"&&e.type==="button"||t==="button"},input:function(e){return V.test(e.nodeName)},focus:function(e){var t=e.ownerDocument;return e===t.activeElement&&(!t.hasFocus||t.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},active:function(e){return e===e.ownerDocument.activeElement},first:st(function(){return[0]}),last:st(function(e,t){return[t-1]}),eq:st(function(e,t,n){return[n<0?n+t:n]}),even:st(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:st(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:st(function(e,t,n){for(var r=n<0?n+t:n;--r>=0;)e.push(r);return e}),gt:st(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}},f=y.compareDocumentPosition?function(e,t){return e===t?(l=!0,0):(!e.compareDocumentPosition||!t.compareDocumentPosition?e.compareDocumentPosition:e.compareDocumentPosition(t)&4)?-1:1}:function(e,t){if(e===t)return l=!0,0;if(e.sourceIndex&&t.sourceIndex)return e.sourceIndex-t.sourceIndex;var n,r,i=[],s=[],o=e.parentNode,u=t.parentNode,a=o;if(o===u)return ot(e,t);if(!o)return-1;if(!u)return 1;while(a)i.unshift(a),a=a.parentNode;a=u;while(a)s.unshift(a),a=a.parentNode;n=i.length,r=s.length;for(var f=0;f<n&&f<r;f++)if(i[f]!==s[f])return ot(i[f],s[f]);return f===n?ot(e,s[f],-1):ot(i[f],t,1)},[0,0].sort(f),h=!l,nt.uniqueSort=function(e){var t,n=[],r=1,i=0;l=h,e.sort(f);if(l){for(;t=e[r];r++)t===e[r-1]&&(i=n.push(r));while(i--)e.splice(n[i],1)}return e},nt.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},a=nt.compile=function(e,t){var n,r=[],i=[],s=A[d][e+" "];if(!s){t||(t=ut(e)),n=t.length;while(n--)s=ht(t[n]),s[d]?r.push(s):i.push(s);s=A(e,pt(i,r))}return s},g.querySelectorAll&&function(){var e,t=vt,n=/'|\\/g,r=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,i=[":focus"],s=[":active"],u=y.matchesSelector||y.mozMatchesSelector||y.webkitMatchesSelector||y.oMatchesSelector||y.msMatchesSelector;K(function(e){e.innerHTML="<select><option selected=''></option></select>",e.querySelectorAll("[selected]").length||i.push("\\["+O+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||i.push(":checked")}),K(function(e){e.innerHTML="<p test=''></p>",e.querySelectorAll("[test^='']").length&&i.push("[*^$]="+O+"*(?:\"\"|'')"),e.innerHTML="<input type='hidden'/>",e.querySelectorAll(":enabled").length||i.push(":enabled",":disabled")}),i=new RegExp(i.join("|")),vt=function(e,r,s,o,u){if(!o&&!u&&!i.test(e)){var a,f,l=!0,c=d,h=r,p=r.nodeType===9&&e;if(r.nodeType===1&&r.nodeName.toLowerCase()!=="object"){a=ut(e),(l=r.getAttribute("id"))?c=l.replace(n,"\\$&"):r.setAttribute("id",c),c="[id='"+c+"'] ",f=a.length;while(f--)a[f]=c+a[f].join("");h=z.test(e)&&r.parentNode||r,p=a.join(",")}if(p)try{return S.apply(s,x.call(h.querySelectorAll(p),0)),s}catch(v){}finally{l||r.removeAttribute("id")}}return t(e,r,s,o,u)},u&&(K(function(t){e=u.call(t,"div");try{u.call(t,"[test!='']:sizzle"),s.push("!=",H)}catch(n){}}),s=new RegExp(s.join("|")),nt.matchesSelector=function(t,n){n=n.replace(r,"='$1']");if(!o(t)&&!s.test(n)&&!i.test(n))try{var a=u.call(t,n);if(a||e||t.document&&t.document.nodeType!==11)return a}catch(f){}return nt(n,null,null,[t]).length>0})}(),i.pseudos.nth=i.pseudos.eq,i.filters=mt.prototype=i.pseudos,i.setFilters=new mt,nt.attr=v.attr,v.find=nt,v.expr=nt.selectors,v.expr[":"]=v.expr.pseudos,v.unique=nt.uniqueSort,v.text=nt.getText,v.isXMLDoc=nt.isXML,v.contains=nt.contains}(e);var nt=/Until$/,rt=/^(?:parents|prev(?:Until|All))/,it=/^.[^:#\[\.,]*$/,st=v.expr.match.needsContext,ot={children:!0,contents:!0,next:!0,prev:!0};v.fn.extend({find:function(e){var t,n,r,i,s,o,u=this;if(typeof e!="string")return v(e).filter(function(){for(t=0,n=u.length;t<n;t++)if(v.contains(u[t],this))return!0});o=this.pushStack("","find",e);for(t=0,n=this.length;t<n;t++){r=o.length,v.find(e,this[t],o);if(t>0)for(i=r;i<o.length;i++)for(s=0;s<r;s++)if(o[s]===o[i]){o.splice(i--,1);break}}return o},has:function(e){var t,n=v(e,this),r=n.length;return this.filter(function(){for(t=0;t<r;t++)if(v.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e,!1),"not",e)},filter:function(e){return this.pushStack(ft(this,e,!0),"filter",e)},is:function(e){return!!e&&(typeof e=="string"?st.test(e)?v(e,this.context).index(this[0])>=0:v.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,s=[],o=st.test(e)||typeof e!="string"?v(e,t||this.context):0;for(;r<i;r++){n=this[r];while(n&&n.ownerDocument&&n!==t&&n.nodeType!==11){if(o?o.index(n)>-1:v.find.matchesSelector(n,e)){s.push(n);break}n=n.parentNode}}return s=s.length>1?v.unique(s):s,this.pushStack(s,"closest",e)},index:function(e){return e?typeof e=="string"?v.inArray(this[0],v(e)):v.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(e,t){var n=typeof e=="string"?v(e,t):v.makeArray(e&&e.nodeType?[e]:e),r=v.merge(this.get(),n);return this.pushStack(ut(n[0])||ut(r[0])?r:v.unique(r))},addBack:function(e){return this.add(e==null?this.prevObject:this.prevObject.filter(e))}}),v.fn.andSelf=v.fn.addBack,v.each({parent:function(e){var t=e.parentNode;return t&&t.nodeType!==11?t:null},parents:function(e){return v.dir(e,"parentNode")},parentsUntil:function(e,t,n){return v.dir(e,"parentNode",n)},next:function(e){return at(e,"nextSibling")},prev:function(e){return at(e,"previousSibling")},nextAll:function(e){return v.dir(e,"nextSibling")},prevAll:function(e){return v.dir(e,"previousSibling")},nextUntil:function(e,t,n){return v.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return v.dir(e,"previousSibling",n)},siblings:function(e){return v.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return v.sibling(e.firstChild)},contents:function(e){return v.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:v.merge([],e.childNodes)}},function(e,t){v.fn[e]=function(n,r){var i=v.map(this,t,n);return nt.test(e)||(r=n),r&&typeof r=="string"&&(i=v.filter(r,i)),i=this.length>1&&!ot[e]?v.unique(i):i,this.length>1&&rt.test(e)&&(i=i.reverse()),this.pushStack(i,e,l.call(arguments).join(","))}}),v.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),t.length===1?v.find.matchesSelector(t[0],e)?[t[0]]:[]:v.find.matches(e,t)},dir:function(e,n,r){var i=[],s=e[n];while(s&&s.nodeType!==9&&(r===t||s.nodeType!==1||!v(s).is(r)))s.nodeType===1&&i.push(s),s=s[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)e.nodeType===1&&e!==t&&n.push(e);return n}});var ct="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ht=/ jQuery\d+="(?:null|\d+)"/g,pt=/^\s+/,dt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,vt=/<([\w:]+)/,mt=/<tbody/i,gt=/<|&#?\w+;/,yt=/<(?:script|style|link)/i,bt=/<(?:script|object|embed|option|style)/i,wt=new RegExp("<(?:"+ct+")[\\s/>]","i"),Et=/^(?:checkbox|radio)$/,St=/checked\s*(?:[^=]|=\s*.checked.)/i,xt=/\/(java|ecma)script/i,Tt=/^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g,Nt={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},Ct=lt(i),kt=Ct.appendChild(i.createElement("div"));Nt.optgroup=Nt.option,Nt.tbody=Nt.tfoot=Nt.colgroup=Nt.caption=Nt.thead,Nt.th=Nt.td,v.support.htmlSerialize||(Nt._default=[1,"X<div>","</div>"]),v.fn.extend({text:function(e){return v.access(this,function(e){return e===t?v.text(this):this.empty().append((this[0]&&this[0].ownerDocument||i).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(v.isFunction(e))return this.each(function(t){v(this).wrapAll(e.call(this,t))});if(this[0]){var t=v(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&e.firstChild.nodeType===1)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return v.isFunction(e)?this.each(function(t){v(this).wrapInner(e.call(this,t))}):this.each(function(){var t=v(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=v.isFunction(e);return this.each(function(n){v(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){v.nodeName(this,"body")||v(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(this.nodeType===1||this.nodeType===11)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(e,this.firstChild)})},before:function(){if(!ut(this[0]))return this.domManip(arguments,!1,function(e){this.parentNode.insertBefore(e,this)});if(arguments.length){var e=v.clean(arguments);return this.pushStack(v.merge(e,this),"before",this.selector)}},after:function(){if(!ut(this[0]))return this.domManip(arguments,!1,function(e){this.parentNode.insertBefore(e,this.nextSibling)});if(arguments.length){var e=v.clean(arguments);return this.pushStack(v.merge(this,e),"after",this.selector)}},remove:function(e,t){var n,r=0;for(;(n=this[r])!=null;r++)if(!e||v.filter(e,[n]).length)!t&&n.nodeType===1&&(v.cleanData(n.getElementsByTagName("*")),v.cleanData([n])),n.parentNode&&n.parentNode.removeChild(n);return this},empty:function(){var e,t=0;for(;(e=this[t])!=null;t++){e.nodeType===1&&v.cleanData(e.getElementsByTagName("*"));while(e.firstChild)e.removeChild(e.firstChild)}return this},clone:function(e,t){return e=e==null?!1:e,t=t==null?e:t,this.map(function(){return v.clone(this,e,t)})},html:function(e){return v.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return n.nodeType===1?n.innerHTML.replace(ht,""):t;if(typeof e=="string"&&!yt.test(e)&&(v.support.htmlSerialize||!wt.test(e))&&(v.support.leadingWhitespace||!pt.test(e))&&!Nt[(vt.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(dt,"<$1></$2>");try{for(;r<i;r++)n=this[r]||{},n.nodeType===1&&(v.cleanData(n.getElementsByTagName("*")),n.innerHTML=e);n=0}catch(s){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(e){return ut(this[0])?this.length?this.pushStack(v(v.isFunction(e)?e():e),"replaceWith",e):this:v.isFunction(e)?this.each(function(t){var n=v(this),r=n.html();n.replaceWith(e.call(this,t,r))}):(typeof e!="string"&&(e=v(e).detach()),this.each(function(){var t=this.nextSibling,n=this.parentNode;v(this).remove(),t?v(t).before(e):v(n).append(e)}))},detach:function(e){return this.remove(e,!0)},domManip:function(e,n,r){e=[].concat.apply([],e);var i,s,o,u,a=0,f=e[0],l=[],c=this.length;if(!v.support.checkClone&&c>1&&typeof f=="string"&&St.test(f))return this.each(function(){v(this).domManip(e,n,r)});if(v.isFunction(f))return this.each(function(i){var s=v(this);e[0]=f.call(this,i,n?s.html():t),s.domManip(e,n,r)});if(this[0]){i=v.buildFragment(e,this,l),o=i.fragment,s=o.firstChild,o.childNodes.length===1&&(o=s);if(s){n=n&&v.nodeName(s,"tr");for(u=i.cacheable||c-1;a<c;a++)r.call(n&&v.nodeName(this[a],"table")?Lt(this[a],"tbody"):this[a],a===u?o:v.clone(o,!0,!0))}o=s=null,l.length&&v.each(l,function(e,t){t.src?v.ajax?v.ajax({url:t.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):v.error("no ajax"):v.globalEval((t.text||t.textContent||t.innerHTML||"").replace(Tt,"")),t.parentNode&&t.parentNode.removeChild(t)})}return this}}),v.buildFragment=function(e,n,r){var s,o,u,a=e[0];return n=n||i,n=!n.nodeType&&n[0]||n,n=n.ownerDocument||n,e.length===1&&typeof a=="string"&&a.length<512&&n===i&&a.charAt(0)==="<"&&!bt.test(a)&&(v.support.checkClone||!St.test(a))&&(v.support.html5Clone||!wt.test(a))&&(o=!0,s=v.fragments[a],u=s!==t),s||(s=n.createDocumentFragment(),v.clean(e,n,s,r),o&&(v.fragments[a]=u&&s)),{fragment:s,cacheable:o}},v.fragments={},v.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){v.fn[e]=function(n){var r,i=0,s=[],o=v(n),u=o.length,a=this.length===1&&this[0].parentNode;if((a==null||a&&a.nodeType===11&&a.childNodes.length===1)&&u===1)return o[t](this[0]),this;for(;i<u;i++)r=(i>0?this.clone(!0):this).get(),v(o[i])[t](r),s=s.concat(r);return this.pushStack(s,e,o.selector)}}),v.extend({clone:function(e,t,n){var r,i,s,o;v.support.html5Clone||v.isXMLDoc(e)||!wt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(kt.innerHTML=e.outerHTML,kt.removeChild(o=kt.firstChild));if((!v.support.noCloneEvent||!v.support.noCloneChecked)&&(e.nodeType===1||e.nodeType===11)&&!v.isXMLDoc(e)){Ot(e,o),r=Mt(e),i=Mt(o);for(s=0;r[s];++s)i[s]&&Ot(r[s],i[s])}if(t){At(e,o);if(n){r=Mt(e),i=Mt(o);for(s=0;r[s];++s)At(r[s],i[s])}}return r=i=null,o},clean:function(e,t,n,r){var s,o,u,a,f,l,c,h,p,d,m,g,y=t===i&&Ct,b=[];if(!t||typeof t.createDocumentFragment=="undefined")t=i;for(s=0;(u=e[s])!=null;s++){typeof u=="number"&&(u+="");if(!u)continue;if(typeof u=="string")if(!gt.test(u))u=t.createTextNode(u);else{y=y||lt(t),c=t.createElement("div"),y.appendChild(c),u=u.replace(dt,"<$1></$2>"),a=(vt.exec(u)||["",""])[1].toLowerCase(),f=Nt[a]||Nt._default,l=f[0],c.innerHTML=f[1]+u+f[2];while(l--)c=c.lastChild;if(!v.support.tbody){h=mt.test(u),p=a==="table"&&!h?c.firstChild&&c.firstChild.childNodes:f[1]==="<table>"&&!h?c.childNodes:[];for(o=p.length-1;o>=0;--o)v.nodeName(p[o],"tbody")&&!p[o].childNodes.length&&p[o].parentNode.removeChild(p[o])}!v.support.leadingWhitespace&&pt.test(u)&&c.insertBefore(t.createTextNode(pt.exec(u)[0]),c.firstChild),u=c.childNodes,c.parentNode.removeChild(c)}u.nodeType?b.push(u):v.merge(b,u)}c&&(u=c=y=null);if(!v.support.appendChecked)for(s=0;(u=b[s])!=null;s++)v.nodeName(u,"input")?_t(u):typeof u.getElementsByTagName!="undefined"&&v.grep(u.getElementsByTagName("input"),_t);if(n){m=function(e){if(!e.type||xt.test(e.type))return r?r.push(e.parentNode?e.parentNode.removeChild(e):e):n.appendChild(e)};for(s=0;(u=b[s])!=null;s++)if(!v.nodeName(u,"script")||!m(u))n.appendChild(u),typeof u.getElementsByTagName!="undefined"&&(g=v.grep(v.merge([],u.getElementsByTagName("script")),m),b.splice.apply(b,[s+1,0].concat(g)),s+=g.length)}return b},cleanData:function(e,t){var n,r,i,s,o=0,u=v.expando,a=v.cache,f=v.support.deleteExpando,l=v.event.special;for(;(i=e[o])!=null;o++)if(t||v.acceptData(i)){r=i[u],n=r&&a[r];if(n){if(n.events)for(s in n.events)l[s]?v.event.remove(i,s):v.removeEvent(i,s,n.handle);a[r]&&(delete a[r],f?delete i[u]:i.removeAttribute?i.removeAttribute(u):i[u]=null,v.deletedIds.push(r))}}}}),function(){var e,t;v.uaMatch=function(e){e=e.toLowerCase();var t=/(chrome)[ \/]([\w.]+)/.exec(e)||/(webkit)[ \/]([\w.]+)/.exec(e)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(e)||/(msie) ([\w.]+)/.exec(e)||e.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(e)||[];return{browser:t[1]||"",version:t[2]||"0"}},e=v.uaMatch(o.userAgent),t={},e.browser&&(t[e.browser]=!0,t.version=e.version),t.chrome?t.webkit=!0:t.webkit&&(t.safari=!0),v.browser=t,v.sub=function(){function e(t,n){return new e.fn.init(t,n)}v.extend(!0,e,this),e.superclass=this,e.fn=e.prototype=this(),e.fn.constructor=e,e.sub=this.sub,e.fn.init=function(r,i){return i&&i instanceof v&&!(i instanceof e)&&(i=e(i)),v.fn.init.call(this,r,i,t)},e.fn.init.prototype=e.fn;var t=e(i);return e}}();var Dt,Pt,Ht,Bt=/alpha\([^)]*\)/i,jt=/opacity=([^)]*)/,Ft=/^(top|right|bottom|left)$/,It=/^(none|table(?!-c[ea]).+)/,qt=/^margin/,Rt=new RegExp("^("+m+")(.*)$","i"),Ut=new RegExp("^("+m+")(?!px)[a-z%]+$","i"),zt=new RegExp("^([-+])=("+m+")","i"),Wt={BODY:"block"},Xt={position:"absolute",visibility:"hidden",display:"block"},Vt={letterSpacing:0,fontWeight:400},$t=["Top","Right","Bottom","Left"],Jt=["Webkit","O","Moz","ms"],Kt=v.fn.toggle;v.fn.extend({css:function(e,n){return v.access(this,function(e,n,r){return r!==t?v.style(e,n,r):v.css(e,n)},e,n,arguments.length>1)},show:function(){return Yt(this,!0)},hide:function(){return Yt(this)},toggle:function(e,t){var n=typeof e=="boolean";return v.isFunction(e)&&v.isFunction(t)?Kt.apply(this,arguments):this.each(function(){(n?e:Gt(this))?v(this).show():v(this).hide()})}}),v.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Dt(e,"opacity");return n===""?"1":n}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":v.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(!e||e.nodeType===3||e.nodeType===8||!e.style)return;var s,o,u,a=v.camelCase(n),f=e.style;n=v.cssProps[a]||(v.cssProps[a]=Qt(f,a)),u=v.cssHooks[n]||v.cssHooks[a];if(r===t)return u&&"get"in u&&(s=u.get(e,!1,i))!==t?s:f[n];o=typeof r,o==="string"&&(s=zt.exec(r))&&(r=(s[1]+1)*s[2]+parseFloat(v.css(e,n)),o="number");if(r==null||o==="number"&&isNaN(r))return;o==="number"&&!v.cssNumber[a]&&(r+="px");if(!u||!("set"in u)||(r=u.set(e,r,i))!==t)try{f[n]=r}catch(l){}},css:function(e,n,r,i){var s,o,u,a=v.camelCase(n);return n=v.cssProps[a]||(v.cssProps[a]=Qt(e.style,a)),u=v.cssHooks[n]||v.cssHooks[a],u&&"get"in u&&(s=u.get(e,!0,i)),s===t&&(s=Dt(e,n)),s==="normal"&&n in Vt&&(s=Vt[n]),r||i!==t?(o=parseFloat(s),r||v.isNumeric(o)?o||0:s):s},swap:function(e,t,n){var r,i,s={};for(i in t)s[i]=e.style[i],e.style[i]=t[i];r=n.call(e);for(i in t)e.style[i]=s[i];return r}}),e.getComputedStyle?Dt=function(t,n){var r,i,s,o,u=e.getComputedStyle(t,null),a=t.style;return u&&(r=u.getPropertyValue(n)||u[n],r===""&&!v.contains(t.ownerDocument,t)&&(r=v.style(t,n)),Ut.test(r)&&qt.test(n)&&(i=a.width,s=a.minWidth,o=a.maxWidth,a.minWidth=a.maxWidth=a.width=r,r=u.width,a.width=i,a.minWidth=s,a.maxWidth=o)),r}:i.documentElement.currentStyle&&(Dt=function(e,t){var n,r,i=e.currentStyle&&e.currentStyle[t],s=e.style;return i==null&&s&&s[t]&&(i=s[t]),Ut.test(i)&&!Ft.test(t)&&(n=s.left,r=e.runtimeStyle&&e.runtimeStyle.left,r&&(e.runtimeStyle.left=e.currentStyle.left),s.left=t==="fontSize"?"1em":i,i=s.pixelLeft+"px",s.left=n,r&&(e.runtimeStyle.left=r)),i===""?"auto":i}),v.each(["height","width"],function(e,t){v.cssHooks[t]={get:function(e,n,r){if(n)return e.offsetWidth===0&&It.test(Dt(e,"display"))?v.swap(e,Xt,function(){return tn(e,t,r)}):tn(e,t,r)},set:function(e,n,r){return Zt(e,n,r?en(e,t,r,v.support.boxSizing&&v.css(e,"boxSizing")==="border-box"):0)}}}),v.support.opacity||(v.cssHooks.opacity={get:function(e,t){return jt.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=v.isNumeric(t)?"alpha(opacity="+t*100+")":"",s=r&&r.filter||n.filter||"";n.zoom=1;if(t>=1&&v.trim(s.replace(Bt,""))===""&&n.removeAttribute){n.removeAttribute("filter");if(r&&!r.filter)return}n.filter=Bt.test(s)?s.replace(Bt,i):s+" "+i}}),v(function(){v.support.reliableMarginRight||(v.cssHooks.marginRight={get:function(e,t){return v.swap(e,{display:"inline-block"},function(){if(t)return Dt(e,"marginRight")})}}),!v.support.pixelPosition&&v.fn.position&&v.each(["top","left"],function(e,t){v.cssHooks[t]={get:function(e,n){if(n){var r=Dt(e,t);return Ut.test(r)?v(e).position()[t]+"px":r}}}})}),v.expr&&v.expr.filters&&(v.expr.filters.hidden=function(e){return e.offsetWidth===0&&e.offsetHeight===0||!v.support.reliableHiddenOffsets&&(e.style&&e.style.display||Dt(e,"display"))==="none"},v.expr.filters.visible=function(e){return!v.expr.filters.hidden(e)}),v.each({margin:"",padding:"",border:"Width"},function(e,t){v.cssHooks[e+t]={expand:function(n){var r,i=typeof n=="string"?n.split(" "):[n],s={};for(r=0;r<4;r++)s[e+$t[r]+t]=i[r]||i[r-2]||i[0];return s}},qt.test(e)||(v.cssHooks[e+t].set=Zt)});var rn=/%20/g,sn=/\[\]$/,on=/\r?\n/g,un=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,an=/^(?:select|textarea)/i;v.fn.extend({serialize:function(){return v.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?v.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||an.test(this.nodeName)||un.test(this.type))}).map(function(e,t){var n=v(this).val();return n==null?null:v.isArray(n)?v.map(n,function(e,n){return{name:t.name,value:e.replace(on,"\r\n")}}):{name:t.name,value:n.replace(on,"\r\n")}}).get()}}),v.param=function(e,n){var r,i=[],s=function(e,t){t=v.isFunction(t)?t():t==null?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};n===t&&(n=v.ajaxSettings&&v.ajaxSettings.traditional);if(v.isArray(e)||e.jquery&&!v.isPlainObject(e))v.each(e,function(){s(this.name,this.value)});else for(r in e)fn(r,e[r],n,s);return i.join("&").replace(rn,"+")};var ln,cn,hn=/#.*$/,pn=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,dn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,vn=/^(?:GET|HEAD)$/,mn=/^\/\//,gn=/\?/,yn=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bn=/([?&])_=[^&]*/,wn=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,En=v.fn.load,Sn={},xn={},Tn=["*/"]+["*"];try{cn=s.href}catch(Nn){cn=i.createElement("a"),cn.href="",cn=cn.href}ln=wn.exec(cn.toLowerCase())||[],v.fn.load=function(e,n,r){if(typeof e!="string"&&En)return En.apply(this,arguments);if(!this.length)return this;var i,s,o,u=this,a=e.indexOf(" ");return a>=0&&(i=e.slice(a,e.length),e=e.slice(0,a)),v.isFunction(n)?(r=n,n=t):n&&typeof n=="object"&&(s="POST"),v.ajax({url:e,type:s,dataType:"html",data:n,complete:function(e,t){r&&u.each(r,o||[e.responseText,t,e])}}).done(function(e){o=arguments,u.html(i?v("<div>").append(e.replace(yn,"")).find(i):e)}),this},v.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,t){v.fn[t]=function(e){return this.on(t,e)}}),v.each(["get","post"],function(e,n){v[n]=function(e,r,i,s){return v.isFunction(r)&&(s=s||i,i=r,r=t),v.ajax({type:n,url:e,data:r,success:i,dataType:s})}}),v.extend({getScript:function(e,n){return v.get(e,t,n,"script")},getJSON:function(e,t,n){return v.get(e,t,n,"json")},ajaxSetup:function(e,t){return t?Ln(e,v.ajaxSettings):(t=e,e=v.ajaxSettings),Ln(e,t),e},ajaxSettings:{url:cn,isLocal:dn.test(ln[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":Tn},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":e.String,"text html":!0,"text json":v.parseJSON,"text xml":v.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:Cn(Sn),ajaxTransport:Cn(xn),ajax:function(e,n){function T(e,n,s,a){var l,y,b,w,S,T=n;if(E===2)return;E=2,u&&clearTimeout(u),o=t,i=a||"",x.readyState=e>0?4:0,s&&(w=An(c,x,s));if(e>=200&&e<300||e===304)c.ifModified&&(S=x.getResponseHeader("Last-Modified"),S&&(v.lastModified[r]=S),S=x.getResponseHeader("Etag"),S&&(v.etag[r]=S)),e===304?(T="notmodified",l=!0):(l=On(c,w),T=l.state,y=l.data,b=l.error,l=!b);else{b=T;if(!T||e)T="error",e<0&&(e=0)}x.status=e,x.statusText=(n||T)+"",l?d.resolveWith(h,[y,T,x]):d.rejectWith(h,[x,T,b]),x.statusCode(g),g=t,f&&p.trigger("ajax"+(l?"Success":"Error"),[x,c,l?y:b]),m.fireWith(h,[x,T]),f&&(p.trigger("ajaxComplete",[x,c]),--v.active||v.event.trigger("ajaxStop"))}typeof e=="object"&&(n=e,e=t),n=n||{};var r,i,s,o,u,a,f,l,c=v.ajaxSetup({},n),h=c.context||c,p=h!==c&&(h.nodeType||h instanceof v)?v(h):v.event,d=v.Deferred(),m=v.Callbacks("once memory"),g=c.statusCode||{},b={},w={},E=0,S="canceled",x={readyState:0,setRequestHeader:function(e,t){if(!E){var n=e.toLowerCase();e=w[n]=w[n]||e,b[e]=t}return this},getAllResponseHeaders:function(){return E===2?i:null},getResponseHeader:function(e){var n;if(E===2){if(!s){s={};while(n=pn.exec(i))s[n[1].toLowerCase()]=n[2]}n=s[e.toLowerCase()]}return n===t?null:n},overrideMimeType:function(e){return E||(c.mimeType=e),this},abort:function(e){return e=e||S,o&&o.abort(e),T(0,e),this}};d.promise(x),x.success=x.done,x.error=x.fail,x.complete=m.add,x.statusCode=function(e){if(e){var t;if(E<2)for(t in e)g[t]=[g[t],e[t]];else t=e[x.status],x.always(t)}return this},c.url=((e||c.url)+"").replace(hn,"").replace(mn,ln[1]+"//"),c.dataTypes=v.trim(c.dataType||"*").toLowerCase().split(y),c.crossDomain==null&&(a=wn.exec(c.url.toLowerCase()),c.crossDomain=!(!a||a[1]===ln[1]&&a[2]===ln[2]&&(a[3]||(a[1]==="http:"?80:443))==(ln[3]||(ln[1]==="http:"?80:443)))),c.data&&c.processData&&typeof c.data!="string"&&(c.data=v.param(c.data,c.traditional)),kn(Sn,c,n,x);if(E===2)return x;f=c.global,c.type=c.type.toUpperCase(),c.hasContent=!vn.test(c.type),f&&v.active++===0&&v.event.trigger("ajaxStart");if(!c.hasContent){c.data&&(c.url+=(gn.test(c.url)?"&":"?")+c.data,delete c.data),r=c.url;if(c.cache===!1){var N=v.now(),C=c.url.replace(bn,"$1_="+N);c.url=C+(C===c.url?(gn.test(c.url)?"&":"?")+"_="+N:"")}}(c.data&&c.hasContent&&c.contentType!==!1||n.contentType)&&x.setRequestHeader("Content-Type",c.contentType),c.ifModified&&(r=r||c.url,v.lastModified[r]&&x.setRequestHeader("If-Modified-Since",v.lastModified[r]),v.etag[r]&&x.setRequestHeader("If-None-Match",v.etag[r])),x.setRequestHeader("Accept",c.dataTypes[0]&&c.accepts[c.dataTypes[0]]?c.accepts[c.dataTypes[0]]+(c.dataTypes[0]!=="*"?", "+Tn+"; q=0.01":""):c.accepts["*"]);for(l in c.headers)x.setRequestHeader(l,c.headers[l]);if(!c.beforeSend||c.beforeSend.call(h,x,c)!==!1&&E!==2){S="abort";for(l in{success:1,error:1,complete:1})x[l](c[l]);o=kn(xn,c,n,x);if(!o)T(-1,"No Transport");else{x.readyState=1,f&&p.trigger("ajaxSend",[x,c]),c.async&&c.timeout>0&&(u=setTimeout(function(){x.abort("timeout")},c.timeout));try{E=1,o.send(b,T)}catch(k){if(!(E<2))throw k;T(-1,k)}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var Mn=[],_n=/\?/,Dn=/(=)\?(?=&|$)|\?\?/,Pn=v.now();v.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Mn.pop()||v.expando+"_"+Pn++;return this[e]=!0,e}}),v.ajaxPrefilter("json jsonp",function(n,r,i){var s,o,u,a=n.data,f=n.url,l=n.jsonp!==!1,c=l&&Dn.test(f),h=l&&!c&&typeof a=="string"&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Dn.test(a);if(n.dataTypes[0]==="jsonp"||c||h)return s=n.jsonpCallback=v.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,o=e[s],c?n.url=f.replace(Dn,"$1"+s):h?n.data=a.replace(Dn,"$1"+s):l&&(n.url+=(_n.test(f)?"&":"?")+n.jsonp+"="+s),n.converters["script json"]=function(){return u||v.error(s+" was not called"),u[0]},n.dataTypes[0]="json",e[s]=function(){u=arguments},i.always(function(){e[s]=o,n[s]&&(n.jsonpCallback=r.jsonpCallback,Mn.push(s)),u&&v.isFunction(o)&&o(u[0]),u=o=t}),"script"}),v.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(e){return v.globalEval(e),e}}}),v.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),v.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=i.head||i.getElementsByTagName("head")[0]||i.documentElement;return{send:function(s,o){n=i.createElement("script"),n.async="async",e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,i){if(i||!n.readyState||/loaded|complete/.test(n.readyState))n.onload=n.onreadystatechange=null,r&&n.parentNode&&r.removeChild(n),n=t,i||o(200,"success")},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(0,1)}}}});var Hn,Bn=e.ActiveXObject?function(){for(var e in Hn)Hn[e](0,1)}:!1,jn=0;v.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&Fn()||In()}:Fn,function(e){v.extend(v.support,{ajax:!!e,cors:!!e&&"withCredentials"in e})}(v.ajaxSettings.xhr()),v.support.ajax&&v.ajaxTransport(function(n){if(!n.crossDomain||v.support.cors){var r;return{send:function(i,s){var o,u,a=n.xhr();n.username?a.open(n.type,n.url,n.async,n.username,n.password):a.open(n.type,n.url,n.async);if(n.xhrFields)for(u in n.xhrFields)a[u]=n.xhrFields[u];n.mimeType&&a.overrideMimeType&&a.overrideMimeType(n.mimeType),!n.crossDomain&&!i["X-Requested-With"]&&(i["X-Requested-With"]="XMLHttpRequest");try{for(u in i)a.setRequestHeader(u,i[u])}catch(f){}a.send(n.hasContent&&n.data||null),r=function(e,i){var u,f,l,c,h;try{if(r&&(i||a.readyState===4)){r=t,o&&(a.onreadystatechange=v.noop,Bn&&delete Hn[o]);if(i)a.readyState!==4&&a.abort();else{u=a.status,l=a.getAllResponseHeaders(),c={},h=a.responseXML,h&&h.documentElement&&(c.xml=h);try{c.text=a.responseText}catch(p){}try{f=a.statusText}catch(p){f=""}!u&&n.isLocal&&!n.crossDomain?u=c.text?200:404:u===1223&&(u=204)}}}catch(d){i||s(-1,d)}c&&s(u,f,c,l)},n.async?a.readyState===4?setTimeout(r,0):(o=++jn,Bn&&(Hn||(Hn={},v(e).unload(Bn)),Hn[o]=r),a.onreadystatechange=r):r()},abort:function(){r&&r(0,1)}}}});var qn,Rn,Un=/^(?:toggle|show|hide)$/,zn=new RegExp("^(?:([-+])=|)("+m+")([a-z%]*)$","i"),Wn=/queueHooks$/,Xn=[Gn],Vn={"*":[function(e,t){var n,r,i=this.createTween(e,t),s=zn.exec(t),o=i.cur(),u=+o||0,a=1,f=20;if(s){n=+s[2],r=s[3]||(v.cssNumber[e]?"":"px");if(r!=="px"&&u){u=v.css(i.elem,e,!0)||n||1;do a=a||".5",u/=a,v.style(i.elem,e,u+r);while(a!==(a=i.cur()/o)&&a!==1&&--f)}i.unit=r,i.start=u,i.end=s[1]?u+(s[1]+1)*n:n}return i}]};v.Animation=v.extend(Kn,{tweener:function(e,t){v.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;r<i;r++)n=e[r],Vn[n]=Vn[n]||[],Vn[n].unshift(t)},prefilter:function(e,t){t?Xn.unshift(e):Xn.push(e)}}),v.Tween=Yn,Yn.prototype={constructor:Yn,init:function(e,t,n,r,i,s){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=s||(v.cssNumber[n]?"":"px")},cur:function(){var e=Yn.propHooks[this.prop];return e&&e.get?e.get(this):Yn.propHooks._default.get(this)},run:function(e){var t,n=Yn.propHooks[this.prop];return this.options.duration?this.pos=t=v.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):Yn.propHooks._default.set(this),this}},Yn.prototype.init.prototype=Yn.prototype,Yn.propHooks={_default:{get:function(e){var t;return e.elem[e.prop]==null||!!e.elem.style&&e.elem.style[e.prop]!=null?(t=v.css(e.elem,e.prop,!1,""),!t||t==="auto"?0:t):e.elem[e.prop]},set:function(e){v.fx.step[e.prop]?v.fx.step[e.prop](e):e.elem.style&&(e.elem.style[v.cssProps[e.prop]]!=null||v.cssHooks[e.prop])?v.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},Yn.propHooks.scrollTop=Yn.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},v.each(["toggle","show","hide"],function(e,t){var n=v.fn[t];v.fn[t]=function(r,i,s){return r==null||typeof r=="boolean"||!e&&v.isFunction(r)&&v.isFunction(i)?n.apply(this,arguments):this.animate(Zn(t,!0),r,i,s)}}),v.fn.extend({fadeTo:function(e,t,n,r){return this.filter(Gt).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=v.isEmptyObject(e),s=v.speed(t,n,r),o=function(){var t=Kn(this,v.extend({},e),s);i&&t.stop(!0)};return i||s.queue===!1?this.each(o):this.queue(s.queue,o)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return typeof e!="string"&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,n=e!=null&&e+"queueHooks",s=v.timers,o=v._data(this);if(n)o[n]&&o[n].stop&&i(o[n]);else for(n in o)o[n]&&o[n].stop&&Wn.test(n)&&i(o[n]);for(n=s.length;n--;)s[n].elem===this&&(e==null||s[n].queue===e)&&(s[n].anim.stop(r),t=!1,s.splice(n,1));(t||!r)&&v.dequeue(this,e)})}}),v.each({slideDown:Zn("show"),slideUp:Zn("hide"),slideToggle:Zn("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){v.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),v.speed=function(e,t,n){var r=e&&typeof e=="object"?v.extend({},e):{complete:n||!n&&t||v.isFunction(e)&&e,duration:e,easing:n&&t||t&&!v.isFunction(t)&&t};r.duration=v.fx.off?0:typeof r.duration=="number"?r.duration:r.duration in v.fx.speeds?v.fx.speeds[r.duration]:v.fx.speeds._default;if(r.queue==null||r.queue===!0)r.queue="fx";return r.old=r.complete,r.complete=function(){v.isFunction(r.old)&&r.old.call(this),r.queue&&v.dequeue(this,r.queue)},r},v.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},v.timers=[],v.fx=Yn.prototype.init,v.fx.tick=function(){var e,n=v.timers,r=0;qn=v.now();for(;r<n.length;r++)e=n[r],!e()&&n[r]===e&&n.splice(r--,1);n.length||v.fx.stop(),qn=t},v.fx.timer=function(e){e()&&v.timers.push(e)&&!Rn&&(Rn=setInterval(v.fx.tick,v.fx.interval))},v.fx.interval=13,v.fx.stop=function(){clearInterval(Rn),Rn=null},v.fx.speeds={slow:600,fast:200,_default:400},v.fx.step={},v.expr&&v.expr.filters&&(v.expr.filters.animated=function(e){return v.grep(v.timers,function(t){return e===t.elem}).length});var er=/^(?:body|html)$/i;v.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){v.offset.setOffset(this,e,t)});var n,r,i,s,o,u,a,f={top:0,left:0},l=this[0],c=l&&l.ownerDocument;if(!c)return;return(r=c.body)===l?v.offset.bodyOffset(l):(n=c.documentElement,v.contains(n,l)?(typeof l.getBoundingClientRect!="undefined"&&(f=l.getBoundingClientRect()),i=tr(c),s=n.clientTop||r.clientTop||0,o=n.clientLeft||r.clientLeft||0,u=i.pageYOffset||n.scrollTop,a=i.pageXOffset||n.scrollLeft,{top:f.top+u-s,left:f.left+a-o}):f)},v.offset={bodyOffset:function(e){var t=e.offsetTop,n=e.offsetLeft;return v.support.doesNotIncludeMarginInBodyOffset&&(t+=parseFloat(v.css(e,"marginTop"))||0,n+=parseFloat(v.css(e,"marginLeft"))||0),{top:t,left:n}},setOffset:function(e,t,n){var r=v.css(e,"position");r==="static"&&(e.style.position="relative");var i=v(e),s=i.offset(),o=v.css(e,"top"),u=v.css(e,"left"),a=(r==="absolute"||r==="fixed")&&v.inArray("auto",[o,u])>-1,f={},l={},c,h;a?(l=i.position(),c=l.top,h=l.left):(c=parseFloat(o)||0,h=parseFloat(u)||0),v.isFunction(t)&&(t=t.call(e,n,s)),t.top!=null&&(f.top=t.top-s.top+c),t.left!=null&&(f.left=t.left-s.left+h),"using"in t?t.using.call(e,f):i.css(f)}},v.fn.extend({position:function(){if(!this[0])return;var e=this[0],t=this.offsetParent(),n=this.offset(),r=er.test(t[0].nodeName)?{top:0,left:0}:t.offset();return n.top-=parseFloat(v.css(e,"marginTop"))||0,n.left-=parseFloat(v.css(e,"marginLeft"))||0,r.top+=parseFloat(v.css(t[0],"borderTopWidth"))||0,r.left+=parseFloat(v.css(t[0],"borderLeftWidth"))||0,{top:n.top-r.top,left:n.left-r.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||i.body;while(e&&!er.test(e.nodeName)&&v.css(e,"position")==="static")e=e.offsetParent;return e||i.body})}}),v.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);v.fn[e]=function(i){return v.access(this,function(e,i,s){var o=tr(e);if(s===t)return o?n in o?o[n]:o.document.documentElement[i]:e[i];o?o.scrollTo(r?v(o).scrollLeft():s,r?s:v(o).scrollTop()):e[i]=s},e,i,arguments.length,null)}}),v.each({Height:"height",Width:"width"},function(e,n){v.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){v.fn[i]=function(i,s){var o=arguments.length&&(r||typeof i!="boolean"),u=r||(i===!0||s===!0?"margin":"border");return v.access(this,function(n,r,i){var s;return v.isWindow(n)?n.document.documentElement["client"+e]:n.nodeType===9?(s=n.documentElement,Math.max(n.body["scroll"+e],s["scroll"+e],n.body["offset"+e],s["offset"+e],s["client"+e])):i===t?v.css(n,r,i,u):v.style(n,r,i,u)},n,o?i:t,o,null)}})}),e.jQuery=e.$=v,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return v})})(window);
\ No newline at end of file
diff --git a/servers/admin/public/javascripts/vendors/jquery-ui-1.9.2.custom.js b/servers/admin/public/javascripts/vendors/jquery-ui-1.9.2.custom.js
deleted file mode 100755
index 8beda0f..0000000
--- a/servers/admin/public/javascripts/vendors/jquery-ui-1.9.2.custom.js
+++ /dev/null
@@ -1,14879 +0,0 @@
-/*! jQuery UI - v1.9.2 - 2013-01-03
-* http://jqueryui.com
-* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.sortable.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.menu.js, jquery.ui.progressbar.js, jquery.ui.slider.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js, jquery.ui.effect.js, jquery.ui.effect-blind.js, jquery.ui.effect-bounce.js, jquery.ui.effect-clip.js, jquery.ui.effect-drop.js, jquery.ui.effect-explode.js, jquery.ui.effect-fade.js, jquery.ui.effect-fold.js, jquery.ui.effect-highlight.js, jquery.ui.effect-pulsate.js, jquery.ui.effect-scale.js, jquery.ui.effect-shake.js, jquery.ui.effect-slide.js, jquery.ui.effect-transfer.js
-* Copyright (c) 2013 jQuery Foundation and other contributors Licensed MIT */
-
-(function( $, undefined ) {
-
-var uuid = 0,
-	runiqueId = /^ui-id-\d+$/;
-
-// prevent duplicate loading
-// this is only a problem because we proxy existing functions
-// and we don't want to double proxy them
-$.ui = $.ui || {};
-if ( $.ui.version ) {
-	return;
-}
-
-$.extend( $.ui, {
-	version: "1.9.2",
-
-	keyCode: {
-		BACKSPACE: 8,
-		COMMA: 188,
-		DELETE: 46,
-		DOWN: 40,
-		END: 35,
-		ENTER: 13,
-		ESCAPE: 27,
-		HOME: 36,
-		LEFT: 37,
-		NUMPAD_ADD: 107,
-		NUMPAD_DECIMAL: 110,
-		NUMPAD_DIVIDE: 111,
-		NUMPAD_ENTER: 108,
-		NUMPAD_MULTIPLY: 106,
-		NUMPAD_SUBTRACT: 109,
-		PAGE_DOWN: 34,
-		PAGE_UP: 33,
-		PERIOD: 190,
-		RIGHT: 39,
-		SPACE: 32,
-		TAB: 9,
-		UP: 38
-	}
-});
-
-// plugins
-$.fn.extend({
-	_focus: $.fn.focus,
-	focus: function( delay, fn ) {
-		return typeof delay === "number" ?
-			this.each(function() {
-				var elem = this;
-				setTimeout(function() {
-					$( elem ).focus();
-					if ( fn ) {
-						fn.call( elem );
-					}
-				}, delay );
-			}) :
-			this._focus.apply( this, arguments );
-	},
-
-	scrollParent: function() {
-		var scrollParent;
-		if (($.ui.ie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
-			scrollParent = this.parents().filter(function() {
-				return (/(relative|absolute|fixed)/).test($.css(this,'position')) && (/(auto|scroll)/).test($.css(this,'overflow')+$.css(this,'overflow-y')+$.css(this,'overflow-x'));
-			}).eq(0);
-		} else {
-			scrollParent = this.parents().filter(function() {
-				return (/(auto|scroll)/).test($.css(this,'overflow')+$.css(this,'overflow-y')+$.css(this,'overflow-x'));
-			}).eq(0);
-		}
-
-		return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
-	},
-
-	zIndex: function( zIndex ) {
-		if ( zIndex !== undefined ) {
-			return this.css( "zIndex", zIndex );
-		}
-
-		if ( this.length ) {
-			var elem = $( this[ 0 ] ), position, value;
-			while ( elem.length && elem[ 0 ] !== document ) {
-				// Ignore z-index if position is set to a value where z-index is ignored by the browser
-				// This makes behavior of this function consistent across browsers
-				// WebKit always returns auto if the element is positioned
-				position = elem.css( "position" );
-				if ( position === "absolute" || position === "relative" || position === "fixed" ) {
-					// IE returns 0 when zIndex is not specified
-					// other browsers return a string
-					// we ignore the case of nested elements with an explicit value of 0
-					// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
-					value = parseInt( elem.css( "zIndex" ), 10 );
-					if ( !isNaN( value ) && value !== 0 ) {
-						return value;
-					}
-				}
-				elem = elem.parent();
-			}
-		}
-
-		return 0;
-	},
-
-	uniqueId: function() {
-		return this.each(function() {
-			if ( !this.id ) {
-				this.id = "ui-id-" + (++uuid);
-			}
-		});
-	},
-
-	removeUniqueId: function() {
-		return this.each(function() {
-			if ( runiqueId.test( this.id ) ) {
-				$( this ).removeAttr( "id" );
-			}
-		});
-	}
-});
-
-// selectors
-function focusable( element, isTabIndexNotNaN ) {
-	var map, mapName, img,
-		nodeName = element.nodeName.toLowerCase();
-	if ( "area" === nodeName ) {
-		map = element.parentNode;
-		mapName = map.name;
-		if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
-			return false;
-		}
-		img = $( "img[usemap=#" + mapName + "]" )[0];
-		return !!img && visible( img );
-	}
-	return ( /input|select|textarea|button|object/.test( nodeName ) ?
-		!element.disabled :
-		"a" === nodeName ?
-			element.href || isTabIndexNotNaN :
-			isTabIndexNotNaN) &&
-		// the element and all of its ancestors must be visible
-		visible( element );
-}
-
-function visible( element ) {
-	return $.expr.filters.visible( element ) &&
-		!$( element ).parents().andSelf().filter(function() {
-			return $.css( this, "visibility" ) === "hidden";
-		}).length;
-}
-
-$.extend( $.expr[ ":" ], {
-	data: $.expr.createPseudo ?
-		$.expr.createPseudo(function( dataName ) {
-			return function( elem ) {
-				return !!$.data( elem, dataName );
-			};
-		}) :
-		// support: jQuery <1.8
-		function( elem, i, match ) {
-			return !!$.data( elem, match[ 3 ] );
-		},
-
-	focusable: function( element ) {
-		return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
-	},
-
-	tabbable: function( element ) {
-		var tabIndex = $.attr( element, "tabindex" ),
-			isTabIndexNaN = isNaN( tabIndex );
-		return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
-	}
-});
-
-// support
-$(function() {
-	var body = document.body,
-		div = body.appendChild( div = document.createElement( "div" ) );
-
-	// access offsetHeight before setting the style to prevent a layout bug
-	// in IE 9 which causes the element to continue to take up space even
-	// after it is removed from the DOM (#8026)
-	div.offsetHeight;
-
-	$.extend( div.style, {
-		minHeight: "100px",
-		height: "auto",
-		padding: 0,
-		borderWidth: 0
-	});
-
-	$.support.minHeight = div.offsetHeight === 100;
-	$.support.selectstart = "onselectstart" in div;
-
-	// set display to none to avoid a layout bug in IE
-	// http://dev.jquery.com/ticket/4014
-	body.removeChild( div ).style.display = "none";
-});
-
-// support: jQuery <1.8
-if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
-	$.each( [ "Width", "Height" ], function( i, name ) {
-		var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
-			type = name.toLowerCase(),
-			orig = {
-				innerWidth: $.fn.innerWidth,
-				innerHeight: $.fn.innerHeight,
-				outerWidth: $.fn.outerWidth,
-				outerHeight: $.fn.outerHeight
-			};
-
-		function reduce( elem, size, border, margin ) {
-			$.each( side, function() {
-				size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
-				if ( border ) {
-					size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
-				}
-				if ( margin ) {
-					size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
-				}
-			});
-			return size;
-		}
-
-		$.fn[ "inner" + name ] = function( size ) {
-			if ( size === undefined ) {
-				return orig[ "inner" + name ].call( this );
-			}
-
-			return this.each(function() {
-				$( this ).css( type, reduce( this, size ) + "px" );
-			});
-		};
-
-		$.fn[ "outer" + name] = function( size, margin ) {
-			if ( typeof size !== "number" ) {
-				return orig[ "outer" + name ].call( this, size );
-			}
-
-			return this.each(function() {
-				$( this).css( type, reduce( this, size, true, margin ) + "px" );
-			});
-		};
-	});
-}
-
-// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
-if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
-	$.fn.removeData = (function( removeData ) {
-		return function( key ) {
-			if ( arguments.length ) {
-				return removeData.call( this, $.camelCase( key ) );
-			} else {
-				return removeData.call( this );
-			}
-		};
-	})( $.fn.removeData );
-}
-
-
-
-
-
-// deprecated
-
-(function() {
-	var uaMatch = /msie ([\w.]+)/.exec( navigator.userAgent.toLowerCase() ) || [];
-	$.ui.ie = uaMatch.length ? true : false;
-	$.ui.ie6 = parseFloat( uaMatch[ 1 ], 10 ) === 6;
-})();
-
-$.fn.extend({
-	disableSelection: function() {
-		return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
-			".ui-disableSelection", function( event ) {
-				event.preventDefault();
-			});
-	},
-
-	enableSelection: function() {
-		return this.unbind( ".ui-disableSelection" );
-	}
-});
-
-$.extend( $.ui, {
-	// $.ui.plugin is deprecated.  Use the proxy pattern instead.
-	plugin: {
-		add: function( module, option, set ) {
-			var i,
-				proto = $.ui[ module ].prototype;
-			for ( i in set ) {
-				proto.plugins[ i ] = proto.plugins[ i ] || [];
-				proto.plugins[ i ].push( [ option, set[ i ] ] );
-			}
-		},
-		call: function( instance, name, args ) {
-			var i,
-				set = instance.plugins[ name ];
-			if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) {
-				return;
-			}
-
-			for ( i = 0; i < set.length; i++ ) {
-				if ( instance.options[ set[ i ][ 0 ] ] ) {
-					set[ i ][ 1 ].apply( instance.element, args );
-				}
-			}
-		}
-	},
-
-	contains: $.contains,
-
-	// only used by resizable
-	hasScroll: function( el, a ) {
-
-		//If overflow is hidden, the element might have extra content, but the user wants to hide it
-		if ( $( el ).css( "overflow" ) === "hidden") {
-			return false;
-		}
-
-		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
-			has = false;
-
-		if ( el[ scroll ] > 0 ) {
-			return true;
-		}
-
-		// TODO: determine which cases actually cause this to happen
-		// if the element doesn't have the scroll set, see if it's possible to
-		// set the scroll
-		el[ scroll ] = 1;
-		has = ( el[ scroll ] > 0 );
-		el[ scroll ] = 0;
-		return has;
-	},
-
-	// these are odd functions, fix the API or move into individual plugins
-	isOverAxis: function( x, reference, size ) {
-		//Determines when x coordinate is over "b" element axis
-		return ( x > reference ) && ( x < ( reference + size ) );
-	},
-	isOver: function( y, x, top, left, height, width ) {
-		//Determines when x, y coordinates is over "b" element
-		return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
-	}
-});
-
-})( jQuery );
-(function( $, undefined ) {
-
-var uuid = 0,
-	slice = Array.prototype.slice,
-	_cleanData = $.cleanData;
-$.cleanData = function( elems ) {
-	for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
-		try {
-			$( elem ).triggerHandler( "remove" );
-		// http://bugs.jquery.com/ticket/8235
-		} catch( e ) {}
-	}
-	_cleanData( elems );
-};
-
-$.widget = function( name, base, prototype ) {
-	var fullName, existingConstructor, constructor, basePrototype,
-		namespace = name.split( "." )[ 0 ];
-
-	name = name.split( "." )[ 1 ];
-	fullName = namespace + "-" + name;
-
-	if ( !prototype ) {
-		prototype = base;
-		base = $.Widget;
-	}
-
-	// create selector for plugin
-	$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
-		return !!$.data( elem, fullName );
-	};
-
-	$[ namespace ] = $[ namespace ] || {};
-	existingConstructor = $[ namespace ][ name ];
-	constructor = $[ namespace ][ name ] = function( options, element ) {
-		// allow instantiation without "new" keyword
-		if ( !this._createWidget ) {
-			return new constructor( options, element );
-		}
-
-		// allow instantiation without initializing for simple inheritance
-		// must use "new" keyword (the code above always passes args)
-		if ( arguments.length ) {
-			this._createWidget( options, element );
-		}
-	};
-	// extend with the existing constructor to carry over any static properties
-	$.extend( constructor, existingConstructor, {
-		version: prototype.version,
-		// copy the object used to create the prototype in case we need to
-		// redefine the widget later
-		_proto: $.extend( {}, prototype ),
-		// track widgets that inherit from this widget in case this widget is
-		// redefined after a widget inherits from it
-		_childConstructors: []
-	});
-
-	basePrototype = new base();
-	// we need to make the options hash a property directly on the new instance
-	// otherwise we'll modify the options hash on the prototype that we're
-	// inheriting from
-	basePrototype.options = $.widget.extend( {}, basePrototype.options );
-	$.each( prototype, function( prop, value ) {
-		if ( $.isFunction( value ) ) {
-			prototype[ prop ] = (function() {
-				var _super = function() {
-						return base.prototype[ prop ].apply( this, arguments );
-					},
-					_superApply = function( args ) {
-						return base.prototype[ prop ].apply( this, args );
-					};
-				return function() {
-					var __super = this._super,
-						__superApply = this._superApply,
-						returnValue;
-
-					this._super = _super;
-					this._superApply = _superApply;
-
-					returnValue = value.apply( this, arguments );
-
-					this._super = __super;
-					this._superApply = __superApply;
-
-					return returnValue;
-				};
-			})();
-		}
-	});
-	constructor.prototype = $.widget.extend( basePrototype, {
-		// TODO: remove support for widgetEventPrefix
-		// always use the name + a colon as the prefix, e.g., draggable:start
-		// don't prefix for widgets that aren't DOM-based
-		widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name
-	}, prototype, {
-		constructor: constructor,
-		namespace: namespace,
-		widgetName: name,
-		// TODO remove widgetBaseClass, see #8155
-		widgetBaseClass: fullName,
-		widgetFullName: fullName
-	});
-
-	// If this widget is being redefined then we need to find all widgets that
-	// are inheriting from it and redefine all of them so that they inherit from
-	// the new version of this widget. We're essentially trying to replace one
-	// level in the prototype chain.
-	if ( existingConstructor ) {
-		$.each( existingConstructor._childConstructors, function( i, child ) {
-			var childPrototype = child.prototype;
-
-			// redefine the child widget using the same prototype that was
-			// originally used, but inherit from the new version of the base
-			$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
-		});
-		// remove the list of existing child constructors from the old constructor
-		// so the old child constructors can be garbage collected
-		delete existingConstructor._childConstructors;
-	} else {
-		base._childConstructors.push( constructor );
-	}
-
-	$.widget.bridge( name, constructor );
-};
-
-$.widget.extend = function( target ) {
-	var input = slice.call( arguments, 1 ),
-		inputIndex = 0,
-		inputLength = input.length,
-		key,
-		value;
-	for ( ; inputIndex < inputLength; inputIndex++ ) {
-		for ( key in input[ inputIndex ] ) {
-			value = input[ inputIndex ][ key ];
-			if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
-				// Clone objects
-				if ( $.isPlainObject( value ) ) {
-					target[ key ] = $.isPlainObject( target[ key ] ) ?
-						$.widget.extend( {}, target[ key ], value ) :
-						// Don't extend strings, arrays, etc. with objects
-						$.widget.extend( {}, value );
-				// Copy everything else by reference
-				} else {
-					target[ key ] = value;
-				}
-			}
-		}
-	}
-	return target;
-};
-
-$.widget.bridge = function( name, object ) {
-	var fullName = object.prototype.widgetFullName || name;
-	$.fn[ name ] = function( options ) {
-		var isMethodCall = typeof options === "string",
-			args = slice.call( arguments, 1 ),
-			returnValue = this;
-
-		// allow multiple hashes to be passed on init
-		options = !isMethodCall && args.length ?
-			$.widget.extend.apply( null, [ options ].concat(args) ) :
-			options;
-
-		if ( isMethodCall ) {
-			this.each(function() {
-				var methodValue,
-					instance = $.data( this, fullName );
-				if ( !instance ) {
-					return $.error( "cannot call methods on " + name + " prior to initialization; " +
-						"attempted to call method '" + options + "'" );
-				}
-				if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
-					return $.error( "no such method '" + options + "' for " + name + " widget instance" );
-				}
-				methodValue = instance[ options ].apply( instance, args );
-				if ( methodValue !== instance && methodValue !== undefined ) {
-					returnValue = methodValue && methodValue.jquery ?
-						returnValue.pushStack( methodValue.get() ) :
-						methodValue;
-					return false;
-				}
-			});
-		} else {
-			this.each(function() {
-				var instance = $.data( this, fullName );
-				if ( instance ) {
-					instance.option( options || {} )._init();
-				} else {
-					$.data( this, fullName, new object( options, this ) );
-				}
-			});
-		}
-
-		return returnValue;
-	};
-};
-
-$.Widget = function( /* options, element */ ) {};
-$.Widget._childConstructors = [];
-
-$.Widget.prototype = {
-	widgetName: "widget",
-	widgetEventPrefix: "",
-	defaultElement: "<div>",
-	options: {
-		disabled: false,
-
-		// callbacks
-		create: null
-	},
-	_createWidget: function( options, element ) {
-		element = $( element || this.defaultElement || this )[ 0 ];
-		this.element = $( element );
-		this.uuid = uuid++;
-		this.eventNamespace = "." + this.widgetName + this.uuid;
-		this.options = $.widget.extend( {},
-			this.options,
-			this._getCreateOptions(),
-			options );
-
-		this.bindings = $();
-		this.hoverable = $();
-		this.focusable = $();
-
-		if ( element !== this ) {
-			// 1.9 BC for #7810
-			// TODO remove dual storage
-			$.data( element, this.widgetName, this );
-			$.data( element, this.widgetFullName, this );
-			this._on( true, this.element, {
-				remove: function( event ) {
-					if ( event.target === element ) {
-						this.destroy();
-					}
-				}
-			});
-			this.document = $( element.style ?
-				// element within the document
-				element.ownerDocument :
-				// element is window or document
-				element.document || element );
-			this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
-		}
-
-		this._create();
-		this._trigger( "create", null, this._getCreateEventData() );
-		this._init();
-	},
-	_getCreateOptions: $.noop,
-	_getCreateEventData: $.noop,
-	_create: $.noop,
-	_init: $.noop,
-
-	destroy: function() {
-		this._destroy();
-		// we can probably remove the unbind calls in 2.0
-		// all event bindings should go through this._on()
-		this.element
-			.unbind( this.eventNamespace )
-			// 1.9 BC for #7810
-			// TODO remove dual storage
-			.removeData( this.widgetName )
-			.removeData( this.widgetFullName )
-			// support: jquery <1.6.3
-			// http://bugs.jquery.com/ticket/9413
-			.removeData( $.camelCase( this.widgetFullName ) );
-		this.widget()
-			.unbind( this.eventNamespace )
-			.removeAttr( "aria-disabled" )
-			.removeClass(
-				this.widgetFullName + "-disabled " +
-				"ui-state-disabled" );
-
-		// clean up events and states
-		this.bindings.unbind( this.eventNamespace );
-		this.hoverable.removeClass( "ui-state-hover" );
-		this.focusable.removeClass( "ui-state-focus" );
-	},
-	_destroy: $.noop,
-
-	widget: function() {
-		return this.element;
-	},
-
-	option: function( key, value ) {
-		var options = key,
-			parts,
-			curOption,
-			i;
-
-		if ( arguments.length === 0 ) {
-			// don't return a reference to the internal hash
-			return $.widget.extend( {}, this.options );
-		}
-
-		if ( typeof key === "string" ) {
-			// handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
-			options = {};
-			parts = key.split( "." );
-			key = parts.shift();
-			if ( parts.length ) {
-				curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
-				for ( i = 0; i < parts.length - 1; i++ ) {
-					curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
-					curOption = curOption[ parts[ i ] ];
-				}
-				key = parts.pop();
-				if ( value === undefined ) {
-					return curOption[ key ] === undefined ? null : curOption[ key ];
-				}
-				curOption[ key ] = value;
-			} else {
-				if ( value === undefined ) {
-					return this.options[ key ] === undefined ? null : this.options[ key ];
-				}
-				options[ key ] = value;
-			}
-		}
-
-		this._setOptions( options );
-
-		return this;
-	},
-	_setOptions: function( options ) {
-		var key;
-
-		for ( key in options ) {
-			this._setOption( key, options[ key ] );
-		}
-
-		return this;
-	},
-	_setOption: function( key, value ) {
-		this.options[ key ] = value;
-
-		if ( key === "disabled" ) {
-			this.widget()
-				.toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value )
-				.attr( "aria-disabled", value );
-			this.hoverable.removeClass( "ui-state-hover" );
-			this.focusable.removeClass( "ui-state-focus" );
-		}
-
-		return this;
-	},
-
-	enable: function() {
-		return this._setOption( "disabled", false );
-	},
-	disable: function() {
-		return this._setOption( "disabled", true );
-	},
-
-	_on: function( suppressDisabledCheck, element, handlers ) {
-		var delegateElement,
-			instance = this;
-
-		// no suppressDisabledCheck flag, shuffle arguments
-		if ( typeof suppressDisabledCheck !== "boolean" ) {
-			handlers = element;
-			element = suppressDisabledCheck;
-			suppressDisabledCheck = false;
-		}
-
-		// no element argument, shuffle and use this.element
-		if ( !handlers ) {
-			handlers = element;
-			element = this.element;
-			delegateElement = this.widget();
-		} else {
-			// accept selectors, DOM elements
-			element = delegateElement = $( element );
-			this.bindings = this.bindings.add( element );
-		}
-
-		$.each( handlers, function( event, handler ) {
-			function handlerProxy() {
-				// allow widgets to customize the disabled handling
-				// - disabled as an array instead of boolean
-				// - disabled class as method for disabling individual parts
-				if ( !suppressDisabledCheck &&
-						( instance.options.disabled === true ||
-							$( this ).hasClass( "ui-state-disabled" ) ) ) {
-					return;
-				}
-				return ( typeof handler === "string" ? instance[ handler ] : handler )
-					.apply( instance, arguments );
-			}
-
-			// copy the guid so direct unbinding works
-			if ( typeof handler !== "string" ) {
-				handlerProxy.guid = handler.guid =
-					handler.guid || handlerProxy.guid || $.guid++;
-			}
-
-			var match = event.match( /^(\w+)\s*(.*)$/ ),
-				eventName = match[1] + instance.eventNamespace,
-				selector = match[2];
-			if ( selector ) {
-				delegateElement.delegate( selector, eventName, handlerProxy );
-			} else {
-				element.bind( eventName, handlerProxy );
-			}
-		});
-	},
-
-	_off: function( element, eventName ) {
-		eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;
-		element.unbind( eventName ).undelegate( eventName );
-	},
-
-	_delay: function( handler, delay ) {
-		function handlerProxy() {
-			return ( typeof handler === "string" ? instance[ handler ] : handler )
-				.apply( instance, arguments );
-		}
-		var instance = this;
-		return setTimeout( handlerProxy, delay || 0 );
-	},
-
-	_hoverable: function( element ) {
-		this.hoverable = this.hoverable.add( element );
-		this._on( element, {
-			mouseenter: function( event ) {
-				$( event.currentTarget ).addClass( "ui-state-hover" );
-			},
-			mouseleave: function( event ) {
-				$( event.currentTarget ).removeClass( "ui-state-hover" );
-			}
-		});
-	},
-
-	_focusable: function( element ) {
-		this.focusable = this.focusable.add( element );
-		this._on( element, {
-			focusin: function( event ) {
-				$( event.currentTarget ).addClass( "ui-state-focus" );
-			},
-			focusout: function( event ) {
-				$( event.currentTarget ).removeClass( "ui-state-focus" );
-			}
-		});
-	},
-
-	_trigger: function( type, event, data ) {
-		var prop, orig,
-			callback = this.options[ type ];
-
-		data = data || {};
-		event = $.Event( event );
-		event.type = ( type === this.widgetEventPrefix ?
-			type :
-			this.widgetEventPrefix + type ).toLowerCase();
-		// the original event may come from any element
-		// so we need to reset the target on the new event
-		event.target = this.element[ 0 ];
-
-		// copy original event properties over to the new event
-		orig = event.originalEvent;
-		if ( orig ) {
-			for ( prop in orig ) {
-				if ( !( prop in event ) ) {
-					event[ prop ] = orig[ prop ];
-				}
-			}
-		}
-
-		this.element.trigger( event, data );
-		return !( $.isFunction( callback ) &&
-			callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
-			event.isDefaultPrevented() );
-	}
-};
-
-$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
-	$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
-		if ( typeof options === "string" ) {
-			options = { effect: options };
-		}
-		var hasOptions,
-			effectName = !options ?
-				method :
-				options === true || typeof options === "number" ?
-					defaultEffect :
-					options.effect || defaultEffect;
-		options = options || {};
-		if ( typeof options === "number" ) {
-			options = { duration: options };
-		}
-		hasOptions = !$.isEmptyObject( options );
-		options.complete = callback;
-		if ( options.delay ) {
-			element.delay( options.delay );
-		}
-		if ( hasOptions && $.effects && ( $.effects.effect[ effectName ] || $.uiBackCompat !== false && $.effects[ effectName ] ) ) {
-			element[ method ]( options );
-		} else if ( effectName !== method && element[ effectName ] ) {
-			element[ effectName ]( options.duration, options.easing, callback );
-		} else {
-			element.queue(function( next ) {
-				$( this )[ method ]();
-				if ( callback ) {
-					callback.call( element[ 0 ] );
-				}
-				next();
-			});
-		}
-	};
-});
-
-// DEPRECATED
-if ( $.uiBackCompat !== false ) {
-	$.Widget.prototype._getCreateOptions = function() {
-		return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
-	};
-}
-
-})( jQuery );
-(function( $, undefined ) {
-
-var mouseHandled = false;
-$( document ).mouseup( function( e ) {
-	mouseHandled = false;
-});
-
-$.widget("ui.mouse", {
-	version: "1.9.2",
-	options: {
-		cancel: 'input,textarea,button,select,option',
-		distance: 1,
-		delay: 0
-	},
-	_mouseInit: function() {
-		var that = this;
-
-		this.element
-			.bind('mousedown.'+this.widgetName, function(event) {
-				return that._mouseDown(event);
-			})
-			.bind('click.'+this.widgetName, function(event) {
-				if (true === $.data(event.target, that.widgetName + '.preventClickEvent')) {
-					$.removeData(event.target, that.widgetName + '.preventClickEvent');
-					event.stopImmediatePropagation();
-					return false;
-				}
-			});
-
-		this.started = false;
-	},
-
-	// TODO: make sure destroying one instance of mouse doesn't mess with
-	// other instances of mouse
-	_mouseDestroy: function() {
-		this.element.unbind('.'+this.widgetName);
-		if ( this._mouseMoveDelegate ) {
-			$(document)
-				.unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
-				.unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
-		}
-	},
-
-	_mouseDown: function(event) {
-		// don't let more than one widget handle mouseStart
-		if( mouseHandled ) { return; }
-
-		// we may have missed mouseup (out of window)
-		(this._mouseStarted && this._mouseUp(event));
-
-		this._mouseDownEvent = event;
-
-		var that = this,
-			btnIsLeft = (event.which === 1),
-			// event.target.nodeName works around a bug in IE 8 with
-			// disabled inputs (#7620)
-			elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
-		if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
-			return true;
-		}
-
-		this.mouseDelayMet = !this.options.delay;
-		if (!this.mouseDelayMet) {
-			this._mouseDelayTimer = setTimeout(function() {
-				that.mouseDelayMet = true;
-			}, this.options.delay);
-		}
-
-		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
-			this._mouseStarted = (this._mouseStart(event) !== false);
-			if (!this._mouseStarted) {
-				event.preventDefault();
-				return true;
-			}
-		}
-
-		// Click event may never have fired (Gecko & Opera)
-		if (true === $.data(event.target, this.widgetName + '.preventClickEvent')) {
-			$.removeData(event.target, this.widgetName + '.preventClickEvent');
-		}
-
-		// these delegates are required to keep context
-		this._mouseMoveDelegate = function(event) {
-			return that._mouseMove(event);
-		};
-		this._mouseUpDelegate = function(event) {
-			return that._mouseUp(event);
-		};
-		$(document)
-			.bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
-			.bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
-
-		event.preventDefault();
-
-		mouseHandled = true;
-		return true;
-	},
-
-	_mouseMove: function(event) {
-		// IE mouseup check - mouseup happened when mouse was out of window
-		if ($.ui.ie && !(document.documentMode >= 9) && !event.button) {
-			return this._mouseUp(event);
-		}
-
-		if (this._mouseStarted) {
-			this._mouseDrag(event);
-			return event.preventDefault();
-		}
-
-		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
-			this._mouseStarted =
-				(this._mouseStart(this._mouseDownEvent, event) !== false);
-			(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
-		}
-
-		return !this._mouseStarted;
-	},
-
-	_mouseUp: function(event) {
-		$(document)
-			.unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
-			.unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
-
-		if (this._mouseStarted) {
-			this._mouseStarted = false;
-
-			if (event.target === this._mouseDownEvent.target) {
-				$.data(event.target, this.widgetName + '.preventClickEvent', true);
-			}
-
-			this._mouseStop(event);
-		}
-
-		return false;
-	},
-
-	_mouseDistanceMet: function(event) {
-		return (Math.max(
-				Math.abs(this._mouseDownEvent.pageX - event.pageX),
-				Math.abs(this._mouseDownEvent.pageY - event.pageY)
-			) >= this.options.distance
-		);
-	},
-
-	_mouseDelayMet: function(event) {
-		return this.mouseDelayMet;
-	},
-
-	// These are placeholder methods, to be overriden by extending plugin
-	_mouseStart: function(event) {},
-	_mouseDrag: function(event) {},
-	_mouseStop: function(event) {},
-	_mouseCapture: function(event) { return true; }
-});
-
-})(jQuery);
-(function( $, undefined ) {
-
-$.ui = $.ui || {};
-
-var cachedScrollbarWidth,
-	max = Math.max,
-	abs = Math.abs,
-	round = Math.round,
-	rhorizontal = /left|center|right/,
-	rvertical = /top|center|bottom/,
-	roffset = /[\+\-]\d+%?/,
-	rposition = /^\w+/,
-	rpercent = /%$/,
-	_position = $.fn.position;
-
-function getOffsets( offsets, width, height ) {
-	return [
-		parseInt( offsets[ 0 ], 10 ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
-		parseInt( offsets[ 1 ], 10 ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
-	];
-}
-function parseCss( element, property ) {
-	return parseInt( $.css( element, property ), 10 ) || 0;
-}
-
-$.position = {
-	scrollbarWidth: function() {
-		if ( cachedScrollbarWidth !== undefined ) {
-			return cachedScrollbarWidth;
-		}
-		var w1, w2,
-			div = $( "<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ),
-			innerDiv = div.children()[0];
-
-		$( "body" ).append( div );
-		w1 = innerDiv.offsetWidth;
-		div.css( "overflow", "scroll" );
-
-		w2 = innerDiv.offsetWidth;
-
-		if ( w1 === w2 ) {
-			w2 = div[0].clientWidth;
-		}
-
-		div.remove();
-
-		return (cachedScrollbarWidth = w1 - w2);
-	},
-	getScrollInfo: function( within ) {
-		var overflowX = within.isWindow ? "" : within.element.css( "overflow-x" ),
-			overflowY = within.isWindow ? "" : within.element.css( "overflow-y" ),
-			hasOverflowX = overflowX === "scroll" ||
-				( overflowX === "auto" && within.width < within.element[0].scrollWidth ),
-			hasOverflowY = overflowY === "scroll" ||
-				( overflowY === "auto" && within.height < within.element[0].scrollHeight );
-		return {
-			width: hasOverflowX ? $.position.scrollbarWidth() : 0,
-			height: hasOverflowY ? $.position.scrollbarWidth() : 0
-		};
-	},
-	getWithinInfo: function( element ) {
-		var withinElement = $( element || window ),
-			isWindow = $.isWindow( withinElement[0] );
-		return {
-			element: withinElement,
-			isWindow: isWindow,
-			offset: withinElement.offset() || { left: 0, top: 0 },
-			scrollLeft: withinElement.scrollLeft(),
-			scrollTop: withinElement.scrollTop(),
-			width: isWindow ? withinElement.width() : withinElement.outerWidth(),
-			height: isWindow ? withinElement.height() : withinElement.outerHeight()
-		};
-	}
-};
-
-$.fn.position = function( options ) {
-	if ( !options || !options.of ) {
-		return _position.apply( this, arguments );
-	}
-
-	// make a copy, we don't want to modify arguments
-	options = $.extend( {}, options );
-
-	var atOffset, targetWidth, targetHeight, targetOffset, basePosition,
-		target = $( options.of ),
-		within = $.position.getWithinInfo( options.within ),
-		scrollInfo = $.position.getScrollInfo( within ),
-		targetElem = target[0],
-		collision = ( options.collision || "flip" ).split( " " ),
-		offsets = {};
-
-	if ( targetElem.nodeType === 9 ) {
-		targetWidth = target.width();
-		targetHeight = target.height();
-		targetOffset = { top: 0, left: 0 };
-	} else if ( $.isWindow( targetElem ) ) {
-		targetWidth = target.width();
-		targetHeight = target.height();
-		targetOffset = { top: target.scrollTop(), left: target.scrollLeft() };
-	} else if ( targetElem.preventDefault ) {
-		// force left top to allow flipping
-		options.at = "left top";
-		targetWidth = targetHeight = 0;
-		targetOffset = { top: targetElem.pageY, left: targetElem.pageX };
-	} else {
-		targetWidth = target.outerWidth();
-		targetHeight = target.outerHeight();
-		targetOffset = target.offset();
-	}
-	// clone to reuse original targetOffset later
-	basePosition = $.extend( {}, targetOffset );
-
-	// force my and at to have valid horizontal and vertical positions
-	// if a value is missing or invalid, it will be converted to center
-	$.each( [ "my", "at" ], function() {
-		var pos = ( options[ this ] || "" ).split( " " ),
-			horizontalOffset,
-			verticalOffset;
-
-		if ( pos.length === 1) {
-			pos = rhorizontal.test( pos[ 0 ] ) ?
-				pos.concat( [ "center" ] ) :
-				rvertical.test( pos[ 0 ] ) ?
-					[ "center" ].concat( pos ) :
-					[ "center", "center" ];
-		}
-		pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
-		pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
-
-		// calculate offsets
-		horizontalOffset = roffset.exec( pos[ 0 ] );
-		verticalOffset = roffset.exec( pos[ 1 ] );
-		offsets[ this ] = [
-			horizontalOffset ? horizontalOffset[ 0 ] : 0,
-			verticalOffset ? verticalOffset[ 0 ] : 0
-		];
-
-		// reduce to just the positions without the offsets
-		options[ this ] = [
-			rposition.exec( pos[ 0 ] )[ 0 ],
-			rposition.exec( pos[ 1 ] )[ 0 ]
-		];
-	});
-
-	// normalize collision option
-	if ( collision.length === 1 ) {
-		collision[ 1 ] = collision[ 0 ];
-	}
-
-	if ( options.at[ 0 ] === "right" ) {
-		basePosition.left += targetWidth;
-	} else if ( options.at[ 0 ] === "center" ) {
-		basePosition.left += targetWidth / 2;
-	}
-
-	if ( options.at[ 1 ] === "bottom" ) {
-		basePosition.top += targetHeight;
-	} else if ( options.at[ 1 ] === "center" ) {
-		basePosition.top += targetHeight / 2;
-	}
-
-	atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
-	basePosition.left += atOffset[ 0 ];
-	basePosition.top += atOffset[ 1 ];
-
-	return this.each(function() {
-		var collisionPosition, using,
-			elem = $( this ),
-			elemWidth = elem.outerWidth(),
-			elemHeight = elem.outerHeight(),
-			marginLeft = parseCss( this, "marginLeft" ),
-			marginTop = parseCss( this, "marginTop" ),
-			collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width,
-			collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height,
-			position = $.extend( {}, basePosition ),
-			myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
-
-		if ( options.my[ 0 ] === "right" ) {
-			position.left -= elemWidth;
-		} else if ( options.my[ 0 ] === "center" ) {
-			position.left -= elemWidth / 2;
-		}
-
-		if ( options.my[ 1 ] === "bottom" ) {
-			position.top -= elemHeight;
-		} else if ( options.my[ 1 ] === "center" ) {
-			position.top -= elemHeight / 2;
-		}
-
-		position.left += myOffset[ 0 ];
-		position.top += myOffset[ 1 ];
-
-		// if the browser doesn't support fractions, then round for consistent results
-		if ( !$.support.offsetFractions ) {
-			position.left = round( position.left );
-			position.top = round( position.top );
-		}
-
-		collisionPosition = {
-			marginLeft: marginLeft,
-			marginTop: marginTop
-		};
-
-		$.each( [ "left", "top" ], function( i, dir ) {
-			if ( $.ui.position[ collision[ i ] ] ) {
-				$.ui.position[ collision[ i ] ][ dir ]( position, {
-					targetWidth: targetWidth,
-					targetHeight: targetHeight,
-					elemWidth: elemWidth,
-					elemHeight: elemHeight,
-					collisionPosition: collisionPosition,
-					collisionWidth: collisionWidth,
-					collisionHeight: collisionHeight,
-					offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
-					my: options.my,
-					at: options.at,
-					within: within,
-					elem : elem
-				});
-			}
-		});
-
-		if ( $.fn.bgiframe ) {
-			elem.bgiframe();
-		}
-
-		if ( options.using ) {
-			// adds feedback as second argument to using callback, if present
-			using = function( props ) {
-				var left = targetOffset.left - position.left,
-					right = left + targetWidth - elemWidth,
-					top = targetOffset.top - position.top,
-					bottom = top + targetHeight - elemHeight,
-					feedback = {
-						target: {
-							element: target,
-							left: targetOffset.left,
-							top: targetOffset.top,
-							width: targetWidth,
-							height: targetHeight
-						},
-						element: {
-							element: elem,
-							left: position.left,
-							top: position.top,
-							width: elemWidth,
-							height: elemHeight
-						},
-						horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
-						vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
-					};
-				if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
-					feedback.horizontal = "center";
-				}
-				if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
-					feedback.vertical = "middle";
-				}
-				if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
-					feedback.important = "horizontal";
-				} else {
-					feedback.important = "vertical";
-				}
-				options.using.call( this, props, feedback );
-			};
-		}
-
-		elem.offset( $.extend( position, { using: using } ) );
-	});
-};
-
-$.ui.position = {
-	fit: {
-		left: function( position, data ) {
-			var within = data.within,
-				withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
-				outerWidth = within.width,
-				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
-				overLeft = withinOffset - collisionPosLeft,
-				overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
-				newOverRight;
-
-			// element is wider than within
-			if ( data.collisionWidth > outerWidth ) {
-				// element is initially over the left side of within
-				if ( overLeft > 0 && overRight <= 0 ) {
-					newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
-					position.left += overLeft - newOverRight;
-				// element is initially over right side of within
-				} else if ( overRight > 0 && overLeft <= 0 ) {
-					position.left = withinOffset;
-				// element is initially over both left and right sides of within
-				} else {
-					if ( overLeft > overRight ) {
-						position.left = withinOffset + outerWidth - data.collisionWidth;
-					} else {
-						position.left = withinOffset;
-					}
-				}
-			// too far left -> align with left edge
-			} else if ( overLeft > 0 ) {
-				position.left += overLeft;
-			// too far right -> align with right edge
-			} else if ( overRight > 0 ) {
-				position.left -= overRight;
-			// adjust based on position and margin
-			} else {
-				position.left = max( position.left - collisionPosLeft, position.left );
-			}
-		},
-		top: function( position, data ) {
-			var within = data.within,
-				withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
-				outerHeight = data.within.height,
-				collisionPosTop = position.top - data.collisionPosition.marginTop,
-				overTop = withinOffset - collisionPosTop,
-				overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
-				newOverBottom;
-
-			// element is taller than within
-			if ( data.collisionHeight > outerHeight ) {
-				// element is initially over the top of within
-				if ( overTop > 0 && overBottom <= 0 ) {
-					newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
-					position.top += overTop - newOverBottom;
-				// element is initially over bottom of within
-				} else if ( overBottom > 0 && overTop <= 0 ) {
-					position.top = withinOffset;
-				// element is initially over both top and bottom of within
-				} else {
-					if ( overTop > overBottom ) {
-						position.top = withinOffset + outerHeight - data.collisionHeight;
-					} else {
-						position.top = withinOffset;
-					}
-				}
-			// too far up -> align with top
-			} else if ( overTop > 0 ) {
-				position.top += overTop;
-			// too far down -> align with bottom edge
-			} else if ( overBottom > 0 ) {
-				position.top -= overBottom;
-			// adjust based on position and margin
-			} else {
-				position.top = max( position.top - collisionPosTop, position.top );
-			}
-		}
-	},
-	flip: {
-		left: function( position, data ) {
-			var within = data.within,
-				withinOffset = within.offset.left + within.scrollLeft,
-				outerWidth = within.width,
-				offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
-				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
-				overLeft = collisionPosLeft - offsetLeft,
-				overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
-				myOffset = data.my[ 0 ] === "left" ?
-					-data.elemWidth :
-					data.my[ 0 ] === "right" ?
-						data.elemWidth :
-						0,
-				atOffset = data.at[ 0 ] === "left" ?
-					data.targetWidth :
-					data.at[ 0 ] === "right" ?
-						-data.targetWidth :
-						0,
-				offset = -2 * data.offset[ 0 ],
-				newOverRight,
-				newOverLeft;
-
-			if ( overLeft < 0 ) {
-				newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
-				if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
-					position.left += myOffset + atOffset + offset;
-				}
-			}
-			else if ( overRight > 0 ) {
-				newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;
-				if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
-					position.left += myOffset + atOffset + offset;
-				}
-			}
-		},
-		top: function( position, data ) {
-			var within = data.within,
-				withinOffset = within.offset.top + within.scrollTop,
-				outerHeight = within.height,
-				offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
-				collisionPosTop = position.top - data.collisionPosition.marginTop,
-				overTop = collisionPosTop - offsetTop,
-				overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
-				top = data.my[ 1 ] === "top",
-				myOffset = top ?
-					-data.elemHeight :
-					data.my[ 1 ] === "bottom" ?
-						data.elemHeight :
-						0,
-				atOffset = data.at[ 1 ] === "top" ?
-					data.targetHeight :
-					data.at[ 1 ] === "bottom" ?
-						-data.targetHeight :
-						0,
-				offset = -2 * data.offset[ 1 ],
-				newOverTop,
-				newOverBottom;
-			if ( overTop < 0 ) {
-				newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
-				if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) {
-					position.top += myOffset + atOffset + offset;
-				}
-			}
-			else if ( overBottom > 0 ) {
-				newOverTop = position.top -  data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;
-				if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) {
-					position.top += myOffset + atOffset + offset;
-				}
-			}
-		}
-	},
-	flipfit: {
-		left: function() {
-			$.ui.position.flip.left.apply( this, arguments );
-			$.ui.position.fit.left.apply( this, arguments );
-		},
-		top: function() {
-			$.ui.position.flip.top.apply( this, arguments );
-			$.ui.position.fit.top.apply( this, arguments );
-		}
-	}
-};
-
-// fraction support test
-(function () {
-	var testElement, testElementParent, testElementStyle, offsetLeft, i,
-		body = document.getElementsByTagName( "body" )[ 0 ],
-		div = document.createElement( "div" );
-
-	//Create a "fake body" for testing based on method used in jQuery.support
-	testElement = document.createElement( body ? "div" : "body" );
-	testElementStyle = {
-		visibility: "hidden",
-		width: 0,
-		height: 0,
-		border: 0,
-		margin: 0,
-		background: "none"
-	};
-	if ( body ) {
-		$.extend( testElementStyle, {
-			position: "absolute",
-			left: "-1000px",
-			top: "-1000px"
-		});
-	}
-	for ( i in testElementStyle ) {
-		testElement.style[ i ] = testElementStyle[ i ];
-	}
-	testElement.appendChild( div );
-	testElementParent = body || document.documentElement;
-	testElementParent.insertBefore( testElement, testElementParent.firstChild );
-
-	div.style.cssText = "position: absolute; left: 10.7432222px;";
-
-	offsetLeft = $( div ).offset().left;
-	$.support.offsetFractions = offsetLeft > 10 && offsetLeft < 11;
-
-	testElement.innerHTML = "";
-	testElementParent.removeChild( testElement );
-})();
-
-// DEPRECATED
-if ( $.uiBackCompat !== false ) {
-	// offset option
-	(function( $ ) {
-		var _position = $.fn.position;
-		$.fn.position = function( options ) {
-			if ( !options || !options.offset ) {
-				return _position.call( this, options );
-			}
-			var offset = options.offset.split( " " ),
-				at = options.at.split( " " );
-			if ( offset.length === 1 ) {
-				offset[ 1 ] = offset[ 0 ];
-			}
-			if ( /^\d/.test( offset[ 0 ] ) ) {
-				offset[ 0 ] = "+" + offset[ 0 ];
-			}
-			if ( /^\d/.test( offset[ 1 ] ) ) {
-				offset[ 1 ] = "+" + offset[ 1 ];
-			}
-			if ( at.length === 1 ) {
-				if ( /left|center|right/.test( at[ 0 ] ) ) {
-					at[ 1 ] = "center";
-				} else {
-					at[ 1 ] = at[ 0 ];
-					at[ 0 ] = "center";
-				}
-			}
-			return _position.call( this, $.extend( options, {
-				at: at[ 0 ] + offset[ 0 ] + " " + at[ 1 ] + offset[ 1 ],
-				offset: undefined
-			} ) );
-		};
-	}( jQuery ) );
-}
-
-}( jQuery ) );
-(function( $, undefined ) {
-
-$.widget("ui.draggable", $.ui.mouse, {
-	version: "1.9.2",
-	widgetEventPrefix: "drag",
-	options: {
-		addClasses: true,
-		appendTo: "parent",
-		axis: false,
-		connectToSortable: false,
-		containment: false,
-		cursor: "auto",
-		cursorAt: false,
-		grid: false,
-		handle: false,
-		helper: "original",
-		iframeFix: false,
-		opacity: false,
-		refreshPositions: false,
-		revert: false,
-		revertDuration: 500,
-		scope: "default",
-		scroll: true,
-		scrollSensitivity: 20,
-		scrollSpeed: 20,
-		snap: false,
-		snapMode: "both",
-		snapTolerance: 20,
-		stack: false,
-		zIndex: false
-	},
-	_create: function() {
-
-		if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
-			this.element[0].style.position = 'relative';
-
-		(this.options.addClasses && this.element.addClass("ui-draggable"));
-		(this.options.disabled && this.element.addClass("ui-draggable-disabled"));
-
-		this._mouseInit();
-
-	},
-
-	_destroy: function() {
-		this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" );
-		this._mouseDestroy();
-	},
-
-	_mouseCapture: function(event) {
-
-		var o = this.options;
-
-		// among others, prevent a drag on a resizable-handle
-		if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
-			return false;
-
-		//Quit if we're not on a valid handle
-		this.handle = this._getHandle(event);
-		if (!this.handle)
-			return false;
-
-		$(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
-			$('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
-			.css({
-				width: this.offsetWidth+"px", height: this.offsetHeight+"px",
-				position: "absolute", opacity: "0.001", zIndex: 1000
-			})
-			.css($(this).offset())
-			.appendTo("body");
-		});
-
-		return true;
-
-	},
-
-	_mouseStart: function(event) {
-
-		var o = this.options;
-
-		//Create and append the visible helper
-		this.helper = this._createHelper(event);
-
-		this.helper.addClass("ui-draggable-dragging");
-
-		//Cache the helper size
-		this._cacheHelperProportions();
-
-		//If ddmanager is used for droppables, set the global draggable
-		if($.ui.ddmanager)
-			$.ui.ddmanager.current = this;
-
-		/*
-		 * - Position generation -
-		 * This block generates everything position related - it's the core of draggables.
-		 */
-
-		//Cache the margins of the original element
-		this._cacheMargins();
-
-		//Store the helper's css position
-		this.cssPosition = this.helper.css("position");
-		this.scrollParent = this.helper.scrollParent();
-
-		//The element's absolute position on the page minus margins
-		this.offset = this.positionAbs = this.element.offset();
-		this.offset = {
-			top: this.offset.top - this.margins.top,
-			left: this.offset.left - this.margins.left
-		};
-
-		$.extend(this.offset, {
-			click: { //Where the click happened, relative to the element
-				left: event.pageX - this.offset.left,
-				top: event.pageY - this.offset.top
-			},
-			parent: this._getParentOffset(),
-			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
-		});
-
-		//Generate the original position
-		this.originalPosition = this.position = this._generatePosition(event);
-		this.originalPageX = event.pageX;
-		this.originalPageY = event.pageY;
-
-		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
-		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
-
-		//Set a containment if given in the options
-		if(o.containment)
-			this._setContainment();
-
-		//Trigger event + callbacks
-		if(this._trigger("start", event) === false) {
-			this._clear();
-			return false;
-		}
-
-		//Recache the helper size
-		this._cacheHelperProportions();
-
-		//Prepare the droppable offsets
-		if ($.ui.ddmanager && !o.dropBehaviour)
-			$.ui.ddmanager.prepareOffsets(this, event);
-
-
-		this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
-
-		//If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
-		if ( $.ui.ddmanager ) $.ui.ddmanager.dragStart(this, event);
-
-		return true;
-	},
-
-	_mouseDrag: function(event, noPropagation) {
-
-		//Compute the helpers position
-		this.position = this._generatePosition(event);
-		this.positionAbs = this._convertPositionTo("absolute");
-
-		//Call plugins and callbacks and use the resulting position if something is returned
-		if (!noPropagation) {
-			var ui = this._uiHash();
-			if(this._trigger('drag', event, ui) === false) {
-				this._mouseUp({});
-				return false;
-			}
-			this.position = ui.position;
-		}
-
-		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
-		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
-		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
-
-		return false;
-	},
-
-	_mouseStop: function(event) {
-
-		//If we are using droppables, inform the manager about the drop
-		var dropped = false;
-		if ($.ui.ddmanager && !this.options.dropBehaviour)
-			dropped = $.ui.ddmanager.drop(this, event);
-
-		//if a drop comes from outside (a sortable)
-		if(this.dropped) {
-			dropped = this.dropped;
-			this.dropped = false;
-		}
-
-		//if the original element is no longer in the DOM don't bother to continue (see #8269)
-		var element = this.element[0], elementInDom = false;
-		while ( element && (element = element.parentNode) ) {
-			if (element == document ) {
-				elementInDom = true;
-			}
-		}
-		if ( !elementInDom && this.options.helper === "original" )
-			return false;
-
-		if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
-			var that = this;
-			$(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
-				if(that._trigger("stop", event) !== false) {
-					that._clear();
-				}
-			});
-		} else {
-			if(this._trigger("stop", event) !== false) {
-				this._clear();
-			}
-		}
-
-		return false;
-	},
-
-	_mouseUp: function(event) {
-		//Remove frame helpers
-		$("div.ui-draggable-iframeFix").each(function() {
-			this.parentNode.removeChild(this);
-		});
-
-		//If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
-		if( $.ui.ddmanager ) $.ui.ddmanager.dragStop(this, event);
-
-		return $.ui.mouse.prototype._mouseUp.call(this, event);
-	},
-
-	cancel: function() {
-
-		if(this.helper.is(".ui-draggable-dragging")) {
-			this._mouseUp({});
-		} else {
-			this._clear();
-		}
-
-		return this;
-
-	},
-
-	_getHandle: function(event) {
-
-		var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
-		$(this.options.handle, this.element)
-			.find("*")
-			.andSelf()
-			.each(function() {
-				if(this == event.target) handle = true;
-			});
-
-		return handle;
-
-	},
-
-	_createHelper: function(event) {
-
-		var o = this.options;
-		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone().removeAttr('id') : this.element);
-
-		if(!helper.parents('body').length)
-			helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
-
-		if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
-			helper.css("position", "absolute");
-
-		return helper;
-
-	},
-
-	_adjustOffsetFromHelper: function(obj) {
-		if (typeof obj == 'string') {
-			obj = obj.split(' ');
-		}
-		if ($.isArray(obj)) {
-			obj = {left: +obj[0], top: +obj[1] || 0};
-		}
-		if ('left' in obj) {
-			this.offset.click.left = obj.left + this.margins.left;
-		}
-		if ('right' in obj) {
-			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
-		}
-		if ('top' in obj) {
-			this.offset.click.top = obj.top + this.margins.top;
-		}
-		if ('bottom' in obj) {
-			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
-		}
-	},
-
-	_getParentOffset: function() {
-
-		//Get the offsetParent and cache its position
-		this.offsetParent = this.helper.offsetParent();
-		var po = this.offsetParent.offset();
-
-		// This is a special case where we need to modify a offset calculated on start, since the following happened:
-		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
-		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
-		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
-		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
-			po.left += this.scrollParent.scrollLeft();
-			po.top += this.scrollParent.scrollTop();
-		}
-
-		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
-		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.ui.ie)) //Ugly IE fix
-			po = { top: 0, left: 0 };
-
-		return {
-			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
-			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
-		};
-
-	},
-
-	_getRelativeOffset: function() {
-
-		if(this.cssPosition == "relative") {
-			var p = this.element.position();
-			return {
-				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
-				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
-			};
-		} else {
-			return { top: 0, left: 0 };
-		}
-
-	},
-
-	_cacheMargins: function() {
-		this.margins = {
-			left: (parseInt(this.element.css("marginLeft"),10) || 0),
-			top: (parseInt(this.element.css("marginTop"),10) || 0),
-			right: (parseInt(this.element.css("marginRight"),10) || 0),
-			bottom: (parseInt(this.element.css("marginBottom"),10) || 0)
-		};
-	},
-
-	_cacheHelperProportions: function() {
-		this.helperProportions = {
-			width: this.helper.outerWidth(),
-			height: this.helper.outerHeight()
-		};
-	},
-
-	_setContainment: function() {
-
-		var o = this.options;
-		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
-		if(o.containment == 'document' || o.containment == 'window') this.containment = [
-			o.containment == 'document' ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
-			o.containment == 'document' ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top,
-			(o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
-			(o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
-		];
-
-		if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
-			var c = $(o.containment);
-			var ce = c[0]; if(!ce) return;
-			var co = c.offset();
-			var over = ($(ce).css("overflow") != 'hidden');
-
-			this.containment = [
-				(parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0),
-				(parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0),
-				(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left - this.margins.right,
-				(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top  - this.margins.bottom
-			];
-			this.relative_container = c;
-
-		} else if(o.containment.constructor == Array) {
-			this.containment = o.containment;
-		}
-
-	},
-
-	_convertPositionTo: function(d, pos) {
-
-		if(!pos) pos = this.position;
-		var mod = d == "absolute" ? 1 : -1;
-		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
-
-		return {
-			top: (
-				pos.top																	// The absolute mouse position
-				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
-				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
-				- ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
-			),
-			left: (
-				pos.left																// The absolute mouse position
-				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
-				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
-				- ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
-			)
-		};
-
-	},
-
-	_generatePosition: function(event) {
-
-		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
-		var pageX = event.pageX;
-		var pageY = event.pageY;
-
-		/*
-		 * - Position constraining -
-		 * Constrain the position to a mix of grid, containment.
-		 */
-
-		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
-			var containment;
-			if(this.containment) {
-			if (this.relative_container){
-				var co = this.relative_container.offset();
-				containment = [ this.containment[0] + co.left,
-					this.containment[1] + co.top,
-					this.containment[2] + co.left,
-					this.containment[3] + co.top ];
-			}
-			else {
-				containment = this.containment;
-			}
-
-				if(event.pageX - this.offset.click.left < containment[0]) pageX = containment[0] + this.offset.click.left;
-				if(event.pageY - this.offset.click.top < containment[1]) pageY = containment[1] + this.offset.click.top;
-				if(event.pageX - this.offset.click.left > containment[2]) pageX = containment[2] + this.offset.click.left;
-				if(event.pageY - this.offset.click.top > containment[3]) pageY = containment[3] + this.offset.click.top;
-			}
-
-			if(o.grid) {
-				//Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
-				var top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
-				pageY = containment ? (!(top - this.offset.click.top < containment[1] || top - this.offset.click.top > containment[3]) ? top : (!(top - this.offset.click.top < containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
-
-				var left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
-				pageX = containment ? (!(left - this.offset.click.left < containment[0] || left - this.offset.click.left > containment[2]) ? left : (!(left - this.offset.click.left < containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
-			}
-
-		}
-
-		return {
-			top: (
-				pageY																// The absolute mouse position
-				- this.offset.click.top													// Click offset (relative to the element)
-				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
-				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
-				+ ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
-			),
-			left: (
-				pageX																// The absolute mouse position
-				- this.offset.click.left												// Click offset (relative to the element)
-				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
-				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
-				+ ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
-			)
-		};
-
-	},
-
-	_clear: function() {
-		this.helper.removeClass("ui-draggable-dragging");
-		if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
-		//if($.ui.ddmanager) $.ui.ddmanager.current = null;
-		this.helper = null;
-		this.cancelHelperRemoval = false;
-	},
-
-	// From now on bulk stuff - mainly helpers
-
-	_trigger: function(type, event, ui) {
-		ui = ui || this._uiHash();
-		$.ui.plugin.call(this, type, [event, ui]);
-		if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
-		return $.Widget.prototype._trigger.call(this, type, event, ui);
-	},
-
-	plugins: {},
-
-	_uiHash: function(event) {
-		return {
-			helper: this.helper,
-			position: this.position,
-			originalPosition: this.originalPosition,
-			offset: this.positionAbs
-		};
-	}
-
-});
-
-$.ui.plugin.add("draggable", "connectToSortable", {
-	start: function(event, ui) {
-
-		var inst = $(this).data("draggable"), o = inst.options,
-			uiSortable = $.extend({}, ui, { item: inst.element });
-		inst.sortables = [];
-		$(o.connectToSortable).each(function() {
-			var sortable = $.data(this, 'sortable');
-			if (sortable && !sortable.options.disabled) {
-				inst.sortables.push({
-					instance: sortable,
-					shouldRevert: sortable.options.revert
-				});
-				sortable.refreshPositions();	// Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page).
-				sortable._trigger("activate", event, uiSortable);
-			}
-		});
-
-	},
-	stop: function(event, ui) {
-
-		//If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
-		var inst = $(this).data("draggable"),
-			uiSortable = $.extend({}, ui, { item: inst.element });
-
-		$.each(inst.sortables, function() {
-			if(this.instance.isOver) {
-
-				this.instance.isOver = 0;
-
-				inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
-				this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
-
-				//The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
-				if(this.shouldRevert) this.instance.options.revert = true;
-
-				//Trigger the stop of the sortable
-				this.instance._mouseStop(event);
-
-				this.instance.options.helper = this.instance.options._helper;
-
-				//If the helper has been the original item, restore properties in the sortable
-				if(inst.options.helper == 'original')
-					this.instance.currentItem.css({ top: 'auto', left: 'auto' });
-
-			} else {
-				this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
-				this.instance._trigger("deactivate", event, uiSortable);
-			}
-
-		});
-
-	},
-	drag: function(event, ui) {
-
-		var inst = $(this).data("draggable"), that = this;
-
-		var checkPos = function(o) {
-			var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
-			var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
-			var itemHeight = o.height, itemWidth = o.width;
-			var itemTop = o.top, itemLeft = o.left;
-
-			return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
-		};
-
-		$.each(inst.sortables, function(i) {
-
-			var innermostIntersecting = false;
-			var thisSortable = this;
-			//Copy over some variables to allow calling the sortable's native _intersectsWith
-			this.instance.positionAbs = inst.positionAbs;
-			this.instance.helperProportions = inst.helperProportions;
-			this.instance.offset.click = inst.offset.click;
-
-			if(this.instance._intersectsWith(this.instance.containerCache)) {
-				innermostIntersecting = true;
-				$.each(inst.sortables, function () {
-					this.instance.positionAbs = inst.positionAbs;
-					this.instance.helperProportions = inst.helperProportions;
-					this.instance.offset.click = inst.offset.click;
-					if  (this != thisSortable
-						&& this.instance._intersectsWith(this.instance.containerCache)
-						&& $.ui.contains(thisSortable.instance.element[0], this.instance.element[0]))
-						innermostIntersecting = false;
-						return innermostIntersecting;
-				});
-			}
-
-
-			if(innermostIntersecting) {
-				//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
-				if(!this.instance.isOver) {
-
-					this.instance.isOver = 1;
-					//Now we fake the start of dragging for the sortable instance,
-					//by cloning the list group item, appending it to the sortable and using it as inst.currentItem
-					//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
-					this.instance.currentItem = $(that).clone().removeAttr('id').appendTo(this.instance.element).data("sortable-item", true);
-					this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
-					this.instance.options.helper = function() { return ui.helper[0]; };
-
-					event.target = this.instance.currentItem[0];
-					this.instance._mouseCapture(event, true);
-					this.instance._mouseStart(event, true, true);
-
-					//Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
-					this.instance.offset.click.top = inst.offset.click.top;
-					this.instance.offset.click.left = inst.offset.click.left;
-					this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
-					this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
-
-					inst._trigger("toSortable", event);
-					inst.dropped = this.instance.element; //draggable revert needs that
-					//hack so receive/update callbacks work (mostly)
-					inst.currentItem = inst.element;
-					this.instance.fromOutside = inst;
-
-				}
-
-				//Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
-				if(this.instance.currentItem) this.instance._mouseDrag(event);
-
-			} else {
-
-				//If it doesn't intersect with the sortable, and it intersected before,
-				//we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
-				if(this.instance.isOver) {
-
-					this.instance.isOver = 0;
-					this.instance.cancelHelperRemoval = true;
-
-					//Prevent reverting on this forced stop
-					this.instance.options.revert = false;
-
-					// The out event needs to be triggered independently
-					this.instance._trigger('out', event, this.instance._uiHash(this.instance));
-
-					this.instance._mouseStop(event, true);
-					this.instance.options.helper = this.instance.options._helper;
-
-					//Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
-					this.instance.currentItem.remove();
-					if(this.instance.placeholder) this.instance.placeholder.remove();
-
-					inst._trigger("fromSortable", event);
-					inst.dropped = false; //draggable revert needs that
-				}
-
-			};
-
-		});
-
-	}
-});
-
-$.ui.plugin.add("draggable", "cursor", {
-	start: function(event, ui) {
-		var t = $('body'), o = $(this).data('draggable').options;
-		if (t.css("cursor")) o._cursor = t.css("cursor");
-		t.css("cursor", o.cursor);
-	},
-	stop: function(event, ui) {
-		var o = $(this).data('draggable').options;
-		if (o._cursor) $('body').css("cursor", o._cursor);
-	}
-});
-
-$.ui.plugin.add("draggable", "opacity", {
-	start: function(event, ui) {
-		var t = $(ui.helper), o = $(this).data('draggable').options;
-		if(t.css("opacity")) o._opacity = t.css("opacity");
-		t.css('opacity', o.opacity);
-	},
-	stop: function(event, ui) {
-		var o = $(this).data('draggable').options;
-		if(o._opacity) $(ui.helper).css('opacity', o._opacity);
-	}
-});
-
-$.ui.plugin.add("draggable", "scroll", {
-	start: function(event, ui) {
-		var i = $(this).data("draggable");
-		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
-	},
-	drag: function(event, ui) {
-
-		var i = $(this).data("draggable"), o = i.options, scrolled = false;
-
-		if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
-
-			if(!o.axis || o.axis != 'x') {
-				if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
-					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
-				else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
-					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
-			}
-
-			if(!o.axis || o.axis != 'y') {
-				if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
-					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
-				else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
-					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
-			}
-
-		} else {
-
-			if(!o.axis || o.axis != 'x') {
-				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
-					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
-				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
-					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
-			}
-
-			if(!o.axis || o.axis != 'y') {
-				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
-					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
-				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
-					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
-			}
-
-		}
-
-		if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
-			$.ui.ddmanager.prepareOffsets(i, event);
-
-	}
-});
-
-$.ui.plugin.add("draggable", "snap", {
-	start: function(event, ui) {
-
-		var i = $(this).data("draggable"), o = i.options;
-		i.snapElements = [];
-
-		$(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
-			var $t = $(this); var $o = $t.offset();
-			if(this != i.element[0]) i.snapElements.push({
-				item: this,
-				width: $t.outerWidth(), height: $t.outerHeight(),
-				top: $o.top, left: $o.left
-			});
-		});
-
-	},
-	drag: function(event, ui) {
-
-		var inst = $(this).data("draggable"), o = inst.options;
-		var d = o.snapTolerance;
-
-		var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
-			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
-
-		for (var i = inst.snapElements.length - 1; i >= 0; i--){
-
-			var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
-				t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
-
-			//Yes, I know, this is insane ;)
-			if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
-				if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
-				inst.snapElements[i].snapping = false;
-				continue;
-			}
-
-			if(o.snapMode != 'inner') {
-				var ts = Math.abs(t - y2) <= d;
-				var bs = Math.abs(b - y1) <= d;
-				var ls = Math.abs(l - x2) <= d;
-				var rs = Math.abs(r - x1) <= d;
-				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
-				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
-				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
-				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
-			}
-
-			var first = (ts || bs || ls || rs);
-
-			if(o.snapMode != 'outer') {
-				var ts = Math.abs(t - y1) <= d;
-				var bs = Math.abs(b - y2) <= d;
-				var ls = Math.abs(l - x1) <= d;
-				var rs = Math.abs(r - x2) <= d;
-				if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
-				if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
-				if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
-				if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
-			}
-
-			if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
-				(inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
-			inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
-
-		};
-
-	}
-});
-
-$.ui.plugin.add("draggable", "stack", {
-	start: function(event, ui) {
-
-		var o = $(this).data("draggable").options;
-
-		var group = $.makeArray($(o.stack)).sort(function(a,b) {
-			return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
-		});
-		if (!group.length) { return; }
-
-		var min = parseInt(group[0].style.zIndex) || 0;
-		$(group).each(function(i) {
-			this.style.zIndex = min + i;
-		});
-
-		this[0].style.zIndex = min + group.length;
-
-	}
-});
-
-$.ui.plugin.add("draggable", "zIndex", {
-	start: function(event, ui) {
-		var t = $(ui.helper), o = $(this).data("draggable").options;
-		if(t.css("zIndex")) o._zIndex = t.css("zIndex");
-		t.css('zIndex', o.zIndex);
-	},
-	stop: function(event, ui) {
-		var o = $(this).data("draggable").options;
-		if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
-	}
-});
-
-})(jQuery);
-(function( $, undefined ) {
-
-$.widget("ui.droppable", {
-	version: "1.9.2",
-	widgetEventPrefix: "drop",
-	options: {
-		accept: '*',
-		activeClass: false,
-		addClasses: true,
-		greedy: false,
-		hoverClass: false,
-		scope: 'default',
-		tolerance: 'intersect'
-	},
-	_create: function() {
-
-		var o = this.options, accept = o.accept;
-		this.isover = 0; this.isout = 1;
-
-		this.accept = $.isFunction(accept) ? accept : function(d) {
-			return d.is(accept);
-		};
-
-		//Store the droppable's proportions
-		this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
-
-		// Add the reference and positions to the manager
-		$.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
-		$.ui.ddmanager.droppables[o.scope].push(this);
-
-		(o.addClasses && this.element.addClass("ui-droppable"));
-
-	},
-
-	_destroy: function() {
-		var drop = $.ui.ddmanager.droppables[this.options.scope];
-		for ( var i = 0; i < drop.length; i++ )
-			if ( drop[i] == this )
-				drop.splice(i, 1);
-
-		this.element.removeClass("ui-droppable ui-droppable-disabled");
-	},
-
-	_setOption: function(key, value) {
-
-		if(key == 'accept') {
-			this.accept = $.isFunction(value) ? value : function(d) {
-				return d.is(value);
-			};
-		}
-		$.Widget.prototype._setOption.apply(this, arguments);
-	},
-
-	_activate: function(event) {
-		var draggable = $.ui.ddmanager.current;
-		if(this.options.activeClass) this.element.addClass(this.options.activeClass);
-		(draggable && this._trigger('activate', event, this.ui(draggable)));
-	},
-
-	_deactivate: function(event) {
-		var draggable = $.ui.ddmanager.current;
-		if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
-		(draggable && this._trigger('deactivate', event, this.ui(draggable)));
-	},
-
-	_over: function(event) {
-
-		var draggable = $.ui.ddmanager.current;
-		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
-
-		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
-			if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
-			this._trigger('over', event, this.ui(draggable));
-		}
-
-	},
-
-	_out: function(event) {
-
-		var draggable = $.ui.ddmanager.current;
-		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
-
-		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
-			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
-			this._trigger('out', event, this.ui(draggable));
-		}
-
-	},
-
-	_drop: function(event,custom) {
-
-		var draggable = custom || $.ui.ddmanager.current;
-		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
-
-		var childrenIntersection = false;
-		this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
-			var inst = $.data(this, 'droppable');
-			if(
-				inst.options.greedy
-				&& !inst.options.disabled
-				&& inst.options.scope == draggable.options.scope
-				&& inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
-				&& $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
-			) { childrenIntersection = true; return false; }
-		});
-		if(childrenIntersection) return false;
-
-		if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
-			if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
-			if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
-			this._trigger('drop', event, this.ui(draggable));
-			return this.element;
-		}
-
-		return false;
-
-	},
-
-	ui: function(c) {
-		return {
-			draggable: (c.currentItem || c.element),
-			helper: c.helper,
-			position: c.position,
-			offset: c.positionAbs
-		};
-	}
-
-});
-
-$.ui.intersect = function(draggable, droppable, toleranceMode) {
-
-	if (!droppable.offset) return false;
-
-	var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
-		y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
-	var l = droppable.offset.left, r = l + droppable.proportions.width,
-		t = droppable.offset.top, b = t + droppable.proportions.height;
-
-	switch (toleranceMode) {
-		case 'fit':
-			return (l <= x1 && x2 <= r
-				&& t <= y1 && y2 <= b);
-			break;
-		case 'intersect':
-			return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
-				&& x2 - (draggable.helperProportions.width / 2) < r // Left Half
-				&& t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
-				&& y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
-			break;
-		case 'pointer':
-			var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
-				draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
-				isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
-			return isOver;
-			break;
-		case 'touch':
-			return (
-					(y1 >= t && y1 <= b) ||	// Top edge touching
-					(y2 >= t && y2 <= b) ||	// Bottom edge touching
-					(y1 < t && y2 > b)		// Surrounded vertically
-				) && (
-					(x1 >= l && x1 <= r) ||	// Left edge touching
-					(x2 >= l && x2 <= r) ||	// Right edge touching
-					(x1 < l && x2 > r)		// Surrounded horizontally
-				);
-			break;
-		default:
-			return false;
-			break;
-		}
-
-};
-
-/*
-	This manager tracks offsets of draggables and droppables
-*/
-$.ui.ddmanager = {
-	current: null,
-	droppables: { 'default': [] },
-	prepareOffsets: function(t, event) {
-
-		var m = $.ui.ddmanager.droppables[t.options.scope] || [];
-		var type = event ? event.type : null; // workaround for #2317
-		var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
-
-		droppablesLoop: for (var i = 0; i < m.length; i++) {
-
-			if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue;	//No disabled and non-accepted
-			for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
-			m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; 									//If the element is not visible, continue
-
-			if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
-
-			m[i].offset = m[i].element.offset();
-			m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
-
-		}
-
-	},
-	drop: function(draggable, event) {
-
-		var dropped = false;
-		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
-
-			if(!this.options) return;
-			if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
-				dropped = this._drop.call(this, event) || dropped;
-
-			if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
-				this.isout = 1; this.isover = 0;
-				this._deactivate.call(this, event);
-			}
-
-		});
-		return dropped;
-
-	},
-	dragStart: function( draggable, event ) {
-		//Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
-		draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() {
-			if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
-		});
-	},
-	drag: function(draggable, event) {
-
-		//If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
-		if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
-
-		//Run through all droppables and check their positions based on specific tolerance options
-		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
-
-			if(this.options.disabled || this.greedyChild || !this.visible) return;
-			var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
-
-			var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
-			if(!c) return;
-
-			var parentInstance;
-			if (this.options.greedy) {
-				// find droppable parents with same scope
-				var scope = this.options.scope;
-				var parent = this.element.parents(':data(droppable)').filter(function () {
-					return $.data(this, 'droppable').options.scope === scope;
-				});
-
-				if (parent.length) {
-					parentInstance = $.data(parent[0], 'droppable');
-					parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
-				}
-			}
-
-			// we just moved into a greedy child
-			if (parentInstance && c == 'isover') {
-				parentInstance['isover'] = 0;
-				parentInstance['isout'] = 1;
-				parentInstance._out.call(parentInstance, event);
-			}
-
-			this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
-			this[c == "isover" ? "_over" : "_out"].call(this, event);
-
-			// we just moved out of a greedy child
-			if (parentInstance && c == 'isout') {
-				parentInstance['isout'] = 0;
-				parentInstance['isover'] = 1;
-				parentInstance._over.call(parentInstance, event);
-			}
-		});
-
-	},
-	dragStop: function( draggable, event ) {
-		draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" );
-		//Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
-		if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
-	}
-};
-
-})(jQuery);
-(function( $, undefined ) {
-
-$.widget("ui.resizable", $.ui.mouse, {
-	version: "1.9.2",
-	widgetEventPrefix: "resize",
-	options: {
-		alsoResize: false,
-		animate: false,
-		animateDuration: "slow",
-		animateEasing: "swing",
-		aspectRatio: false,
-		autoHide: false,
-		containment: false,
-		ghost: false,
-		grid: false,
-		handles: "e,s,se",
-		helper: false,
-		maxHeight: null,
-		maxWidth: null,
-		minHeight: 10,
-		minWidth: 10,
-		zIndex: 1000
-	},
-	_create: function() {
-
-		var that = this, o = this.options;
-		this.element.addClass("ui-resizable");
-
-		$.extend(this, {
-			_aspectRatio: !!(o.aspectRatio),
-			aspectRatio: o.aspectRatio,
-			originalElement: this.element,
-			_proportionallyResizeElements: [],
-			_helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
-		});
-
-		//Wrap the element if it cannot hold child nodes
-		if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
-
-			//Create a wrapper element and set the wrapper to the new current internal element
-			this.element.wrap(
-				$('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
-					position: this.element.css('position'),
-					width: this.element.outerWidth(),
-					height: this.element.outerHeight(),
-					top: this.element.css('top'),
-					left: this.element.css('left')
-				})
-			);
-
-			//Overwrite the original this.element
-			this.element = this.element.parent().data(
-				"resizable", this.element.data('resizable')
-			);
-
-			this.elementIsWrapper = true;
-
-			//Move margins to the wrapper
-			this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
-			this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
-
-			//Prevent Safari textarea resize
-			this.originalResizeStyle = this.originalElement.css('resize');
-			this.originalElement.css('resize', 'none');
-
-			//Push the actual element to our proportionallyResize internal array
-			this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
-
-			// avoid IE jump (hard set the margin)
-			this.originalElement.css({ margin: this.originalElement.css('margin') });
-
-			// fix handlers offset
-			this._proportionallyResize();
-
-		}
-
-		this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' });
-		if(this.handles.constructor == String) {
-
-			if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
-			var n = this.handles.split(","); this.handles = {};
-
-			for(var i = 0; i < n.length; i++) {
-
-				var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
-				var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
-
-				// Apply zIndex to all handles - see #7960
-				axis.css({ zIndex: o.zIndex });
-
-				//TODO : What's going on here?
-				if ('se' == handle) {
-					axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
-				};
-
-				//Insert into internal handles object and append to element
-				this.handles[handle] = '.ui-resizable-'+handle;
-				this.element.append(axis);
-			}
-
-		}
-
-		this._renderAxis = function(target) {
-
-			target = target || this.element;
-
-			for(var i in this.handles) {
-
-				if(this.handles[i].constructor == String)
-					this.handles[i] = $(this.handles[i], this.element).show();
-
-				//Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
-				if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
-
-					var axis = $(this.handles[i], this.element), padWrapper = 0;
-
-					//Checking the correct pad and border
-					padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
-
-					//The padding type i have to apply...
-					var padPos = [ 'padding',
-						/ne|nw|n/.test(i) ? 'Top' :
-						/se|sw|s/.test(i) ? 'Bottom' :
-						/^e$/.test(i) ? 'Right' : 'Left' ].join("");
-
-					target.css(padPos, padWrapper);
-
-					this._proportionallyResize();
-
-				}
-
-				//TODO: What's that good for? There's not anything to be executed left
-				if(!$(this.handles[i]).length)
-					continue;
-
-			}
-		};
-
-		//TODO: make renderAxis a prototype function
-		this._renderAxis(this.element);
-
-		this._handles = $('.ui-resizable-handle', this.element)
-			.disableSelection();
-
-		//Matching axis name
-		this._handles.mouseover(function() {
-			if (!that.resizing) {
-				if (this.className)
-					var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
-				//Axis, default = se
-				that.axis = axis && axis[1] ? axis[1] : 'se';
-			}
-		});
-
-		//If we want to auto hide the elements
-		if (o.autoHide) {
-			this._handles.hide();
-			$(this.element)
-				.addClass("ui-resizable-autohide")
-				.mouseenter(function() {
-					if (o.disabled) return;
-					$(this).removeClass("ui-resizable-autohide");
-					that._handles.show();
-				})
-				.mouseleave(function(){
-					if (o.disabled) return;
-					if (!that.resizing) {
-						$(this).addClass("ui-resizable-autohide");
-						that._handles.hide();
-					}
-				});
-		}
-
-		//Initialize the mouse interaction
-		this._mouseInit();
-
-	},
-
-	_destroy: function() {
-
-		this._mouseDestroy();
-
-		var _destroy = function(exp) {
-			$(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
-				.removeData("resizable").removeData("ui-resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
-		};
-
-		//TODO: Unwrap at same DOM position
-		if (this.elementIsWrapper) {
-			_destroy(this.element);
-			var wrapper = this.element;
-			this.originalElement.css({
-				position: wrapper.css('position'),
-				width: wrapper.outerWidth(),
-				height: wrapper.outerHeight(),
-				top: wrapper.css('top'),
-				left: wrapper.css('left')
-			}).insertAfter( wrapper );
-			wrapper.remove();
-		}
-
-		this.originalElement.css('resize', this.originalResizeStyle);
-		_destroy(this.originalElement);
-
-		return this;
-	},
-
-	_mouseCapture: function(event) {
-		var handle = false;
-		for (var i in this.handles) {
-			if ($(this.handles[i])[0] == event.target) {
-				handle = true;
-			}
-		}
-
-		return !this.options.disabled && handle;
-	},
-
-	_mouseStart: function(event) {
-
-		var o = this.options, iniPos = this.element.position(), el = this.element;
-
-		this.resizing = true;
-		this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
-
-		// bugfix for http://dev.jquery.com/ticket/1749
-		if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
-			el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
-		}
-
-		this._renderProxy();
-
-		var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
-
-		if (o.containment) {
-			curleft += $(o.containment).scrollLeft() || 0;
-			curtop += $(o.containment).scrollTop() || 0;
-		}
-
-		//Store needed variables
-		this.offset = this.helper.offset();
-		this.position = { left: curleft, top: curtop };
-		this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
-		this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
-		this.originalPosition = { left: curleft, top: curtop };
-		this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
-		this.originalMousePosition = { left: event.pageX, top: event.pageY };
-
-		//Aspect Ratio
-		this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
-
-		var cursor = $('.ui-resizable-' + this.axis).css('cursor');
-		$('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
-
-		el.addClass("ui-resizable-resizing");
-		this._propagate("start", event);
-		return true;
-	},
-
-	_mouseDrag: function(event) {
-
-		//Increase performance, avoid regex
-		var el = this.helper, o = this.options, props = {},
-			that = this, smp = this.originalMousePosition, a = this.axis;
-
-		var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
-		var trigger = this._change[a];
-		if (!trigger) return false;
-
-		// Calculate the attrs that will be change
-		var data = trigger.apply(this, [event, dx, dy]);
-
-		// Put this in the mouseDrag handler since the user can start pressing shift while resizing
-		this._updateVirtualBoundaries(event.shiftKey);
-		if (this._aspectRatio || event.shiftKey)
-			data = this._updateRatio(data, event);
-
-		data = this._respectSize(data, event);
-
-		// plugins callbacks need to be called first
-		this._propagate("resize", event);
-
-		el.css({
-			top: this.position.top + "px", left: this.position.left + "px",
-			width: this.size.width + "px", height: this.size.height + "px"
-		});
-
-		if (!this._helper && this._proportionallyResizeElements.length)
-			this._proportionallyResize();
-
-		this._updateCache(data);
-
-		// calling the user callback at the end
-		this._trigger('resize', event, this.ui());
-
-		return false;
-	},
-
-	_mouseStop: function(event) {
-
-		this.resizing = false;
-		var o = this.options, that = this;
-
-		if(this._helper) {
-			var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
-				soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : that.sizeDiff.height,
-				soffsetw = ista ? 0 : that.sizeDiff.width;
-
-			var s = { width: (that.helper.width()  - soffsetw), height: (that.helper.height() - soffseth) },
-				left = (parseInt(that.element.css('left'), 10) + (that.position.left - that.originalPosition.left)) || null,
-				top = (parseInt(that.element.css('top'), 10) + (that.position.top - that.originalPosition.top)) || null;
-
-			if (!o.animate)
-				this.element.css($.extend(s, { top: top, left: left }));
-
-			that.helper.height(that.size.height);
-			that.helper.width(that.size.width);
-
-			if (this._helper && !o.animate) this._proportionallyResize();
-		}
-
-		$('body').css('cursor', 'auto');
-
-		this.element.removeClass("ui-resizable-resizing");
-
-		this._propagate("stop", event);
-
-		if (this._helper) this.helper.remove();
-		return false;
-
-	},
-
-	_updateVirtualBoundaries: function(forceAspectRatio) {
-		var o = this.options, pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b;
-
-		b = {
-			minWidth: isNumber(o.minWidth) ? o.minWidth : 0,
-			maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity,
-			minHeight: isNumber(o.minHeight) ? o.minHeight : 0,
-			maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity
-		};
-
-		if(this._aspectRatio || forceAspectRatio) {
-			// We want to create an enclosing box whose aspect ration is the requested one
-			// First, compute the "projected" size for each dimension based on the aspect ratio and other dimension
-			pMinWidth = b.minHeight * this.aspectRatio;
-			pMinHeight = b.minWidth / this.aspectRatio;
-			pMaxWidth = b.maxHeight * this.aspectRatio;
-			pMaxHeight = b.maxWidth / this.aspectRatio;
-
-			if(pMinWidth > b.minWidth) b.minWidth = pMinWidth;
-			if(pMinHeight > b.minHeight) b.minHeight = pMinHeight;
-			if(pMaxWidth < b.maxWidth) b.maxWidth = pMaxWidth;
-			if(pMaxHeight < b.maxHeight) b.maxHeight = pMaxHeight;
-		}
-		this._vBoundaries = b;
-	},
-
-	_updateCache: function(data) {
-		var o = this.options;
-		this.offset = this.helper.offset();
-		if (isNumber(data.left)) this.position.left = data.left;
-		if (isNumber(data.top)) this.position.top = data.top;
-		if (isNumber(data.height)) this.size.height = data.height;
-		if (isNumber(data.width)) this.size.width = data.width;
-	},
-
-	_updateRatio: function(data, event) {
-
-		var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
-
-		if (isNumber(data.height)) data.width = (data.height * this.aspectRatio);
-		else if (isNumber(data.width)) data.height = (data.width / this.aspectRatio);
-
-		if (a == 'sw') {
-			data.left = cpos.left + (csize.width - data.width);
-			data.top = null;
-		}
-		if (a == 'nw') {
-			data.top = cpos.top + (csize.height - data.height);
-			data.left = cpos.left + (csize.width - data.width);
-		}
-
-		return data;
-	},
-
-	_respectSize: function(data, event) {
-
-		var el = this.helper, o = this._vBoundaries, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
-				ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
-					isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
-
-		if (isminw) data.width = o.minWidth;
-		if (isminh) data.height = o.minHeight;
-		if (ismaxw) data.width = o.maxWidth;
-		if (ismaxh) data.height = o.maxHeight;
-
-		var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
-		var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
-
-		if (isminw && cw) data.left = dw - o.minWidth;
-		if (ismaxw && cw) data.left = dw - o.maxWidth;
-		if (isminh && ch)	data.top = dh - o.minHeight;
-		if (ismaxh && ch)	data.top = dh - o.maxHeight;
-
-		// fixing jump error on top/left - bug #2330
-		var isNotwh = !data.width && !data.height;
-		if (isNotwh && !data.left && data.top) data.top = null;
-		else if (isNotwh && !data.top && data.left) data.left = null;
-
-		return data;
-	},
-
-	_proportionallyResize: function() {
-
-		var o = this.options;
-		if (!this._proportionallyResizeElements.length) return;
-		var element = this.helper || this.element;
-
-		for (var i=0; i < this._proportionallyResizeElements.length; i++) {
-
-			var prel = this._proportionallyResizeElements[i];
-
-			if (!this.borderDif) {
-				var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
-					p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
-
-				this.borderDif = $.map(b, function(v, i) {
-					var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
-					return border + padding;
-				});
-			}
-
-			prel.css({
-				height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
-				width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
-			});
-
-		};
-
-	},
-
-	_renderProxy: function() {
-
-		var el = this.element, o = this.options;
-		this.elementOffset = el.offset();
-
-		if(this._helper) {
-
-			this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
-
-			// fix ie6 offset TODO: This seems broken
-			var ie6offset = ($.ui.ie6 ? 1 : 0),
-			pxyoffset = ( $.ui.ie6 ? 2 : -1 );
-
-			this.helper.addClass(this._helper).css({
-				width: this.element.outerWidth() + pxyoffset,
-				height: this.element.outerHeight() + pxyoffset,
-				position: 'absolute',
-				left: this.elementOffset.left - ie6offset +'px',
-				top: this.elementOffset.top - ie6offset +'px',
-				zIndex: ++o.zIndex //TODO: Don't modify option
-			});
-
-			this.helper
-				.appendTo("body")
-				.disableSelection();
-
-		} else {
-			this.helper = this.element;
-		}
-
-	},
-
-	_change: {
-		e: function(event, dx, dy) {
-			return { width: this.originalSize.width + dx };
-		},
-		w: function(event, dx, dy) {
-			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
-			return { left: sp.left + dx, width: cs.width - dx };
-		},
-		n: function(event, dx, dy) {
-			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
-			return { top: sp.top + dy, height: cs.height - dy };
-		},
-		s: function(event, dx, dy) {
-			return { height: this.originalSize.height + dy };
-		},
-		se: function(event, dx, dy) {
-			return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
-		},
-		sw: function(event, dx, dy) {
-			return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
-		},
-		ne: function(event, dx, dy) {
-			return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
-		},
-		nw: function(event, dx, dy) {
-			return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
-		}
-	},
-
-	_propagate: function(n, event) {
-		$.ui.plugin.call(this, n, [event, this.ui()]);
-		(n != "resize" && this._trigger(n, event, this.ui()));
-	},
-
-	plugins: {},
-
-	ui: function() {
-		return {
-			originalElement: this.originalElement,
-			element: this.element,
-			helper: this.helper,
-			position: this.position,
-			size: this.size,
-			originalSize: this.originalSize,
-			originalPosition: this.originalPosition
-		};
-	}
-
-});
-
-/*
- * Resizable Extensions
- */
-
-$.ui.plugin.add("resizable", "alsoResize", {
-
-	start: function (event, ui) {
-		var that = $(this).data("resizable"), o = that.options;
-
-		var _store = function (exp) {
-			$(exp).each(function() {
-				var el = $(this);
-				el.data("resizable-alsoresize", {
-					width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
-					left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10)
-				});
-			});
-		};
-
-		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
-			if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
-			else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
-		}else{
-			_store(o.alsoResize);
-		}
-	},
-
-	resize: function (event, ui) {
-		var that = $(this).data("resizable"), o = that.options, os = that.originalSize, op = that.originalPosition;
-
-		var delta = {
-			height: (that.size.height - os.height) || 0, width: (that.size.width - os.width) || 0,
-			top: (that.position.top - op.top) || 0, left: (that.position.left - op.left) || 0
-		},
-
-		_alsoResize = function (exp, c) {
-			$(exp).each(function() {
-				var el = $(this), start = $(this).data("resizable-alsoresize"), style = {},
-					css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
-
-				$.each(css, function (i, prop) {
-					var sum = (start[prop]||0) + (delta[prop]||0);
-					if (sum && sum >= 0)
-						style[prop] = sum || null;
-				});
-
-				el.css(style);
-			});
-		};
-
-		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
-			$.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
-		}else{
-			_alsoResize(o.alsoResize);
-		}
-	},
-
-	stop: function (event, ui) {
-		$(this).removeData("resizable-alsoresize");
-	}
-});
-
-$.ui.plugin.add("resizable", "animate", {
-
-	stop: function(event, ui) {
-		var that = $(this).data("resizable"), o = that.options;
-
-		var pr = that._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
-					soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : that.sizeDiff.height,
-						soffsetw = ista ? 0 : that.sizeDiff.width;
-
-		var style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) },
-					left = (parseInt(that.element.css('left'), 10) + (that.position.left - that.originalPosition.left)) || null,
-						top = (parseInt(that.element.css('top'), 10) + (that.position.top - that.originalPosition.top)) || null;
-
-		that.element.animate(
-			$.extend(style, top && left ? { top: top, left: left } : {}), {
-				duration: o.animateDuration,
-				easing: o.animateEasing,
-				step: function() {
-
-					var data = {
-						width: parseInt(that.element.css('width'), 10),
-						height: parseInt(that.element.css('height'), 10),
-						top: parseInt(that.element.css('top'), 10),
-						left: parseInt(that.element.css('left'), 10)
-					};
-
-					if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
-
-					// propagating resize, and updating values for each animation step
-					that._updateCache(data);
-					that._propagate("resize", event);
-
-				}
-			}
-		);
-	}
-
-});
-
-$.ui.plugin.add("resizable", "containment", {
-
-	start: function(event, ui) {
-		var that = $(this).data("resizable"), o = that.options, el = that.element;
-		var oc = o.containment,	ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
-		if (!ce) return;
-
-		that.containerElement = $(ce);
-
-		if (/document/.test(oc) || oc == document) {
-			that.containerOffset = { left: 0, top: 0 };
-			that.containerPosition = { left: 0, top: 0 };
-
-			that.parentData = {
-				element: $(document), left: 0, top: 0,
-				width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
-			};
-		}
-
-		// i'm a node, so compute top, left, right, bottom
-		else {
-			var element = $(ce), p = [];
-			$([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
-
-			that.containerOffset = element.offset();
-			that.containerPosition = element.position();
-			that.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
-
-			var co = that.containerOffset, ch = that.containerSize.height,	cw = that.containerSize.width,
-						width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
-
-			that.parentData = {
-				element: ce, left: co.left, top: co.top, width: width, height: height
-			};
-		}
-	},
-
-	resize: function(event, ui) {
-		var that = $(this).data("resizable"), o = that.options,
-				ps = that.containerSize, co = that.containerOffset, cs = that.size, cp = that.position,
-				pRatio = that._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = that.containerElement;
-
-		if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
-
-		if (cp.left < (that._helper ? co.left : 0)) {
-			that.size.width = that.size.width + (that._helper ? (that.position.left - co.left) : (that.position.left - cop.left));
-			if (pRatio) that.size.height = that.size.width / that.aspectRatio;
-			that.position.left = o.helper ? co.left : 0;
-		}
-
-		if (cp.top < (that._helper ? co.top : 0)) {
-			that.size.height = that.size.height + (that._helper ? (that.position.top - co.top) : that.position.top);
-			if (pRatio) that.size.width = that.size.height * that.aspectRatio;
-			that.position.top = that._helper ? co.top : 0;
-		}
-
-		that.offset.left = that.parentData.left+that.position.left;
-		that.offset.top = that.parentData.top+that.position.top;
-
-		var woset = Math.abs( (that._helper ? that.offset.left - cop.left : (that.offset.left - cop.left)) + that.sizeDiff.width ),
-					hoset = Math.abs( (that._helper ? that.offset.top - cop.top : (that.offset.top - co.top)) + that.sizeDiff.height );
-
-		var isParent = that.containerElement.get(0) == that.element.parent().get(0),
-			isOffsetRelative = /relative|absolute/.test(that.containerElement.css('position'));
-
-		if(isParent && isOffsetRelative) woset -= that.parentData.left;
-
-		if (woset + that.size.width >= that.parentData.width) {
-			that.size.width = that.parentData.width - woset;
-			if (pRatio) that.size.height = that.size.width / that.aspectRatio;
-		}
-
-		if (hoset + that.size.height >= that.parentData.height) {
-			that.size.height = that.parentData.height - hoset;
-			if (pRatio) that.size.width = that.size.height * that.aspectRatio;
-		}
-	},
-
-	stop: function(event, ui){
-		var that = $(this).data("resizable"), o = that.options, cp = that.position,
-				co = that.containerOffset, cop = that.containerPosition, ce = that.containerElement;
-
-		var helper = $(that.helper), ho = helper.offset(), w = helper.outerWidth() - that.sizeDiff.width, h = helper.outerHeight() - that.sizeDiff.height;
-
-		if (that._helper && !o.animate && (/relative/).test(ce.css('position')))
-			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
-
-		if (that._helper && !o.animate && (/static/).test(ce.css('position')))
-			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
-
-	}
-});
-
-$.ui.plugin.add("resizable", "ghost", {
-
-	start: function(event, ui) {
-
-		var that = $(this).data("resizable"), o = that.options, cs = that.size;
-
-		that.ghost = that.originalElement.clone();
-		that.ghost
-			.css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
-			.addClass('ui-resizable-ghost')
-			.addClass(typeof o.ghost == 'string' ? o.ghost : '');
-
-		that.ghost.appendTo(that.helper);
-
-	},
-
-	resize: function(event, ui){
-		var that = $(this).data("resizable"), o = that.options;
-		if (that.ghost) that.ghost.css({ position: 'relative', height: that.size.height, width: that.size.width });
-	},
-
-	stop: function(event, ui){
-		var that = $(this).data("resizable"), o = that.options;
-		if (that.ghost && that.helper) that.helper.get(0).removeChild(that.ghost.get(0));
-	}
-
-});
-
-$.ui.plugin.add("resizable", "grid", {
-
-	resize: function(event, ui) {
-		var that = $(this).data("resizable"), o = that.options, cs = that.size, os = that.originalSize, op = that.originalPosition, a = that.axis, ratio = o._aspectRatio || event.shiftKey;
-		o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
-		var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);
-
-		if (/^(se|s|e)$/.test(a)) {
-			that.size.width = os.width + ox;
-			that.size.height = os.height + oy;
-		}
-		else if (/^(ne)$/.test(a)) {
-			that.size.width = os.width + ox;
-			that.size.height = os.height + oy;
-			that.position.top = op.top - oy;
-		}
-		else if (/^(sw)$/.test(a)) {
-			that.size.width = os.width + ox;
-			that.size.height = os.height + oy;
-			that.position.left = op.left - ox;
-		}
-		else {
-			that.size.width = os.width + ox;
-			that.size.height = os.height + oy;
-			that.position.top = op.top - oy;
-			that.position.left = op.left - ox;
-		}
-	}
-
-});
-
-var num = function(v) {
-	return parseInt(v, 10) || 0;
-};
-
-var isNumber = function(value) {
-	return !isNaN(parseInt(value, 10));
-};
-
-})(jQuery);
-(function( $, undefined ) {
-
-$.widget("ui.selectable", $.ui.mouse, {
-	version: "1.9.2",
-	options: {
-		appendTo: 'body',
-		autoRefresh: true,
-		distance: 0,
-		filter: '*',
-		tolerance: 'touch'
-	},
-	_create: function() {
-		var that = this;
-
-		this.element.addClass("ui-selectable");
-
-		this.dragged = false;
-
-		// cache selectee children based on filter
-		var selectees;
-		this.refresh = function() {
-			selectees = $(that.options.filter, that.element[0]);
-			selectees.addClass("ui-selectee");
-			selectees.each(function() {
-				var $this = $(this);
-				var pos = $this.offset();
-				$.data(this, "selectable-item", {
-					element: this,
-					$element: $this,
-					left: pos.left,
-					top: pos.top,
-					right: pos.left + $this.outerWidth(),
-					bottom: pos.top + $this.outerHeight(),
-					startselected: false,
-					selected: $this.hasClass('ui-selected'),
-					selecting: $this.hasClass('ui-selecting'),
-					unselecting: $this.hasClass('ui-unselecting')
-				});
-			});
-		};
-		this.refresh();
-
-		this.selectees = selectees.addClass("ui-selectee");
-
-		this._mouseInit();
-
-		this.helper = $("<div class='ui-selectable-helper'></div>");
-	},
-
-	_destroy: function() {
-		this.selectees
-			.removeClass("ui-selectee")
-			.removeData("selectable-item");
-		this.element
-			.removeClass("ui-selectable ui-selectable-disabled");
-		this._mouseDestroy();
-	},
-
-	_mouseStart: function(event) {
-		var that = this;
-
-		this.opos = [event.pageX, event.pageY];
-
-		if (this.options.disabled)
-			return;
-
-		var options = this.options;
-
-		this.selectees = $(options.filter, this.element[0]);
-
-		this._trigger("start", event);
-
-		$(options.appendTo).append(this.helper);
-		// position helper (lasso)
-		this.helper.css({
-			"left": event.clientX,
-			"top": event.clientY,
-			"width": 0,
-			"height": 0
-		});
-
-		if (options.autoRefresh) {
-			this.refresh();
-		}
-
-		this.selectees.filter('.ui-selected').each(function() {
-			var selectee = $.data(this, "selectable-item");
-			selectee.startselected = true;
-			if (!event.metaKey && !event.ctrlKey) {
-				selectee.$element.removeClass('ui-selected');
-				selectee.selected = false;
-				selectee.$element.addClass('ui-unselecting');
-				selectee.unselecting = true;
-				// selectable UNSELECTING callback
-				that._trigger("unselecting", event, {
-					unselecting: selectee.element
-				});
-			}
-		});
-
-		$(event.target).parents().andSelf().each(function() {
-			var selectee = $.data(this, "selectable-item");
-			if (selectee) {
-				var doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass('ui-selected');
-				selectee.$element
-					.removeClass(doSelect ? "ui-unselecting" : "ui-selected")
-					.addClass(doSelect ? "ui-selecting" : "ui-unselecting");
-				selectee.unselecting = !doSelect;
-				selectee.selecting = doSelect;
-				selectee.selected = doSelect;
-				// selectable (UN)SELECTING callback
-				if (doSelect) {
-					that._trigger("selecting", event, {
-						selecting: selectee.element
-					});
-				} else {
-					that._trigger("unselecting", event, {
-						unselecting: selectee.element
-					});
-				}
-				return false;
-			}
-		});
-
-	},
-
-	_mouseDrag: function(event) {
-		var that = this;
-		this.dragged = true;
-
-		if (this.options.disabled)
-			return;
-
-		var options = this.options;
-
-		var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
-		if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
-		if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
-		this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
-
-		this.selectees.each(function() {
-			var selectee = $.data(this, "selectable-item");
-			//prevent helper from being selected if appendTo: selectable
-			if (!selectee || selectee.element == that.element[0])
-				return;
-			var hit = false;
-			if (options.tolerance == 'touch') {
-				hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
-			} else if (options.tolerance == 'fit') {
-				hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
-			}
-
-			if (hit) {
-				// SELECT
-				if (selectee.selected) {
-					selectee.$element.removeClass('ui-selected');
-					selectee.selected = false;
-				}
-				if (selectee.unselecting) {
-					selectee.$element.removeClass('ui-unselecting');
-					selectee.unselecting = false;
-				}
-				if (!selectee.selecting) {
-					selectee.$element.addClass('ui-selecting');
-					selectee.selecting = true;
-					// selectable SELECTING callback
-					that._trigger("selecting", event, {
-						selecting: selectee.element
-					});
-				}
-			} else {
-				// UNSELECT
-				if (selectee.selecting) {
-					if ((event.metaKey || event.ctrlKey) && selectee.startselected) {
-						selectee.$element.removeClass('ui-selecting');
-						selectee.selecting = false;
-						selectee.$element.addClass('ui-selected');
-						selectee.selected = true;
-					} else {
-						selectee.$element.removeClass('ui-selecting');
-						selectee.selecting = false;
-						if (selectee.startselected) {
-							selectee.$element.addClass('ui-unselecting');
-							selectee.unselecting = true;
-						}
-						// selectable UNSELECTING callback
-						that._trigger("unselecting", event, {
-							unselecting: selectee.element
-						});
-					}
-				}
-				if (selectee.selected) {
-					if (!event.metaKey && !event.ctrlKey && !selectee.startselected) {
-						selectee.$element.removeClass('ui-selected');
-						selectee.selected = false;
-
-						selectee.$element.addClass('ui-unselecting');
-						selectee.unselecting = true;
-						// selectable UNSELECTING callback
-						that._trigger("unselecting", event, {
-							unselecting: selectee.element
-						});
-					}
-				}
-			}
-		});
-
-		return false;
-	},
-
-	_mouseStop: function(event) {
-		var that = this;
-
-		this.dragged = false;
-
-		var options = this.options;
-
-		$('.ui-unselecting', this.element[0]).each(function() {
-			var selectee = $.data(this, "selectable-item");
-			selectee.$element.removeClass('ui-unselecting');
-			selectee.unselecting = false;
-			selectee.startselected = false;
-			that._trigger("unselected", event, {
-				unselected: selectee.element
-			});
-		});
-		$('.ui-selecting', this.element[0]).each(function() {
-			var selectee = $.data(this, "selectable-item");
-			selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
-			selectee.selecting = false;
-			selectee.selected = true;
-			selectee.startselected = true;
-			that._trigger("selected", event, {
-				selected: selectee.element
-			});
-		});
-		this._trigger("stop", event);
-
-		this.helper.remove();
-
-		return false;
-	}
-
-});
-
-})(jQuery);
-(function( $, undefined ) {
-
-$.widget("ui.sortable", $.ui.mouse, {
-	version: "1.9.2",
-	widgetEventPrefix: "sort",
-	ready: false,
-	options: {
-		appendTo: "parent",
-		axis: false,
-		connectWith: false,
-		containment: false,
-		cursor: 'auto',
-		cursorAt: false,
-		dropOnEmpty: true,
-		forcePlaceholderSize: false,
-		forceHelperSize: false,
-		grid: false,
-		handle: false,
-		helper: "original",
-		items: '> *',
-		opacity: false,
-		placeholder: false,
-		revert: false,
-		scroll: true,
-		scrollSensitivity: 20,
-		scrollSpeed: 20,
-		scope: "default",
-		tolerance: "intersect",
-		zIndex: 1000
-	},
-	_create: function() {
-
-		var o = this.options;
-		this.containerCache = {};
-		this.element.addClass("ui-sortable");
-
-		//Get the items
-		this.refresh();
-
-		//Let's determine if the items are being displayed horizontally
-		this.floating = this.items.length ? o.axis === 'x' || (/left|right/).test(this.items[0].item.css('float')) || (/inline|table-cell/).test(this.items[0].item.css('display')) : false;
-
-		//Let's determine the parent's offset
-		this.offset = this.element.offset();
-
-		//Initialize mouse events for interaction
-		this._mouseInit();
-
-		//We're ready to go
-		this.ready = true
-
-	},
-
-	_destroy: function() {
-		this.element
-			.removeClass("ui-sortable ui-sortable-disabled");
-		this._mouseDestroy();
-
-		for ( var i = this.items.length - 1; i >= 0; i-- )
-			this.items[i].item.removeData(this.widgetName + "-item");
-
-		return this;
-	},
-
-	_setOption: function(key, value){
-		if ( key === "disabled" ) {
-			this.options[ key ] = value;
-
-			this.widget().toggleClass( "ui-sortable-disabled", !!value );
-		} else {
-			// Don't call widget base _setOption for disable as it adds ui-state-disabled class
-			$.Widget.prototype._setOption.apply(this, arguments);
-		}
-	},
-
-	_mouseCapture: function(event, overrideHandle) {
-		var that = this;
-
-		if (this.reverting) {
-			return false;
-		}
-
-		if(this.options.disabled || this.options.type == 'static') return false;
-
-		//We have to refresh the items data once first
-		this._refreshItems(event);
-
-		//Find out if the clicked node (or one of its parents) is a actual item in this.items
-		var currentItem = null, nodes = $(event.target).parents().each(function() {
-			if($.data(this, that.widgetName + '-item') == that) {
-				currentItem = $(this);
-				return false;
-			}
-		});
-		if($.data(event.target, that.widgetName + '-item') == that) currentItem = $(event.target);
-
-		if(!currentItem) return false;
-		if(this.options.handle && !overrideHandle) {
-			var validHandle = false;
-
-			$(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
-			if(!validHandle) return false;
-		}
-
-		this.currentItem = currentItem;
-		this._removeCurrentsFromItems();
-		return true;
-
-	},
-
-	_mouseStart: function(event, overrideHandle, noActivation) {
-
-		var o = this.options;
-		this.currentContainer = this;
-
-		//We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
-		this.refreshPositions();
-
-		//Create and append the visible helper
-		this.helper = this._createHelper(event);
-
-		//Cache the helper size
-		this._cacheHelperProportions();
-
-		/*
-		 * - Position generation -
-		 * This block generates everything position related - it's the core of draggables.
-		 */
-
-		//Cache the margins of the original element
-		this._cacheMargins();
-
-		//Get the next scrolling parent
-		this.scrollParent = this.helper.scrollParent();
-
-		//The element's absolute position on the page minus margins
-		this.offset = this.currentItem.offset();
-		this.offset = {
-			top: this.offset.top - this.margins.top,
-			left: this.offset.left - this.margins.left
-		};
-
-		$.extend(this.offset, {
-			click: { //Where the click happened, relative to the element
-				left: event.pageX - this.offset.left,
-				top: event.pageY - this.offset.top
-			},
-			parent: this._getParentOffset(),
-			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
-		});
-
-		// Only after we got the offset, we can change the helper's position to absolute
-		// TODO: Still need to figure out a way to make relative sorting possible
-		this.helper.css("position", "absolute");
-		this.cssPosition = this.helper.css("position");
-
-		//Generate the original position
-		this.originalPosition = this._generatePosition(event);
-		this.originalPageX = event.pageX;
-		this.originalPageY = event.pageY;
-
-		//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
-		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
-
-		//Cache the former DOM position
-		this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
-
-		//If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
-		if(this.helper[0] != this.currentItem[0]) {
-			this.currentItem.hide();
-		}
-
-		//Create the placeholder
-		this._createPlaceholder();
-
-		//Set a containment if given in the options
-		if(o.containment)
-			this._setContainment();
-
-		if(o.cursor) { // cursor option
-			if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
-			$('body').css("cursor", o.cursor);
-		}
-
-		if(o.opacity) { // opacity option
-			if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
-			this.helper.css("opacity", o.opacity);
-		}
-
-		if(o.zIndex) { // zIndex option
-			if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
-			this.helper.css("zIndex", o.zIndex);
-		}
-
-		//Prepare scrolling
-		if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
-			this.overflowOffset = this.scrollParent.offset();
-
-		//Call callbacks
-		this._trigger("start", event, this._uiHash());
-
-		//Recache the helper size
-		if(!this._preserveHelperProportions)
-			this._cacheHelperProportions();
-
-
-		//Post 'activate' events to possible containers
-		if(!noActivation) {
-			 for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, this._uiHash(this)); }
-		}
-
-		//Prepare possible droppables
-		if($.ui.ddmanager)
-			$.ui.ddmanager.current = this;
-
-		if ($.ui.ddmanager && !o.dropBehaviour)
-			$.ui.ddmanager.prepareOffsets(this, event);
-
-		this.dragging = true;
-
-		this.helper.addClass("ui-sortable-helper");
-		this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
-		return true;
-
-	},
-
-	_mouseDrag: function(event) {
-
-		//Compute the helpers position
-		this.position = this._generatePosition(event);
-		this.positionAbs = this._convertPositionTo("absolute");
-
-		if (!this.lastPositionAbs) {
-			this.lastPositionAbs = this.positionAbs;
-		}
-
-		//Do scrolling
-		if(this.options.scroll) {
-			var o = this.options, scrolled = false;
-			if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
-
-				if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
-					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
-				else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
-					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
-
-				if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
-					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
-				else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
-					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
-
-			} else {
-
-				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
-					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
-				else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
-					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
-
-				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
-					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
-				else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
-					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
-
-			}
-
-			if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
-				$.ui.ddmanager.prepareOffsets(this, event);
-		}
-
-		//Regenerate the absolute position used for position checks
-		this.positionAbs = this._convertPositionTo("absolute");
-
-		//Set the helper position
-		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
-		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
-
-		//Rearrange
-		for (var i = this.items.length - 1; i >= 0; i--) {
-
-			//Cache variables and intersection, continue if no intersection
-			var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
-			if (!intersection) continue;
-
-			// Only put the placeholder inside the current Container, skip all
-			// items form other containers. This works because when moving
-			// an item from one container to another the
-			// currentContainer is switched before the placeholder is moved.
-			//
-			// Without this moving items in "sub-sortables" can cause the placeholder to jitter
-			// beetween the outer and inner container.
-			if (item.instance !== this.currentContainer) continue;
-
-			if (itemElement != this.currentItem[0] //cannot intersect with itself
-				&&	this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
-				&&	!$.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
-				&& (this.options.type == 'semi-dynamic' ? !$.contains(this.element[0], itemElement) : true)
-				//&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
-			) {
-
-				this.direction = intersection == 1 ? "down" : "up";
-
-				if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
-					this._rearrange(event, item);
-				} else {
-					break;
-				}
-
-				this._trigger("change", event, this._uiHash());
-				break;
-			}
-		}
-
-		//Post events to containers
-		this._contactContainers(event);
-
-		//Interconnect with droppables
-		if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
-
-		//Call callbacks
-		this._trigger('sort', event, this._uiHash());
-
-		this.lastPositionAbs = this.positionAbs;
-		return false;
-
-	},
-
-	_mouseStop: function(event, noPropagation) {
-
-		if(!event) return;
-
-		//If we are using droppables, inform the manager about the drop
-		if ($.ui.ddmanager && !this.options.dropBehaviour)
-			$.ui.ddmanager.drop(this, event);
-
-		if(this.options.revert) {
-			var that = this;
-			var cur = this.placeholder.offset();
-
-			this.reverting = true;
-
-			$(this.helper).animate({
-				left: cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
-				top: cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
-			}, parseInt(this.options.revert, 10) || 500, function() {
-				that._clear(event);
-			});
-		} else {
-			this._clear(event, noPropagation);
-		}
-
-		return false;
-
-	},
-
-	cancel: function() {
-
-		if(this.dragging) {
-
-			this._mouseUp({ target: null });
-
-			if(this.options.helper == "original")
-				this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
-			else
-				this.currentItem.show();
-
-			//Post deactivating events to containers
-			for (var i = this.containers.length - 1; i >= 0; i--){
-				this.containers[i]._trigger("deactivate", null, this._uiHash(this));
-				if(this.containers[i].containerCache.over) {
-					this.containers[i]._trigger("out", null, this._uiHash(this));
-					this.containers[i].containerCache.over = 0;
-				}
-			}
-
-		}
-
-		if (this.placeholder) {
-			//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
-			if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
-			if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
-
-			$.extend(this, {
-				helper: null,
-				dragging: false,
-				reverting: false,
-				_noFinalSort: null
-			});
-
-			if(this.domPosition.prev) {
-				$(this.domPosition.prev).after(this.currentItem);
-			} else {
-				$(this.domPosition.parent).prepend(this.currentItem);
-			}
-		}
-
-		return this;
-
-	},
-
-	serialize: function(o) {
-
-		var items = this._getItemsAsjQuery(o && o.connected);
-		var str = []; o = o || {};
-
-		$(items).each(function() {
-			var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
-			if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
-		});
-
-		if(!str.length && o.key) {
-			str.push(o.key + '=');
-		}
-
-		return str.join('&');
-
-	},
-
-	toArray: function(o) {
-
-		var items = this._getItemsAsjQuery(o && o.connected);
-		var ret = []; o = o || {};
-
-		items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
-		return ret;
-
-	},
-
-	/* Be careful with the following core functions */
-	_intersectsWith: function(item) {
-
-		var x1 = this.positionAbs.left,
-			x2 = x1 + this.helperProportions.width,
-			y1 = this.positionAbs.top,
-			y2 = y1 + this.helperProportions.height;
-
-		var l = item.left,
-			r = l + item.width,
-			t = item.top,
-			b = t + item.height;
-
-		var dyClick = this.offset.click.top,
-			dxClick = this.offset.click.left;
-
-		var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
-
-		if(	   this.options.tolerance == "pointer"
-			|| this.options.forcePointerForContainers
-			|| (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
-		) {
-			return isOverElement;
-		} else {
-
-			return (l < x1 + (this.helperProportions.width / 2) // Right Half
-				&& x2 - (this.helperProportions.width / 2) < r // Left Half
-				&& t < y1 + (this.helperProportions.height / 2) // Bottom Half
-				&& y2 - (this.helperProportions.height / 2) < b ); // Top Half
-
-		}
-	},
-
-	_intersectsWithPointer: function(item) {
-
-		var isOverElementHeight = (this.options.axis === 'x') || $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
-			isOverElementWidth = (this.options.axis === 'y') || $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
-			isOverElement = isOverElementHeight && isOverElementWidth,
-			verticalDirection = this._getDragVerticalDirection(),
-			horizontalDirection = this._getDragHorizontalDirection();
-
-		if (!isOverElement)
-			return false;
-
-		return this.floating ?
-			( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
-			: ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
-
-	},
-
-	_intersectsWithSides: function(item) {
-
-		var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
-			isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
-			verticalDirection = this._getDragVerticalDirection(),
-			horizontalDirection = this._getDragHorizontalDirection();
-
-		if (this.floating && horizontalDirection) {
-			return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
-		} else {
-			return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
-		}
-
-	},
-
-	_getDragVerticalDirection: function() {
-		var delta = this.positionAbs.top - this.lastPositionAbs.top;
-		return delta != 0 && (delta > 0 ? "down" : "up");
-	},
-
-	_getDragHorizontalDirection: function() {
-		var delta = this.positionAbs.left - this.lastPositionAbs.left;
-		return delta != 0 && (delta > 0 ? "right" : "left");
-	},
-
-	refresh: function(event) {
-		this._refreshItems(event);
-		this.refreshPositions();
-		return this;
-	},
-
-	_connectWith: function() {
-		var options = this.options;
-		return options.connectWith.constructor == String
-			? [options.connectWith]
-			: options.connectWith;
-	},
-
-	_getItemsAsjQuery: function(connected) {
-
-		var items = [];
-		var queries = [];
-		var connectWith = this._connectWith();
-
-		if(connectWith && connected) {
-			for (var i = connectWith.length - 1; i >= 0; i--){
-				var cur = $(connectWith[i]);
-				for (var j = cur.length - 1; j >= 0; j--){
-					var inst = $.data(cur[j], this.widgetName);
-					if(inst && inst != this && !inst.options.disabled) {
-						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]);
-					}
-				};
-			};
-		}
-
-		queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]);
-
-		for (var i = queries.length - 1; i >= 0; i--){
-			queries[i][0].each(function() {
-				items.push(this);
-			});
-		};
-
-		return $(items);
-
-	},
-
-	_removeCurrentsFromItems: function() {
-
-		var list = this.currentItem.find(":data(" + this.widgetName + "-item)");
-
-		this.items = $.grep(this.items, function (item) {
-			for (var j=0; j < list.length; j++) {
-				if(list[j] == item.item[0])
-					return false;
-			};
-			return true;
-		});
-
-	},
-
-	_refreshItems: function(event) {
-
-		this.items = [];
-		this.containers = [this];
-		var items = this.items;
-		var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
-		var connectWith = this._connectWith();
-
-		if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down
-			for (var i = connectWith.length - 1; i >= 0; i--){
-				var cur = $(connectWith[i]);
-				for (var j = cur.length - 1; j >= 0; j--){
-					var inst = $.data(cur[j], this.widgetName);
-					if(inst && inst != this && !inst.options.disabled) {
-						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
-						this.containers.push(inst);
-					}
-				};
-			};
-		}
-
-		for (var i = queries.length - 1; i >= 0; i--) {
-			var targetData = queries[i][1];
-			var _queries = queries[i][0];
-
-			for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
-				var item = $(_queries[j]);
-
-				item.data(this.widgetName + '-item', targetData); // Data for target checking (mouse manager)
-
-				items.push({
-					item: item,
-					instance: targetData,
-					width: 0, height: 0,
-					left: 0, top: 0
-				});
-			};
-		};
-
-	},
-
-	refreshPositions: function(fast) {
-
-		//This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
-		if(this.offsetParent && this.helper) {
-			this.offset.parent = this._getParentOffset();
-		}
-
-		for (var i = this.items.length - 1; i >= 0; i--){
-			var item = this.items[i];
-
-			//We ignore calculating positions of all connected containers when we're not over them
-			if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0])
-				continue;
-
-			var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
-
-			if (!fast) {
-				item.width = t.outerWidth();
-				item.height = t.outerHeight();
-			}
-
-			var p = t.offset();
-			item.left = p.left;
-			item.top = p.top;
-		};
-
-		if(this.options.custom && this.options.custom.refreshContainers) {
-			this.options.custom.refreshContainers.call(this);
-		} else {
-			for (var i = this.containers.length - 1; i >= 0; i--){
-				var p = this.containers[i].element.offset();
-				this.containers[i].containerCache.left = p.left;
-				this.containers[i].containerCache.top = p.top;
-				this.containers[i].containerCache.width	= this.containers[i].element.outerWidth();
-				this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
-			};
-		}
-
-		return this;
-	},
-
-	_createPlaceholder: function(that) {
-		that = that || this;
-		var o = that.options;
-
-		if(!o.placeholder || o.placeholder.constructor == String) {
-			var className = o.placeholder;
-			o.placeholder = {
-				element: function() {
-
-					var el = $(document.createElement(that.currentItem[0].nodeName))
-						.addClass(className || that.currentItem[0].className+" ui-sortable-placeholder")
-						.removeClass("ui-sortable-helper")[0];
-
-					if(!className)
-						el.style.visibility = "hidden";
-
-					return el;
-				},
-				update: function(container, p) {
-
-					// 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
-					// 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
-					if(className && !o.forcePlaceholderSize) return;
-
-					//If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
-					if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css('paddingTop')||0, 10) - parseInt(that.currentItem.css('paddingBottom')||0, 10)); };
-					if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css('paddingLeft')||0, 10) - parseInt(that.currentItem.css('paddingRight')||0, 10)); };
-				}
-			};
-		}
-
-		//Create the placeholder
-		that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem));
-
-		//Append it after the actual current item
-		that.currentItem.after(that.placeholder);
-
-		//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
-		o.placeholder.update(that, that.placeholder);
-
-	},
-
-	_contactContainers: function(event) {
-
-		// get innermost container that intersects with item
-		var innermostContainer = null, innermostIndex = null;
-
-
-		for (var i = this.containers.length - 1; i >= 0; i--){
-
-			// never consider a container that's located within the item itself
-			if($.contains(this.currentItem[0], this.containers[i].element[0]))
-				continue;
-
-			if(this._intersectsWith(this.containers[i].containerCache)) {
-
-				// if we've already found a container and it's more "inner" than this, then continue
-				if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0]))
-					continue;
-
-				innermostContainer = this.containers[i];
-				innermostIndex = i;
-
-			} else {
-				// container doesn't intersect. trigger "out" event if necessary
-				if(this.containers[i].containerCache.over) {
-					this.containers[i]._trigger("out", event, this._uiHash(this));
-					this.containers[i].containerCache.over = 0;
-				}
-			}
-
-		}
-
-		// if no intersecting containers found, return
-		if(!innermostContainer) return;
-
-		// move the item into the container if it's not there already
-		if(this.containers.length === 1) {
-			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
-			this.containers[innermostIndex].containerCache.over = 1;
-		} else {
-
-			//When entering a new container, we will find the item with the least distance and append our item near it
-			var dist = 10000; var itemWithLeastDistance = null;
-			var posProperty = this.containers[innermostIndex].floating ? 'left' : 'top';
-			var sizeProperty = this.containers[innermostIndex].floating ? 'width' : 'height';
-			var base = this.positionAbs[posProperty] + this.offset.click[posProperty];
-			for (var j = this.items.length - 1; j >= 0; j--) {
-				if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue;
-				if(this.items[j].item[0] == this.currentItem[0]) continue;
-				var cur = this.items[j].item.offset()[posProperty];
-				var nearBottom = false;
-				if(Math.abs(cur - base) > Math.abs(cur + this.items[j][sizeProperty] - base)){
-					nearBottom = true;
-					cur += this.items[j][sizeProperty];
-				}
-
-				if(Math.abs(cur - base) < dist) {
-					dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
-					this.direction = nearBottom ? "up": "down";
-				}
-			}
-
-			if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled
-				return;
-
-			this.currentContainer = this.containers[innermostIndex];
-			itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
-			this._trigger("change", event, this._uiHash());
-			this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
-
-			//Update the placeholder
-			this.options.placeholder.update(this.currentContainer, this.placeholder);
-
-			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
-			this.containers[innermostIndex].containerCache.over = 1;
-		}
-
-
-	},
-
-	_createHelper: function(event) {
-
-		var o = this.options;
-		var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
-
-		if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
-			$(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
-
-		if(helper[0] == this.currentItem[0])
-			this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };
-
-		if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
-		if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
-
-		return helper;
-
-	},
-
-	_adjustOffsetFromHelper: function(obj) {
-		if (typeof obj == 'string') {
-			obj = obj.split(' ');
-		}
-		if ($.isArray(obj)) {
-			obj = {left: +obj[0], top: +obj[1] || 0};
-		}
-		if ('left' in obj) {
-			this.offset.click.left = obj.left + this.margins.left;
-		}
-		if ('right' in obj) {
-			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
-		}
-		if ('top' in obj) {
-			this.offset.click.top = obj.top + this.margins.top;
-		}
-		if ('bottom' in obj) {
-			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
-		}
-	},
-
-	_getParentOffset: function() {
-
-
-		//Get the offsetParent and cache its position
-		this.offsetParent = this.helper.offsetParent();
-		var po = this.offsetParent.offset();
-
-		// This is a special case where we need to modify a offset calculated on start, since the following happened:
-		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
-		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
-		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
-		if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
-			po.left += this.scrollParent.scrollLeft();
-			po.top += this.scrollParent.scrollTop();
-		}
-
-		if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
-		|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.ui.ie)) //Ugly IE fix
-			po = { top: 0, left: 0 };
-
-		return {
-			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
-			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
-		};
-
-	},
-
-	_getRelativeOffset: function() {
-
-		if(this.cssPosition == "relative") {
-			var p = this.currentItem.position();
-			return {
-				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
-				left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
-			};
-		} else {
-			return { top: 0, left: 0 };
-		}
-
-	},
-
-	_cacheMargins: function() {
-		this.margins = {
-			left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
-			top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
-		};
-	},
-
-	_cacheHelperProportions: function() {
-		this.helperProportions = {
-			width: this.helper.outerWidth(),
-			height: this.helper.outerHeight()
-		};
-	},
-
-	_setContainment: function() {
-
-		var o = this.options;
-		if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
-		if(o.containment == 'document' || o.containment == 'window') this.containment = [
-			0 - this.offset.relative.left - this.offset.parent.left,
-			0 - this.offset.relative.top - this.offset.parent.top,
-			$(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
-			($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
-		];
-
-		if(!(/^(document|window|parent)$/).test(o.containment)) {
-			var ce = $(o.containment)[0];
-			var co = $(o.containment).offset();
-			var over = ($(ce).css("overflow") != 'hidden');
-
-			this.containment = [
-				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
-				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
-				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
-				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
-			];
-		}
-
-	},
-
-	_convertPositionTo: function(d, pos) {
-
-		if(!pos) pos = this.position;
-		var mod = d == "absolute" ? 1 : -1;
-		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
-
-		return {
-			top: (
-				pos.top																	// The absolute mouse position
-				+ this.offset.relative.top * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
-				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
-				- ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
-			),
-			left: (
-				pos.left																// The absolute mouse position
-				+ this.offset.relative.left * mod										// Only for relative positioned nodes: Relative offset from element to offset parent
-				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
-				- ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
-			)
-		};
-
-	},
-
-	_generatePosition: function(event) {
-
-		var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
-
-		// This is another very weird special case that only happens for relative elements:
-		// 1. If the css position is relative
-		// 2. and the scroll parent is the document or similar to the offset parent
-		// we have to refresh the relative offset during the scroll so there are no jumps
-		if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
-			this.offset.relative = this._getRelativeOffset();
-		}
-
-		var pageX = event.pageX;
-		var pageY = event.pageY;
-
-		/*
-		 * - Position constraining -
-		 * Constrain the position to a mix of grid, containment.
-		 */
-
-		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
-
-			if(this.containment) {
-				if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
-				if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
-				if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
-				if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
-			}
-
-			if(o.grid) {
-				var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
-				pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
-
-				var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
-				pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
-			}
-
-		}
-
-		return {
-			top: (
-				pageY																// The absolute mouse position
-				- this.offset.click.top													// Click offset (relative to the element)
-				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
-				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
-				+ ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
-			),
-			left: (
-				pageX																// The absolute mouse position
-				- this.offset.click.left												// Click offset (relative to the element)
-				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
-				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
-				+ ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
-			)
-		};
-
-	},
-
-	_rearrange: function(event, i, a, hardRefresh) {
-
-		a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling));
-
-		//Various things done here to improve the performance:
-		// 1. we create a setTimeout, that calls refreshPositions
-		// 2. on the instance, we have a counter variable, that get's higher after every append
-		// 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
-		// 4. this lets only the last addition to the timeout stack through
-		this.counter = this.counter ? ++this.counter : 1;
-		var counter = this.counter;
-
-		this._delay(function() {
-			if(counter == this.counter) this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
-		});
-
-	},
-
-	_clear: function(event, noPropagation) {
-
-		this.reverting = false;
-		// We delay all events that have to be triggered to after the point where the placeholder has been removed and
-		// everything else normalized again
-		var delayedTriggers = [];
-
-		// We first have to update the dom position of the actual currentItem
-		// Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
-		if(!this._noFinalSort && this.currentItem.parent().length) this.placeholder.before(this.currentItem);
-		this._noFinalSort = null;
-
-		if(this.helper[0] == this.currentItem[0]) {
-			for(var i in this._storedCSS) {
-				if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
-			}
-			this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
-		} else {
-			this.currentItem.show();
-		}
-
-		if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
-		if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
-
-		// Check if the items Container has Changed and trigger appropriate
-		// events.
-		if (this !== this.currentContainer) {
-			if(!noPropagation) {
-				delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
-				delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.currentContainer));
-				delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.currentContainer));
-			}
-		}
-
-
-		//Post events to containers
-		for (var i = this.containers.length - 1; i >= 0; i--){
-			if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
-			if(this.containers[i].containerCache.over) {
-				delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
-				this.containers[i].containerCache.over = 0;
-			}
-		}
-
-		//Do what was originally in plugins
-		if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
-		if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
-		if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
-
-		this.dragging = false;
-		if(this.cancelHelperRemoval) {
-			if(!noPropagation) {
-				this._trigger("beforeStop", event, this._uiHash());
-				for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
-				this._trigger("stop", event, this._uiHash());
-			}
-
-			this.fromOutside = false;
-			return false;
-		}
-
-		if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
-
-		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
-		this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
-
-		if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
-
-		if(!noPropagation) {
-			for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
-			this._trigger("stop", event, this._uiHash());
-		}
-
-		this.fromOutside = false;
-		return true;
-
-	},
-
-	_trigger: function() {
-		if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
-			this.cancel();
-		}
-	},
-
-	_uiHash: function(_inst) {
-		var inst = _inst || this;
-		return {
-			helper: inst.helper,
-			placeholder: inst.placeholder || $([]),
-			position: inst.position,
-			originalPosition: inst.originalPosition,
-			offset: inst.positionAbs,
-			item: inst.currentItem,
-			sender: _inst ? _inst.element : null
-		};
-	}
-
-});
-
-})(jQuery);
-(function( $, undefined ) {
-
-var uid = 0,
-	hideProps = {},
-	showProps = {};
-
-hideProps.height = hideProps.paddingTop = hideProps.paddingBottom =
-	hideProps.borderTopWidth = hideProps.borderBottomWidth = "hide";
-showProps.height = showProps.paddingTop = showProps.paddingBottom =
-	showProps.borderTopWidth = showProps.borderBottomWidth = "show";
-
-$.widget( "ui.accordion", {
-	version: "1.9.2",
-	options: {
-		active: 0,
-		animate: {},
-		collapsible: false,
-		event: "click",
-		header: "> li > :first-child,> :not(li):even",
-		heightStyle: "auto",
-		icons: {
-			activeHeader: "ui-icon-triangle-1-s",
-			header: "ui-icon-triangle-1-e"
-		},
-
-		// callbacks
-		activate: null,
-		beforeActivate: null
-	},
-
-	_create: function() {
-		var accordionId = this.accordionId = "ui-accordion-" +
-				(this.element.attr( "id" ) || ++uid),
-			options = this.options;
-
-		this.prevShow = this.prevHide = $();
-		this.element.addClass( "ui-accordion ui-widget ui-helper-reset" );
-
-		this.headers = this.element.find( options.header )
-			.addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" );
-		this._hoverable( this.headers );
-		this._focusable( this.headers );
-
-		this.headers.next()
-			.addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" )
-			.hide();
-
-		// don't allow collapsible: false and active: false / null
-		if ( !options.collapsible && (options.active === false || options.active == null) ) {
-			options.active = 0;
-		}
-		// handle negative values
-		if ( options.active < 0 ) {
-			options.active += this.headers.length;
-		}
-		this.active = this._findActive( options.active )
-			.addClass( "ui-accordion-header-active ui-state-active" )
-			.toggleClass( "ui-corner-all ui-corner-top" );
-		this.active.next()
-			.addClass( "ui-accordion-content-active" )
-			.show();
-
-		this._createIcons();
-		this.refresh();
-
-		// ARIA
-		this.element.attr( "role", "tablist" );
-
-		this.headers
-			.attr( "role", "tab" )
-			.each(function( i ) {
-				var header = $( this ),
-					headerId = header.attr( "id" ),
-					panel = header.next(),
-					panelId = panel.attr( "id" );
-				if ( !headerId ) {
-					headerId = accordionId + "-header-" + i;
-					header.attr( "id", headerId );
-				}
-				if ( !panelId ) {
-					panelId = accordionId + "-panel-" + i;
-					panel.attr( "id", panelId );
-				}
-				header.attr( "aria-controls", panelId );
-				panel.attr( "aria-labelledby", headerId );
-			})
-			.next()
-				.attr( "role", "tabpanel" );
-
-		this.headers
-			.not( this.active )
-			.attr({
-				"aria-selected": "false",
-				tabIndex: -1
-			})
-			.next()
-				.attr({
-					"aria-expanded": "false",
-					"aria-hidden": "true"
-				})
-				.hide();
-
-		// make sure at least one header is in the tab order
-		if ( !this.active.length ) {
-			this.headers.eq( 0 ).attr( "tabIndex", 0 );
-		} else {
-			this.active.attr({
-				"aria-selected": "true",
-				tabIndex: 0
-			})
-			.next()
-				.attr({
-					"aria-expanded": "true",
-					"aria-hidden": "false"
-				});
-		}
-
-		this._on( this.headers, { keydown: "_keydown" });
-		this._on( this.headers.next(), { keydown: "_panelKeyDown" });
-		this._setupEvents( options.event );
-	},
-
-	_getCreateEventData: function() {
-		return {
-			header: this.active,
-			content: !this.active.length ? $() : this.active.next()
-		};
-	},
-
-	_createIcons: function() {
-		var icons = this.options.icons;
-		if ( icons ) {
-			$( "<span>" )
-				.addClass( "ui-accordion-header-icon ui-icon " + icons.header )
-				.prependTo( this.headers );
-			this.active.children( ".ui-accordion-header-icon" )
-				.removeClass( icons.header )
-				.addClass( icons.activeHeader );
-			this.headers.addClass( "ui-accordion-icons" );
-		}
-	},
-
-	_destroyIcons: function() {
-		this.headers
-			.removeClass( "ui-accordion-icons" )
-			.children( ".ui-accordion-header-icon" )
-				.remove();
-	},
-
-	_destroy: function() {
-		var contents;
-
-		// clean up main element
-		this.element
-			.removeClass( "ui-accordion ui-widget ui-helper-reset" )
-			.removeAttr( "role" );
-
-		// clean up headers
-		this.headers
-			.removeClass( "ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
-			.removeAttr( "role" )
-			.removeAttr( "aria-selected" )
-			.removeAttr( "aria-controls" )
-			.removeAttr( "tabIndex" )
-			.each(function() {
-				if ( /^ui-accordion/.test( this.id ) ) {
-					this.removeAttribute( "id" );
-				}
-			});
-		this._destroyIcons();
-
-		// clean up content panels
-		contents = this.headers.next()
-			.css( "display", "" )
-			.removeAttr( "role" )
-			.removeAttr( "aria-expanded" )
-			.removeAttr( "aria-hidden" )
-			.removeAttr( "aria-labelledby" )
-			.removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled" )
-			.each(function() {
-				if ( /^ui-accordion/.test( this.id ) ) {
-					this.removeAttribute( "id" );
-				}
-			});
-		if ( this.options.heightStyle !== "content" ) {
-			contents.css( "height", "" );
-		}
-	},
-
-	_setOption: function( key, value ) {
-		if ( key === "active" ) {
-			// _activate() will handle invalid values and update this.options
-			this._activate( value );
-			return;
-		}
-
-		if ( key === "event" ) {
-			if ( this.options.event ) {
-				this._off( this.headers, this.options.event );
-			}
-			this._setupEvents( value );
-		}
-
-		this._super( key, value );
-
-		// setting collapsible: false while collapsed; open first panel
-		if ( key === "collapsible" && !value && this.options.active === false ) {
-			this._activate( 0 );
-		}
-
-		if ( key === "icons" ) {
-			this._destroyIcons();
-			if ( value ) {
-				this._createIcons();
-			}
-		}
-
-		// #5332 - opacity doesn't cascade to positioned elements in IE
-		// so we need to add the disabled class to the headers and panels
-		if ( key === "disabled" ) {
-			this.headers.add( this.headers.next() )
-				.toggleClass( "ui-state-disabled", !!value );
-		}
-	},
-
-	_keydown: function( event ) {
-		if ( event.altKey || event.ctrlKey ) {
-			return;
-		}
-
-		var keyCode = $.ui.keyCode,
-			length = this.headers.length,
-			currentIndex = this.headers.index( event.target ),
-			toFocus = false;
-
-		switch ( event.keyCode ) {
-			case keyCode.RIGHT:
-			case keyCode.DOWN:
-				toFocus = this.headers[ ( currentIndex + 1 ) % length ];
-				break;
-			case keyCode.LEFT:
-			case keyCode.UP:
-				toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
-				break;
-			case keyCode.SPACE:
-			case keyCode.ENTER:
-				this._eventHandler( event );
-				break;
-			case keyCode.HOME:
-				toFocus = this.headers[ 0 ];
-				break;
-			case keyCode.END:
-				toFocus = this.headers[ length - 1 ];
-				break;
-		}
-
-		if ( toFocus ) {
-			$( event.target ).attr( "tabIndex", -1 );
-			$( toFocus ).attr( "tabIndex", 0 );
-			toFocus.focus();
-			event.preventDefault();
-		}
-	},
-
-	_panelKeyDown : function( event ) {
-		if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
-			$( event.currentTarget ).prev().focus();
-		}
-	},
-
-	refresh: function() {
-		var maxHeight, overflow,
-			heightStyle = this.options.heightStyle,
-			parent = this.element.parent();
-
-
-		if ( heightStyle === "fill" ) {
-			// IE 6 treats height like minHeight, so we need to turn off overflow
-			// in order to get a reliable height
-			// we use the minHeight support test because we assume that only
-			// browsers that don't support minHeight will treat height as minHeight
-			if ( !$.support.minHeight ) {
-				overflow = parent.css( "overflow" );
-				parent.css( "overflow", "hidden");
-			}
-			maxHeight = parent.height();
-			this.element.siblings( ":visible" ).each(function() {
-				var elem = $( this ),
-					position = elem.css( "position" );
-
-				if ( position === "absolute" || position === "fixed" ) {
-					return;
-				}
-				maxHeight -= elem.outerHeight( true );
-			});
-			if ( overflow ) {
-				parent.css( "overflow", overflow );
-			}
-
-			this.headers.each(function() {
-				maxHeight -= $( this ).outerHeight( true );
-			});
-
-			this.headers.next()
-				.each(function() {
-					$( this ).height( Math.max( 0, maxHeight -
-						$( this ).innerHeight() + $( this ).height() ) );
-				})
-				.css( "overflow", "auto" );
-		} else if ( heightStyle === "auto" ) {
-			maxHeight = 0;
-			this.headers.next()
-				.each(function() {
-					maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
-				})
-				.height( maxHeight );
-		}
-	},
-
-	_activate: function( index ) {
-		var active = this._findActive( index )[ 0 ];
-
-		// trying to activate the already active panel
-		if ( active === this.active[ 0 ] ) {
-			return;
-		}
-
-		// trying to collapse, simulate a click on the currently active header
-		active = active || this.active[ 0 ];
-
-		this._eventHandler({
-			target: active,
-			currentTarget: active,
-			preventDefault: $.noop
-		});
-	},
-
-	_findActive: function( selector ) {
-		return typeof selector === "number" ? this.headers.eq( selector ) : $();
-	},
-
-	_setupEvents: function( event ) {
-		var events = {};
-		if ( !event ) {
-			return;
-		}
-		$.each( event.split(" "), function( index, eventName ) {
-			events[ eventName ] = "_eventHandler";
-		});
-		this._on( this.headers, events );
-	},
-
-	_eventHandler: function( event ) {
-		var options = this.options,
-			active = this.active,
-			clicked = $( event.currentTarget ),
-			clickedIsActive = clicked[ 0 ] === active[ 0 ],
-			collapsing = clickedIsActive && options.collapsible,
-			toShow = collapsing ? $() : clicked.next(),
-			toHide = active.next(),
-			eventData = {
-				oldHeader: active,
-				oldPanel: toHide,
-				newHeader: collapsing ? $() : clicked,
-				newPanel: toShow
-			};
-
-		event.preventDefault();
-
-		if (
-				// click on active header, but not collapsible
-				( clickedIsActive && !options.collapsible ) ||
-				// allow canceling activation
-				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
-			return;
-		}
-
-		options.active = collapsing ? false : this.headers.index( clicked );
-
-		// when the call to ._toggle() comes after the class changes
-		// it causes a very odd bug in IE 8 (see #6720)
-		this.active = clickedIsActive ? $() : clicked;
-		this._toggle( eventData );
-
-		// switch classes
-		// corner classes on the previously active header stay after the animation
-		active.removeClass( "ui-accordion-header-active ui-state-active" );
-		if ( options.icons ) {
-			active.children( ".ui-accordion-header-icon" )
-				.removeClass( options.icons.activeHeader )
-				.addClass( options.icons.header );
-		}
-
-		if ( !clickedIsActive ) {
-			clicked
-				.removeClass( "ui-corner-all" )
-				.addClass( "ui-accordion-header-active ui-state-active ui-corner-top" );
-			if ( options.icons ) {
-				clicked.children( ".ui-accordion-header-icon" )
-					.removeClass( options.icons.header )
-					.addClass( options.icons.activeHeader );
-			}
-
-			clicked
-				.next()
-				.addClass( "ui-accordion-content-active" );
-		}
-	},
-
-	_toggle: function( data ) {
-		var toShow = data.newPanel,
-			toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
-
-		// handle activating a panel during the animation for another activation
-		this.prevShow.add( this.prevHide ).stop( true, true );
-		this.prevShow = toShow;
-		this.prevHide = toHide;
-
-		if ( this.options.animate ) {
-			this._animate( toShow, toHide, data );
-		} else {
-			toHide.hide();
-			toShow.show();
-			this._toggleComplete( data );
-		}
-
-		toHide.attr({
-			"aria-expanded": "false",
-			"aria-hidden": "true"
-		});
-		toHide.prev().attr( "aria-selected", "false" );
-		// if we're switching panels, remove the old header from the tab order
-		// if we're opening from collapsed state, remove the previous header from the tab order
-		// if we're collapsing, then keep the collapsing header in the tab order
-		if ( toShow.length && toHide.length ) {
-			toHide.prev().attr( "tabIndex", -1 );
-		} else if ( toShow.length ) {
-			this.headers.filter(function() {
-				return $( this ).attr( "tabIndex" ) === 0;
-			})
-			.attr( "tabIndex", -1 );
-		}
-
-		toShow
-			.attr({
-				"aria-expanded": "true",
-				"aria-hidden": "false"
-			})
-			.prev()
-				.attr({
-					"aria-selected": "true",
-					tabIndex: 0
-				});
-	},
-
-	_animate: function( toShow, toHide, data ) {
-		var total, easing, duration,
-			that = this,
-			adjust = 0,
-			down = toShow.length &&
-				( !toHide.length || ( toShow.index() < toHide.index() ) ),
-			animate = this.options.animate || {},
-			options = down && animate.down || animate,
-			complete = function() {
-				that._toggleComplete( data );
-			};
-
-		if ( typeof options === "number" ) {
-			duration = options;
-		}
-		if ( typeof options === "string" ) {
-			easing = options;
-		}
-		// fall back from options to animation in case of partial down settings
-		easing = easing || options.easing || animate.easing;
-		duration = duration || options.duration || animate.duration;
-
-		if ( !toHide.length ) {
-			return toShow.animate( showProps, duration, easing, complete );
-		}
-		if ( !toShow.length ) {
-			return toHide.animate( hideProps, duration, easing, complete );
-		}
-
-		total = toShow.show().outerHeight();
-		toHide.animate( hideProps, {
-			duration: duration,
-			easing: easing,
-			step: function( now, fx ) {
-				fx.now = Math.round( now );
-			}
-		});
-		toShow
-			.hide()
-			.animate( showProps, {
-				duration: duration,
-				easing: easing,
-				complete: complete,
-				step: function( now, fx ) {
-					fx.now = Math.round( now );
-					if ( fx.prop !== "height" ) {
-						adjust += fx.now;
-					} else if ( that.options.heightStyle !== "content" ) {
-						fx.now = Math.round( total - toHide.outerHeight() - adjust );
-						adjust = 0;
-					}
-				}
-			});
-	},
-
-	_toggleComplete: function( data ) {
-		var toHide = data.oldPanel;
-
-		toHide
-			.removeClass( "ui-accordion-content-active" )
-			.prev()
-				.removeClass( "ui-corner-top" )
-				.addClass( "ui-corner-all" );
-
-		// Work around for rendering bug in IE (#5421)
-		if ( toHide.length ) {
-			toHide.parent()[0].className = toHide.parent()[0].className;
-		}
-
-		this._trigger( "activate", null, data );
-	}
-});
-
-
-
-// DEPRECATED
-if ( $.uiBackCompat !== false ) {
-	// navigation options
-	(function( $, prototype ) {
-		$.extend( prototype.options, {
-			navigation: false,
-			navigationFilter: function() {
-				return this.href.toLowerCase() === location.href.toLowerCase();
-			}
-		});
-
-		var _create = prototype._create;
-		prototype._create = function() {
-			if ( this.options.navigation ) {
-				var that = this,
-					headers = this.element.find( this.options.header ),
-					content = headers.next(),
-					current = headers.add( content )
-						.find( "a" )
-						.filter( this.options.navigationFilter )
-						[ 0 ];
-				if ( current ) {
-					headers.add( content ).each( function( index ) {
-						if ( $.contains( this, current ) ) {
-							that.options.active = Math.floor( index / 2 );
-							return false;
-						}
-					});
-				}
-			}
-			_create.call( this );
-		};
-	}( jQuery, jQuery.ui.accordion.prototype ) );
-
-	// height options
-	(function( $, prototype ) {
-		$.extend( prototype.options, {
-			heightStyle: null, // remove default so we fall back to old values
-			autoHeight: true, // use heightStyle: "auto"
-			clearStyle: false, // use heightStyle: "content"
-			fillSpace: false // use heightStyle: "fill"
-		});
-
-		var _create = prototype._create,
-			_setOption = prototype._setOption;
-
-		$.extend( prototype, {
-			_create: function() {
-				this.options.heightStyle = this.options.heightStyle ||
-					this._mergeHeightStyle();
-
-				_create.call( this );
-			},
-
-			_setOption: function( key ) {
-				if ( key === "autoHeight" || key === "clearStyle" || key === "fillSpace" ) {
-					this.options.heightStyle = this._mergeHeightStyle();
-				}
-				_setOption.apply( this, arguments );
-			},
-
-			_mergeHeightStyle: function() {
-				var options = this.options;
-
-				if ( options.fillSpace ) {
-					return "fill";
-				}
-
-				if ( options.clearStyle ) {
-					return "content";
-				}
-
-				if ( options.autoHeight ) {
-					return "auto";
-				}
-			}
-		});
-	}( jQuery, jQuery.ui.accordion.prototype ) );
-
-	// icon options
-	(function( $, prototype ) {
-		$.extend( prototype.options.icons, {
-			activeHeader: null, // remove default so we fall back to old values
-			headerSelected: "ui-icon-triangle-1-s"
-		});
-
-		var _createIcons = prototype._createIcons;
-		prototype._createIcons = function() {
-			if ( this.options.icons ) {
-				this.options.icons.activeHeader = this.options.icons.activeHeader ||
-					this.options.icons.headerSelected;
-			}
-			_createIcons.call( this );
-		};
-	}( jQuery, jQuery.ui.accordion.prototype ) );
-
-	// expanded active option, activate method
-	(function( $, prototype ) {
-		prototype.activate = prototype._activate;
-
-		var _findActive = prototype._findActive;
-		prototype._findActive = function( index ) {
-			if ( index === -1 ) {
-				index = false;
-			}
-			if ( index && typeof index !== "number" ) {
-				index = this.headers.index( this.headers.filter( index ) );
-				if ( index === -1 ) {
-					index = false;
-				}
-			}
-			return _findActive.call( this, index );
-		};
-	}( jQuery, jQuery.ui.accordion.prototype ) );
-
-	// resize method
-	jQuery.ui.accordion.prototype.resize = jQuery.ui.accordion.prototype.refresh;
-
-	// change events
-	(function( $, prototype ) {
-		$.extend( prototype.options, {
-			change: null,
-			changestart: null
-		});
-
-		var _trigger = prototype._trigger;
-		prototype._trigger = function( type, event, data ) {
-			var ret = _trigger.apply( this, arguments );
-			if ( !ret ) {
-				return false;
-			}
-
-			if ( type === "beforeActivate" ) {
-				ret = _trigger.call( this, "changestart", event, {
-					oldHeader: data.oldHeader,
-					oldContent: data.oldPanel,
-					newHeader: data.newHeader,
-					newContent: data.newPanel
-				});
-			} else if ( type === "activate" ) {
-				ret = _trigger.call( this, "change", event, {
-					oldHeader: data.oldHeader,
-					oldContent: data.oldPanel,
-					newHeader: data.newHeader,
-					newContent: data.newPanel
-				});
-			}
-			return ret;
-		};
-	}( jQuery, jQuery.ui.accordion.prototype ) );
-
-	// animated option
-	// NOTE: this only provides support for "slide", "bounceslide", and easings
-	// not the full $.ui.accordion.animations API
-	(function( $, prototype ) {
-		$.extend( prototype.options, {
-			animate: null,
-			animated: "slide"
-		});
-
-		var _create = prototype._create;
-		prototype._create = function() {
-			var options = this.options;
-			if ( options.animate === null ) {
-				if ( !options.animated ) {
-					options.animate = false;
-				} else if ( options.animated === "slide" ) {
-					options.animate = 300;
-				} else if ( options.animated === "bounceslide" ) {
-					options.animate = {
-						duration: 200,
-						down: {
-							easing: "easeOutBounce",
-							duration: 1000
-						}
-					};
-				} else {
-					options.animate = options.animated;
-				}
-			}
-
-			_create.call( this );
-		};
-	}( jQuery, jQuery.ui.accordion.prototype ) );
-}
-
-})( jQuery );
-(function( $, undefined ) {
-
-// used to prevent race conditions with remote data sources
-var requestIndex = 0;
-
-$.widget( "ui.autocomplete", {
-	version: "1.9.2",
-	defaultElement: "<input>",
-	options: {
-		appendTo: "body",
-		autoFocus: false,
-		delay: 300,
-		minLength: 1,
-		position: {
-			my: "left top",
-			at: "left bottom",
-			collision: "none"
-		},
-		source: null,
-
-		// callbacks
-		change: null,
-		close: null,
-		focus: null,
-		open: null,
-		response: null,
-		search: null,
-		select: null
-	},
-
-	pending: 0,
-
-	_create: function() {
-		// Some browsers only repeat keydown events, not keypress events,
-		// so we use the suppressKeyPress flag to determine if we've already
-		// handled the keydown event. #7269
-		// Unfortunately the code for & in keypress is the same as the up arrow,
-		// so we use the suppressKeyPressRepeat flag to avoid handling keypress
-		// events when we know the keydown event was used to modify the
-		// search term. #7799
-		var suppressKeyPress, suppressKeyPressRepeat, suppressInput;
-
-		this.isMultiLine = this._isMultiLine();
-		this.valueMethod = this.element[ this.element.is( "input,textarea" ) ? "val" : "text" ];
-		this.isNewMenu = true;
-
-		this.element
-			.addClass( "ui-autocomplete-input" )
-			.attr( "autocomplete", "off" );
-
-		this._on( this.element, {
-			keydown: function( event ) {
-				if ( this.element.prop( "readOnly" ) ) {
-					suppressKeyPress = true;
-					suppressInput = true;
-					suppressKeyPressRepeat = true;
-					return;
-				}
-
-				suppressKeyPress = false;
-				suppressInput = false;
-				suppressKeyPressRepeat = false;
-				var keyCode = $.ui.keyCode;
-				switch( event.keyCode ) {
-				case keyCode.PAGE_UP:
-					suppressKeyPress = true;
-					this._move( "previousPage", event );
-					break;
-				case keyCode.PAGE_DOWN:
-					suppressKeyPress = true;
-					this._move( "nextPage", event );
-					break;
-				case keyCode.UP:
-					suppressKeyPress = true;
-					this._keyEvent( "previous", event );
-					break;
-				case keyCode.DOWN:
-					suppressKeyPress = true;
-					this._keyEvent( "next", event );
-					break;
-				case keyCode.ENTER:
-				case keyCode.NUMPAD_ENTER:
-					// when menu is open and has focus
-					if ( this.menu.active ) {
-						// #6055 - Opera still allows the keypress to occur
-						// which causes forms to submit
-						suppressKeyPress = true;
-						event.preventDefault();
-						this.menu.select( event );
-					}
-					break;
-				case keyCode.TAB:
-					if ( this.menu.active ) {
-						this.menu.select( event );
-					}
-					break;
-				case keyCode.ESCAPE:
-					if ( this.menu.element.is( ":visible" ) ) {
-						this._value( this.term );
-						this.close( event );
-						// Different browsers have different default behavior for escape
-						// Single press can mean undo or clear
-						// Double press in IE means clear the whole form
-						event.preventDefault();
-					}
-					break;
-				default:
-					suppressKeyPressRepeat = true;
-					// search timeout should be triggered before the input value is changed
-					this._searchTimeout( event );
-					break;
-				}
-			},
-			keypress: function( event ) {
-				if ( suppressKeyPress ) {
-					suppressKeyPress = false;
-					event.preventDefault();
-					return;
-				}
-				if ( suppressKeyPressRepeat ) {
-					return;
-				}
-
-				// replicate some key handlers to allow them to repeat in Firefox and Opera
-				var keyCode = $.ui.keyCode;
-				switch( event.keyCode ) {
-				case keyCode.PAGE_UP:
-					this._move( "previousPage", event );
-					break;
-				case keyCode.PAGE_DOWN:
-					this._move( "nextPage", event );
-					break;
-				case keyCode.UP:
-					this._keyEvent( "previous", event );
-					break;
-				case keyCode.DOWN:
-					this._keyEvent( "next", event );
-					break;
-				}
-			},
-			input: function( event ) {
-				if ( suppressInput ) {
-					suppressInput = false;
-					event.preventDefault();
-					return;
-				}
-				this._searchTimeout( event );
-			},
-			focus: function() {
-				this.selectedItem = null;
-				this.previous = this._value();
-			},
-			blur: function( event ) {
-				if ( this.cancelBlur ) {
-					delete this.cancelBlur;
-					return;
-				}
-
-				clearTimeout( this.searching );
-				this.close( event );
-				this._change( event );
-			}
-		});
-
-		this._initSource();
-		this.menu = $( "<ul>" )
-			.addClass( "ui-autocomplete" )
-			.appendTo( this.document.find( this.options.appendTo || "body" )[ 0 ] )
-			.menu({
-				// custom key handling for now
-				input: $(),
-				// disable ARIA support, the live region takes care of that
-				role: null
-			})
-			.zIndex( this.element.zIndex() + 1 )
-			.hide()
-			.data( "menu" );
-
-		this._on( this.menu.element, {
-			mousedown: function( event ) {
-				// prevent moving focus out of the text field
-				event.preventDefault();
-
-				// IE doesn't prevent moving focus even with event.preventDefault()
-				// so we set a flag to know when we should ignore the blur event
-				this.cancelBlur = true;
-				this._delay(function() {
-					delete this.cancelBlur;
-				});
-
-				// clicking on the scrollbar causes focus to shift to the body
-				// but we can't detect a mouseup or a click immediately afterward
-				// so we have to track the next mousedown and close the menu if
-				// the user clicks somewhere outside of the autocomplete
-				var menuElement = this.menu.element[ 0 ];
-				if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
-					this._delay(function() {
-						var that = this;
-						this.document.one( "mousedown", function( event ) {
-							if ( event.target !== that.element[ 0 ] &&
-									event.target !== menuElement &&
-									!$.contains( menuElement, event.target ) ) {
-								that.close();
-							}
-						});
-					});
-				}
-			},
-			menufocus: function( event, ui ) {
-				// #7024 - Prevent accidental activation of menu items in Firefox
-				if ( this.isNewMenu ) {
-					this.isNewMenu = false;
-					if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
-						this.menu.blur();
-
-						this.document.one( "mousemove", function() {
-							$( event.target ).trigger( event.originalEvent );
-						});
-
-						return;
-					}
-				}
-
-				// back compat for _renderItem using item.autocomplete, via #7810
-				// TODO remove the fallback, see #8156
-				var item = ui.item.data( "ui-autocomplete-item" ) || ui.item.data( "item.autocomplete" );
-				if ( false !== this._trigger( "focus", event, { item: item } ) ) {
-					// use value to match what will end up in the input, if it was a key event
-					if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
-						this._value( item.value );
-					}
-				} else {
-					// Normally the input is populated with the item's value as the
-					// menu is navigated, causing screen readers to notice a change and
-					// announce the item. Since the focus event was canceled, this doesn't
-					// happen, so we update the live region so that screen readers can
-					// still notice the change and announce it.
-					this.liveRegion.text( item.value );
-				}
-			},
-			menuselect: function( event, ui ) {
-				// back compat for _renderItem using item.autocomplete, via #7810
-				// TODO remove the fallback, see #8156
-				var item = ui.item.data( "ui-autocomplete-item" ) || ui.item.data( "item.autocomplete" ),
-					previous = this.previous;
-
-				// only trigger when focus was lost (click on menu)
-				if ( this.element[0] !== this.document[0].activeElement ) {
-					this.element.focus();
-					this.previous = previous;
-					// #6109 - IE triggers two focus events and the second
-					// is asynchronous, so we need to reset the previous
-					// term synchronously and asynchronously :-(
-					this._delay(function() {
-						this.previous = previous;
-						this.selectedItem = item;
-					});
-				}
-
-				if ( false !== this._trigger( "select", event, { item: item } ) ) {
-					this._value( item.value );
-				}
-				// reset the term after the select event
-				// this allows custom select handling to work properly
-				this.term = this._value();
-
-				this.close( event );
-				this.selectedItem = item;
-			}
-		});
-
-		this.liveRegion = $( "<span>", {
-				role: "status",
-				"aria-live": "polite"
-			})
-			.addClass( "ui-helper-hidden-accessible" )
-			.insertAfter( this.element );
-
-		if ( $.fn.bgiframe ) {
-			this.menu.element.bgiframe();
-		}
-
-		// turning off autocomplete prevents the browser from remembering the
-		// value when navigating through history, so we re-enable autocomplete
-		// if the page is unloaded before the widget is destroyed. #7790
-		this._on( this.window, {
-			beforeunload: function() {
-				this.element.removeAttr( "autocomplete" );
-			}
-		});
-	},
-
-	_destroy: function() {
-		clearTimeout( this.searching );
-		this.element
-			.removeClass( "ui-autocomplete-input" )
-			.removeAttr( "autocomplete" );
-		this.menu.element.remove();
-		this.liveRegion.remove();
-	},
-
-	_setOption: function( key, value ) {
-		this._super( key, value );
-		if ( key === "source" ) {
-			this._initSource();
-		}
-		if ( key === "appendTo" ) {
-			this.menu.element.appendTo( this.document.find( value || "body" )[0] );
-		}
-		if ( key === "disabled" && value && this.xhr ) {
-			this.xhr.abort();
-		}
-	},
-
-	_isMultiLine: function() {
-		// Textareas are always multi-line
-		if ( this.element.is( "textarea" ) ) {
-			return true;
-		}
-		// Inputs are always single-line, even if inside a contentEditable element
-		// IE also treats inputs as contentEditable
-		if ( this.element.is( "input" ) ) {
-			return false;
-		}
-		// All other element types are determined by whether or not they're contentEditable
-		return this.element.prop( "isContentEditable" );
-	},
-
-	_initSource: function() {
-		var array, url,
-			that = this;
-		if ( $.isArray(this.options.source) ) {
-			array = this.options.source;
-			this.source = function( request, response ) {
-				response( $.ui.autocomplete.filter( array, request.term ) );
-			};
-		} else if ( typeof this.options.source === "string" ) {
-			url = this.options.source;
-			this.source = function( request, response ) {
-				if ( that.xhr ) {
-					that.xhr.abort();
-				}
-				that.xhr = $.ajax({
-					url: url,
-					data: request,
-					dataType: "json",
-					success: function( data ) {
-						response( data );
-					},
-					error: function() {
-						response( [] );
-					}
-				});
-			};
-		} else {
-			this.source = this.options.source;
-		}
-	},
-
-	_searchTimeout: function( event ) {
-		clearTimeout( this.searching );
-		this.searching = this._delay(function() {
-			// only search if the value has changed
-			if ( this.term !== this._value() ) {
-				this.selectedItem = null;
-				this.search( null, event );
-			}
-		}, this.options.delay );
-	},
-
-	search: function( value, event ) {
-		value = value != null ? value : this._value();
-
-		// always save the actual value, not the one passed as an argument
-		this.term = this._value();
-
-		if ( value.length < this.options.minLength ) {
-			return this.close( event );
-		}
-
-		if ( this._trigger( "search", event ) === false ) {
-			return;
-		}
-
-		return this._search( value );
-	},
-
-	_search: function( value ) {
-		this.pending++;
-		this.element.addClass( "ui-autocomplete-loading" );
-		this.cancelSearch = false;
-
-		this.source( { term: value }, this._response() );
-	},
-
-	_response: function() {
-		var that = this,
-			index = ++requestIndex;
-
-		return function( content ) {
-			if ( index === requestIndex ) {
-				that.__response( content );
-			}
-
-			that.pending--;
-			if ( !that.pending ) {
-				that.element.removeClass( "ui-autocomplete-loading" );
-			}
-		};
-	},
-
-	__response: function( content ) {
-		if ( content ) {
-			content = this._normalize( content );
-		}
-		this._trigger( "response", null, { content: content } );
-		if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
-			this._suggest( content );
-			this._trigger( "open" );
-		} else {
-			// use ._close() instead of .close() so we don't cancel future searches
-			this._close();
-		}
-	},
-
-	close: function( event ) {
-		this.cancelSearch = true;
-		this._close( event );
-	},
-
-	_close: function( event ) {
-		if ( this.menu.element.is( ":visible" ) ) {
-			this.menu.element.hide();
-			this.menu.blur();
-			this.isNewMenu = true;
-			this._trigger( "close", event );
-		}
-	},
-
-	_change: function( event ) {
-		if ( this.previous !== this._value() ) {
-			this._trigger( "change", event, { item: this.selectedItem } );
-		}
-	},
-
-	_normalize: function( items ) {
-		// assume all items have the right format when the first item is complete
-		if ( items.length && items[0].label && items[0].value ) {
-			return items;
-		}
-		return $.map( items, function( item ) {
-			if ( typeof item === "string" ) {
-				return {
-					label: item,
-					value: item
-				};
-			}
-			return $.extend({
-				label: item.label || item.value,
-				value: item.value || item.label
-			}, item );
-		});
-	},
-
-	_suggest: function( items ) {
-		var ul = this.menu.element
-			.empty()
-			.zIndex( this.element.zIndex() + 1 );
-		this._renderMenu( ul, items );
-		this.menu.refresh();
-
-		// size and position menu
-		ul.show();
-		this._resizeMenu();
-		ul.position( $.extend({
-			of: this.element
-		}, this.options.position ));
-
-		if ( this.options.autoFocus ) {
-			this.menu.next();
-		}
-	},
-
-	_resizeMenu: function() {
-		var ul = this.menu.element;
-		ul.outerWidth( Math.max(
-			// Firefox wraps long text (possibly a rounding bug)
-			// so we add 1px to avoid the wrapping (#7513)
-			ul.width( "" ).outerWidth() + 1,
-			this.element.outerWidth()
-		) );
-	},
-
-	_renderMenu: function( ul, items ) {
-		var that = this;
-		$.each( items, function( index, item ) {
-			that._renderItemData( ul, item );
-		});
-	},
-
-	_renderItemData: function( ul, item ) {
-		return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
-	},
-
-	_renderItem: function( ul, item ) {
-		return $( "<li>" )
-			.append( $( "<a>" ).text( item.label ) )
-			.appendTo( ul );
-	},
-
-	_move: function( direction, event ) {
-		if ( !this.menu.element.is( ":visible" ) ) {
-			this.search( null, event );
-			return;
-		}
-		if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
-				this.menu.isLastItem() && /^next/.test( direction ) ) {
-			this._value( this.term );
-			this.menu.blur();
-			return;
-		}
-		this.menu[ direction ]( event );
-	},
-
-	widget: function() {
-		return this.menu.element;
-	},
-
-	_value: function() {
-		return this.valueMethod.apply( this.element, arguments );
-	},
-
-	_keyEvent: function( keyEvent, event ) {
-		if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
-			this._move( keyEvent, event );
-
-			// prevents moving cursor to beginning/end of the text field in some browsers
-			event.preventDefault();
-		}
-	}
-});
-
-$.extend( $.ui.autocomplete, {
-	escapeRegex: function( value ) {
-		return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
-	},
-	filter: function(array, term) {
-		var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
-		return $.grep( array, function(value) {
-			return matcher.test( value.label || value.value || value );
-		});
-	}
-});
-
-
-// live region extension, adding a `messages` option
-// NOTE: This is an experimental API. We are still investigating
-// a full solution for string manipulation and internationalization.
-$.widget( "ui.autocomplete", $.ui.autocomplete, {
-	options: {
-		messages: {
-			noResults: "No search results.",
-			results: function( amount ) {
-				return amount + ( amount > 1 ? " results are" : " result is" ) +
-					" available, use up and down arrow keys to navigate.";
-			}
-		}
-	},
-
-	__response: function( content ) {
-		var message;
-		this._superApply( arguments );
-		if ( this.options.disabled || this.cancelSearch ) {
-			return;
-		}
-		if ( content && content.length ) {
-			message = this.options.messages.results( content.length );
-		} else {
-			message = this.options.messages.noResults;
-		}
-		this.liveRegion.text( message );
-	}
-});
-
-
-}( jQuery ));
-(function( $, undefined ) {
-
-var lastActive, startXPos, startYPos, clickDragged,
-	baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
-	stateClasses = "ui-state-hover ui-state-active ",
-	typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
-	formResetHandler = function() {
-		var buttons = $( this ).find( ":ui-button" );
-		setTimeout(function() {
-			buttons.button( "refresh" );
-		}, 1 );
-	},
-	radioGroup = function( radio ) {
-		var name = radio.name,
-			form = radio.form,
-			radios = $( [] );
-		if ( name ) {
-			if ( form ) {
-				radios = $( form ).find( "[name='" + name + "']" );
-			} else {
-				radios = $( "[name='" + name + "']", radio.ownerDocument )
-					.filter(function() {
-						return !this.form;
-					});
-			}
-		}
-		return radios;
-	};
-
-$.widget( "ui.button", {
-	version: "1.9.2",
-	defaultElement: "<button>",
-	options: {
-		disabled: null,
-		text: true,
-		label: null,
-		icons: {
-			primary: null,
-			secondary: null
-		}
-	},
-	_create: function() {
-		this.element.closest( "form" )
-			.unbind( "reset" + this.eventNamespace )
-			.bind( "reset" + this.eventNamespace, formResetHandler );
-
-		if ( typeof this.options.disabled !== "boolean" ) {
-			this.options.disabled = !!this.element.prop( "disabled" );
-		} else {
-			this.element.prop( "disabled", this.options.disabled );
-		}
-
-		this._determineButtonType();
-		this.hasTitle = !!this.buttonElement.attr( "title" );
-
-		var that = this,
-			options = this.options,
-			toggleButton = this.type === "checkbox" || this.type === "radio",
-			activeClass = !toggleButton ? "ui-state-active" : "",
-			focusClass = "ui-state-focus";
-
-		if ( options.label === null ) {
-			options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html());
-		}
-
-		this._hoverable( this.buttonElement );
-
-		this.buttonElement
-			.addClass( baseClasses )
-			.attr( "role", "button" )
-			.bind( "mouseenter" + this.eventNamespace, function() {
-				if ( options.disabled ) {
-					return;
-				}
-				if ( this === lastActive ) {
-					$( this ).addClass( "ui-state-active" );
-				}
-			})
-			.bind( "mouseleave" + this.eventNamespace, function() {
-				if ( options.disabled ) {
-					return;
-				}
-				$( this ).removeClass( activeClass );
-			})
-			.bind( "click" + this.eventNamespace, function( event ) {
-				if ( options.disabled ) {
-					event.preventDefault();
-					event.stopImmediatePropagation();
-				}
-			});
-
-		this.element
-			.bind( "focus" + this.eventNamespace, function() {
-				// no need to check disabled, focus won't be triggered anyway
-				that.buttonElement.addClass( focusClass );
-			})
-			.bind( "blur" + this.eventNamespace, function() {
-				that.buttonElement.removeClass( focusClass );
-			});
-
-		if ( toggleButton ) {
-			this.element.bind( "change" + this.eventNamespace, function() {
-				if ( clickDragged ) {
-					return;
-				}
-				that.refresh();
-			});
-			// if mouse moves between mousedown and mouseup (drag) set clickDragged flag
-			// prevents issue where button state changes but checkbox/radio checked state
-			// does not in Firefox (see ticket #6970)
-			this.buttonElement
-				.bind( "mousedown" + this.eventNamespace, function( event ) {
-					if ( options.disabled ) {
-						return;
-					}
-					clickDragged = false;
-					startXPos = event.pageX;
-					startYPos = event.pageY;
-				})
-				.bind( "mouseup" + this.eventNamespace, function( event ) {
-					if ( options.disabled ) {
-						return;
-					}
-					if ( startXPos !== event.pageX || startYPos !== event.pageY ) {
-						clickDragged = true;
-					}
-			});
-		}
-
-		if ( this.type === "checkbox" ) {
-			this.buttonElement.bind( "click" + this.eventNamespace, function() {
-				if ( options.disabled || clickDragged ) {
-					return false;
-				}
-				$( this ).toggleClass( "ui-state-active" );
-				that.buttonElement.attr( "aria-pressed", that.element[0].checked );
-			});
-		} else if ( this.type === "radio" ) {
-			this.buttonElement.bind( "click" + this.eventNamespace, function() {
-				if ( options.disabled || clickDragged ) {
-					return false;
-				}
-				$( this ).addClass( "ui-state-active" );
-				that.buttonElement.attr( "aria-pressed", "true" );
-
-				var radio = that.element[ 0 ];
-				radioGroup( radio )
-					.not( radio )
-					.map(function() {
-						return $( this ).button( "widget" )[ 0 ];
-					})
-					.removeClass( "ui-state-active" )
-					.attr( "aria-pressed", "false" );
-			});
-		} else {
-			this.buttonElement
-				.bind( "mousedown" + this.eventNamespace, function() {
-					if ( options.disabled ) {
-						return false;
-					}
-					$( this ).addClass( "ui-state-active" );
-					lastActive = this;
-					that.document.one( "mouseup", function() {
-						lastActive = null;
-					});
-				})
-				.bind( "mouseup" + this.eventNamespace, function() {
-					if ( options.disabled ) {
-						return false;
-					}
-					$( this ).removeClass( "ui-state-active" );
-				})
-				.bind( "keydown" + this.eventNamespace, function(event) {
-					if ( options.disabled ) {
-						return false;
-					}
-					if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) {
-						$( this ).addClass( "ui-state-active" );
-					}
-				})
-				.bind( "keyup" + this.eventNamespace, function() {
-					$( this ).removeClass( "ui-state-active" );
-				});
-
-			if ( this.buttonElement.is("a") ) {
-				this.buttonElement.keyup(function(event) {
-					if ( event.keyCode === $.ui.keyCode.SPACE ) {
-						// TODO pass through original event correctly (just as 2nd argument doesn't work)
-						$( this ).click();
-					}
-				});
-			}
-		}
-
-		// TODO: pull out $.Widget's handling for the disabled option into
-		// $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
-		// be overridden by individual plugins
-		this._setOption( "disabled", options.disabled );
-		this._resetButton();
-	},
-
-	_determineButtonType: function() {
-		var ancestor, labelSelector, checked;
-
-		if ( this.element.is("[type=checkbox]") ) {
-			this.type = "checkbox";
-		} else if ( this.element.is("[type=radio]") ) {
-			this.type = "radio";
-		} else if ( this.element.is("input") ) {
-			this.type = "input";
-		} else {
-			this.type = "button";
-		}
-
-		if ( this.type === "checkbox" || this.type === "radio" ) {
-			// we don't search against the document in case the element
-			// is disconnected from the DOM
-			ancestor = this.element.parents().last();
-			labelSelector = "label[for='" + this.element.attr("id") + "']";
-			this.buttonElement = ancestor.find( labelSelector );
-			if ( !this.buttonElement.length ) {
-				ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
-				this.buttonElement = ancestor.filter( labelSelector );
-				if ( !this.buttonElement.length ) {
-					this.buttonElement = ancestor.find( labelSelector );
-				}
-			}
-			this.element.addClass( "ui-helper-hidden-accessible" );
-
-			checked = this.element.is( ":checked" );
-			if ( checked ) {
-				this.buttonElement.addClass( "ui-state-active" );
-			}
-			this.buttonElement.prop( "aria-pressed", checked );
-		} else {
-			this.buttonElement = this.element;
-		}
-	},
-
-	widget: function() {
-		return this.buttonElement;
-	},
-
-	_destroy: function() {
-		this.element
-			.removeClass( "ui-helper-hidden-accessible" );
-		this.buttonElement
-			.removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
-			.removeAttr( "role" )
-			.removeAttr( "aria-pressed" )
-			.html( this.buttonElement.find(".ui-button-text").html() );
-
-		if ( !this.hasTitle ) {
-			this.buttonElement.removeAttr( "title" );
-		}
-	},
-
-	_setOption: function( key, value ) {
-		this._super( key, value );
-		if ( key === "disabled" ) {
-			if ( value ) {
-				this.element.prop( "disabled", true );
-			} else {
-				this.element.prop( "disabled", false );
-			}
-			return;
-		}
-		this._resetButton();
-	},
-
-	refresh: function() {
-		//See #8237 & #8828
-		var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" );
-
-		if ( isDisabled !== this.options.disabled ) {
-			this._setOption( "disabled", isDisabled );
-		}
-		if ( this.type === "radio" ) {
-			radioGroup( this.element[0] ).each(function() {
-				if ( $( this ).is( ":checked" ) ) {
-					$( this ).button( "widget" )
-						.addClass( "ui-state-active" )
-						.attr( "aria-pressed", "true" );
-				} else {
-					$( this ).button( "widget" )
-						.removeClass( "ui-state-active" )
-						.attr( "aria-pressed", "false" );
-				}
-			});
-		} else if ( this.type === "checkbox" ) {
-			if ( this.element.is( ":checked" ) ) {
-				this.buttonElement
-					.addClass( "ui-state-active" )
-					.attr( "aria-pressed", "true" );
-			} else {
-				this.buttonElement
-					.removeClass( "ui-state-active" )
-					.attr( "aria-pressed", "false" );
-			}
-		}
-	},
-
-	_resetButton: function() {
-		if ( this.type === "input" ) {
-			if ( this.options.label ) {
-				this.element.val( this.options.label );
-			}
-			return;
-		}
-		var buttonElement = this.buttonElement.removeClass( typeClasses ),
-			buttonText = $( "<span></span>", this.document[0] )
-				.addClass( "ui-button-text" )
-				.html( this.options.label )
-				.appendTo( buttonElement.empty() )
-				.text(),
-			icons = this.options.icons,
-			multipleIcons = icons.primary && icons.secondary,
-			buttonClasses = [];
-
-		if ( icons.primary || icons.secondary ) {
-			if ( this.options.text ) {
-				buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
-			}
-
-			if ( icons.primary ) {
-				buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
-			}
-
-			if ( icons.secondary ) {
-				buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
-			}
-
-			if ( !this.options.text ) {
-				buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
-
-				if ( !this.hasTitle ) {
-					buttonElement.attr( "title", $.trim( buttonText ) );
-				}
-			}
-		} else {
-			buttonClasses.push( "ui-button-text-only" );
-		}
-		buttonElement.addClass( buttonClasses.join( " " ) );
-	}
-});
-
-$.widget( "ui.buttonset", {
-	version: "1.9.2",
-	options: {
-		items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(button)"
-	},
-
-	_create: function() {
-		this.element.addClass( "ui-buttonset" );
-	},
-
-	_init: function() {
-		this.refresh();
-	},
-
-	_setOption: function( key, value ) {
-		if ( key === "disabled" ) {
-			this.buttons.button( "option", key, value );
-		}
-
-		this._super( key, value );
-	},
-
-	refresh: function() {
-		var rtl = this.element.css( "direction" ) === "rtl";
-
-		this.buttons = this.element.find( this.options.items )
-			.filter( ":ui-button" )
-				.button( "refresh" )
-			.end()
-			.not( ":ui-button" )
-				.button()
-			.end()
-			.map(function() {
-				return $( this ).button( "widget" )[ 0 ];
-			})
-				.removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
-				.filter( ":first" )
-					.addClass( rtl ? "ui-corner-right" : "ui-corner-left" )
-				.end()
-				.filter( ":last" )
-					.addClass( rtl ? "ui-corner-left" : "ui-corner-right" )
-				.end()
-			.end();
-	},
-
-	_destroy: function() {
-		this.element.removeClass( "ui-buttonset" );
-		this.buttons
-			.map(function() {
-				return $( this ).button( "widget" )[ 0 ];
-			})
-				.removeClass( "ui-corner-left ui-corner-right" )
-			.end()
-			.button( "destroy" );
-	}
-});
-
-}( jQuery ) );
-(function( $, undefined ) {
-
-$.extend($.ui, { datepicker: { version: "1.9.2" } });
-
-var PROP_NAME = 'datepicker';
-var dpuuid = new Date().getTime();
-var instActive;
-
-/* Date picker manager.
-   Use the singleton instance of this class, $.datepicker, to interact with the date picker.
-   Settings for (groups of) date pickers are maintained in an instance object,
-   allowing multiple different settings on the same page. */
-
-function Datepicker() {
-	this.debug = false; // Change this to true to start debugging
-	this._curInst = null; // The current instance in use
-	this._keyEvent = false; // If the last event was a key event
-	this._disabledInputs = []; // List of date picker inputs that have been disabled
-	this._datepickerShowing = false; // True if the popup picker is showing , false if not
-	this._inDialog = false; // True if showing within a "dialog", false if not
-	this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
-	this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
-	this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
-	this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
-	this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
-	this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
-	this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
-	this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
-	this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
-	this.regional = []; // Available regional settings, indexed by language code
-	this.regional[''] = { // Default regional settings
-		closeText: 'Done', // Display text for close link
-		prevText: 'Prev', // Display text for previous month link
-		nextText: 'Next', // Display text for next month link
-		currentText: 'Today', // Display text for current month link
-		monthNames: ['January','February','March','April','May','June',
-			'July','August','September','October','November','December'], // Names of months for drop-down and formatting
-		monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
-		dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
-		dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
-		dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
-		weekHeader: 'Wk', // Column header for week of the year
-		dateFormat: 'mm/dd/yy', // See format options on parseDate
-		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
-		isRTL: false, // True if right-to-left language, false if left-to-right
-		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
-		yearSuffix: '' // Additional text to append to the year in the month headers
-	};
-	this._defaults = { // Global defaults for all the date picker instances
-		showOn: 'focus', // 'focus' for popup on focus,
-			// 'button' for trigger button, or 'both' for either
-		showAnim: 'fadeIn', // Name of jQuery animation for popup
-		showOptions: {}, // Options for enhanced animations
-		defaultDate: null, // Used when field is blank: actual date,
-			// +/-number for offset from today, null for today
-		appendText: '', // Display text following the input box, e.g. showing the format
-		buttonText: '...', // Text for trigger button
-		buttonImage: '', // URL for trigger button image
-		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
-		hideIfNoPrevNext: false, // True to hide next/previous month links
-			// if not applicable, false to just disable them
-		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
-		gotoCurrent: false, // True if today link goes back to current selection instead
-		changeMonth: false, // True if month can be selected directly, false if only prev/next
-		changeYear: false, // True if year can be selected directly, false if only prev/next
-		yearRange: 'c-10:c+10', // Range of years to display in drop-down,
-			// either relative to today's year (-nn:+nn), relative to currently displayed year
-			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
-		showOtherMonths: false, // True to show dates in other months, false to leave blank
-		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
-		showWeek: false, // True to show week of the year, false to not show it
-		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
-			// takes a Date and returns the number of the week for it
-		shortYearCutoff: '+10', // Short year values < this are in the current century,
-			// > this are in the previous century,
-			// string value starting with '+' for current year + value
-		minDate: null, // The earliest selectable date, or null for no limit
-		maxDate: null, // The latest selectable date, or null for no limit
-		duration: 'fast', // Duration of display/closure
-		beforeShowDay: null, // Function that takes a date and returns an array with
-			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
-			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
-		beforeShow: null, // Function that takes an input field and
-			// returns a set of custom settings for the date picker
-		onSelect: null, // Define a callback function when a date is selected
-		onChangeMonthYear: null, // Define a callback function when the month or year is changed
-		onClose: null, // Define a callback function when the datepicker is closed
-		numberOfMonths: 1, // Number of months to show at a time
-		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
-		stepMonths: 1, // Number of months to step back/forward
-		stepBigMonths: 12, // Number of months to step back/forward for the big links
-		altField: '', // Selector for an alternate field to store selected dates into
-		altFormat: '', // The date format to use for the alternate field
-		constrainInput: true, // The input is constrained by the current date format
-		showButtonPanel: false, // True to show button panel, false to not show it
-		autoSize: false, // True to size the input for the date format, false to leave as is
-		disabled: false // The initial disabled state
-	};
-	$.extend(this._defaults, this.regional['']);
-	this.dpDiv = bindHover($('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'));
-}
-
-$.extend(Datepicker.prototype, {
-	/* Class name added to elements to indicate already configured with a date picker. */
-	markerClassName: 'hasDatepicker',
-
-	//Keep track of the maximum number of rows displayed (see #7043)
-	maxRows: 4,
-
-	/* Debug logging (if enabled). */
-	log: function () {
-		if (this.debug)
-			console.log.apply('', arguments);
-	},
-
-	// TODO rename to "widget" when switching to widget factory
-	_widgetDatepicker: function() {
-		return this.dpDiv;
-	},
-
-	/* Override the default settings for all instances of the date picker.
-	   @param  settings  object - the new settings to use as defaults (anonymous object)
-	   @return the manager object */
-	setDefaults: function(settings) {
-		extendRemove(this._defaults, settings || {});
-		return this;
-	},
-
-	/* Attach the date picker to a jQuery selection.
-	   @param  target    element - the target input field or division or span
-	   @param  settings  object - the new settings to use for this date picker instance (anonymous) */
-	_attachDatepicker: function(target, settings) {
-		// check for settings on the control itself - in namespace 'date:'
-		var inlineSettings = null;
-		for (var attrName in this._defaults) {
-			var attrValue = target.getAttribute('date:' + attrName);
-			if (attrValue) {
-				inlineSettings = inlineSettings || {};
-				try {
-					inlineSettings[attrName] = eval(attrValue);
-				} catch (err) {
-					inlineSettings[attrName] = attrValue;
-				}
-			}
-		}
-		var nodeName = target.nodeName.toLowerCase();
-		var inline = (nodeName == 'div' || nodeName == 'span');
-		if (!target.id) {
-			this.uuid += 1;
-			target.id = 'dp' + this.uuid;
-		}
-		var inst = this._newInst($(target), inline);
-		inst.settings = $.extend({}, settings || {}, inlineSettings || {});
-		if (nodeName == 'input') {
-			this._connectDatepicker(target, inst);
-		} else if (inline) {
-			this._inlineDatepicker(target, inst);
-		}
-	},
-
-	/* Create a new instance object. */
-	_newInst: function(target, inline) {
-		var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
-		return {id: id, input: target, // associated target
-			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
-			drawMonth: 0, drawYear: 0, // month being drawn
-			inline: inline, // is datepicker inline or not
-			dpDiv: (!inline ? this.dpDiv : // presentation div
-			bindHover($('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')))};
-	},
-
-	/* Attach the date picker to an input field. */
-	_connectDatepicker: function(target, inst) {
-		var input = $(target);
-		inst.append = $([]);
-		inst.trigger = $([]);
-		if (input.hasClass(this.markerClassName))
-			return;
-		this._attachments(input, inst);
-		input.addClass(this.markerClassName).keydown(this._doKeyDown).
-			keypress(this._doKeyPress).keyup(this._doKeyUp).
-			bind("setData.datepicker", function(event, key, value) {
-				inst.settings[key] = value;
-			}).bind("getData.datepicker", function(event, key) {
-				return this._get(inst, key);
-			});
-		this._autoSize(inst);
-		$.data(target, PROP_NAME, inst);
-		//If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
-		if( inst.settings.disabled ) {
-			this._disableDatepicker( target );
-		}
-	},
-
-	/* Make attachments based on settings. */
-	_attachments: function(input, inst) {
-		var appendText = this._get(inst, 'appendText');
-		var isRTL = this._get(inst, 'isRTL');
-		if (inst.append)
-			inst.append.remove();
-		if (appendText) {
-			inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
-			input[isRTL ? 'before' : 'after'](inst.append);
-		}
-		input.unbind('focus', this._showDatepicker);
-		if (inst.trigger)
-			inst.trigger.remove();
-		var showOn = this._get(inst, 'showOn');
-		if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
-			input.focus(this._showDatepicker);
-		if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
-			var buttonText = this._get(inst, 'buttonText');
-			var buttonImage = this._get(inst, 'buttonImage');
-			inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
-				$('<img/>').addClass(this._triggerClass).
-					attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
-				$('<button type="button"></button>').addClass(this._triggerClass).
-					html(buttonImage == '' ? buttonText : $('<img/>').attr(
-					{ src:buttonImage, alt:buttonText, title:buttonText })));
-			input[isRTL ? 'before' : 'after'](inst.trigger);
-			inst.trigger.click(function() {
-				if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
-					$.datepicker._hideDatepicker();
-				else if ($.datepicker._datepickerShowing && $.datepicker._lastInput != input[0]) {
-					$.datepicker._hideDatepicker();
-					$.datepicker._showDatepicker(input[0]);
-				} else
-					$.datepicker._showDatepicker(input[0]);
-				return false;
-			});
-		}
-	},
-
-	/* Apply the maximum length for the date format. */
-	_autoSize: function(inst) {
-		if (this._get(inst, 'autoSize') && !inst.inline) {
-			var date = new Date(2009, 12 - 1, 20); // Ensure double digits
-			var dateFormat = this._get(inst, 'dateFormat');
-			if (dateFormat.match(/[DM]/)) {
-				var findMax = function(names) {
-					var max = 0;
-					var maxI = 0;
-					for (var i = 0; i < names.length; i++) {
-						if (names[i].length > max) {
-							max = names[i].length;
-							maxI = i;
-						}
-					}
-					return maxI;
-				};
-				date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
-					'monthNames' : 'monthNamesShort'))));
-				date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
-					'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
-			}
-			inst.input.attr('size', this._formatDate(inst, date).length);
-		}
-	},
-
-	/* Attach an inline date picker to a div. */
-	_inlineDatepicker: function(target, inst) {
-		var divSpan = $(target);
-		if (divSpan.hasClass(this.markerClassName))
-			return;
-		divSpan.addClass(this.markerClassName).append(inst.dpDiv).
-			bind("setData.datepicker", function(event, key, value){
-				inst.settings[key] = value;
-			}).bind("getData.datepicker", function(event, key){
-				return this._get(inst, key);
-			});
-		$.data(target, PROP_NAME, inst);
-		this._setDate(inst, this._getDefaultDate(inst), true);
-		this._updateDatepicker(inst);
-		this._updateAlternate(inst);
-		//If disabled option is true, disable the datepicker before showing it (see ticket #5665)
-		if( inst.settings.disabled ) {
-			this._disableDatepicker( target );
-		}
-		// Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
-		// http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
-		inst.dpDiv.css( "display", "block" );
-	},
-
-	/* Pop-up the date picker in a "dialog" box.
-	   @param  input     element - ignored
-	   @param  date      string or Date - the initial date to display
-	   @param  onSelect  function - the function to call when a date is selected
-	   @param  settings  object - update the dialog date picker instance's settings (anonymous object)
-	   @param  pos       int[2] - coordinates for the dialog's position within the screen or
-	                     event - with x/y coordinates or
-	                     leave empty for default (screen centre)
-	   @return the manager object */
-	_dialogDatepicker: function(input, date, onSelect, settings, pos) {
-		var inst = this._dialogInst; // internal instance
-		if (!inst) {
-			this.uuid += 1;
-			var id = 'dp' + this.uuid;
-			this._dialogInput = $('<input type="text" id="' + id +
-				'" style="position: absolute; top: -100px; width: 0px;"/>');
-			this._dialogInput.keydown(this._doKeyDown);
-			$('body').append(this._dialogInput);
-			inst = this._dialogInst = this._newInst(this._dialogInput, false);
-			inst.settings = {};
-			$.data(this._dialogInput[0], PROP_NAME, inst);
-		}
-		extendRemove(inst.settings, settings || {});
-		date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
-		this._dialogInput.val(date);
-
-		this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
-		if (!this._pos) {
-			var browserWidth = document.documentElement.clientWidth;
-			var browserHeight = document.documentElement.clientHeight;
-			var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
-			var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
-			this._pos = // should use actual width/height below
-				[(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
-		}
-
-		// move input on screen for focus, but hidden behind dialog
-		this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
-		inst.settings.onSelect = onSelect;
-		this._inDialog = true;
-		this.dpDiv.addClass(this._dialogClass);
-		this._showDatepicker(this._dialogInput[0]);
-		if ($.blockUI)
-			$.blockUI(this.dpDiv);
-		$.data(this._dialogInput[0], PROP_NAME, inst);
-		return this;
-	},
-
-	/* Detach a datepicker from its control.
-	   @param  target    element - the target input field or division or span */
-	_destroyDatepicker: function(target) {
-		var $target = $(target);
-		var inst = $.data(target, PROP_NAME);
-		if (!$target.hasClass(this.markerClassName)) {
-			return;
-		}
-		var nodeName = target.nodeName.toLowerCase();
-		$.removeData(target, PROP_NAME);
-		if (nodeName == 'input') {
-			inst.append.remove();
-			inst.trigger.remove();
-			$target.removeClass(this.markerClassName).
-				unbind('focus', this._showDatepicker).
-				unbind('keydown', this._doKeyDown).
-				unbind('keypress', this._doKeyPress).
-				unbind('keyup', this._doKeyUp);
-		} else if (nodeName == 'div' || nodeName == 'span')
-			$target.removeClass(this.markerClassName).empty();
-	},
-
-	/* Enable the date picker to a jQuery selection.
-	   @param  target    element - the target input field or division or span */
-	_enableDatepicker: function(target) {
-		var $target = $(target);
-		var inst = $.data(target, PROP_NAME);
-		if (!$target.hasClass(this.markerClassName)) {
-			return;
-		}
-		var nodeName = target.nodeName.toLowerCase();
-		if (nodeName == 'input') {
-			target.disabled = false;
-			inst.trigger.filter('button').
-				each(function() { this.disabled = false; }).end().
-				filter('img').css({opacity: '1.0', cursor: ''});
-		}
-		else if (nodeName == 'div' || nodeName == 'span') {
-			var inline = $target.children('.' + this._inlineClass);
-			inline.children().removeClass('ui-state-disabled');
-			inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
-				prop("disabled", false);
-		}
-		this._disabledInputs = $.map(this._disabledInputs,
-			function(value) { return (value == target ? null : value); }); // delete entry
-	},
-
-	/* Disable the date picker to a jQuery selection.
-	   @param  target    element - the target input field or division or span */
-	_disableDatepicker: function(target) {
-		var $target = $(target);
-		var inst = $.data(target, PROP_NAME);
-		if (!$target.hasClass(this.markerClassName)) {
-			return;
-		}
-		var nodeName = target.nodeName.toLowerCase();
-		if (nodeName == 'input') {
-			target.disabled = true;
-			inst.trigger.filter('button').
-				each(function() { this.disabled = true; }).end().
-				filter('img').css({opacity: '0.5', cursor: 'default'});
-		}
-		else if (nodeName == 'div' || nodeName == 'span') {
-			var inline = $target.children('.' + this._inlineClass);
-			inline.children().addClass('ui-state-disabled');
-			inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
-				prop("disabled", true);
-		}
-		this._disabledInputs = $.map(this._disabledInputs,
-			function(value) { return (value == target ? null : value); }); // delete entry
-		this._disabledInputs[this._disabledInputs.length] = target;
-	},
-
-	/* Is the first field in a jQuery collection disabled as a datepicker?
-	   @param  target    element - the target input field or division or span
-	   @return boolean - true if disabled, false if enabled */
-	_isDisabledDatepicker: function(target) {
-		if (!target) {
-			return false;
-		}
-		for (var i = 0; i < this._disabledInputs.length; i++) {
-			if (this._disabledInputs[i] == target)
-				return true;
-		}
-		return false;
-	},
-
-	/* Retrieve the instance data for the target control.
-	   @param  target  element - the target input field or division or span
-	   @return  object - the associated instance data
-	   @throws  error if a jQuery problem getting data */
-	_getInst: function(target) {
-		try {
-			return $.data(target, PROP_NAME);
-		}
-		catch (err) {
-			throw 'Missing instance data for this datepicker';
-		}
-	},
-
-	/* Update or retrieve the settings for a date picker attached to an input field or division.
-	   @param  target  element - the target input field or division or span
-	   @param  name    object - the new settings to update or
-	                   string - the name of the setting to change or retrieve,
-	                   when retrieving also 'all' for all instance settings or
-	                   'defaults' for all global defaults
-	   @param  value   any - the new value for the setting
-	                   (omit if above is an object or to retrieve a value) */
-	_optionDatepicker: function(target, name, value) {
-		var inst = this._getInst(target);
-		if (arguments.length == 2 && typeof name == 'string') {
-			return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
-				(inst ? (name == 'all' ? $.extend({}, inst.settings) :
-				this._get(inst, name)) : null));
-		}
-		var settings = name || {};
-		if (typeof name == 'string') {
-			settings = {};
-			settings[name] = value;
-		}
-		if (inst) {
-			if (this._curInst == inst) {
-				this._hideDatepicker();
-			}
-			var date = this._getDateDatepicker(target, true);
-			var minDate = this._getMinMaxDate(inst, 'min');
-			var maxDate = this._getMinMaxDate(inst, 'max');
-			extendRemove(inst.settings, settings);
-			// reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
-			if (minDate !== null && settings['dateFormat'] !== undefined && settings['minDate'] === undefined)
-				inst.settings.minDate = this._formatDate(inst, minDate);
-			if (maxDate !== null && settings['dateFormat'] !== undefined && settings['maxDate'] === undefined)
-				inst.settings.maxDate = this._formatDate(inst, maxDate);
-			this._attachments($(target), inst);
-			this._autoSize(inst);
-			this._setDate(inst, date);
-			this._updateAlternate(inst);
-			this._updateDatepicker(inst);
-		}
-	},
-
-	// change method deprecated
-	_changeDatepicker: function(target, name, value) {
-		this._optionDatepicker(target, name, value);
-	},
-
-	/* Redraw the date picker attached to an input field or division.
-	   @param  target  element - the target input field or division or span */
-	_refreshDatepicker: function(target) {
-		var inst = this._getInst(target);
-		if (inst) {
-			this._updateDatepicker(inst);
-		}
-	},
-
-	/* Set the dates for a jQuery selection.
-	   @param  target   element - the target input field or division or span
-	   @param  date     Date - the new date */
-	_setDateDatepicker: function(target, date) {
-		var inst = this._getInst(target);
-		if (inst) {
-			this._setDate(inst, date);
-			this._updateDatepicker(inst);
-			this._updateAlternate(inst);
-		}
-	},
-
-	/* Get the date(s) for the first entry in a jQuery selection.
-	   @param  target     element - the target input field or division or span
-	   @param  noDefault  boolean - true if no default date is to be used
-	   @return Date - the current date */
-	_getDateDatepicker: function(target, noDefault) {
-		var inst = this._getInst(target);
-		if (inst && !inst.inline)
-			this._setDateFromField(inst, noDefault);
-		return (inst ? this._getDate(inst) : null);
-	},
-
-	/* Handle keystrokes. */
-	_doKeyDown: function(event) {
-		var inst = $.datepicker._getInst(event.target);
-		var handled = true;
-		var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
-		inst._keyEvent = true;
-		if ($.datepicker._datepickerShowing)
-			switch (event.keyCode) {
-				case 9: $.datepicker._hideDatepicker();
-						handled = false;
-						break; // hide on tab out
-				case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' +
-									$.datepicker._currentClass + ')', inst.dpDiv);
-						if (sel[0])
-							$.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
-							var onSelect = $.datepicker._get(inst, 'onSelect');
-							if (onSelect) {
-								var dateStr = $.datepicker._formatDate(inst);
-
-								// trigger custom callback
-								onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
-							}
-						else
-							$.datepicker._hideDatepicker();
-						return false; // don't submit the form
-						break; // select the value on enter
-				case 27: $.datepicker._hideDatepicker();
-						break; // hide on escape
-				case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
-							-$.datepicker._get(inst, 'stepBigMonths') :
-							-$.datepicker._get(inst, 'stepMonths')), 'M');
-						break; // previous month/year on page up/+ ctrl
-				case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
-							+$.datepicker._get(inst, 'stepBigMonths') :
-							+$.datepicker._get(inst, 'stepMonths')), 'M');
-						break; // next month/year on page down/+ ctrl
-				case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
-						handled = event.ctrlKey || event.metaKey;
-						break; // clear on ctrl or command +end
-				case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
-						handled = event.ctrlKey || event.metaKey;
-						break; // current on ctrl or command +home
-				case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
-						handled = event.ctrlKey || event.metaKey;
-						// -1 day on ctrl or command +left
-						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
-									-$.datepicker._get(inst, 'stepBigMonths') :
-									-$.datepicker._get(inst, 'stepMonths')), 'M');
-						// next month/year on alt +left on Mac
-						break;
-				case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
-						handled = event.ctrlKey || event.metaKey;
-						break; // -1 week on ctrl or command +up
-				case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
-						handled = event.ctrlKey || event.metaKey;
-						// +1 day on ctrl or command +right
-						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
-									+$.datepicker._get(inst, 'stepBigMonths') :
-									+$.datepicker._get(inst, 'stepMonths')), 'M');
-						// next month/year on alt +right
-						break;
-				case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
-						handled = event.ctrlKey || event.metaKey;
-						break; // +1 week on ctrl or command +down
-				default: handled = false;
-			}
-		else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
-			$.datepicker._showDatepicker(this);
-		else {
-			handled = false;
-		}
-		if (handled) {
-			event.preventDefault();
-			event.stopPropagation();
-		}
-	},
-
-	/* Filter entered characters - based on date format. */
-	_doKeyPress: function(event) {
-		var inst = $.datepicker._getInst(event.target);
-		if ($.datepicker._get(inst, 'constrainInput')) {
-			var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
-			var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
-			return event.ctrlKey || event.metaKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
-		}
-	},
-
-	/* Synchronise manual entry and field/alternate field. */
-	_doKeyUp: function(event) {
-		var inst = $.datepicker._getInst(event.target);
-		if (inst.input.val() != inst.lastVal) {
-			try {
-				var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
-					(inst.input ? inst.input.val() : null),
-					$.datepicker._getFormatConfig(inst));
-				if (date) { // only if valid
-					$.datepicker._setDateFromField(inst);
-					$.datepicker._updateAlternate(inst);
-					$.datepicker._updateDatepicker(inst);
-				}
-			}
-			catch (err) {
-				$.datepicker.log(err);
-			}
-		}
-		return true;
-	},
-
-	/* Pop-up the date picker for a given input field.
-	   If false returned from beforeShow event handler do not show.
-	   @param  input  element - the input field attached to the date picker or
-	                  event - if triggered by focus */
-	_showDatepicker: function(input) {
-		input = input.target || input;
-		if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
-			input = $('input', input.parentNode)[0];
-		if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
-			return;
-		var inst = $.datepicker._getInst(input);
-		if ($.datepicker._curInst && $.datepicker._curInst != inst) {
-			$.datepicker._curInst.dpDiv.stop(true, true);
-			if ( inst && $.datepicker._datepickerShowing ) {
-				$.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
-			}
-		}
-		var beforeShow = $.datepicker._get(inst, 'beforeShow');
-		var beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
-		if(beforeShowSettings === false){
-			//false
-			return;
-		}
-		extendRemove(inst.settings, beforeShowSettings);
-		inst.lastVal = null;
-		$.datepicker._lastInput = input;
-		$.datepicker._setDateFromField(inst);
-		if ($.datepicker._inDialog) // hide cursor
-			input.value = '';
-		if (!$.datepicker._pos) { // position below input
-			$.datepicker._pos = $.datepicker._findPos(input);
-			$.datepicker._pos[1] += input.offsetHeight; // add the height
-		}
-		var isFixed = false;
-		$(input).parents().each(function() {
-			isFixed |= $(this).css('position') == 'fixed';
-			return !isFixed;
-		});
-		var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
-		$.datepicker._pos = null;
-		//to avoid flashes on Firefox
-		inst.dpDiv.empty();
-		// determine sizing offscreen
-		inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
-		$.datepicker._updateDatepicker(inst);
-		// fix width for dynamic number of date pickers
-		// and adjust position before showing
-		offset = $.datepicker._checkOffset(inst, offset, isFixed);
-		inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
-			'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
-			left: offset.left + 'px', top: offset.top + 'px'});
-		if (!inst.inline) {
-			var showAnim = $.datepicker._get(inst, 'showAnim');
-			var duration = $.datepicker._get(inst, 'duration');
-			var postProcess = function() {
-				var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
-				if( !! cover.length ){
-					var borders = $.datepicker._getBorders(inst.dpDiv);
-					cover.css({left: -borders[0], top: -borders[1],
-						width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
-				}
-			};
-			inst.dpDiv.zIndex($(input).zIndex()+1);
-			$.datepicker._datepickerShowing = true;
-
-			// DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
-			if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) )
-				inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
-			else
-				inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
-			if (!showAnim || !duration)
-				postProcess();
-			if (inst.input.is(':visible') && !inst.input.is(':disabled'))
-				inst.input.focus();
-			$.datepicker._curInst = inst;
-		}
-	},
-
-	/* Generate the date picker content. */
-	_updateDatepicker: function(inst) {
-		this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
-		var borders = $.datepicker._getBorders(inst.dpDiv);
-		instActive = inst; // for delegate hover events
-		inst.dpDiv.empty().append(this._generateHTML(inst));
-		this._attachHandlers(inst);
-		var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
-		if( !!cover.length ){ //avoid call to outerXXXX() when not in IE6
-			cover.css({left: -borders[0], top: -borders[1], width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
-		}
-		inst.dpDiv.find('.' + this._dayOverClass + ' a').mouseover();
-		var numMonths = this._getNumberOfMonths(inst);
-		var cols = numMonths[1];
-		var width = 17;
-		inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
-		if (cols > 1)
-			inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
-		inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
-			'Class']('ui-datepicker-multi');
-		inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
-			'Class']('ui-datepicker-rtl');
-		if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
-				// #6694 - don't focus the input if it's already focused
-				// this breaks the change event in IE
-				inst.input.is(':visible') && !inst.input.is(':disabled') && inst.input[0] != document.activeElement)
-			inst.input.focus();
-		// deffered render of the years select (to avoid flashes on Firefox)
-		if( inst.yearshtml ){
-			var origyearshtml = inst.yearshtml;
-			setTimeout(function(){
-				//assure that inst.yearshtml didn't change.
-				if( origyearshtml === inst.yearshtml && inst.yearshtml ){
-					inst.dpDiv.find('select.ui-datepicker-year:first').replaceWith(inst.yearshtml);
-				}
-				origyearshtml = inst.yearshtml = null;
-			}, 0);
-		}
-	},
-
-	/* Retrieve the size of left and top borders for an element.
-	   @param  elem  (jQuery object) the element of interest
-	   @return  (number[2]) the left and top borders */
-	_getBorders: function(elem) {
-		var convert = function(value) {
-			return {thin: 1, medium: 2, thick: 3}[value] || value;
-		};
-		return [parseFloat(convert(elem.css('border-left-width'))),
-			parseFloat(convert(elem.css('border-top-width')))];
-	},
-
-	/* Check positioning to remain on screen. */
-	_checkOffset: function(inst, offset, isFixed) {
-		var dpWidth = inst.dpDiv.outerWidth();
-		var dpHeight = inst.dpDiv.outerHeight();
-		var inputWidth = inst.input ? inst.input.outerWidth() : 0;
-		var inputHeight = inst.input ? inst.input.outerHeight() : 0;
-		var viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft());
-		var viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
-
-		offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
-		offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
-		offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
-
-		// now check if datepicker is showing outside window viewport - move to a better place if so.
-		offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
-			Math.abs(offset.left + dpWidth - viewWidth) : 0);
-		offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
-			Math.abs(dpHeight + inputHeight) : 0);
-
-		return offset;
-	},
-
-	/* Find an object's position on the screen. */
-	_findPos: function(obj) {
-		var inst = this._getInst(obj);
-		var isRTL = this._get(inst, 'isRTL');
-		while (obj && (obj.type == 'hidden' || obj.nodeType != 1 || $.expr.filters.hidden(obj))) {
-			obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
-		}
-		var position = $(obj).offset();
-		return [position.left, position.top];
-	},
-
-	/* Hide the date picker from view.
-	   @param  input  element - the input field attached to the date picker */
-	_hideDatepicker: function(input) {
-		var inst = this._curInst;
-		if (!inst || (input && inst != $.data(input, PROP_NAME)))
-			return;
-		if (this._datepickerShowing) {
-			var showAnim = this._get(inst, 'showAnim');
-			var duration = this._get(inst, 'duration');
-			var postProcess = function() {
-				$.datepicker._tidyDialog(inst);
-			};
-
-			// DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
-			if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) )
-				inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
-			else
-				inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
-					(showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
-			if (!showAnim)
-				postProcess();
-			this._datepickerShowing = false;
-			var onClose = this._get(inst, 'onClose');
-			if (onClose)
-				onClose.apply((inst.input ? inst.input[0] : null),
-					[(inst.input ? inst.input.val() : ''), inst]);
-			this._lastInput = null;
-			if (this._inDialog) {
-				this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
-				if ($.blockUI) {
-					$.unblockUI();
-					$('body').append(this.dpDiv);
-				}
-			}
-			this._inDialog = false;
-		}
-	},
-
-	/* Tidy up after a dialog display. */
-	_tidyDialog: function(inst) {
-		inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
-	},
-
-	/* Close date picker if clicked elsewhere. */
-	_checkExternalClick: function(event) {
-		if (!$.datepicker._curInst)
-			return;
-
-		var $target = $(event.target),
-			inst = $.datepicker._getInst($target[0]);
-
-		if ( ( ( $target[0].id != $.datepicker._mainDivId &&
-				$target.parents('#' + $.datepicker._mainDivId).length == 0 &&
-				!$target.hasClass($.datepicker.markerClassName) &&
-				!$target.closest("." + $.datepicker._triggerClass).length &&
-				$.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
-			( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst != inst ) )
-			$.datepicker._hideDatepicker();
-	},
-
-	/* Adjust one of the date sub-fields. */
-	_adjustDate: function(id, offset, period) {
-		var target = $(id);
-		var inst = this._getInst(target[0]);
-		if (this._isDisabledDatepicker(target[0])) {
-			return;
-		}
-		this._adjustInstDate(inst, offset +
-			(period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
-			period);
-		this._updateDatepicker(inst);
-	},
-
-	/* Action for current link. */
-	_gotoToday: function(id) {
-		var target = $(id);
-		var inst = this._getInst(target[0]);
-		if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
-			inst.selectedDay = inst.currentDay;
-			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
-			inst.drawYear = inst.selectedYear = inst.currentYear;
-		}
-		else {
-			var date = new Date();
-			inst.selectedDay = date.getDate();
-			inst.drawMonth = inst.selectedMonth = date.getMonth();
-			inst.drawYear = inst.selectedYear = date.getFullYear();
-		}
-		this._notifyChange(inst);
-		this._adjustDate(target);
-	},
-
-	/* Action for selecting a new month/year. */
-	_selectMonthYear: function(id, select, period) {
-		var target = $(id);
-		var inst = this._getInst(target[0]);
-		inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
-		inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
-			parseInt(select.options[select.selectedIndex].value,10);
-		this._notifyChange(inst);
-		this._adjustDate(target);
-	},
-
-	/* Action for selecting a day. */
-	_selectDay: function(id, month, year, td) {
-		var target = $(id);
-		if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
-			return;
-		}
-		var inst = this._getInst(target[0]);
-		inst.selectedDay = inst.currentDay = $('a', td).html();
-		inst.selectedMonth = inst.currentMonth = month;
-		inst.selectedYear = inst.currentYear = year;
-		this._selectDate(id, this._formatDate(inst,
-			inst.currentDay, inst.currentMonth, inst.currentYear));
-	},
-
-	/* Erase the input field and hide the date picker. */
-	_clearDate: function(id) {
-		var target = $(id);
-		var inst = this._getInst(target[0]);
-		this._selectDate(target, '');
-	},
-
-	/* Update the input field with the selected date. */
-	_selectDate: function(id, dateStr) {
-		var target = $(id);
-		var inst = this._getInst(target[0]);
-		dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
-		if (inst.input)
-			inst.input.val(dateStr);
-		this._updateAlternate(inst);
-		var onSelect = this._get(inst, 'onSelect');
-		if (onSelect)
-			onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
-		else if (inst.input)
-			inst.input.trigger('change'); // fire the change event
-		if (inst.inline)
-			this._updateDatepicker(inst);
-		else {
-			this._hideDatepicker();
-			this._lastInput = inst.input[0];
-			if (typeof(inst.input[0]) != 'object')
-				inst.input.focus(); // restore focus
-			this._lastInput = null;
-		}
-	},
-
-	/* Update any alternate field to synchronise with the main field. */
-	_updateAlternate: function(inst) {
-		var altField = this._get(inst, 'altField');
-		if (altField) { // update alternate field too
-			var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
-			var date = this._getDate(inst);
-			var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
-			$(altField).each(function() { $(this).val(dateStr); });
-		}
-	},
-
-	/* Set as beforeShowDay function to prevent selection of weekends.
-	   @param  date  Date - the date to customise
-	   @return [boolean, string] - is this date selectable?, what is its CSS class? */
-	noWeekends: function(date) {
-		var day = date.getDay();
-		return [(day > 0 && day < 6), ''];
-	},
-
-	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
-	   @param  date  Date - the date to get the week for
-	   @return  number - the number of the week within the year that contains this date */
-	iso8601Week: function(date) {
-		var checkDate = new Date(date.getTime());
-		// Find Thursday of this week starting on Monday
-		checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
-		var time = checkDate.getTime();
-		checkDate.setMonth(0); // Compare with Jan 1
-		checkDate.setDate(1);
-		return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
-	},
-
-	/* Parse a string value into a date object.
-	   See formatDate below for the possible formats.
-
-	   @param  format    string - the expected format of the date
-	   @param  value     string - the date in the above format
-	   @param  settings  Object - attributes include:
-	                     shortYearCutoff  number - the cutoff year for determining the century (optional)
-	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
-	                     dayNames         string[7] - names of the days from Sunday (optional)
-	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
-	                     monthNames       string[12] - names of the months (optional)
-	   @return  Date - the extracted date value or null if value is blank */
-	parseDate: function (format, value, settings) {
-		if (format == null || value == null)
-			throw 'Invalid arguments';
-		value = (typeof value == 'object' ? value.toString() : value + '');
-		if (value == '')
-			return null;
-		var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
-		shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
-				new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
-		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
-		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
-		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
-		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
-		var year = -1;
-		var month = -1;
-		var day = -1;
-		var doy = -1;
-		var literal = false;
-		// Check whether a format character is doubled
-		var lookAhead = function(match) {
-			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
-			if (matches)
-				iFormat++;
-			return matches;
-		};
-		// Extract a number from the string value
-		var getNumber = function(match) {
-			var isDoubled = lookAhead(match);
-			var size = (match == '@' ? 14 : (match == '!' ? 20 :
-				(match == 'y' && isDoubled ? 4 : (match == 'o' ? 3 : 2))));
-			var digits = new RegExp('^\\d{1,' + size + '}');
-			var num = value.substring(iValue).match(digits);
-			if (!num)
-				throw 'Missing number at position ' + iValue;
-			iValue += num[0].length;
-			return parseInt(num[0], 10);
-		};
-		// Extract a name from the string value and convert to an index
-		var getName = function(match, shortNames, longNames) {
-			var names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
-				return [ [k, v] ];
-			}).sort(function (a, b) {
-				return -(a[1].length - b[1].length);
-			});
-			var index = -1;
-			$.each(names, function (i, pair) {
-				var name = pair[1];
-				if (value.substr(iValue, name.length).toLowerCase() == name.toLowerCase()) {
-					index = pair[0];
-					iValue += name.length;
-					return false;
-				}
-			});
-			if (index != -1)
-				return index + 1;
-			else
-				throw 'Unknown name at position ' + iValue;
-		};
-		// Confirm that a literal character matches the string value
-		var checkLiteral = function() {
-			if (value.charAt(iValue) != format.charAt(iFormat))
-				throw 'Unexpected literal at position ' + iValue;
-			iValue++;
-		};
-		var iValue = 0;
-		for (var iFormat = 0; iFormat < format.length; iFormat++) {
-			if (literal)
-				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
-					literal = false;
-				else
-					checkLiteral();
-			else
-				switch (format.charAt(iFormat)) {
-					case 'd':
-						day = getNumber('d');
-						break;
-					case 'D':
-						getName('D', dayNamesShort, dayNames);
-						break;
-					case 'o':
-						doy = getNumber('o');
-						break;
-					case 'm':
-						month = getNumber('m');
-						break;
-					case 'M':
-						month = getName('M', monthNamesShort, monthNames);
-						break;
-					case 'y':
-						year = getNumber('y');
-						break;
-					case '@':
-						var date = new Date(getNumber('@'));
-						year = date.getFullYear();
-						month = date.getMonth() + 1;
-						day = date.getDate();
-						break;
-					case '!':
-						var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
-						year = date.getFullYear();
-						month = date.getMonth() + 1;
-						day = date.getDate();
-						break;
-					case "'":
-						if (lookAhead("'"))
-							checkLiteral();
-						else
-							literal = true;
-						break;
-					default:
-						checkLiteral();
-				}
-		}
-		if (iValue < value.length){
-			var extra = value.substr(iValue);
-			if (!/^\s+/.test(extra)) {
-				throw "Extra/unparsed characters found in date: " + extra;
-			}
-		}
-		if (year == -1)
-			year = new Date().getFullYear();
-		else if (year < 100)
-			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
-				(year <= shortYearCutoff ? 0 : -100);
-		if (doy > -1) {
-			month = 1;
-			day = doy;
-			do {
-				var dim = this._getDaysInMonth(year, month - 1);
-				if (day <= dim)
-					break;
-				month++;
-				day -= dim;
-			} while (true);
-		}
-		var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
-		if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
-			throw 'Invalid date'; // E.g. 31/02/00
-		return date;
-	},
-
-	/* Standard date formats. */
-	ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
-	COOKIE: 'D, dd M yy',
-	ISO_8601: 'yy-mm-dd',
-	RFC_822: 'D, d M y',
-	RFC_850: 'DD, dd-M-y',
-	RFC_1036: 'D, d M y',
-	RFC_1123: 'D, d M yy',
-	RFC_2822: 'D, d M yy',
-	RSS: 'D, d M y', // RFC 822
-	TICKS: '!',
-	TIMESTAMP: '@',
-	W3C: 'yy-mm-dd', // ISO 8601
-
-	_ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
-		Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
-
-	/* Format a date object into a string value.
-	   The format can be combinations of the following:
-	   d  - day of month (no leading zero)
-	   dd - day of month (two digit)
-	   o  - day of year (no leading zeros)
-	   oo - day of year (three digit)
-	   D  - day name short
-	   DD - day name long
-	   m  - month of year (no leading zero)
-	   mm - month of year (two digit)
-	   M  - month name short
-	   MM - month name long
-	   y  - year (two digit)
-	   yy - year (four digit)
-	   @ - Unix timestamp (ms since 01/01/1970)
-	   ! - Windows ticks (100ns since 01/01/0001)
-	   '...' - literal text
-	   '' - single quote
-
-	   @param  format    string - the desired format of the date
-	   @param  date      Date - the date value to format
-	   @param  settings  Object - attributes include:
-	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
-	                     dayNames         string[7] - names of the days from Sunday (optional)
-	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
-	                     monthNames       string[12] - names of the months (optional)
-	   @return  string - the date in the above format */
-	formatDate: function (format, date, settings) {
-		if (!date)
-			return '';
-		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
-		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
-		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
-		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
-		// Check whether a format character is doubled
-		var lookAhead = function(match) {
-			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
-			if (matches)
-				iFormat++;
-			return matches;
-		};
-		// Format a number, with leading zero if necessary
-		var formatNumber = function(match, value, len) {
-			var num = '' + value;
-			if (lookAhead(match))
-				while (num.length < len)
-					num = '0' + num;
-			return num;
-		};
-		// Format a name, short or long as requested
-		var formatName = function(match, value, shortNames, longNames) {
-			return (lookAhead(match) ? longNames[value] : shortNames[value]);
-		};
-		var output = '';
-		var literal = false;
-		if (date)
-			for (var iFormat = 0; iFormat < format.length; iFormat++) {
-				if (literal)
-					if (format.charAt(iFormat) == "'" && !lookAhead("'"))
-						literal = false;
-					else
-						output += format.charAt(iFormat);
-				else
-					switch (format.charAt(iFormat)) {
-						case 'd':
-							output += formatNumber('d', date.getDate(), 2);
-							break;
-						case 'D':
-							output += formatName('D', date.getDay(), dayNamesShort, dayNames);
-							break;
-						case 'o':
-							output += formatNumber('o',
-								Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
-							break;
-						case 'm':
-							output += formatNumber('m', date.getMonth() + 1, 2);
-							break;
-						case 'M':
-							output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
-							break;
-						case 'y':
-							output += (lookAhead('y') ? date.getFullYear() :
-								(date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
-							break;
-						case '@':
-							output += date.getTime();
-							break;
-						case '!':
-							output += date.getTime() * 10000 + this._ticksTo1970;
-							break;
-						case "'":
-							if (lookAhead("'"))
-								output += "'";
-							else
-								literal = true;
-							break;
-						default:
-							output += format.charAt(iFormat);
-					}
-			}
-		return output;
-	},
-
-	/* Extract all possible characters from the date format. */
-	_possibleChars: function (format) {
-		var chars = '';
-		var literal = false;
-		// Check whether a format character is doubled
-		var lookAhead = function(match) {
-			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
-			if (matches)
-				iFormat++;
-			return matches;
-		};
-		for (var iFormat = 0; iFormat < format.length; iFormat++)
-			if (literal)
-				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
-					literal = false;
-				else
-					chars += format.charAt(iFormat);
-			else
-				switch (format.charAt(iFormat)) {
-					case 'd': case 'm': case 'y': case '@':
-						chars += '0123456789';
-						break;
-					case 'D': case 'M':
-						return null; // Accept anything
-					case "'":
-						if (lookAhead("'"))
-							chars += "'";
-						else
-							literal = true;
-						break;
-					default:
-						chars += format.charAt(iFormat);
-				}
-		return chars;
-	},
-
-	/* Get a setting value, defaulting if necessary. */
-	_get: function(inst, name) {
-		return inst.settings[name] !== undefined ?
-			inst.settings[name] : this._defaults[name];
-	},
-
-	/* Parse existing date and initialise date picker. */
-	_setDateFromField: function(inst, noDefault) {
-		if (inst.input.val() == inst.lastVal) {
-			return;
-		}
-		var dateFormat = this._get(inst, 'dateFormat');
-		var dates = inst.lastVal = inst.input ? inst.input.val() : null;
-		var date, defaultDate;
-		date = defaultDate = this._getDefaultDate(inst);
-		var settings = this._getFormatConfig(inst);
-		try {
-			date = this.parseDate(dateFormat, dates, settings) || defaultDate;
-		} catch (event) {
-			this.log(event);
-			dates = (noDefault ? '' : dates);
-		}
-		inst.selectedDay = date.getDate();
-		inst.drawMonth = inst.selectedMonth = date.getMonth();
-		inst.drawYear = inst.selectedYear = date.getFullYear();
-		inst.currentDay = (dates ? date.getDate() : 0);
-		inst.currentMonth = (dates ? date.getMonth() : 0);
-		inst.currentYear = (dates ? date.getFullYear() : 0);
-		this._adjustInstDate(inst);
-	},
-
-	/* Retrieve the default date shown on opening. */
-	_getDefaultDate: function(inst) {
-		return this._restrictMinMax(inst,
-			this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
-	},
-
-	/* A date may be specified as an exact value or a relative one. */
-	_determineDate: function(inst, date, defaultDate) {
-		var offsetNumeric = function(offset) {
-			var date = new Date();
-			date.setDate(date.getDate() + offset);
-			return date;
-		};
-		var offsetString = function(offset) {
-			try {
-				return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
-					offset, $.datepicker._getFormatConfig(inst));
-			}
-			catch (e) {
-				// Ignore
-			}
-			var date = (offset.toLowerCase().match(/^c/) ?
-				$.datepicker._getDate(inst) : null) || new Date();
-			var year = date.getFullYear();
-			var month = date.getMonth();
-			var day = date.getDate();
-			var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
-			var matches = pattern.exec(offset);
-			while (matches) {
-				switch (matches[2] || 'd') {
-					case 'd' : case 'D' :
-						day += parseInt(matches[1],10); break;
-					case 'w' : case 'W' :
-						day += parseInt(matches[1],10) * 7; break;
-					case 'm' : case 'M' :
-						month += parseInt(matches[1],10);
-						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
-						break;
-					case 'y': case 'Y' :
-						year += parseInt(matches[1],10);
-						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
-						break;
-				}
-				matches = pattern.exec(offset);
-			}
-			return new Date(year, month, day);
-		};
-		var newDate = (date == null || date === '' ? defaultDate : (typeof date == 'string' ? offsetString(date) :
-			(typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
-		newDate = (newDate && newDate.toString() == 'Invalid Date' ? defaultDate : newDate);
-		if (newDate) {
-			newDate.setHours(0);
-			newDate.setMinutes(0);
-			newDate.setSeconds(0);
-			newDate.setMilliseconds(0);
-		}
-		return this._daylightSavingAdjust(newDate);
-	},
-
-	/* Handle switch to/from daylight saving.
-	   Hours may be non-zero on daylight saving cut-over:
-	   > 12 when midnight changeover, but then cannot generate
-	   midnight datetime, so jump to 1AM, otherwise reset.
-	   @param  date  (Date) the date to check
-	   @return  (Date) the corrected date */
-	_daylightSavingAdjust: function(date) {
-		if (!date) return null;
-		date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
-		return date;
-	},
-
-	/* Set the date(s) directly. */
-	_setDate: function(inst, date, noChange) {
-		var clear = !date;
-		var origMonth = inst.selectedMonth;
-		var origYear = inst.selectedYear;
-		var newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
-		inst.selectedDay = inst.currentDay = newDate.getDate();
-		inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
-		inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
-		if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
-			this._notifyChange(inst);
-		this._adjustInstDate(inst);
-		if (inst.input) {
-			inst.input.val(clear ? '' : this._formatDate(inst));
-		}
-	},
-
-	/* Retrieve the date(s) directly. */
-	_getDate: function(inst) {
-		var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
-			this._daylightSavingAdjust(new Date(
-			inst.currentYear, inst.currentMonth, inst.currentDay)));
-			return startDate;
-	},
-
-	/* Attach the onxxx handlers.  These are declared statically so
-	 * they work with static code transformers like Caja.
-	 */
-	_attachHandlers: function(inst) {
-		var stepMonths = this._get(inst, 'stepMonths');
-		var id = '#' + inst.id.replace( /\\\\/g, "\\" );
-		inst.dpDiv.find('[data-handler]').map(function () {
-			var handler = {
-				prev: function () {
-					window['DP_jQuery_' + dpuuid].datepicker._adjustDate(id, -stepMonths, 'M');
-				},
-				next: function () {
-					window['DP_jQuery_' + dpuuid].datepicker._adjustDate(id, +stepMonths, 'M');
-				},
-				hide: function () {
-					window['DP_jQuery_' + dpuuid].datepicker._hideDatepicker();
-				},
-				today: function () {
-					window['DP_jQuery_' + dpuuid].datepicker._gotoToday(id);
-				},
-				selectDay: function () {
-					window['DP_jQuery_' + dpuuid].datepicker._selectDay(id, +this.getAttribute('data-month'), +this.getAttribute('data-year'), this);
-					return false;
-				},
-				selectMonth: function () {
-					window['DP_jQuery_' + dpuuid].datepicker._selectMonthYear(id, this, 'M');
-					return false;
-				},
-				selectYear: function () {
-					window['DP_jQuery_' + dpuuid].datepicker._selectMonthYear(id, this, 'Y');
-					return false;
-				}
-			};
-			$(this).bind(this.getAttribute('data-event'), handler[this.getAttribute('data-handler')]);
-		});
-	},
-
-	/* Generate the HTML for the current state of the date picker. */
-	_generateHTML: function(inst) {
-		var today = new Date();
-		today = this._daylightSavingAdjust(
-			new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
-		var isRTL = this._get(inst, 'isRTL');
-		var showButtonPanel = this._get(inst, 'showButtonPanel');
-		var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
-		var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
-		var numMonths = this._getNumberOfMonths(inst);
-		var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
-		var stepMonths = this._get(inst, 'stepMonths');
-		var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
-		var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
-			new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
-		var minDate = this._getMinMaxDate(inst, 'min');
-		var maxDate = this._getMinMaxDate(inst, 'max');
-		var drawMonth = inst.drawMonth - showCurrentAtPos;
-		var drawYear = inst.drawYear;
-		if (drawMonth < 0) {
-			drawMonth += 12;
-			drawYear--;
-		}
-		if (maxDate) {
-			var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
-				maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
-			maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
-			while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
-				drawMonth--;
-				if (drawMonth < 0) {
-					drawMonth = 11;
-					drawYear--;
-				}
-			}
-		}
-		inst.drawMonth = drawMonth;
-		inst.drawYear = drawYear;
-		var prevText = this._get(inst, 'prevText');
-		prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
-			this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
-			this._getFormatConfig(inst)));
-		var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
-			'<a class="ui-datepicker-prev ui-corner-all" data-handler="prev" data-event="click"' +
-			' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
-			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
-		var nextText = this._get(inst, 'nextText');
-		nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
-			this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
-			this._getFormatConfig(inst)));
-		var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
-			'<a class="ui-datepicker-next ui-corner-all" data-handler="next" data-event="click"' +
-			' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
-			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
-		var currentText = this._get(inst, 'currentText');
-		var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
-		currentText = (!navigationAsDateFormat ? currentText :
-			this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
-		var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" data-handler="hide" data-event="click">' +
-			this._get(inst, 'closeText') + '</button>' : '');
-		var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
-			(this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" data-handler="today" data-event="click"' +
-			'>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
-		var firstDay = parseInt(this._get(inst, 'firstDay'),10);
-		firstDay = (isNaN(firstDay) ? 0 : firstDay);
-		var showWeek = this._get(inst, 'showWeek');
-		var dayNames = this._get(inst, 'dayNames');
-		var dayNamesShort = this._get(inst, 'dayNamesShort');
-		var dayNamesMin = this._get(inst, 'dayNamesMin');
-		var monthNames = this._get(inst, 'monthNames');
-		var monthNamesShort = this._get(inst, 'monthNamesShort');
-		var beforeShowDay = this._get(inst, 'beforeShowDay');
-		var showOtherMonths = this._get(inst, 'showOtherMonths');
-		var selectOtherMonths = this._get(inst, 'selectOtherMonths');
-		var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
-		var defaultDate = this._getDefaultDate(inst);
-		var html = '';
-		for (var row = 0; row < numMonths[0]; row++) {
-			var group = '';
-			this.maxRows = 4;
-			for (var col = 0; col < numMonths[1]; col++) {
-				var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
-				var cornerClass = ' ui-corner-all';
-				var calender = '';
-				if (isMultiMonth) {
-					calender += '<div class="ui-datepicker-group';
-					if (numMonths[1] > 1)
-						switch (col) {
-							case 0: calender += ' ui-datepicker-group-first';
-								cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
-							case numMonths[1]-1: calender += ' ui-datepicker-group-last';
-								cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
-							default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
-						}
-					calender += '">';
-				}
-				calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
-					(/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
-					(/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
-					this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
-					row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
-					'</div><table class="ui-datepicker-calendar"><thead>' +
-					'<tr>';
-				var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
-				for (var dow = 0; dow < 7; dow++) { // days of the week
-					var day = (dow + firstDay) % 7;
-					thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
-						'<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
-				}
-				calender += thead + '</tr></thead><tbody>';
-				var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
-				if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
-					inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
-				var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
-				var curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
-				var numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
-				this.maxRows = numRows;
-				var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
-				for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
-					calender += '<tr>';
-					var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
-						this._get(inst, 'calculateWeek')(printDate) + '</td>');
-					for (var dow = 0; dow < 7; dow++) { // create date picker days
-						var daySettings = (beforeShowDay ?
-							beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
-						var otherMonth = (printDate.getMonth() != drawMonth);
-						var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
-							(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
-						tbody += '<td class="' +
-							((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
-							(otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
-							((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
-							(defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
-							// or defaultDate is current printedDate and defaultDate is selectedDate
-							' ' + this._dayOverClass : '') + // highlight selected day
-							(unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') +  // highlight unselectable days
-							(otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
-							(printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
-							(printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
-							((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
-							(unselectable ? '' : ' data-handler="selectDay" data-event="click" data-month="' + printDate.getMonth() + '" data-year="' + printDate.getFullYear() + '"') + '>' + // actions
-							(otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
-							(unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
-							(printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
-							(printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
-							(otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
-							'" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
-						printDate.setDate(printDate.getDate() + 1);
-						printDate = this._daylightSavingAdjust(printDate);
-					}
-					calender += tbody + '</tr>';
-				}
-				drawMonth++;
-				if (drawMonth > 11) {
-					drawMonth = 0;
-					drawYear++;
-				}
-				calender += '</tbody></table>' + (isMultiMonth ? '</div>' +
-							((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
-				group += calender;
-			}
-			html += group;
-		}
-		html += buttonPanel + ($.ui.ie6 && !inst.inline ?
-			'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
-		inst._keyEvent = false;
-		return html;
-	},
-
-	/* Generate the month and year header. */
-	_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
-			secondary, monthNames, monthNamesShort) {
-		var changeMonth = this._get(inst, 'changeMonth');
-		var changeYear = this._get(inst, 'changeYear');
-		var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
-		var html = '<div class="ui-datepicker-title">';
-		var monthHtml = '';
-		// month selection
-		if (secondary || !changeMonth)
-			monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
-		else {
-			var inMinYear = (minDate && minDate.getFullYear() == drawYear);
-			var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
-			monthHtml += '<select class="ui-datepicker-month" data-handler="selectMonth" data-event="change">';
-			for (var month = 0; month < 12; month++) {
-				if ((!inMinYear || month >= minDate.getMonth()) &&
-						(!inMaxYear || month <= maxDate.getMonth()))
-					monthHtml += '<option value="' + month + '"' +
-						(month == drawMonth ? ' selected="selected"' : '') +
-						'>' + monthNamesShort[month] + '</option>';
-			}
-			monthHtml += '</select>';
-		}
-		if (!showMonthAfterYear)
-			html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
-		// year selection
-		if ( !inst.yearshtml ) {
-			inst.yearshtml = '';
-			if (secondary || !changeYear)
-				html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
-			else {
-				// determine range of years to display
-				var years = this._get(inst, 'yearRange').split(':');
-				var thisYear = new Date().getFullYear();
-				var determineYear = function(value) {
-					var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
-						(value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
-						parseInt(value, 10)));
-					return (isNaN(year) ? thisYear : year);
-				};
-				var year = determineYear(years[0]);
-				var endYear = Math.max(year, determineYear(years[1] || ''));
-				year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
-				endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
-				inst.yearshtml += '<select class="ui-datepicker-year" data-handler="selectYear" data-event="change">';
-				for (; year <= endYear; year++) {
-					inst.yearshtml += '<option value="' + year + '"' +
-						(year == drawYear ? ' selected="selected"' : '') +
-						'>' + year + '</option>';
-				}
-				inst.yearshtml += '</select>';
-
-				html += inst.yearshtml;
-				inst.yearshtml = null;
-			}
-		}
-		html += this._get(inst, 'yearSuffix');
-		if (showMonthAfterYear)
-			html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
-		html += '</div>'; // Close datepicker_header
-		return html;
-	},
-
-	/* Adjust one of the date sub-fields. */
-	_adjustInstDate: function(inst, offset, period) {
-		var year = inst.drawYear + (period == 'Y' ? offset : 0);
-		var month = inst.drawMonth + (period == 'M' ? offset : 0);
-		var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
-			(period == 'D' ? offset : 0);
-		var date = this._restrictMinMax(inst,
-			this._daylightSavingAdjust(new Date(year, month, day)));
-		inst.selectedDay = date.getDate();
-		inst.drawMonth = inst.selectedMonth = date.getMonth();
-		inst.drawYear = inst.selectedYear = date.getFullYear();
-		if (period == 'M' || period == 'Y')
-			this._notifyChange(inst);
-	},
-
-	/* Ensure a date is within any min/max bounds. */
-	_restrictMinMax: function(inst, date) {
-		var minDate = this._getMinMaxDate(inst, 'min');
-		var maxDate = this._getMinMaxDate(inst, 'max');
-		var newDate = (minDate && date < minDate ? minDate : date);
-		newDate = (maxDate && newDate > maxDate ? maxDate : newDate);
-		return newDate;
-	},
-
-	/* Notify change of month/year. */
-	_notifyChange: function(inst) {
-		var onChange = this._get(inst, 'onChangeMonthYear');
-		if (onChange)
-			onChange.apply((inst.input ? inst.input[0] : null),
-				[inst.selectedYear, inst.selectedMonth + 1, inst]);
-	},
-
-	/* Determine the number of months to show. */
-	_getNumberOfMonths: function(inst) {
-		var numMonths = this._get(inst, 'numberOfMonths');
-		return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
-	},
-
-	/* Determine the current maximum date - ensure no time components are set. */
-	_getMinMaxDate: function(inst, minMax) {
-		return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
-	},
-
-	/* Find the number of days in a given month. */
-	_getDaysInMonth: function(year, month) {
-		return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
-	},
-
-	/* Find the day of the week of the first of a month. */
-	_getFirstDayOfMonth: function(year, month) {
-		return new Date(year, month, 1).getDay();
-	},
-
-	/* Determines if we should allow a "next/prev" month display change. */
-	_canAdjustMonth: function(inst, offset, curYear, curMonth) {
-		var numMonths = this._getNumberOfMonths(inst);
-		var date = this._daylightSavingAdjust(new Date(curYear,
-			curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
-		if (offset < 0)
-			date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
-		return this._isInRange(inst, date);
-	},
-
-	/* Is the given date in the accepted range? */
-	_isInRange: function(inst, date) {
-		var minDate = this._getMinMaxDate(inst, 'min');
-		var maxDate = this._getMinMaxDate(inst, 'max');
-		return ((!minDate || date.getTime() >= minDate.getTime()) &&
-			(!maxDate || date.getTime() <= maxDate.getTime()));
-	},
-
-	/* Provide the configuration settings for formatting/parsing. */
-	_getFormatConfig: function(inst) {
-		var shortYearCutoff = this._get(inst, 'shortYearCutoff');
-		shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
-			new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
-		return {shortYearCutoff: shortYearCutoff,
-			dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
-			monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
-	},
-
-	/* Format the given date for display. */
-	_formatDate: function(inst, day, month, year) {
-		if (!day) {
-			inst.currentDay = inst.selectedDay;
-			inst.currentMonth = inst.selectedMonth;
-			inst.currentYear = inst.selectedYear;
-		}
-		var date = (day ? (typeof day == 'object' ? day :
-			this._daylightSavingAdjust(new Date(year, month, day))) :
-			this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
-		return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
-	}
-});
-
-/*
- * Bind hover events for datepicker elements.
- * Done via delegate so the binding only occurs once in the lifetime of the parent div.
- * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
- */
-function bindHover(dpDiv) {
-	var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a';
-	return dpDiv.delegate(selector, 'mouseout', function() {
-			$(this).removeClass('ui-state-hover');
-			if (this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
-			if (this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
-		})
-		.delegate(selector, 'mouseover', function(){
-			if (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) {
-				$(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
-				$(this).addClass('ui-state-hover');
-				if (this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
-				if (this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
-			}
-		});
-}
-
-/* jQuery extend now ignores nulls! */
-function extendRemove(target, props) {
-	$.extend(target, props);
-	for (var name in props)
-		if (props[name] == null || props[name] == undefined)
-			target[name] = props[name];
-	return target;
-};
-
-/* Invoke the datepicker functionality.
-   @param  options  string - a command, optionally followed by additional parameters or
-	                Object - settings for attaching new datepicker functionality
-   @return  jQuery object */
-$.fn.datepicker = function(options){
-
-	/* Verify an empty collection wasn't passed - Fixes #6976 */
-	if ( !this.length ) {
-		return this;
-	}
-
-	/* Initialise the date picker. */
-	if (!$.datepicker.initialized) {
-		$(document).mousedown($.datepicker._checkExternalClick).
-			find(document.body).append($.datepicker.dpDiv);
-		$.datepicker.initialized = true;
-	}
-
-	var otherArgs = Array.prototype.slice.call(arguments, 1);
-	if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
-		return $.datepicker['_' + options + 'Datepicker'].
-			apply($.datepicker, [this[0]].concat(otherArgs));
-	if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
-		return $.datepicker['_' + options + 'Datepicker'].
-			apply($.datepicker, [this[0]].concat(otherArgs));
-	return this.each(function() {
-		typeof options == 'string' ?
-			$.datepicker['_' + options + 'Datepicker'].
-				apply($.datepicker, [this].concat(otherArgs)) :
-			$.datepicker._attachDatepicker(this, options);
-	});
-};
-
-$.datepicker = new Datepicker(); // singleton instance
-$.datepicker.initialized = false;
-$.datepicker.uuid = new Date().getTime();
-$.datepicker.version = "1.9.2";
-
-// Workaround for #4055
-// Add another global to avoid noConflict issues with inline event handlers
-window['DP_jQuery_' + dpuuid] = $;
-
-})(jQuery);
-(function( $, undefined ) {
-
-var uiDialogClasses = "ui-dialog ui-widget ui-widget-content ui-corner-all ",
-	sizeRelatedOptions = {
-		buttons: true,
-		height: true,
-		maxHeight: true,
-		maxWidth: true,
-		minHeight: true,
-		minWidth: true,
-		width: true
-	},
-	resizableRelatedOptions = {
-		maxHeight: true,
-		maxWidth: true,
-		minHeight: true,
-		minWidth: true
-	};
-
-$.widget("ui.dialog", {
-	version: "1.9.2",
-	options: {
-		autoOpen: true,
-		buttons: {},
-		closeOnEscape: true,
-		closeText: "close",
-		dialogClass: "",
-		draggable: true,
-		hide: null,
-		height: "auto",
-		maxHeight: false,
-		maxWidth: false,
-		minHeight: 150,
-		minWidth: 150,
-		modal: false,
-		position: {
-			my: "center",
-			at: "center",
-			of: window,
-			collision: "fit",
-			// ensure that the titlebar is never outside the document
-			using: function( pos ) {
-				var topOffset = $( this ).css( pos ).offset().top;
-				if ( topOffset < 0 ) {
-					$( this ).css( "top", pos.top - topOffset );
-				}
-			}
-		},
-		resizable: true,
-		show: null,
-		stack: true,
-		title: "",
-		width: 300,
-		zIndex: 1000
-	},
-
-	_create: function() {
-		this.originalTitle = this.element.attr( "title" );
-		// #5742 - .attr() might return a DOMElement
-		if ( typeof this.originalTitle !== "string" ) {
-			this.originalTitle = "";
-		}
-		this.oldPosition = {
-			parent: this.element.parent(),
-			index: this.element.parent().children().index( this.element )
-		};
-		this.options.title = this.options.title || this.originalTitle;
-		var that = this,
-			options = this.options,
-
-			title = options.title || "&#160;",
-			uiDialog,
-			uiDialogTitlebar,
-			uiDialogTitlebarClose,
-			uiDialogTitle,
-			uiDialogButtonPane;
-
-			uiDialog = ( this.uiDialog = $( "<div>" ) )
-				.addClass( uiDialogClasses + options.dialogClass )
-				.css({
-					display: "none",
-					outline: 0, // TODO: move to stylesheet
-					zIndex: options.zIndex
-				})
-				// setting tabIndex makes the div focusable
-				.attr( "tabIndex", -1)
-				.keydown(function( event ) {
-					if ( options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
-							event.keyCode === $.ui.keyCode.ESCAPE ) {
-						that.close( event );
-						event.preventDefault();
-					}
-				})
-				.mousedown(function( event ) {
-					that.moveToTop( false, event );
-				})
-				.appendTo( "body" );
-
-			this.element
-				.show()
-				.removeAttr( "title" )
-				.addClass( "ui-dialog-content ui-widget-content" )
-				.appendTo( uiDialog );
-
-			uiDialogTitlebar = ( this.uiDialogTitlebar = $( "<div>" ) )
-				.addClass( "ui-dialog-titlebar  ui-widget-header  " +
-					"ui-corner-all  ui-helper-clearfix" )
-				.bind( "mousedown", function() {
-					// Dialog isn't getting focus when dragging (#8063)
-					uiDialog.focus();
-				})
-				.prependTo( uiDialog );
-
-			uiDialogTitlebarClose = $( "<a href='#'></a>" )
-				.addClass( "ui-dialog-titlebar-close  ui-corner-all" )
-				.attr( "role", "button" )
-				.click(function( event ) {
-					event.preventDefault();
-					that.close( event );
-				})
-				.appendTo( uiDialogTitlebar );
-
-			( this.uiDialogTitlebarCloseText = $( "<span>" ) )
-				.addClass( "ui-icon ui-icon-closethick" )
-				.text( options.closeText )
-				.appendTo( uiDialogTitlebarClose );
-
-			uiDialogTitle = $( "<span>" )
-				.uniqueId()
-				.addClass( "ui-dialog-title" )
-				.html( title )
-				.prependTo( uiDialogTitlebar );
-
-			uiDialogButtonPane = ( this.uiDialogButtonPane = $( "<div>" ) )
-				.addClass( "ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" );
-
-			( this.uiButtonSet = $( "<div>" ) )
-				.addClass( "ui-dialog-buttonset" )
-				.appendTo( uiDialogButtonPane );
-
-		uiDialog.attr({
-			role: "dialog",
-			"aria-labelledby": uiDialogTitle.attr( "id" )
-		});
-
-		uiDialogTitlebar.find( "*" ).add( uiDialogTitlebar ).disableSelection();
-		this._hoverable( uiDialogTitlebarClose );
-		this._focusable( uiDialogTitlebarClose );
-
-		if ( options.draggable && $.fn.draggable ) {
-			this._makeDraggable();
-		}
-		if ( options.resizable && $.fn.resizable ) {
-			this._makeResizable();
-		}
-
-		this._createButtons( options.buttons );
-		this._isOpen = false;
-
-		if ( $.fn.bgiframe ) {
-			uiDialog.bgiframe();
-		}
-
-		// prevent tabbing out of modal dialogs
-		this._on( uiDialog, { keydown: function( event ) {
-			if ( !options.modal || event.keyCode !== $.ui.keyCode.TAB ) {
-				return;
-			}
-
-			var tabbables = $( ":tabbable", uiDialog ),
-				first = tabbables.filter( ":first" ),
-				last  = tabbables.filter( ":last" );
-
-			if ( event.target === last[0] && !event.shiftKey ) {
-				first.focus( 1 );
-				return false;
-			} else if ( event.target === first[0] && event.shiftKey ) {
-				last.focus( 1 );
-				return false;
-			}
-		}});
-	},
-
-	_init: function() {
-		if ( this.options.autoOpen ) {
-			this.open();
-		}
-	},
-
-	_destroy: function() {
-		var next,
-			oldPosition = this.oldPosition;
-
-		if ( this.overlay ) {
-			this.overlay.destroy();
-		}
-		this.uiDialog.hide();
-		this.element
-			.removeClass( "ui-dialog-content ui-widget-content" )
-			.hide()
-			.appendTo( "body" );
-		this.uiDialog.remove();
-
-		if ( this.originalTitle ) {
-			this.element.attr( "title", this.originalTitle );
-		}
-
-		next = oldPosition.parent.children().eq( oldPosition.index );
-		// Don't try to place the dialog next to itself (#8613)
-		if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
-			next.before( this.element );
-		} else {
-			oldPosition.parent.append( this.element );
-		}
-	},
-
-	widget: function() {
-		return this.uiDialog;
-	},
-
-	close: function( event ) {
-		var that = this,
-			maxZ, thisZ;
-
-		if ( !this._isOpen ) {
-			return;
-		}
-
-		if ( false === this._trigger( "beforeClose", event ) ) {
-			return;
-		}
-
-		this._isOpen = false;
-
-		if ( this.overlay ) {
-			this.overlay.destroy();
-		}
-
-		if ( this.options.hide ) {
-			this._hide( this.uiDialog, this.options.hide, function() {
-				that._trigger( "close", event );
-			});
-		} else {
-			this.uiDialog.hide();
-			this._trigger( "close", event );
-		}
-
-		$.ui.dialog.overlay.resize();
-
-		// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
-		if ( this.options.modal ) {
-			maxZ = 0;
-			$( ".ui-dialog" ).each(function() {
-				if ( this !== that.uiDialog[0] ) {
-					thisZ = $( this ).css( "z-index" );
-					if ( !isNaN( thisZ ) ) {
-						maxZ = Math.max( maxZ, thisZ );
-					}
-				}
-			});
-			$.ui.dialog.maxZ = maxZ;
-		}
-
-		return this;
-	},
-
-	isOpen: function() {
-		return this._isOpen;
-	},
-
-	// the force parameter allows us to move modal dialogs to their correct
-	// position on open
-	moveToTop: function( force, event ) {
-		var options = this.options,
-			saveScroll;
-
-		if ( ( options.modal && !force ) ||
-				( !options.stack && !options.modal ) ) {
-			return this._trigger( "focus", event );
-		}
-
-		if ( options.zIndex > $.ui.dialog.maxZ ) {
-			$.ui.dialog.maxZ = options.zIndex;
-		}
-		if ( this.overlay ) {
-			$.ui.dialog.maxZ += 1;
-			$.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ;
-			this.overlay.$el.css( "z-index", $.ui.dialog.overlay.maxZ );
-		}
-
-		// Save and then restore scroll
-		// Opera 9.5+ resets when parent z-index is changed.
-		// http://bugs.jqueryui.com/ticket/3193
-		saveScroll = {
-			scrollTop: this.element.scrollTop(),
-			scrollLeft: this.element.scrollLeft()
-		};
-		$.ui.dialog.maxZ += 1;
-		this.uiDialog.css( "z-index", $.ui.dialog.maxZ );
-		this.element.attr( saveScroll );
-		this._trigger( "focus", event );
-
-		return this;
-	},
-
-	open: function() {
-		if ( this._isOpen ) {
-			return;
-		}
-
-		var hasFocus,
-			options = this.options,
-			uiDialog = this.uiDialog;
-
-		this._size();
-		this._position( options.position );
-		uiDialog.show( options.show );
-		this.overlay = options.modal ? new $.ui.dialog.overlay( this ) : null;
-		this.moveToTop( true );
-
-		// set focus to the first tabbable element in the content area or the first button
-		// if there are no tabbable elements, set focus on the dialog itself
-		hasFocus = this.element.find( ":tabbable" );
-		if ( !hasFocus.length ) {
-			hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
-			if ( !hasFocus.length ) {
-				hasFocus = uiDialog;
-			}
-		}
-		hasFocus.eq( 0 ).focus();
-
-		this._isOpen = true;
-		this._trigger( "open" );
-
-		return this;
-	},
-
-	_createButtons: function( buttons ) {
-		var that = this,
-			hasButtons = false;
-
-		// if we already have a button pane, remove it
-		this.uiDialogButtonPane.remove();
-		this.uiButtonSet.empty();
-
-		if ( typeof buttons === "object" && buttons !== null ) {
-			$.each( buttons, function() {
-				return !(hasButtons = true);
-			});
-		}
-		if ( hasButtons ) {
-			$.each( buttons, function( name, props ) {
-				var button, click;
-				props = $.isFunction( props ) ?
-					{ click: props, text: name } :
-					props;
-				// Default to a non-submitting button
-				props = $.extend( { type: "button" }, props );
-				// Change the context for the click callback to be the main element
-				click = props.click;
-				props.click = function() {
-					click.apply( that.element[0], arguments );
-				};
-				button = $( "<button></button>", props )
-					.appendTo( that.uiButtonSet );
-				if ( $.fn.button ) {
-					button.button();
-				}
-			});
-			this.uiDialog.addClass( "ui-dialog-buttons" );
-			this.uiDialogButtonPane.appendTo( this.uiDialog );
-		} else {
-			this.uiDialog.removeClass( "ui-dialog-buttons" );
-		}
-	},
-
-	_makeDraggable: function() {
-		var that = this,
-			options = this.options;
-
-		function filteredUi( ui ) {
-			return {
-				position: ui.position,
-				offset: ui.offset
-			};
-		}
-
-		this.uiDialog.draggable({
-			cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
-			handle: ".ui-dialog-titlebar",
-			containment: "document",
-			start: function( event, ui ) {
-				$( this )
-					.addClass( "ui-dialog-dragging" );
-				that._trigger( "dragStart", event, filteredUi( ui ) );
-			},
-			drag: function( event, ui ) {
-				that._trigger( "drag", event, filteredUi( ui ) );
-			},
-			stop: function( event, ui ) {
-				options.position = [
-					ui.position.left - that.document.scrollLeft(),
-					ui.position.top - that.document.scrollTop()
-				];
-				$( this )
-					.removeClass( "ui-dialog-dragging" );
-				that._trigger( "dragStop", event, filteredUi( ui ) );
-				$.ui.dialog.overlay.resize();
-			}
-		});
-	},
-
-	_makeResizable: function( handles ) {
-		handles = (handles === undefined ? this.options.resizable : handles);
-		var that = this,
-			options = this.options,
-			// .ui-resizable has position: relative defined in the stylesheet
-			// but dialogs have to use absolute or fixed positioning
-			position = this.uiDialog.css( "position" ),
-			resizeHandles = typeof handles === 'string' ?
-				handles	:
-				"n,e,s,w,se,sw,ne,nw";
-
-		function filteredUi( ui ) {
-			return {
-				originalPosition: ui.originalPosition,
-				originalSize: ui.originalSize,
-				position: ui.position,
-				size: ui.size
-			};
-		}
-
-		this.uiDialog.resizable({
-			cancel: ".ui-dialog-content",
-			containment: "document",
-			alsoResize: this.element,
-			maxWidth: options.maxWidth,
-			maxHeight: options.maxHeight,
-			minWidth: options.minWidth,
-			minHeight: this._minHeight(),
-			handles: resizeHandles,
-			start: function( event, ui ) {
-				$( this ).addClass( "ui-dialog-resizing" );
-				that._trigger( "resizeStart", event, filteredUi( ui ) );
-			},
-			resize: function( event, ui ) {
-				that._trigger( "resize", event, filteredUi( ui ) );
-			},
-			stop: function( event, ui ) {
-				$( this ).removeClass( "ui-dialog-resizing" );
-				options.height = $( this ).height();
-				options.width = $( this ).width();
-				that._trigger( "resizeStop", event, filteredUi( ui ) );
-				$.ui.dialog.overlay.resize();
-			}
-		})
-		.css( "position", position )
-		.find( ".ui-resizable-se" )
-			.addClass( "ui-icon ui-icon-grip-diagonal-se" );
-	},
-
-	_minHeight: function() {
-		var options = this.options;
-
-		if ( options.height === "auto" ) {
-			return options.minHeight;
-		} else {
-			return Math.min( options.minHeight, options.height );
-		}
-	},
-
-	_position: function( position ) {
-		var myAt = [],
-			offset = [ 0, 0 ],
-			isVisible;
-
-		if ( position ) {
-			// deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
-	//		if (typeof position == 'string' || $.isArray(position)) {
-	//			myAt = $.isArray(position) ? position : position.split(' ');
-
-			if ( typeof position === "string" || (typeof position === "object" && "0" in position ) ) {
-				myAt = position.split ? position.split( " " ) : [ position[ 0 ], position[ 1 ] ];
-				if ( myAt.length === 1 ) {
-					myAt[ 1 ] = myAt[ 0 ];
-				}
-
-				$.each( [ "left", "top" ], function( i, offsetPosition ) {
-					if ( +myAt[ i ] === myAt[ i ] ) {
-						offset[ i ] = myAt[ i ];
-						myAt[ i ] = offsetPosition;
-					}
-				});
-
-				position = {
-					my: myAt[0] + (offset[0] < 0 ? offset[0] : "+" + offset[0]) + " " +
-						myAt[1] + (offset[1] < 0 ? offset[1] : "+" + offset[1]),
-					at: myAt.join( " " )
-				};
-			}
-
-			position = $.extend( {}, $.ui.dialog.prototype.options.position, position );
-		} else {
-			position = $.ui.dialog.prototype.options.position;
-		}
-
-		// need to show the dialog to get the actual offset in the position plugin
-		isVisible = this.uiDialog.is( ":visible" );
-		if ( !isVisible ) {
-			this.uiDialog.show();
-		}
-		this.uiDialog.position( position );
-		if ( !isVisible ) {
-			this.uiDialog.hide();
-		}
-	},
-
-	_setOptions: function( options ) {
-		var that = this,
-			resizableOptions = {},
-			resize = false;
-
-		$.each( options, function( key, value ) {
-			that._setOption( key, value );
-
-			if ( key in sizeRelatedOptions ) {
-				resize = true;
-			}
-			if ( key in resizableRelatedOptions ) {
-				resizableOptions[ key ] = value;
-			}
-		});
-
-		if ( resize ) {
-			this._size();
-		}
-		if ( this.uiDialog.is( ":data(resizable)" ) ) {
-			this.uiDialog.resizable( "option", resizableOptions );
-		}
-	},
-
-	_setOption: function( key, value ) {
-		var isDraggable, isResizable,
-			uiDialog = this.uiDialog;
-
-		switch ( key ) {
-			case "buttons":
-				this._createButtons( value );
-				break;
-			case "closeText":
-				// ensure that we always pass a string
-				this.uiDialogTitlebarCloseText.text( "" + value );
-				break;
-			case "dialogClass":
-				uiDialog
-					.removeClass( this.options.dialogClass )
-					.addClass( uiDialogClasses + value );
-				break;
-			case "disabled":
-				if ( value ) {
-					uiDialog.addClass( "ui-dialog-disabled" );
-				} else {
-					uiDialog.removeClass( "ui-dialog-disabled" );
-				}
-				break;
-			case "draggable":
-				isDraggable = uiDialog.is( ":data(draggable)" );
-				if ( isDraggable && !value ) {
-					uiDialog.draggable( "destroy" );
-				}
-
-				if ( !isDraggable && value ) {
-					this._makeDraggable();
-				}
-				break;
-			case "position":
-				this._position( value );
-				break;
-			case "resizable":
-				// currently resizable, becoming non-resizable
-				isResizable = uiDialog.is( ":data(resizable)" );
-				if ( isResizable && !value ) {
-					uiDialog.resizable( "destroy" );
-				}
-
-				// currently resizable, changing handles
-				if ( isResizable && typeof value === "string" ) {
-					uiDialog.resizable( "option", "handles", value );
-				}
-
-				// currently non-resizable, becoming resizable
-				if ( !isResizable && value !== false ) {
-					this._makeResizable( value );
-				}
-				break;
-			case "title":
-				// convert whatever was passed in o a string, for html() to not throw up
-				$( ".ui-dialog-title", this.uiDialogTitlebar )
-					.html( "" + ( value || "&#160;" ) );
-				break;
-		}
-
-		this._super( key, value );
-	},
-
-	_size: function() {
-		/* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
-		 * divs will both have width and height set, so we need to reset them
-		 */
-		var nonContentHeight, minContentHeight, autoHeight,
-			options = this.options,
-			isVisible = this.uiDialog.is( ":visible" );
-
-		// reset content sizing
-		this.element.show().css({
-			width: "auto",
-			minHeight: 0,
-			height: 0
-		});
-
-		if ( options.minWidth > options.width ) {
-			options.width = options.minWidth;
-		}
-
-		// reset wrapper sizing
-		// determine the height of all the non-content elements
-		nonContentHeight = this.uiDialog.css({
-				height: "auto",
-				width: options.width
-			})
-			.outerHeight();
-		minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
-
-		if ( options.height === "auto" ) {
-			// only needed for IE6 support
-			if ( $.support.minHeight ) {
-				this.element.css({
-					minHeight: minContentHeight,
-					height: "auto"
-				});
-			} else {
-				this.uiDialog.show();
-				autoHeight = this.element.css( "height", "auto" ).height();
-				if ( !isVisible ) {
-					this.uiDialog.hide();
-				}
-				this.element.height( Math.max( autoHeight, minContentHeight ) );
-			}
-		} else {
-			this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
-		}
-
-		if (this.uiDialog.is( ":data(resizable)" ) ) {
-			this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
-		}
-	}
-});
-
-$.extend($.ui.dialog, {
-	uuid: 0,
-	maxZ: 0,
-
-	getTitleId: function($el) {
-		var id = $el.attr( "id" );
-		if ( !id ) {
-			this.uuid += 1;
-			id = this.uuid;
-		}
-		return "ui-dialog-title-" + id;
-	},
-
-	overlay: function( dialog ) {
-		this.$el = $.ui.dialog.overlay.create( dialog );
-	}
-});
-
-$.extend( $.ui.dialog.overlay, {
-	instances: [],
-	// reuse old instances due to IE memory leak with alpha transparency (see #5185)
-	oldInstances: [],
-	maxZ: 0,
-	events: $.map(
-		"focus,mousedown,mouseup,keydown,keypress,click".split( "," ),
-		function( event ) {
-			return event + ".dialog-overlay";
-		}
-	).join( " " ),
-	create: function( dialog ) {
-		if ( this.instances.length === 0 ) {
-			// prevent use of anchors and inputs
-			// we use a setTimeout in case the overlay is created from an
-			// event that we're going to be cancelling (see #2804)
-			setTimeout(function() {
-				// handle $(el).dialog().dialog('close') (see #4065)
-				if ( $.ui.dialog.overlay.instances.length ) {
-					$( document ).bind( $.ui.dialog.overlay.events, function( event ) {
-						// stop events if the z-index of the target is < the z-index of the overlay
-						// we cannot return true when we don't want to cancel the event (#3523)
-						if ( $( event.target ).zIndex() < $.ui.dialog.overlay.maxZ ) {
-							return false;
-						}
-					});
-				}
-			}, 1 );
-
-			// handle window resize
-			$( window ).bind( "resize.dialog-overlay", $.ui.dialog.overlay.resize );
-		}
-
-		var $el = ( this.oldInstances.pop() || $( "<div>" ).addClass( "ui-widget-overlay" ) );
-
-		// allow closing by pressing the escape key
-		$( document ).bind( "keydown.dialog-overlay", function( event ) {
-			var instances = $.ui.dialog.overlay.instances;
-			// only react to the event if we're the top overlay
-			if ( instances.length !== 0 && instances[ instances.length - 1 ] === $el &&
-				dialog.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
-				event.keyCode === $.ui.keyCode.ESCAPE ) {
-
-				dialog.close( event );
-				event.preventDefault();
-			}
-		});
-
-		$el.appendTo( document.body ).css({
-			width: this.width(),
-			height: this.height()
-		});
-
-		if ( $.fn.bgiframe ) {
-			$el.bgiframe();
-		}
-
-		this.instances.push( $el );
-		return $el;
-	},
-
-	destroy: function( $el ) {
-		var indexOf = $.inArray( $el, this.instances ),
-			maxZ = 0;
-
-		if ( indexOf !== -1 ) {
-			this.oldInstances.push( this.instances.splice( indexOf, 1 )[ 0 ] );
-		}
-
-		if ( this.instances.length === 0 ) {
-			$( [ document, window ] ).unbind( ".dialog-overlay" );
-		}
-
-		$el.height( 0 ).width( 0 ).remove();
-
-		// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
-		$.each( this.instances, function() {
-			maxZ = Math.max( maxZ, this.css( "z-index" ) );
-		});
-		this.maxZ = maxZ;
-	},
-
-	height: function() {
-		var scrollHeight,
-			offsetHeight;
-		// handle IE
-		if ( $.ui.ie ) {
-			scrollHeight = Math.max(
-				document.documentElement.scrollHeight,
-				document.body.scrollHeight
-			);
-			offsetHeight = Math.max(
-				document.documentElement.offsetHeight,
-				document.body.offsetHeight
-			);
-
-			if ( scrollHeight < offsetHeight ) {
-				return $( window ).height() + "px";
-			} else {
-				return scrollHeight + "px";
-			}
-		// handle "good" browsers
-		} else {
-			return $( document ).height() + "px";
-		}
-	},
-
-	width: function() {
-		var scrollWidth,
-			offsetWidth;
-		// handle IE
-		if ( $.ui.ie ) {
-			scrollWidth = Math.max(
-				document.documentElement.scrollWidth,
-				document.body.scrollWidth
-			);
-			offsetWidth = Math.max(
-				document.documentElement.offsetWidth,
-				document.body.offsetWidth
-			);
-
-			if ( scrollWidth < offsetWidth ) {
-				return $( window ).width() + "px";
-			} else {
-				return scrollWidth + "px";
-			}
-		// handle "good" browsers
-		} else {
-			return $( document ).width() + "px";
-		}
-	},
-
-	resize: function() {
-		/* If the dialog is draggable and the user drags it past the
-		 * right edge of the window, the document becomes wider so we
-		 * need to stretch the overlay. If the user then drags the
-		 * dialog back to the left, the document will become narrower,
-		 * so we need to shrink the overlay to the appropriate size.
-		 * This is handled by shrinking the overlay before setting it
-		 * to the full document size.
-		 */
-		var $overlays = $( [] );
-		$.each( $.ui.dialog.overlay.instances, function() {
-			$overlays = $overlays.add( this );
-		});
-
-		$overlays.css({
-			width: 0,
-			height: 0
-		}).css({
-			width: $.ui.dialog.overlay.width(),
-			height: $.ui.dialog.overlay.height()
-		});
-	}
-});
-
-$.extend( $.ui.dialog.overlay.prototype, {
-	destroy: function() {
-		$.ui.dialog.overlay.destroy( this.$el );
-	}
-});
-
-}( jQuery ) );
-(function( $, undefined ) {
-
-var mouseHandled = false;
-
-$.widget( "ui.menu", {
-	version: "1.9.2",
-	defaultElement: "<ul>",
-	delay: 300,
-	options: {
-		icons: {
-			submenu: "ui-icon-carat-1-e"
-		},
-		menus: "ul",
-		position: {
-			my: "left top",
-			at: "right top"
-		},
-		role: "menu",
-
-		// callbacks
-		blur: null,
-		focus: null,
-		select: null
-	},
-
-	_create: function() {
-		this.activeMenu = this.element;
-		this.element
-			.uniqueId()
-			.addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" )
-			.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length )
-			.attr({
-				role: this.options.role,
-				tabIndex: 0
-			})
-			// need to catch all clicks on disabled menu
-			// not possible through _on
-			.bind( "click" + this.eventNamespace, $.proxy(function( event ) {
-				if ( this.options.disabled ) {
-					event.preventDefault();
-				}
-			}, this ));
-
-		if ( this.options.disabled ) {
-			this.element
-				.addClass( "ui-state-disabled" )
-				.attr( "aria-disabled", "true" );
-		}
-
-		this._on({
-			// Prevent focus from sticking to links inside menu after clicking
-			// them (focus should always stay on UL during navigation).
-			"mousedown .ui-menu-item > a": function( event ) {
-				event.preventDefault();
-			},
-			"click .ui-state-disabled > a": function( event ) {
-				event.preventDefault();
-			},
-			"click .ui-menu-item:has(a)": function( event ) {
-				var target = $( event.target ).closest( ".ui-menu-item" );
-				if ( !mouseHandled && target.not( ".ui-state-disabled" ).length ) {
-					mouseHandled = true;
-
-					this.select( event );
-					// Open submenu on click
-					if ( target.has( ".ui-menu" ).length ) {
-						this.expand( event );
-					} else if ( !this.element.is( ":focus" ) ) {
-						// Redirect focus to the menu
-						this.element.trigger( "focus", [ true ] );
-
-						// If the active item is on the top level, let it stay active.
-						// Otherwise, blur the active item since it is no longer visible.
-						if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
-							clearTimeout( this.timer );
-						}
-					}
-				}
-			},
-			"mouseenter .ui-menu-item": function( event ) {
-				var target = $( event.currentTarget );
-				// Remove ui-state-active class from siblings of the newly focused menu item
-				// to avoid a jump caused by adjacent elements both having a class with a border
-				target.siblings().children( ".ui-state-active" ).removeClass( "ui-state-active" );
-				this.focus( event, target );
-			},
-			mouseleave: "collapseAll",
-			"mouseleave .ui-menu": "collapseAll",
-			focus: function( event, keepActiveItem ) {
-				// If there's already an active item, keep it active
-				// If not, activate the first item
-				var item = this.active || this.element.children( ".ui-menu-item" ).eq( 0 );
-
-				if ( !keepActiveItem ) {
-					this.focus( event, item );
-				}
-			},
-			blur: function( event ) {
-				this._delay(function() {
-					if ( !$.contains( this.element[0], this.document[0].activeElement ) ) {
-						this.collapseAll( event );
-					}
-				});
-			},
-			keydown: "_keydown"
-		});
-
-		this.refresh();
-
-		// Clicks outside of a menu collapse any open menus
-		this._on( this.document, {
-			click: function( event ) {
-				if ( !$( event.target ).closest( ".ui-menu" ).length ) {
-					this.collapseAll( event );
-				}
-
-				// Reset the mouseHandled flag
-				mouseHandled = false;
-			}
-		});
-	},
-
-	_destroy: function() {
-		// Destroy (sub)menus
-		this.element
-			.removeAttr( "aria-activedescendant" )
-			.find( ".ui-menu" ).andSelf()
-				.removeClass( "ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons" )
-				.removeAttr( "role" )
-				.removeAttr( "tabIndex" )
-				.removeAttr( "aria-labelledby" )
-				.removeAttr( "aria-expanded" )
-				.removeAttr( "aria-hidden" )
-				.removeAttr( "aria-disabled" )
-				.removeUniqueId()
-				.show();
-
-		// Destroy menu items
-		this.element.find( ".ui-menu-item" )
-			.removeClass( "ui-menu-item" )
-			.removeAttr( "role" )
-			.removeAttr( "aria-disabled" )
-			.children( "a" )
-				.removeUniqueId()
-				.removeClass( "ui-corner-all ui-state-hover" )
-				.removeAttr( "tabIndex" )
-				.removeAttr( "role" )
-				.removeAttr( "aria-haspopup" )
-				.children().each( function() {
-					var elem = $( this );
-					if ( elem.data( "ui-menu-submenu-carat" ) ) {
-						elem.remove();
-					}
-				});
-
-		// Destroy menu dividers
-		this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" );
-	},
-
-	_keydown: function( event ) {
-		var match, prev, character, skip, regex,
-			preventDefault = true;
-
-		function escape( value ) {
-			return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
-		}
-
-		switch ( event.keyCode ) {
-		case $.ui.keyCode.PAGE_UP:
-			this.previousPage( event );
-			break;
-		case $.ui.keyCode.PAGE_DOWN:
-			this.nextPage( event );
-			break;
-		case $.ui.keyCode.HOME:
-			this._move( "first", "first", event );
-			break;
-		case $.ui.keyCode.END:
-			this._move( "last", "last", event );
-			break;
-		case $.ui.keyCode.UP:
-			this.previous( event );
-			break;
-		case $.ui.keyCode.DOWN:
-			this.next( event );
-			break;
-		case $.ui.keyCode.LEFT:
-			this.collapse( event );
-			break;
-		case $.ui.keyCode.RIGHT:
-			if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
-				this.expand( event );
-			}
-			break;
-		case $.ui.keyCode.ENTER:
-		case $.ui.keyCode.SPACE:
-			this._activate( event );
-			break;
-		case $.ui.keyCode.ESCAPE:
-			this.collapse( event );
-			break;
-		default:
-			preventDefault = false;
-			prev = this.previousFilter || "";
-			character = String.fromCharCode( event.keyCode );
-			skip = false;
-
-			clearTimeout( this.filterTimer );
-
-			if ( character === prev ) {
-				skip = true;
-			} else {
-				character = prev + character;
-			}
-
-			regex = new RegExp( "^" + escape( character ), "i" );
-			match = this.activeMenu.children( ".ui-menu-item" ).filter(function() {
-				return regex.test( $( this ).children( "a" ).text() );
-			});
-			match = skip && match.index( this.active.next() ) !== -1 ?
-				this.active.nextAll( ".ui-menu-item" ) :
-				match;
-
-			// If no matches on the current filter, reset to the last character pressed
-			// to move down the menu to the first item that starts with that character
-			if ( !match.length ) {
-				character = String.fromCharCode( event.keyCode );
-				regex = new RegExp( "^" + escape( character ), "i" );
-				match = this.activeMenu.children( ".ui-menu-item" ).filter(function() {
-					return regex.test( $( this ).children( "a" ).text() );
-				});
-			}
-
-			if ( match.length ) {
-				this.focus( event, match );
-				if ( match.length > 1 ) {
-					this.previousFilter = character;
-					this.filterTimer = this._delay(function() {
-						delete this.previousFilter;
-					}, 1000 );
-				} else {
-					delete this.previousFilter;
-				}
-			} else {
-				delete this.previousFilter;
-			}
-		}
-
-		if ( preventDefault ) {
-			event.preventDefault();
-		}
-	},
-
-	_activate: function( event ) {
-		if ( !this.active.is( ".ui-state-disabled" ) ) {
-			if ( this.active.children( "a[aria-haspopup='true']" ).length ) {
-				this.expand( event );
-			} else {
-				this.select( event );
-			}
-		}
-	},
-
-	refresh: function() {
-		var menus,
-			icon = this.options.icons.submenu,
-			submenus = this.element.find( this.options.menus );
-
-		// Initialize nested menus
-		submenus.filter( ":not(.ui-menu)" )
-			.addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" )
-			.hide()
-			.attr({
-				role: this.options.role,
-				"aria-hidden": "true",
-				"aria-expanded": "false"
-			})
-			.each(function() {
-				var menu = $( this ),
-					item = menu.prev( "a" ),
-					submenuCarat = $( "<span>" )
-						.addClass( "ui-menu-icon ui-icon " + icon )
-						.data( "ui-menu-submenu-carat", true );
-
-				item
-					.attr( "aria-haspopup", "true" )
-					.prepend( submenuCarat );
-				menu.attr( "aria-labelledby", item.attr( "id" ) );
-			});
-
-		menus = submenus.add( this.element );
-
-		// Don't refresh list items that are already adapted
-		menus.children( ":not(.ui-menu-item):has(a)" )
-			.addClass( "ui-menu-item" )
-			.attr( "role", "presentation" )
-			.children( "a" )
-				.uniqueId()
-				.addClass( "ui-corner-all" )
-				.attr({
-					tabIndex: -1,
-					role: this._itemRole()
-				});
-
-		// Initialize unlinked menu-items containing spaces and/or dashes only as dividers
-		menus.children( ":not(.ui-menu-item)" ).each(function() {
-			var item = $( this );
-			// hyphen, em dash, en dash
-			if ( !/[^\-—–\s]/.test( item.text() ) ) {
-				item.addClass( "ui-widget-content ui-menu-divider" );
-			}
-		});
-
-		// Add aria-disabled attribute to any disabled menu item
-		menus.children( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
-
-		// If the active item has been removed, blur the menu
-		if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
-			this.blur();
-		}
-	},
-
-	_itemRole: function() {
-		return {
-			menu: "menuitem",
-			listbox: "option"
-		}[ this.options.role ];
-	},
-
-	focus: function( event, item ) {
-		var nested, focused;
-		this.blur( event, event && event.type === "focus" );
-
-		this._scrollIntoView( item );
-
-		this.active = item.first();
-		focused = this.active.children( "a" ).addClass( "ui-state-focus" );
-		// Only update aria-activedescendant if there's a role
-		// otherwise we assume focus is managed elsewhere
-		if ( this.options.role ) {
-			this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
-		}
-
-		// Highlight active parent menu item, if any
-		this.active
-			.parent()
-			.closest( ".ui-menu-item" )
-			.children( "a:first" )
-			.addClass( "ui-state-active" );
-
-		if ( event && event.type === "keydown" ) {
-			this._close();
-		} else {
-			this.timer = this._delay(function() {
-				this._close();
-			}, this.delay );
-		}
-
-		nested = item.children( ".ui-menu" );
-		if ( nested.length && ( /^mouse/.test( event.type ) ) ) {
-			this._startOpening(nested);
-		}
-		this.activeMenu = item.parent();
-
-		this._trigger( "focus", event, { item: item } );
-	},
-
-	_scrollIntoView: function( item ) {
-		var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
-		if ( this._hasScroll() ) {
-			borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0;
-			paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0;
-			offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
-			scroll = this.activeMenu.scrollTop();
-			elementHeight = this.activeMenu.height();
-			itemHeight = item.height();
-
-			if ( offset < 0 ) {
-				this.activeMenu.scrollTop( scroll + offset );
-			} else if ( offset + itemHeight > elementHeight ) {
-				this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
-			}
-		}
-	},
-
-	blur: function( event, fromFocus ) {
-		if ( !fromFocus ) {
-			clearTimeout( this.timer );
-		}
-
-		if ( !this.active ) {
-			return;
-		}
-
-		this.active.children( "a" ).removeClass( "ui-state-focus" );
-		this.active = null;
-
-		this._trigger( "blur", event, { item: this.active } );
-	},
-
-	_startOpening: function( submenu ) {
-		clearTimeout( this.timer );
-
-		// Don't open if already open fixes a Firefox bug that caused a .5 pixel
-		// shift in the submenu position when mousing over the carat icon
-		if ( submenu.attr( "aria-hidden" ) !== "true" ) {
-			return;
-		}
-
-		this.timer = this._delay(function() {
-			this._close();
-			this._open( submenu );
-		}, this.delay );
-	},
-
-	_open: function( submenu ) {
-		var position = $.extend({
-			of: this.active
-		}, this.options.position );
-
-		clearTimeout( this.timer );
-		this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
-			.hide()
-			.attr( "aria-hidden", "true" );
-
-		submenu
-			.show()
-			.removeAttr( "aria-hidden" )
-			.attr( "aria-expanded", "true" )
-			.position( position );
-	},
-
-	collapseAll: function( event, all ) {
-		clearTimeout( this.timer );
-		this.timer = this._delay(function() {
-			// If we were passed an event, look for the submenu that contains the event
-			var currentMenu = all ? this.element :
-				$( event && event.target ).closest( this.element.find( ".ui-menu" ) );
-
-			// If we found no valid submenu ancestor, use the main menu to close all sub menus anyway
-			if ( !currentMenu.length ) {
-				currentMenu = this.element;
-			}
-
-			this._close( currentMenu );
-
-			this.blur( event );
-			this.activeMenu = currentMenu;
-		}, this.delay );
-	},
-
-	// With no arguments, closes the currently active menu - if nothing is active
-	// it closes all menus.  If passed an argument, it will search for menus BELOW
-	_close: function( startMenu ) {
-		if ( !startMenu ) {
-			startMenu = this.active ? this.active.parent() : this.element;
-		}
-
-		startMenu
-			.find( ".ui-menu" )
-				.hide()
-				.attr( "aria-hidden", "true" )
-				.attr( "aria-expanded", "false" )
-			.end()
-			.find( "a.ui-state-active" )
-				.removeClass( "ui-state-active" );
-	},
-
-	collapse: function( event ) {
-		var newItem = this.active &&
-			this.active.parent().closest( ".ui-menu-item", this.element );
-		if ( newItem && newItem.length ) {
-			this._close();
-			this.focus( event, newItem );
-		}
-	},
-
-	expand: function( event ) {
-		var newItem = this.active &&
-			this.active
-				.children( ".ui-menu " )
-				.children( ".ui-menu-item" )
-				.first();
-
-		if ( newItem && newItem.length ) {
-			this._open( newItem.parent() );
-
-			// Delay so Firefox will not hide activedescendant change in expanding submenu from AT
-			this._delay(function() {
-				this.focus( event, newItem );
-			});
-		}
-	},
-
-	next: function( event ) {
-		this._move( "next", "first", event );
-	},
-
-	previous: function( event ) {
-		this._move( "prev", "last", event );
-	},
-
-	isFirstItem: function() {
-		return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
-	},
-
-	isLastItem: function() {
-		return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
-	},
-
-	_move: function( direction, filter, event ) {
-		var next;
-		if ( this.active ) {
-			if ( direction === "first" || direction === "last" ) {
-				next = this.active
-					[ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
-					.eq( -1 );
-			} else {
-				next = this.active
-					[ direction + "All" ]( ".ui-menu-item" )
-					.eq( 0 );
-			}
-		}
-		if ( !next || !next.length || !this.active ) {
-			next = this.activeMenu.children( ".ui-menu-item" )[ filter ]();
-		}
-
-		this.focus( event, next );
-	},
-
-	nextPage: function( event ) {
-		var item, base, height;
-
-		if ( !this.active ) {
-			this.next( event );
-			return;
-		}
-		if ( this.isLastItem() ) {
-			return;
-		}
-		if ( this._hasScroll() ) {
-			base = this.active.offset().top;
-			height = this.element.height();
-			this.active.nextAll( ".ui-menu-item" ).each(function() {
-				item = $( this );
-				return item.offset().top - base - height < 0;
-			});
-
-			this.focus( event, item );
-		} else {
-			this.focus( event, this.activeMenu.children( ".ui-menu-item" )
-				[ !this.active ? "first" : "last" ]() );
-		}
-	},
-
-	previousPage: function( event ) {
-		var item, base, height;
-		if ( !this.active ) {
-			this.next( event );
-			return;
-		}
-		if ( this.isFirstItem() ) {
-			return;
-		}
-		if ( this._hasScroll() ) {
-			base = this.active.offset().top;
-			height = this.element.height();
-			this.active.prevAll( ".ui-menu-item" ).each(function() {
-				item = $( this );
-				return item.offset().top - base + height > 0;
-			});
-
-			this.focus( event, item );
-		} else {
-			this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() );
-		}
-	},
-
-	_hasScroll: function() {
-		return this.element.outerHeight() < this.element.prop( "scrollHeight" );
-	},
-
-	select: function( event ) {
-		// TODO: It should never be possible to not have an active item at this
-		// point, but the tests don't trigger mouseenter before click.
-		this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
-		var ui = { item: this.active };
-		if ( !this.active.has( ".ui-menu" ).length ) {
-			this.collapseAll( event, true );
-		}
-		this._trigger( "select", event, ui );
-	}
-});
-
-}( jQuery ));
-(function( $, undefined ) {
-
-$.widget( "ui.progressbar", {
-	version: "1.9.2",
-	options: {
-		value: 0,
-		max: 100
-	},
-
-	min: 0,
-
-	_create: function() {
-		this.element
-			.addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
-			.attr({
-				role: "progressbar",
-				"aria-valuemin": this.min,
-				"aria-valuemax": this.options.max,
-				"aria-valuenow": this._value()
-			});
-
-		this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
-			.appendTo( this.element );
-
-		this.oldValue = this._value();
-		this._refreshValue();
-	},
-
-	_destroy: function() {
-		this.element
-			.removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
-			.removeAttr( "role" )
-			.removeAttr( "aria-valuemin" )
-			.removeAttr( "aria-valuemax" )
-			.removeAttr( "aria-valuenow" );
-
-		this.valueDiv.remove();
-	},
-
-	value: function( newValue ) {
-		if ( newValue === undefined ) {
-			return this._value();
-		}
-
-		this._setOption( "value", newValue );
-		return this;
-	},
-
-	_setOption: function( key, value ) {
-		if ( key === "value" ) {
-			this.options.value = value;
-			this._refreshValue();
-			if ( this._value() === this.options.max ) {
-				this._trigger( "complete" );
-			}
-		}
-
-		this._super( key, value );
-	},
-
-	_value: function() {
-		var val = this.options.value;
-		// normalize invalid value
-		if ( typeof val !== "number" ) {
-			val = 0;
-		}
-		return Math.min( this.options.max, Math.max( this.min, val ) );
-	},
-
-	_percentage: function() {
-		return 100 * this._value() / this.options.max;
-	},
-
-	_refreshValue: function() {
-		var value = this.value(),
-			percentage = this._percentage();
-
-		if ( this.oldValue !== value ) {
-			this.oldValue = value;
-			this._trigger( "change" );
-		}
-
-		this.valueDiv
-			.toggle( value > this.min )
-			.toggleClass( "ui-corner-right", value === this.options.max )
-			.width( percentage.toFixed(0) + "%" );
-		this.element.attr( "aria-valuenow", value );
-	}
-});
-
-})( jQuery );
-(function( $, undefined ) {
-
-// number of pages in a slider
-// (how many times can you page up/down to go through the whole range)
-var numPages = 5;
-
-$.widget( "ui.slider", $.ui.mouse, {
-	version: "1.9.2",
-	widgetEventPrefix: "slide",
-
-	options: {
-		animate: false,
-		distance: 0,
-		max: 100,
-		min: 0,
-		orientation: "horizontal",
-		range: false,
-		step: 1,
-		value: 0,
-		values: null
-	},
-
-	_create: function() {
-		var i, handleCount,
-			o = this.options,
-			existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
-			handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",
-			handles = [];
-
-		this._keySliding = false;
-		this._mouseSliding = false;
-		this._animateOff = true;
-		this._handleIndex = null;
-		this._detectOrientation();
-		this._mouseInit();
-
-		this.element
-			.addClass( "ui-slider" +
-				" ui-slider-" + this.orientation +
-				" ui-widget" +
-				" ui-widget-content" +
-				" ui-corner-all" +
-				( o.disabled ? " ui-slider-disabled ui-disabled" : "" ) );
-
-		this.range = $([]);
-
-		if ( o.range ) {
-			if ( o.range === true ) {
-				if ( !o.values ) {
-					o.values = [ this._valueMin(), this._valueMin() ];
-				}
-				if ( o.values.length && o.values.length !== 2 ) {
-					o.values = [ o.values[0], o.values[0] ];
-				}
-			}
-
-			this.range = $( "<div></div>" )
-				.appendTo( this.element )
-				.addClass( "ui-slider-range" +
-				// note: this isn't the most fittingly semantic framework class for this element,
-				// but worked best visually with a variety of themes
-				" ui-widget-header" +
-				( ( o.range === "min" || o.range === "max" ) ? " ui-slider-range-" + o.range : "" ) );
-		}
-
-		handleCount = ( o.values && o.values.length ) || 1;
-
-		for ( i = existingHandles.length; i < handleCount; i++ ) {
-			handles.push( handle );
-		}
-
-		this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
-
-		this.handle = this.handles.eq( 0 );
-
-		this.handles.add( this.range ).filter( "a" )
-			.click(function( event ) {
-				event.preventDefault();
-			})
-			.mouseenter(function() {
-				if ( !o.disabled ) {
-					$( this ).addClass( "ui-state-hover" );
-				}
-			})
-			.mouseleave(function() {
-				$( this ).removeClass( "ui-state-hover" );
-			})
-			.focus(function() {
-				if ( !o.disabled ) {
-					$( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
-					$( this ).addClass( "ui-state-focus" );
-				} else {
-					$( this ).blur();
-				}
-			})
-			.blur(function() {
-				$( this ).removeClass( "ui-state-focus" );
-			});
-
-		this.handles.each(function( i ) {
-			$( this ).data( "ui-slider-handle-index", i );
-		});
-
-		this._on( this.handles, {
-			keydown: function( event ) {
-				var allowed, curVal, newVal, step,
-					index = $( event.target ).data( "ui-slider-handle-index" );
-
-				switch ( event.keyCode ) {
-					case $.ui.keyCode.HOME:
-					case $.ui.keyCode.END:
-					case $.ui.keyCode.PAGE_UP:
-					case $.ui.keyCode.PAGE_DOWN:
-					case $.ui.keyCode.UP:
-					case $.ui.keyCode.RIGHT:
-					case $.ui.keyCode.DOWN:
-					case $.ui.keyCode.LEFT:
-						event.preventDefault();
-						if ( !this._keySliding ) {
-							this._keySliding = true;
-							$( event.target ).addClass( "ui-state-active" );
-							allowed = this._start( event, index );
-							if ( allowed === false ) {
-								return;
-							}
-						}
-						break;
-				}
-
-				step = this.options.step;
-				if ( this.options.values && this.options.values.length ) {
-					curVal = newVal = this.values( index );
-				} else {
-					curVal = newVal = this.value();
-				}
-
-				switch ( event.keyCode ) {
-					case $.ui.keyCode.HOME:
-						newVal = this._valueMin();
-						break;
-					case $.ui.keyCode.END:
-						newVal = this._valueMax();
-						break;
-					case $.ui.keyCode.PAGE_UP:
-						newVal = this._trimAlignValue( curVal + ( (this._valueMax() - this._valueMin()) / numPages ) );
-						break;
-					case $.ui.keyCode.PAGE_DOWN:
-						newVal = this._trimAlignValue( curVal - ( (this._valueMax() - this._valueMin()) / numPages ) );
-						break;
-					case $.ui.keyCode.UP:
-					case $.ui.keyCode.RIGHT:
-						if ( curVal === this._valueMax() ) {
-							return;
-						}
-						newVal = this._trimAlignValue( curVal + step );
-						break;
-					case $.ui.keyCode.DOWN:
-					case $.ui.keyCode.LEFT:
-						if ( curVal === this._valueMin() ) {
-							return;
-						}
-						newVal = this._trimAlignValue( curVal - step );
-						break;
-				}
-
-				this._slide( event, index, newVal );
-			},
-			keyup: function( event ) {
-				var index = $( event.target ).data( "ui-slider-handle-index" );
-
-				if ( this._keySliding ) {
-					this._keySliding = false;
-					this._stop( event, index );
-					this._change( event, index );
-					$( event.target ).removeClass( "ui-state-active" );
-				}
-			}
-		});
-
-		this._refreshValue();
-
-		this._animateOff = false;
-	},
-
-	_destroy: function() {
-		this.handles.remove();
-		this.range.remove();
-
-		this.element
-			.removeClass( "ui-slider" +
-				" ui-slider-horizontal" +
-				" ui-slider-vertical" +
-				" ui-slider-disabled" +
-				" ui-widget" +
-				" ui-widget-content" +
-				" ui-corner-all" );
-
-		this._mouseDestroy();
-	},
-
-	_mouseCapture: function( event ) {
-		var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
-			that = this,
-			o = this.options;
-
-		if ( o.disabled ) {
-			return false;
-		}
-
-		this.elementSize = {
-			width: this.element.outerWidth(),
-			height: this.element.outerHeight()
-		};
-		this.elementOffset = this.element.offset();
-
-		position = { x: event.pageX, y: event.pageY };
-		normValue = this._normValueFromMouse( position );
-		distance = this._valueMax() - this._valueMin() + 1;
-		this.handles.each(function( i ) {
-			var thisDistance = Math.abs( normValue - that.values(i) );
-			if ( distance > thisDistance ) {
-				distance = thisDistance;
-				closestHandle = $( this );
-				index = i;
-			}
-		});
-
-		// workaround for bug #3736 (if both handles of a range are at 0,
-		// the first is always used as the one with least distance,
-		// and moving it is obviously prevented by preventing negative ranges)
-		if( o.range === true && this.values(1) === o.min ) {
-			index += 1;
-			closestHandle = $( this.handles[index] );
-		}
-
-		allowed = this._start( event, index );
-		if ( allowed === false ) {
-			return false;
-		}
-		this._mouseSliding = true;
-
-		this._handleIndex = index;
-
-		closestHandle
-			.addClass( "ui-state-active" )
-			.focus();
-
-		offset = closestHandle.offset();
-		mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
-		this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
-			left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
-			top: event.pageY - offset.top -
-				( closestHandle.height() / 2 ) -
-				( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
-				( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
-				( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
-		};
-
-		if ( !this.handles.hasClass( "ui-state-hover" ) ) {
-			this._slide( event, index, normValue );
-		}
-		this._animateOff = true;
-		return true;
-	},
-
-	_mouseStart: function() {
-		return true;
-	},
-
-	_mouseDrag: function( event ) {
-		var position = { x: event.pageX, y: event.pageY },
-			normValue = this._normValueFromMouse( position );
-
-		this._slide( event, this._handleIndex, normValue );
-
-		return false;
-	},
-
-	_mouseStop: function( event ) {
-		this.handles.removeClass( "ui-state-active" );
-		this._mouseSliding = false;
-
-		this._stop( event, this._handleIndex );
-		this._change( event, this._handleIndex );
-
-		this._handleIndex = null;
-		this._clickOffset = null;
-		this._animateOff = false;
-
-		return false;
-	},
-
-	_detectOrientation: function() {
-		this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
-	},
-
-	_normValueFromMouse: function( position ) {
-		var pixelTotal,
-			pixelMouse,
-			percentMouse,
-			valueTotal,
-			valueMouse;
-
-		if ( this.orientation === "horizontal" ) {
-			pixelTotal = this.elementSize.width;
-			pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
-		} else {
-			pixelTotal = this.elementSize.height;
-			pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
-		}
-
-		percentMouse = ( pixelMouse / pixelTotal );
-		if ( percentMouse > 1 ) {
-			percentMouse = 1;
-		}
-		if ( percentMouse < 0 ) {
-			percentMouse = 0;
-		}
-		if ( this.orientation === "vertical" ) {
-			percentMouse = 1 - percentMouse;
-		}
-
-		valueTotal = this._valueMax() - this._valueMin();
-		valueMouse = this._valueMin() + percentMouse * valueTotal;
-
-		return this._trimAlignValue( valueMouse );
-	},
-
-	_start: function( event, index ) {
-		var uiHash = {
-			handle: this.handles[ index ],
-			value: this.value()
-		};
-		if ( this.options.values && this.options.values.length ) {
-			uiHash.value = this.values( index );
-			uiHash.values = this.values();
-		}
-		return this._trigger( "start", event, uiHash );
-	},
-
-	_slide: function( event, index, newVal ) {
-		var otherVal,
-			newValues,
-			allowed;
-
-		if ( this.options.values && this.options.values.length ) {
-			otherVal = this.values( index ? 0 : 1 );
-
-			if ( ( this.options.values.length === 2 && this.options.range === true ) &&
-					( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
-				) {
-				newVal = otherVal;
-			}
-
-			if ( newVal !== this.values( index ) ) {
-				newValues = this.values();
-				newValues[ index ] = newVal;
-				// A slide can be canceled by returning false from the slide callback
-				allowed = this._trigger( "slide", event, {
-					handle: this.handles[ index ],
-					value: newVal,
-					values: newValues
-				} );
-				otherVal = this.values( index ? 0 : 1 );
-				if ( allowed !== false ) {
-					this.values( index, newVal, true );
-				}
-			}
-		} else {
-			if ( newVal !== this.value() ) {
-				// A slide can be canceled by returning false from the slide callback
-				allowed = this._trigger( "slide", event, {
-					handle: this.handles[ index ],
-					value: newVal
-				} );
-				if ( allowed !== false ) {
-					this.value( newVal );
-				}
-			}
-		}
-	},
-
-	_stop: function( event, index ) {
-		var uiHash = {
-			handle: this.handles[ index ],
-			value: this.value()
-		};
-		if ( this.options.values && this.options.values.length ) {
-			uiHash.value = this.values( index );
-			uiHash.values = this.values();
-		}
-
-		this._trigger( "stop", event, uiHash );
-	},
-
-	_change: function( event, index ) {
-		if ( !this._keySliding && !this._mouseSliding ) {
-			var uiHash = {
-				handle: this.handles[ index ],
-				value: this.value()
-			};
-			if ( this.options.values && this.options.values.length ) {
-				uiHash.value = this.values( index );
-				uiHash.values = this.values();
-			}
-
-			this._trigger( "change", event, uiHash );
-		}
-	},
-
-	value: function( newValue ) {
-		if ( arguments.length ) {
-			this.options.value = this._trimAlignValue( newValue );
-			this._refreshValue();
-			this._change( null, 0 );
-			return;
-		}
-
-		return this._value();
-	},
-
-	values: function( index, newValue ) {
-		var vals,
-			newValues,
-			i;
-
-		if ( arguments.length > 1 ) {
-			this.options.values[ index ] = this._trimAlignValue( newValue );
-			this._refreshValue();
-			this._change( null, index );
-			return;
-		}
-
-		if ( arguments.length ) {
-			if ( $.isArray( arguments[ 0 ] ) ) {
-				vals = this.options.values;
-				newValues = arguments[ 0 ];
-				for ( i = 0; i < vals.length; i += 1 ) {
-					vals[ i ] = this._trimAlignValue( newValues[ i ] );
-					this._change( null, i );
-				}
-				this._refreshValue();
-			} else {
-				if ( this.options.values && this.options.values.length ) {
-					return this._values( index );
-				} else {
-					return this.value();
-				}
-			}
-		} else {
-			return this._values();
-		}
-	},
-
-	_setOption: function( key, value ) {
-		var i,
-			valsLength = 0;
-
-		if ( $.isArray( this.options.values ) ) {
-			valsLength = this.options.values.length;
-		}
-
-		$.Widget.prototype._setOption.apply( this, arguments );
-
-		switch ( key ) {
-			case "disabled":
-				if ( value ) {
-					this.handles.filter( ".ui-state-focus" ).blur();
-					this.handles.removeClass( "ui-state-hover" );
-					this.handles.prop( "disabled", true );
-					this.element.addClass( "ui-disabled" );
-				} else {
-					this.handles.prop( "disabled", false );
-					this.element.removeClass( "ui-disabled" );
-				}
-				break;
-			case "orientation":
-				this._detectOrientation();
-				this.element
-					.removeClass( "ui-slider-horizontal ui-slider-vertical" )
-					.addClass( "ui-slider-" + this.orientation );
-				this._refreshValue();
-				break;
-			case "value":
-				this._animateOff = true;
-				this._refreshValue();
-				this._change( null, 0 );
-				this._animateOff = false;
-				break;
-			case "values":
-				this._animateOff = true;
-				this._refreshValue();
-				for ( i = 0; i < valsLength; i += 1 ) {
-					this._change( null, i );
-				}
-				this._animateOff = false;
-				break;
-			case "min":
-			case "max":
-				this._animateOff = true;
-				this._refreshValue();
-				this._animateOff = false;
-				break;
-		}
-	},
-
-	//internal value getter
-	// _value() returns value trimmed by min and max, aligned by step
-	_value: function() {
-		var val = this.options.value;
-		val = this._trimAlignValue( val );
-
-		return val;
-	},
-
-	//internal values getter
-	// _values() returns array of values trimmed by min and max, aligned by step
-	// _values( index ) returns single value trimmed by min and max, aligned by step
-	_values: function( index ) {
-		var val,
-			vals,
-			i;
-
-		if ( arguments.length ) {
-			val = this.options.values[ index ];
-			val = this._trimAlignValue( val );
-
-			return val;
-		} else {
-			// .slice() creates a copy of the array
-			// this copy gets trimmed by min and max and then returned
-			vals = this.options.values.slice();
-			for ( i = 0; i < vals.length; i+= 1) {
-				vals[ i ] = this._trimAlignValue( vals[ i ] );
-			}
-
-			return vals;
-		}
-	},
-
-	// returns the step-aligned value that val is closest to, between (inclusive) min and max
-	_trimAlignValue: function( val ) {
-		if ( val <= this._valueMin() ) {
-			return this._valueMin();
-		}
-		if ( val >= this._valueMax() ) {
-			return this._valueMax();
-		}
-		var step = ( this.options.step > 0 ) ? this.options.step : 1,
-			valModStep = (val - this._valueMin()) % step,
-			alignValue = val - valModStep;
-
-		if ( Math.abs(valModStep) * 2 >= step ) {
-			alignValue += ( valModStep > 0 ) ? step : ( -step );
-		}
-
-		// Since JavaScript has problems with large floats, round
-		// the final value to 5 digits after the decimal point (see #4124)
-		return parseFloat( alignValue.toFixed(5) );
-	},
-
-	_valueMin: function() {
-		return this.options.min;
-	},
-
-	_valueMax: function() {
-		return this.options.max;
-	},
-
-	_refreshValue: function() {
-		var lastValPercent, valPercent, value, valueMin, valueMax,
-			oRange = this.options.range,
-			o = this.options,
-			that = this,
-			animate = ( !this._animateOff ) ? o.animate : false,
-			_set = {};
-
-		if ( this.options.values && this.options.values.length ) {
-			this.handles.each(function( i ) {
-				valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100;
-				_set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
-				$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
-				if ( that.options.range === true ) {
-					if ( that.orientation === "horizontal" ) {
-						if ( i === 0 ) {
-							that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
-						}
-						if ( i === 1 ) {
-							that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
-						}
-					} else {
-						if ( i === 0 ) {
-							that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
-						}
-						if ( i === 1 ) {
-							that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
-						}
-					}
-				}
-				lastValPercent = valPercent;
-			});
-		} else {
-			value = this.value();
-			valueMin = this._valueMin();
-			valueMax = this._valueMax();
-			valPercent = ( valueMax !== valueMin ) ?
-					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
-					0;
-			_set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
-			this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
-
-			if ( oRange === "min" && this.orientation === "horizontal" ) {
-				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
-			}
-			if ( oRange === "max" && this.orientation === "horizontal" ) {
-				this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
-			}
-			if ( oRange === "min" && this.orientation === "vertical" ) {
-				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
-			}
-			if ( oRange === "max" && this.orientation === "vertical" ) {
-				this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
-			}
-		}
-	}
-
-});
-
-}(jQuery));
-(function( $ ) {
-
-function modifier( fn ) {
-	return function() {
-		var previous = this.element.val();
-		fn.apply( this, arguments );
-		this._refresh();
-		if ( previous !== this.element.val() ) {
-			this._trigger( "change" );
-		}
-	};
-}
-
-$.widget( "ui.spinner", {
-	version: "1.9.2",
-	defaultElement: "<input>",
-	widgetEventPrefix: "spin",
-	options: {
-		culture: null,
-		icons: {
-			down: "ui-icon-triangle-1-s",
-			up: "ui-icon-triangle-1-n"
-		},
-		incremental: true,
-		max: null,
-		min: null,
-		numberFormat: null,
-		page: 10,
-		step: 1,
-
-		change: null,
-		spin: null,
-		start: null,
-		stop: null
-	},
-
-	_create: function() {
-		// handle string values that need to be parsed
-		this._setOption( "max", this.options.max );
-		this._setOption( "min", this.options.min );
-		this._setOption( "step", this.options.step );
-
-		// format the value, but don't constrain
-		this._value( this.element.val(), true );
-
-		this._draw();
-		this._on( this._events );
-		this._refresh();
-
-		// turning off autocomplete prevents the browser from remembering the
-		// value when navigating through history, so we re-enable autocomplete
-		// if the page is unloaded before the widget is destroyed. #7790
-		this._on( this.window, {
-			beforeunload: function() {
-				this.element.removeAttr( "autocomplete" );
-			}
-		});
-	},
-
-	_getCreateOptions: function() {
-		var options = {},
-			element = this.element;
-
-		$.each( [ "min", "max", "step" ], function( i, option ) {
-			var value = element.attr( option );
-			if ( value !== undefined && value.length ) {
-				options[ option ] = value;
-			}
-		});
-
-		return options;
-	},
-
-	_events: {
-		keydown: function( event ) {
-			if ( this._start( event ) && this._keydown( event ) ) {
-				event.preventDefault();
-			}
-		},
-		keyup: "_stop",
-		focus: function() {
-			this.previous = this.element.val();
-		},
-		blur: function( event ) {
-			if ( this.cancelBlur ) {
-				delete this.cancelBlur;
-				return;
-			}
-
-			this._refresh();
-			if ( this.previous !== this.element.val() ) {
-				this._trigger( "change", event );
-			}
-		},
-		mousewheel: function( event, delta ) {
-			if ( !delta ) {
-				return;
-			}
-			if ( !this.spinning && !this._start( event ) ) {
-				return false;
-			}
-
-			this._spin( (delta > 0 ? 1 : -1) * this.options.step, event );
-			clearTimeout( this.mousewheelTimer );
-			this.mousewheelTimer = this._delay(function() {
-				if ( this.spinning ) {
-					this._stop( event );
-				}
-			}, 100 );
-			event.preventDefault();
-		},
-		"mousedown .ui-spinner-button": function( event ) {
-			var previous;
-
-			// We never want the buttons to have focus; whenever the user is
-			// interacting with the spinner, the focus should be on the input.
-			// If the input is focused then this.previous is properly set from
-			// when the input first received focus. If the input is not focused
-			// then we need to set this.previous based on the value before spinning.
-			previous = this.element[0] === this.document[0].activeElement ?
-				this.previous : this.element.val();
-			function checkFocus() {
-				var isActive = this.element[0] === this.document[0].activeElement;
-				if ( !isActive ) {
-					this.element.focus();
-					this.previous = previous;
-					// support: IE
-					// IE sets focus asynchronously, so we need to check if focus
-					// moved off of the input because the user clicked on the button.
-					this._delay(function() {
-						this.previous = previous;
-					});
-				}
-			}
-
-			// ensure focus is on (or stays on) the text field
-			event.preventDefault();
-			checkFocus.call( this );
-
-			// support: IE
-			// IE doesn't prevent moving focus even with event.preventDefault()
-			// so we set a flag to know when we should ignore the blur event
-			// and check (again) if focus moved off of the input.
-			this.cancelBlur = true;
-			this._delay(function() {
-				delete this.cancelBlur;
-				checkFocus.call( this );
-			});
-
-			if ( this._start( event ) === false ) {
-				return;
-			}
-
-			this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
-		},
-		"mouseup .ui-spinner-button": "_stop",
-		"mouseenter .ui-spinner-button": function( event ) {
-			// button will add ui-state-active if mouse was down while mouseleave and kept down
-			if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
-				return;
-			}
-
-			if ( this._start( event ) === false ) {
-				return false;
-			}
-			this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
-		},
-		// TODO: do we really want to consider this a stop?
-		// shouldn't we just stop the repeater and wait until mouseup before
-		// we trigger the stop event?
-		"mouseleave .ui-spinner-button": "_stop"
-	},
-
-	_draw: function() {
-		var uiSpinner = this.uiSpinner = this.element
-			.addClass( "ui-spinner-input" )
-			.attr( "autocomplete", "off" )
-			.wrap( this._uiSpinnerHtml() )
-			.parent()
-				// add buttons
-				.append( this._buttonHtml() );
-
-		this.element.attr( "role", "spinbutton" );
-
-		// button bindings
-		this.buttons = uiSpinner.find( ".ui-spinner-button" )
-			.attr( "tabIndex", -1 )
-			.button()
-			.removeClass( "ui-corner-all" );
-
-		// IE 6 doesn't understand height: 50% for the buttons
-		// unless the wrapper has an explicit height
-		if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) &&
-				uiSpinner.height() > 0 ) {
-			uiSpinner.height( uiSpinner.height() );
-		}
-
-		// disable spinner if element was already disabled
-		if ( this.options.disabled ) {
-			this.disable();
-		}
-	},
-
-	_keydown: function( event ) {
-		var options = this.options,
-			keyCode = $.ui.keyCode;
-
-		switch ( event.keyCode ) {
-		case keyCode.UP:
-			this._repeat( null, 1, event );
-			return true;
-		case keyCode.DOWN:
-			this._repeat( null, -1, event );
-			return true;
-		case keyCode.PAGE_UP:
-			this._repeat( null, options.page, event );
-			return true;
-		case keyCode.PAGE_DOWN:
-			this._repeat( null, -options.page, event );
-			return true;
-		}
-
-		return false;
-	},
-
-	_uiSpinnerHtml: function() {
-		return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>";
-	},
-
-	_buttonHtml: function() {
-		return "" +
-			"<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" +
-				"<span class='ui-icon " + this.options.icons.up + "'>&#9650;</span>" +
-			"</a>" +
-			"<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" +
-				"<span class='ui-icon " + this.options.icons.down + "'>&#9660;</span>" +
-			"</a>";
-	},
-
-	_start: function( event ) {
-		if ( !this.spinning && this._trigger( "start", event ) === false ) {
-			return false;
-		}
-
-		if ( !this.counter ) {
-			this.counter = 1;
-		}
-		this.spinning = true;
-		return true;
-	},
-
-	_repeat: function( i, steps, event ) {
-		i = i || 500;
-
-		clearTimeout( this.timer );
-		this.timer = this._delay(function() {
-			this._repeat( 40, steps, event );
-		}, i );
-
-		this._spin( steps * this.options.step, event );
-	},
-
-	_spin: function( step, event ) {
-		var value = this.value() || 0;
-
-		if ( !this.counter ) {
-			this.counter = 1;
-		}
-
-		value = this._adjustValue( value + step * this._increment( this.counter ) );
-
-		if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) {
-			this._value( value );
-			this.counter++;
-		}
-	},
-
-	_increment: function( i ) {
-		var incremental = this.options.incremental;
-
-		if ( incremental ) {
-			return $.isFunction( incremental ) ?
-				incremental( i ) :
-				Math.floor( i*i*i/50000 - i*i/500 + 17*i/200 + 1 );
-		}
-
-		return 1;
-	},
-
-	_precision: function() {
-		var precision = this._precisionOf( this.options.step );
-		if ( this.options.min !== null ) {
-			precision = Math.max( precision, this._precisionOf( this.options.min ) );
-		}
-		return precision;
-	},
-
-	_precisionOf: function( num ) {
-		var str = num.toString(),
-			decimal = str.indexOf( "." );
-		return decimal === -1 ? 0 : str.length - decimal - 1;
-	},
-
-	_adjustValue: function( value ) {
-		var base, aboveMin,
-			options = this.options;
-
-		// make sure we're at a valid step
-		// - find out where we are relative to the base (min or 0)
-		base = options.min !== null ? options.min : 0;
-		aboveMin = value - base;
-		// - round to the nearest step
-		aboveMin = Math.round(aboveMin / options.step) * options.step;
-		// - rounding is based on 0, so adjust back to our base
-		value = base + aboveMin;
-
-		// fix precision from bad JS floating point math
-		value = parseFloat( value.toFixed( this._precision() ) );
-
-		// clamp the value
-		if ( options.max !== null && value > options.max) {
-			return options.max;
-		}
-		if ( options.min !== null && value < options.min ) {
-			return options.min;
-		}
-
-		return value;
-	},
-
-	_stop: function( event ) {
-		if ( !this.spinning ) {
-			return;
-		}
-
-		clearTimeout( this.timer );
-		clearTimeout( this.mousewheelTimer );
-		this.counter = 0;
-		this.spinning = false;
-		this._trigger( "stop", event );
-	},
-
-	_setOption: function( key, value ) {
-		if ( key === "culture" || key === "numberFormat" ) {
-			var prevValue = this._parse( this.element.val() );
-			this.options[ key ] = value;
-			this.element.val( this._format( prevValue ) );
-			return;
-		}
-
-		if ( key === "max" || key === "min" || key === "step" ) {
-			if ( typeof value === "string" ) {
-				value = this._parse( value );
-			}
-		}
-
-		this._super( key, value );
-
-		if ( key === "disabled" ) {
-			if ( value ) {
-				this.element.prop( "disabled", true );
-				this.buttons.button( "disable" );
-			} else {
-				this.element.prop( "disabled", false );
-				this.buttons.button( "enable" );
-			}
-		}
-	},
-
-	_setOptions: modifier(function( options ) {
-		this._super( options );
-		this._value( this.element.val() );
-	}),
-
-	_parse: function( val ) {
-		if ( typeof val === "string" && val !== "" ) {
-			val = window.Globalize && this.options.numberFormat ?
-				Globalize.parseFloat( val, 10, this.options.culture ) : +val;
-		}
-		return val === "" || isNaN( val ) ? null : val;
-	},
-
-	_format: function( value ) {
-		if ( value === "" ) {
-			return "";
-		}
-		return window.Globalize && this.options.numberFormat ?
-			Globalize.format( value, this.options.numberFormat, this.options.culture ) :
-			value;
-	},
-
-	_refresh: function() {
-		this.element.attr({
-			"aria-valuemin": this.options.min,
-			"aria-valuemax": this.options.max,
-			// TODO: what should we do with values that can't be parsed?
-			"aria-valuenow": this._parse( this.element.val() )
-		});
-	},
-
-	// update the value without triggering change
-	_value: function( value, allowAny ) {
-		var parsed;
-		if ( value !== "" ) {
-			parsed = this._parse( value );
-			if ( parsed !== null ) {
-				if ( !allowAny ) {
-					parsed = this._adjustValue( parsed );
-				}
-				value = this._format( parsed );
-			}
-		}
-		this.element.val( value );
-		this._refresh();
-	},
-
-	_destroy: function() {
-		this.element
-			.removeClass( "ui-spinner-input" )
-			.prop( "disabled", false )
-			.removeAttr( "autocomplete" )
-			.removeAttr( "role" )
-			.removeAttr( "aria-valuemin" )
-			.removeAttr( "aria-valuemax" )
-			.removeAttr( "aria-valuenow" );
-		this.uiSpinner.replaceWith( this.element );
-	},
-
-	stepUp: modifier(function( steps ) {
-		this._stepUp( steps );
-	}),
-	_stepUp: function( steps ) {
-		this._spin( (steps || 1) * this.options.step );
-	},
-
-	stepDown: modifier(function( steps ) {
-		this._stepDown( steps );
-	}),
-	_stepDown: function( steps ) {
-		this._spin( (steps || 1) * -this.options.step );
-	},
-
-	pageUp: modifier(function( pages ) {
-		this._stepUp( (pages || 1) * this.options.page );
-	}),
-
-	pageDown: modifier(function( pages ) {
-		this._stepDown( (pages || 1) * this.options.page );
-	}),
-
-	value: function( newVal ) {
-		if ( !arguments.length ) {
-			return this._parse( this.element.val() );
-		}
-		modifier( this._value ).call( this, newVal );
-	},
-
-	widget: function() {
-		return this.uiSpinner;
-	}
-});
-
-}( jQuery ) );
-(function( $, undefined ) {
-
-var tabId = 0,
-	rhash = /#.*$/;
-
-function getNextTabId() {
-	return ++tabId;
-}
-
-function isLocal( anchor ) {
-	return anchor.hash.length > 1 &&
-		anchor.href.replace( rhash, "" ) ===
-			location.href.replace( rhash, "" )
-				// support: Safari 5.1
-				// Safari 5.1 doesn't encode spaces in window.location
-				// but it does encode spaces from anchors (#8777)
-				.replace( /\s/g, "%20" );
-}
-
-$.widget( "ui.tabs", {
-	version: "1.9.2",
-	delay: 300,
-	options: {
-		active: null,
-		collapsible: false,
-		event: "click",
-		heightStyle: "content",
-		hide: null,
-		show: null,
-
-		// callbacks
-		activate: null,
-		beforeActivate: null,
-		beforeLoad: null,
-		load: null
-	},
-
-	_create: function() {
-		var that = this,
-			options = this.options,
-			active = options.active,
-			locationHash = location.hash.substring( 1 );
-
-		this.running = false;
-
-		this.element
-			.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" )
-			.toggleClass( "ui-tabs-collapsible", options.collapsible )
-			// Prevent users from focusing disabled tabs via click
-			.delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) {
-				if ( $( this ).is( ".ui-state-disabled" ) ) {
-					event.preventDefault();
-				}
-			})
-			// support: IE <9
-			// Preventing the default action in mousedown doesn't prevent IE
-			// from focusing the element, so if the anchor gets focused, blur.
-			// We don't have to worry about focusing the previously focused
-			// element since clicking on a non-focusable element should focus
-			// the body anyway.
-			.delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() {
-				if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
-					this.blur();
-				}
-			});
-
-		this._processTabs();
-
-		if ( active === null ) {
-			// check the fragment identifier in the URL
-			if ( locationHash ) {
-				this.tabs.each(function( i, tab ) {
-					if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
-						active = i;
-						return false;
-					}
-				});
-			}
-
-			// check for a tab marked active via a class
-			if ( active === null ) {
-				active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
-			}
-
-			// no active tab, set to false
-			if ( active === null || active === -1 ) {
-				active = this.tabs.length ? 0 : false;
-			}
-		}
-
-		// handle numbers: negative, out of range
-		if ( active !== false ) {
-			active = this.tabs.index( this.tabs.eq( active ) );
-			if ( active === -1 ) {
-				active = options.collapsible ? false : 0;
-			}
-		}
-		options.active = active;
-
-		// don't allow collapsible: false and active: false
-		if ( !options.collapsible && options.active === false && this.anchors.length ) {
-			options.active = 0;
-		}
-
-		// Take disabling tabs via class attribute from HTML
-		// into account and update option properly.
-		if ( $.isArray( options.disabled ) ) {
-			options.disabled = $.unique( options.disabled.concat(
-				$.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
-					return that.tabs.index( li );
-				})
-			) ).sort();
-		}
-
-		// check for length avoids error when initializing empty list
-		if ( this.options.active !== false && this.anchors.length ) {
-			this.active = this._findActive( this.options.active );
-		} else {
-			this.active = $();
-		}
-
-		this._refresh();
-
-		if ( this.active.length ) {
-			this.load( options.active );
-		}
-	},
-
-	_getCreateEventData: function() {
-		return {
-			tab: this.active,
-			panel: !this.active.length ? $() : this._getPanelForTab( this.active )
-		};
-	},
-
-	_tabKeydown: function( event ) {
-		var focusedTab = $( this.document[0].activeElement ).closest( "li" ),
-			selectedIndex = this.tabs.index( focusedTab ),
-			goingForward = true;
-
-		if ( this._handlePageNav( event ) ) {
-			return;
-		}
-
-		switch ( event.keyCode ) {
-			case $.ui.keyCode.RIGHT:
-			case $.ui.keyCode.DOWN:
-				selectedIndex++;
-				break;
-			case $.ui.keyCode.UP:
-			case $.ui.keyCode.LEFT:
-				goingForward = false;
-				selectedIndex--;
-				break;
-			case $.ui.keyCode.END:
-				selectedIndex = this.anchors.length - 1;
-				break;
-			case $.ui.keyCode.HOME:
-				selectedIndex = 0;
-				break;
-			case $.ui.keyCode.SPACE:
-				// Activate only, no collapsing
-				event.preventDefault();
-				clearTimeout( this.activating );
-				this._activate( selectedIndex );
-				return;
-			case $.ui.keyCode.ENTER:
-				// Toggle (cancel delayed activation, allow collapsing)
-				event.preventDefault();
-				clearTimeout( this.activating );
-				// Determine if we should collapse or activate
-				this._activate( selectedIndex === this.options.active ? false : selectedIndex );
-				return;
-			default:
-				return;
-		}
-
-		// Focus the appropriate tab, based on which key was pressed
-		event.preventDefault();
-		clearTimeout( this.activating );
-		selectedIndex = this._focusNextTab( selectedIndex, goingForward );
-
-		// Navigating with control key will prevent automatic activation
-		if ( !event.ctrlKey ) {
-			// Update aria-selected immediately so that AT think the tab is already selected.
-			// Otherwise AT may confuse the user by stating that they need to activate the tab,
-			// but the tab will already be activated by the time the announcement finishes.
-			focusedTab.attr( "aria-selected", "false" );
-			this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
-
-			this.activating = this._delay(function() {
-				this.option( "active", selectedIndex );
-			}, this.delay );
-		}
-	},
-
-	_panelKeydown: function( event ) {
-		if ( this._handlePageNav( event ) ) {
-			return;
-		}
-
-		// Ctrl+up moves focus to the current tab
-		if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
-			event.preventDefault();
-			this.active.focus();
-		}
-	},
-
-	// Alt+page up/down moves focus to the previous/next tab (and activates)
-	_handlePageNav: function( event ) {
-		if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
-			this._activate( this._focusNextTab( this.options.active - 1, false ) );
-			return true;
-		}
-		if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
-			this._activate( this._focusNextTab( this.options.active + 1, true ) );
-			return true;
-		}
-	},
-
-	_findNextTab: function( index, goingForward ) {
-		var lastTabIndex = this.tabs.length - 1;
-
-		function constrain() {
-			if ( index > lastTabIndex ) {
-				index = 0;
-			}
-			if ( index < 0 ) {
-				index = lastTabIndex;
-			}
-			return index;
-		}
-
-		while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
-			index = goingForward ? index + 1 : index - 1;
-		}
-
-		return index;
-	},
-
-	_focusNextTab: function( index, goingForward ) {
-		index = this._findNextTab( index, goingForward );
-		this.tabs.eq( index ).focus();
-		return index;
-	},
-
-	_setOption: function( key, value ) {
-		if ( key === "active" ) {
-			// _activate() will handle invalid values and update this.options
-			this._activate( value );
-			return;
-		}
-
-		if ( key === "disabled" ) {
-			// don't use the widget factory's disabled handling
-			this._setupDisabled( value );
-			return;
-		}
-
-		this._super( key, value);
-
-		if ( key === "collapsible" ) {
-			this.element.toggleClass( "ui-tabs-collapsible", value );
-			// Setting collapsible: false while collapsed; open first panel
-			if ( !value && this.options.active === false ) {
-				this._activate( 0 );
-			}
-		}
-
-		if ( key === "event" ) {
-			this._setupEvents( value );
-		}
-
-		if ( key === "heightStyle" ) {
-			this._setupHeightStyle( value );
-		}
-	},
-
-	_tabId: function( tab ) {
-		return tab.attr( "aria-controls" ) || "ui-tabs-" + getNextTabId();
-	},
-
-	_sanitizeSelector: function( hash ) {
-		return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
-	},
-
-	refresh: function() {
-		var options = this.options,
-			lis = this.tablist.children( ":has(a[href])" );
-
-		// get disabled tabs from class attribute from HTML
-		// this will get converted to a boolean if needed in _refresh()
-		options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
-			return lis.index( tab );
-		});
-
-		this._processTabs();
-
-		// was collapsed or no tabs
-		if ( options.active === false || !this.anchors.length ) {
-			options.active = false;
-			this.active = $();
-		// was active, but active tab is gone
-		} else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
-			// all remaining tabs are disabled
-			if ( this.tabs.length === options.disabled.length ) {
-				options.active = false;
-				this.active = $();
-			// activate previous tab
-			} else {
-				this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
-			}
-		// was active, active tab still exists
-		} else {
-			// make sure active index is correct
-			options.active = this.tabs.index( this.active );
-		}
-
-		this._refresh();
-	},
-
-	_refresh: function() {
-		this._setupDisabled( this.options.disabled );
-		this._setupEvents( this.options.event );
-		this._setupHeightStyle( this.options.heightStyle );
-
-		this.tabs.not( this.active ).attr({
-			"aria-selected": "false",
-			tabIndex: -1
-		});
-		this.panels.not( this._getPanelForTab( this.active ) )
-			.hide()
-			.attr({
-				"aria-expanded": "false",
-				"aria-hidden": "true"
-			});
-
-		// Make sure one tab is in the tab order
-		if ( !this.active.length ) {
-			this.tabs.eq( 0 ).attr( "tabIndex", 0 );
-		} else {
-			this.active
-				.addClass( "ui-tabs-active ui-state-active" )
-				.attr({
-					"aria-selected": "true",
-					tabIndex: 0
-				});
-			this._getPanelForTab( this.active )
-				.show()
-				.attr({
-					"aria-expanded": "true",
-					"aria-hidden": "false"
-				});
-		}
-	},
-
-	_processTabs: function() {
-		var that = this;
-
-		this.tablist = this._getList()
-			.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
-			.attr( "role", "tablist" );
-
-		this.tabs = this.tablist.find( "> li:has(a[href])" )
-			.addClass( "ui-state-default ui-corner-top" )
-			.attr({
-				role: "tab",
-				tabIndex: -1
-			});
-
-		this.anchors = this.tabs.map(function() {
-				return $( "a", this )[ 0 ];
-			})
-			.addClass( "ui-tabs-anchor" )
-			.attr({
-				role: "presentation",
-				tabIndex: -1
-			});
-
-		this.panels = $();
-
-		this.anchors.each(function( i, anchor ) {
-			var selector, panel, panelId,
-				anchorId = $( anchor ).uniqueId().attr( "id" ),
-				tab = $( anchor ).closest( "li" ),
-				originalAriaControls = tab.attr( "aria-controls" );
-
-			// inline tab
-			if ( isLocal( anchor ) ) {
-				selector = anchor.hash;
-				panel = that.element.find( that._sanitizeSelector( selector ) );
-			// remote tab
-			} else {
-				panelId = that._tabId( tab );
-				selector = "#" + panelId;
-				panel = that.element.find( selector );
-				if ( !panel.length ) {
-					panel = that._createPanel( panelId );
-					panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
-				}
-				panel.attr( "aria-live", "polite" );
-			}
-
-			if ( panel.length) {
-				that.panels = that.panels.add( panel );
-			}
-			if ( originalAriaControls ) {
-				tab.data( "ui-tabs-aria-controls", originalAriaControls );
-			}
-			tab.attr({
-				"aria-controls": selector.substring( 1 ),
-				"aria-labelledby": anchorId
-			});
-			panel.attr( "aria-labelledby", anchorId );
-		});
-
-		this.panels
-			.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
-			.attr( "role", "tabpanel" );
-	},
-
-	// allow overriding how to find the list for rare usage scenarios (#7715)
-	_getList: function() {
-		return this.element.find( "ol,ul" ).eq( 0 );
-	},
-
-	_createPanel: function( id ) {
-		return $( "<div>" )
-			.attr( "id", id )
-			.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
-			.data( "ui-tabs-destroy", true );
-	},
-
-	_setupDisabled: function( disabled ) {
-		if ( $.isArray( disabled ) ) {
-			if ( !disabled.length ) {
-				disabled = false;
-			} else if ( disabled.length === this.anchors.length ) {
-				disabled = true;
-			}
-		}
-
-		// disable tabs
-		for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) {
-			if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
-				$( li )
-					.addClass( "ui-state-disabled" )
-					.attr( "aria-disabled", "true" );
-			} else {
-				$( li )
-					.removeClass( "ui-state-disabled" )
-					.removeAttr( "aria-disabled" );
-			}
-		}
-
-		this.options.disabled = disabled;
-	},
-
-	_setupEvents: function( event ) {
-		var events = {
-			click: function( event ) {
-				event.preventDefault();
-			}
-		};
-		if ( event ) {
-			$.each( event.split(" "), function( index, eventName ) {
-				events[ eventName ] = "_eventHandler";
-			});
-		}
-
-		this._off( this.anchors.add( this.tabs ).add( this.panels ) );
-		this._on( this.anchors, events );
-		this._on( this.tabs, { keydown: "_tabKeydown" } );
-		this._on( this.panels, { keydown: "_panelKeydown" } );
-
-		this._focusable( this.tabs );
-		this._hoverable( this.tabs );
-	},
-
-	_setupHeightStyle: function( heightStyle ) {
-		var maxHeight, overflow,
-			parent = this.element.parent();
-
-		if ( heightStyle === "fill" ) {
-			// IE 6 treats height like minHeight, so we need to turn off overflow
-			// in order to get a reliable height
-			// we use the minHeight support test because we assume that only
-			// browsers that don't support minHeight will treat height as minHeight
-			if ( !$.support.minHeight ) {
-				overflow = parent.css( "overflow" );
-				parent.css( "overflow", "hidden");
-			}
-			maxHeight = parent.height();
-			this.element.siblings( ":visible" ).each(function() {
-				var elem = $( this ),
-					position = elem.css( "position" );
-
-				if ( position === "absolute" || position === "fixed" ) {
-					return;
-				}
-				maxHeight -= elem.outerHeight( true );
-			});
-			if ( overflow ) {
-				parent.css( "overflow", overflow );
-			}
-
-			this.element.children().not( this.panels ).each(function() {
-				maxHeight -= $( this ).outerHeight( true );
-			});
-
-			this.panels.each(function() {
-				$( this ).height( Math.max( 0, maxHeight -
-					$( this ).innerHeight() + $( this ).height() ) );
-			})
-			.css( "overflow", "auto" );
-		} else if ( heightStyle === "auto" ) {
-			maxHeight = 0;
-			this.panels.each(function() {
-				maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
-			}).height( maxHeight );
-		}
-	},
-
-	_eventHandler: function( event ) {
-		var options = this.options,
-			active = this.active,
-			anchor = $( event.currentTarget ),
-			tab = anchor.closest( "li" ),
-			clickedIsActive = tab[ 0 ] === active[ 0 ],
-			collapsing = clickedIsActive && options.collapsible,
-			toShow = collapsing ? $() : this._getPanelForTab( tab ),
-			toHide = !active.length ? $() : this._getPanelForTab( active ),
-			eventData = {
-				oldTab: active,
-				oldPanel: toHide,
-				newTab: collapsing ? $() : tab,
-				newPanel: toShow
-			};
-
-		event.preventDefault();
-
-		if ( tab.hasClass( "ui-state-disabled" ) ||
-				// tab is already loading
-				tab.hasClass( "ui-tabs-loading" ) ||
-				// can't switch durning an animation
-				this.running ||
-				// click on active header, but not collapsible
-				( clickedIsActive && !options.collapsible ) ||
-				// allow canceling activation
-				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
-			return;
-		}
-
-		options.active = collapsing ? false : this.tabs.index( tab );
-
-		this.active = clickedIsActive ? $() : tab;
-		if ( this.xhr ) {
-			this.xhr.abort();
-		}
-
-		if ( !toHide.length && !toShow.length ) {
-			$.error( "jQuery UI Tabs: Mismatching fragment identifier." );
-		}
-
-		if ( toShow.length ) {
-			this.load( this.tabs.index( tab ), event );
-		}
-		this._toggle( event, eventData );
-	},
-
-	// handles show/hide for selecting tabs
-	_toggle: function( event, eventData ) {
-		var that = this,
-			toShow = eventData.newPanel,
-			toHide = eventData.oldPanel;
-
-		this.running = true;
-
-		function complete() {
-			that.running = false;
-			that._trigger( "activate", event, eventData );
-		}
-
-		function show() {
-			eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );
-
-			if ( toShow.length && that.options.show ) {
-				that._show( toShow, that.options.show, complete );
-			} else {
-				toShow.show();
-				complete();
-			}
-		}
-
-		// start out by hiding, then showing, then completing
-		if ( toHide.length && this.options.hide ) {
-			this._hide( toHide, this.options.hide, function() {
-				eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
-				show();
-			});
-		} else {
-			eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
-			toHide.hide();
-			show();
-		}
-
-		toHide.attr({
-			"aria-expanded": "false",
-			"aria-hidden": "true"
-		});
-		eventData.oldTab.attr( "aria-selected", "false" );
-		// If we're switching tabs, remove the old tab from the tab order.
-		// If we're opening from collapsed state, remove the previous tab from the tab order.
-		// If we're collapsing, then keep the collapsing tab in the tab order.
-		if ( toShow.length && toHide.length ) {
-			eventData.oldTab.attr( "tabIndex", -1 );
-		} else if ( toShow.length ) {
-			this.tabs.filter(function() {
-				return $( this ).attr( "tabIndex" ) === 0;
-			})
-			.attr( "tabIndex", -1 );
-		}
-
-		toShow.attr({
-			"aria-expanded": "true",
-			"aria-hidden": "false"
-		});
-		eventData.newTab.attr({
-			"aria-selected": "true",
-			tabIndex: 0
-		});
-	},
-
-	_activate: function( index ) {
-		var anchor,
-			active = this._findActive( index );
-
-		// trying to activate the already active panel
-		if ( active[ 0 ] === this.active[ 0 ] ) {
-			return;
-		}
-
-		// trying to collapse, simulate a click on the current active header
-		if ( !active.length ) {
-			active = this.active;
-		}
-
-		anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
-		this._eventHandler({
-			target: anchor,
-			currentTarget: anchor,
-			preventDefault: $.noop
-		});
-	},
-
-	_findActive: function( index ) {
-		return index === false ? $() : this.tabs.eq( index );
-	},
-
-	_getIndex: function( index ) {
-		// meta-function to give users option to provide a href string instead of a numerical index.
-		if ( typeof index === "string" ) {
-			index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) );
-		}
-
-		return index;
-	},
-
-	_destroy: function() {
-		if ( this.xhr ) {
-			this.xhr.abort();
-		}
-
-		this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" );
-
-		this.tablist
-			.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
-			.removeAttr( "role" );
-
-		this.anchors
-			.removeClass( "ui-tabs-anchor" )
-			.removeAttr( "role" )
-			.removeAttr( "tabIndex" )
-			.removeData( "href.tabs" )
-			.removeData( "load.tabs" )
-			.removeUniqueId();
-
-		this.tabs.add( this.panels ).each(function() {
-			if ( $.data( this, "ui-tabs-destroy" ) ) {
-				$( this ).remove();
-			} else {
-				$( this )
-					.removeClass( "ui-state-default ui-state-active ui-state-disabled " +
-						"ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" )
-					.removeAttr( "tabIndex" )
-					.removeAttr( "aria-live" )
-					.removeAttr( "aria-busy" )
-					.removeAttr( "aria-selected" )
-					.removeAttr( "aria-labelledby" )
-					.removeAttr( "aria-hidden" )
-					.removeAttr( "aria-expanded" )
-					.removeAttr( "role" );
-			}
-		});
-
-		this.tabs.each(function() {
-			var li = $( this ),
-				prev = li.data( "ui-tabs-aria-controls" );
-			if ( prev ) {
-				li.attr( "aria-controls", prev );
-			} else {
-				li.removeAttr( "aria-controls" );
-			}
-		});
-
-		this.panels.show();
-
-		if ( this.options.heightStyle !== "content" ) {
-			this.panels.css( "height", "" );
-		}
-	},
-
-	enable: function( index ) {
-		var disabled = this.options.disabled;
-		if ( disabled === false ) {
-			return;
-		}
-
-		if ( index === undefined ) {
-			disabled = false;
-		} else {
-			index = this._getIndex( index );
-			if ( $.isArray( disabled ) ) {
-				disabled = $.map( disabled, function( num ) {
-					return num !== index ? num : null;
-				});
-			} else {
-				disabled = $.map( this.tabs, function( li, num ) {
-					return num !== index ? num : null;
-				});
-			}
-		}
-		this._setupDisabled( disabled );
-	},
-
-	disable: function( index ) {
-		var disabled = this.options.disabled;
-		if ( disabled === true ) {
-			return;
-		}
-
-		if ( index === undefined ) {
-			disabled = true;
-		} else {
-			index = this._getIndex( index );
-			if ( $.inArray( index, disabled ) !== -1 ) {
-				return;
-			}
-			if ( $.isArray( disabled ) ) {
-				disabled = $.merge( [ index ], disabled ).sort();
-			} else {
-				disabled = [ index ];
-			}
-		}
-		this._setupDisabled( disabled );
-	},
-
-	load: function( index, event ) {
-		index = this._getIndex( index );
-		var that = this,
-			tab = this.tabs.eq( index ),
-			anchor = tab.find( ".ui-tabs-anchor" ),
-			panel = this._getPanelForTab( tab ),
-			eventData = {
-				tab: tab,
-				panel: panel
-			};
-
-		// not remote
-		if ( isLocal( anchor[ 0 ] ) ) {
-			return;
-		}
-
-		this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
-
-		// support: jQuery <1.8
-		// jQuery <1.8 returns false if the request is canceled in beforeSend,
-		// but as of 1.8, $.ajax() always returns a jqXHR object.
-		if ( this.xhr && this.xhr.statusText !== "canceled" ) {
-			tab.addClass( "ui-tabs-loading" );
-			panel.attr( "aria-busy", "true" );
-
-			this.xhr
-				.success(function( response ) {
-					// support: jQuery <1.8
-					// http://bugs.jquery.com/ticket/11778
-					setTimeout(function() {
-						panel.html( response );
-						that._trigger( "load", event, eventData );
-					}, 1 );
-				})
-				.complete(function( jqXHR, status ) {
-					// support: jQuery <1.8
-					// http://bugs.jquery.com/ticket/11778
-					setTimeout(function() {
-						if ( status === "abort" ) {
-							that.panels.stop( false, true );
-						}
-
-						tab.removeClass( "ui-tabs-loading" );
-						panel.removeAttr( "aria-busy" );
-
-						if ( jqXHR === that.xhr ) {
-							delete that.xhr;
-						}
-					}, 1 );
-				});
-		}
-	},
-
-	// TODO: Remove this function in 1.10 when ajaxOptions is removed
-	_ajaxSettings: function( anchor, event, eventData ) {
-		var that = this;
-		return {
-			url: anchor.attr( "href" ),
-			beforeSend: function( jqXHR, settings ) {
-				return that._trigger( "beforeLoad", event,
-					$.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) );
-			}
-		};
-	},
-
-	_getPanelForTab: function( tab ) {
-		var id = $( tab ).attr( "aria-controls" );
-		return this.element.find( this._sanitizeSelector( "#" + id ) );
-	}
-});
-
-// DEPRECATED
-if ( $.uiBackCompat !== false ) {
-
-	// helper method for a lot of the back compat extensions
-	$.ui.tabs.prototype._ui = function( tab, panel ) {
-		return {
-			tab: tab,
-			panel: panel,
-			index: this.anchors.index( tab )
-		};
-	};
-
-	// url method
-	$.widget( "ui.tabs", $.ui.tabs, {
-		url: function( index, url ) {
-			this.anchors.eq( index ).attr( "href", url );
-		}
-	});
-
-	// TODO: Remove _ajaxSettings() method when removing this extension
-	// ajaxOptions and cache options
-	$.widget( "ui.tabs", $.ui.tabs, {
-		options: {
-			ajaxOptions: null,
-			cache: false
-		},
-
-		_create: function() {
-			this._super();
-
-			var that = this;
-
-			this._on({ tabsbeforeload: function( event, ui ) {
-				// tab is already cached
-				if ( $.data( ui.tab[ 0 ], "cache.tabs" ) ) {
-					event.preventDefault();
-					return;
-				}
-
-				ui.jqXHR.success(function() {
-					if ( that.options.cache ) {
-						$.data( ui.tab[ 0 ], "cache.tabs", true );
-					}
-				});
-			}});
-		},
-
-		_ajaxSettings: function( anchor, event, ui ) {
-			var ajaxOptions = this.options.ajaxOptions;
-			return $.extend( {}, ajaxOptions, {
-				error: function( xhr, status ) {
-					try {
-						// Passing index avoid a race condition when this method is
-						// called after the user has selected another tab.
-						// Pass the anchor that initiated this request allows
-						// loadError to manipulate the tab content panel via $(a.hash)
-						ajaxOptions.error(
-							xhr, status, ui.tab.closest( "li" ).index(), ui.tab[ 0 ] );
-					}
-					catch ( error ) {}
-				}
-			}, this._superApply( arguments ) );
-		},
-
-		_setOption: function( key, value ) {
-			// reset cache if switching from cached to not cached
-			if ( key === "cache" && value === false ) {
-				this.anchors.removeData( "cache.tabs" );
-			}
-			this._super( key, value );
-		},
-
-		_destroy: function() {
-			this.anchors.removeData( "cache.tabs" );
-			this._super();
-		},
-
-		url: function( index ){
-			this.anchors.eq( index ).removeData( "cache.tabs" );
-			this._superApply( arguments );
-		}
-	});
-
-	// abort method
-	$.widget( "ui.tabs", $.ui.tabs, {
-		abort: function() {
-			if ( this.xhr ) {
-				this.xhr.abort();
-			}
-		}
-	});
-
-	// spinner
-	$.widget( "ui.tabs", $.ui.tabs, {
-		options: {
-			spinner: "<em>Loading&#8230;</em>"
-		},
-		_create: function() {
-			this._super();
-			this._on({
-				tabsbeforeload: function( event, ui ) {
-					// Don't react to nested tabs or tabs that don't use a spinner
-					if ( event.target !== this.element[ 0 ] ||
-							!this.options.spinner ) {
-						return;
-					}
-
-					var span = ui.tab.find( "span" ),
-						html = span.html();
-					span.html( this.options.spinner );
-					ui.jqXHR.complete(function() {
-						span.html( html );
-					});
-				}
-			});
-		}
-	});
-
-	// enable/disable events
-	$.widget( "ui.tabs", $.ui.tabs, {
-		options: {
-			enable: null,
-			disable: null
-		},
-
-		enable: function( index ) {
-			var options = this.options,
-				trigger;
-
-			if ( index && options.disabled === true ||
-					( $.isArray( options.disabled ) && $.inArray( index, options.disabled ) !== -1 ) ) {
-				trigger = true;
-			}
-
-			this._superApply( arguments );
-
-			if ( trigger ) {
-				this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
-			}
-		},
-
-		disable: function( index ) {
-			var options = this.options,
-				trigger;
-
-			if ( index && options.disabled === false ||
-					( $.isArray( options.disabled ) && $.inArray( index, options.disabled ) === -1 ) ) {
-				trigger = true;
-			}
-
-			this._superApply( arguments );
-
-			if ( trigger ) {
-				this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
-			}
-		}
-	});
-
-	// add/remove methods and events
-	$.widget( "ui.tabs", $.ui.tabs, {
-		options: {
-			add: null,
-			remove: null,
-			tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
-		},
-
-		add: function( url, label, index ) {
-			if ( index === undefined ) {
-				index = this.anchors.length;
-			}
-
-			var doInsertAfter, panel,
-				options = this.options,
-				li = $( options.tabTemplate
-					.replace( /#\{href\}/g, url )
-					.replace( /#\{label\}/g, label ) ),
-				id = !url.indexOf( "#" ) ?
-					url.replace( "#", "" ) :
-					this._tabId( li );
-
-			li.addClass( "ui-state-default ui-corner-top" ).data( "ui-tabs-destroy", true );
-			li.attr( "aria-controls", id );
-
-			doInsertAfter = index >= this.tabs.length;
-
-			// try to find an existing element before creating a new one
-			panel = this.element.find( "#" + id );
-			if ( !panel.length ) {
-				panel = this._createPanel( id );
-				if ( doInsertAfter ) {
-					if ( index > 0 ) {
-						panel.insertAfter( this.panels.eq( -1 ) );
-					} else {
-						panel.appendTo( this.element );
-					}
-				} else {
-					panel.insertBefore( this.panels[ index ] );
-				}
-			}
-			panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ).hide();
-
-			if ( doInsertAfter ) {
-				li.appendTo( this.tablist );
-			} else {
-				li.insertBefore( this.tabs[ index ] );
-			}
-
-			options.disabled = $.map( options.disabled, function( n ) {
-				return n >= index ? ++n : n;
-			});
-
-			this.refresh();
-			if ( this.tabs.length === 1 && options.active === false ) {
-				this.option( "active", 0 );
-			}
-
-			this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
-			return this;
-		},
-
-		remove: function( index ) {
-			index = this._getIndex( index );
-			var options = this.options,
-				tab = this.tabs.eq( index ).remove(),
-				panel = this._getPanelForTab( tab ).remove();
-
-			// If selected tab was removed focus tab to the right or
-			// in case the last tab was removed the tab to the left.
-			// We check for more than 2 tabs, because if there are only 2,
-			// then when we remove this tab, there will only be one tab left
-			// so we don't need to detect which tab to activate.
-			if ( tab.hasClass( "ui-tabs-active" ) && this.anchors.length > 2 ) {
-				this._activate( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
-			}
-
-			options.disabled = $.map(
-				$.grep( options.disabled, function( n ) {
-					return n !== index;
-				}),
-				function( n ) {
-					return n >= index ? --n : n;
-				});
-
-			this.refresh();
-
-			this._trigger( "remove", null, this._ui( tab.find( "a" )[ 0 ], panel[ 0 ] ) );
-			return this;
-		}
-	});
-
-	// length method
-	$.widget( "ui.tabs", $.ui.tabs, {
-		length: function() {
-			return this.anchors.length;
-		}
-	});
-
-	// panel ids (idPrefix option + title attribute)
-	$.widget( "ui.tabs", $.ui.tabs, {
-		options: {
-			idPrefix: "ui-tabs-"
-		},
-
-		_tabId: function( tab ) {
-			var a = tab.is( "li" ) ? tab.find( "a[href]" ) : tab;
-			a = a[0];
-			return $( a ).closest( "li" ).attr( "aria-controls" ) ||
-				a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF\-]/g, "" ) ||
-				this.options.idPrefix + getNextTabId();
-		}
-	});
-
-	// _createPanel method
-	$.widget( "ui.tabs", $.ui.tabs, {
-		options: {
-			panelTemplate: "<div></div>"
-		},
-
-		_createPanel: function( id ) {
-			return $( this.options.panelTemplate )
-				.attr( "id", id )
-				.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
-				.data( "ui-tabs-destroy", true );
-		}
-	});
-
-	// selected option
-	$.widget( "ui.tabs", $.ui.tabs, {
-		_create: function() {
-			var options = this.options;
-			if ( options.active === null && options.selected !== undefined ) {
-				options.active = options.selected === -1 ? false : options.selected;
-			}
-			this._super();
-			options.selected = options.active;
-			if ( options.selected === false ) {
-				options.selected = -1;
-			}
-		},
-
-		_setOption: function( key, value ) {
-			if ( key !== "selected" ) {
-				return this._super( key, value );
-			}
-
-			var options = this.options;
-			this._super( "active", value === -1 ? false : value );
-			options.selected = options.active;
-			if ( options.selected === false ) {
-				options.selected = -1;
-			}
-		},
-
-		_eventHandler: function() {
-			this._superApply( arguments );
-			this.options.selected = this.options.active;
-			if ( this.options.selected === false ) {
-				this.options.selected = -1;
-			}
-		}
-	});
-
-	// show and select event
-	$.widget( "ui.tabs", $.ui.tabs, {
-		options: {
-			show: null,
-			select: null
-		},
-		_create: function() {
-			this._super();
-			if ( this.options.active !== false ) {
-				this._trigger( "show", null, this._ui(
-					this.active.find( ".ui-tabs-anchor" )[ 0 ],
-					this._getPanelForTab( this.active )[ 0 ] ) );
-			}
-		},
-		_trigger: function( type, event, data ) {
-			var tab, panel,
-				ret = this._superApply( arguments );
-
-			if ( !ret ) {
-				return false;
-			}
-
-			if ( type === "beforeActivate" ) {
-				tab = data.newTab.length ? data.newTab : data.oldTab;
-				panel = data.newPanel.length ? data.newPanel : data.oldPanel;
-				ret = this._super( "select", event, {
-					tab: tab.find( ".ui-tabs-anchor" )[ 0],
-					panel: panel[ 0 ],
-					index: tab.closest( "li" ).index()
-				});
-			} else if ( type === "activate" && data.newTab.length ) {
-				ret = this._super( "show", event, {
-					tab: data.newTab.find( ".ui-tabs-anchor" )[ 0 ],
-					panel: data.newPanel[ 0 ],
-					index: data.newTab.closest( "li" ).index()
-				});
-			}
-			return ret;
-		}
-	});
-
-	// select method
-	$.widget( "ui.tabs", $.ui.tabs, {
-		select: function( index ) {
-			index = this._getIndex( index );
-			if ( index === -1 ) {
-				if ( this.options.collapsible && this.options.selected !== -1 ) {
-					index = this.options.selected;
-				} else {
-					return;
-				}
-			}
-			this.anchors.eq( index ).trigger( this.options.event + this.eventNamespace );
-		}
-	});
-
-	// cookie option
-	(function() {
-
-	var listId = 0;
-
-	$.widget( "ui.tabs", $.ui.tabs, {
-		options: {
-			cookie: null // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
-		},
-		_create: function() {
-			var options = this.options,
-				active;
-			if ( options.active == null && options.cookie ) {
-				active = parseInt( this._cookie(), 10 );
-				if ( active === -1 ) {
-					active = false;
-				}
-				options.active = active;
-			}
-			this._super();
-		},
-		_cookie: function( active ) {
-			var cookie = [ this.cookie ||
-				( this.cookie = this.options.cookie.name || "ui-tabs-" + (++listId) ) ];
-			if ( arguments.length ) {
-				cookie.push( active === false ? -1 : active );
-				cookie.push( this.options.cookie );
-			}
-			return $.cookie.apply( null, cookie );
-		},
-		_refresh: function() {
-			this._super();
-			if ( this.options.cookie ) {
-				this._cookie( this.options.active, this.options.cookie );
-			}
-		},
-		_eventHandler: function() {
-			this._superApply( arguments );
-			if ( this.options.cookie ) {
-				this._cookie( this.options.active, this.options.cookie );
-			}
-		},
-		_destroy: function() {
-			this._super();
-			if ( this.options.cookie ) {
-				this._cookie( null, this.options.cookie );
-			}
-		}
-	});
-
-	})();
-
-	// load event
-	$.widget( "ui.tabs", $.ui.tabs, {
-		_trigger: function( type, event, data ) {
-			var _data = $.extend( {}, data );
-			if ( type === "load" ) {
-				_data.panel = _data.panel[ 0 ];
-				_data.tab = _data.tab.find( ".ui-tabs-anchor" )[ 0 ];
-			}
-			return this._super( type, event, _data );
-		}
-	});
-
-	// fx option
-	// The new animation options (show, hide) conflict with the old show callback.
-	// The old fx option wins over show/hide anyway (always favor back-compat).
-	// If a user wants to use the new animation API, they must give up the old API.
-	$.widget( "ui.tabs", $.ui.tabs, {
-		options: {
-			fx: null // e.g. { height: "toggle", opacity: "toggle", duration: 200 }
-		},
-
-		_getFx: function() {
-			var hide, show,
-				fx = this.options.fx;
-
-			if ( fx ) {
-				if ( $.isArray( fx ) ) {
-					hide = fx[ 0 ];
-					show = fx[ 1 ];
-				} else {
-					hide = show = fx;
-				}
-			}
-
-			return fx ? { show: show, hide: hide } : null;
-		},
-
-		_toggle: function( event, eventData ) {
-			var that = this,
-				toShow = eventData.newPanel,
-				toHide = eventData.oldPanel,
-				fx = this._getFx();
-
-			if ( !fx ) {
-				return this._super( event, eventData );
-			}
-
-			that.running = true;
-
-			function complete() {
-				that.running = false;
-				that._trigger( "activate", event, eventData );
-			}
-
-			function show() {
-				eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );
-
-				if ( toShow.length && fx.show ) {
-					toShow
-						.animate( fx.show, fx.show.duration, function() {
-							complete();
-						});
-				} else {
-					toShow.show();
-					complete();
-				}
-			}
-
-			// start out by hiding, then showing, then completing
-			if ( toHide.length && fx.hide ) {
-				toHide.animate( fx.hide, fx.hide.duration, function() {
-					eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
-					show();
-				});
-			} else {
-				eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
-				toHide.hide();
-				show();
-			}
-		}
-	});
-}
-
-})( jQuery );
-(function( $ ) {
-
-var increments = 0;
-
-function addDescribedBy( elem, id ) {
-	var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ );
-	describedby.push( id );
-	elem
-		.data( "ui-tooltip-id", id )
-		.attr( "aria-describedby", $.trim( describedby.join( " " ) ) );
-}
-
-function removeDescribedBy( elem ) {
-	var id = elem.data( "ui-tooltip-id" ),
-		describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ),
-		index = $.inArray( id, describedby );
-	if ( index !== -1 ) {
-		describedby.splice( index, 1 );
-	}
-
-	elem.removeData( "ui-tooltip-id" );
-	describedby = $.trim( describedby.join( " " ) );
-	if ( describedby ) {
-		elem.attr( "aria-describedby", describedby );
-	} else {
-		elem.removeAttr( "aria-describedby" );
-	}
-}
-
-$.widget( "ui.tooltip", {
-	version: "1.9.2",
-	options: {
-		content: function() {
-			return $( this ).attr( "title" );
-		},
-		hide: true,
-		// Disabled elements have inconsistent behavior across browsers (#8661)
-		items: "[title]:not([disabled])",
-		position: {
-			my: "left top+15",
-			at: "left bottom",
-			collision: "flipfit flip"
-		},
-		show: true,
-		tooltipClass: null,
-		track: false,
-
-		// callbacks
-		close: null,
-		open: null
-	},
-
-	_create: function() {
-		this._on({
-			mouseover: "open",
-			focusin: "open"
-		});
-
-		// IDs of generated tooltips, needed for destroy
-		this.tooltips = {};
-		// IDs of parent tooltips where we removed the title attribute
-		this.parents = {};
-
-		if ( this.options.disabled ) {
-			this._disable();
-		}
-	},
-
-	_setOption: function( key, value ) {
-		var that = this;
-
-		if ( key === "disabled" ) {
-			this[ value ? "_disable" : "_enable" ]();
-			this.options[ key ] = value;
-			// disable element style changes
-			return;
-		}
-
-		this._super( key, value );
-
-		if ( key === "content" ) {
-			$.each( this.tooltips, function( id, element ) {
-				that._updateContent( element );
-			});
-		}
-	},
-
-	_disable: function() {
-		var that = this;
-
-		// close open tooltips
-		$.each( this.tooltips, function( id, element ) {
-			var event = $.Event( "blur" );
-			event.target = event.currentTarget = element[0];
-			that.close( event, true );
-		});
-
-		// remove title attributes to prevent native tooltips
-		this.element.find( this.options.items ).andSelf().each(function() {
-			var element = $( this );
-			if ( element.is( "[title]" ) ) {
-				element
-					.data( "ui-tooltip-title", element.attr( "title" ) )
-					.attr( "title", "" );
-			}
-		});
-	},
-
-	_enable: function() {
-		// restore title attributes
-		this.element.find( this.options.items ).andSelf().each(function() {
-			var element = $( this );
-			if ( element.data( "ui-tooltip-title" ) ) {
-				element.attr( "title", element.data( "ui-tooltip-title" ) );
-			}
-		});
-	},
-
-	open: function( event ) {
-		var that = this,
-			target = $( event ? event.target : this.element )
-				// we need closest here due to mouseover bubbling,
-				// but always pointing at the same event target
-				.closest( this.options.items );
-
-		// No element to show a tooltip for or the tooltip is already open
-		if ( !target.length || target.data( "ui-tooltip-id" ) ) {
-			return;
-		}
-
-		if ( target.attr( "title" ) ) {
-			target.data( "ui-tooltip-title", target.attr( "title" ) );
-		}
-
-		target.data( "ui-tooltip-open", true );
-
-		// kill parent tooltips, custom or native, for hover
-		if ( event && event.type === "mouseover" ) {
-			target.parents().each(function() {
-				var parent = $( this ),
-					blurEvent;
-				if ( parent.data( "ui-tooltip-open" ) ) {
-					blurEvent = $.Event( "blur" );
-					blurEvent.target = blurEvent.currentTarget = this;
-					that.close( blurEvent, true );
-				}
-				if ( parent.attr( "title" ) ) {
-					parent.uniqueId();
-					that.parents[ this.id ] = {
-						element: this,
-						title: parent.attr( "title" )
-					};
-					parent.attr( "title", "" );
-				}
-			});
-		}
-
-		this._updateContent( target, event );
-	},
-
-	_updateContent: function( target, event ) {
-		var content,
-			contentOption = this.options.content,
-			that = this,
-			eventType = event ? event.type : null;
-
-		if ( typeof contentOption === "string" ) {
-			return this._open( event, target, contentOption );
-		}
-
-		content = contentOption.call( target[0], function( response ) {
-			// ignore async response if tooltip was closed already
-			if ( !target.data( "ui-tooltip-open" ) ) {
-				return;
-			}
-			// IE may instantly serve a cached response for ajax requests
-			// delay this call to _open so the other call to _open runs first
-			that._delay(function() {
-				// jQuery creates a special event for focusin when it doesn't
-				// exist natively. To improve performance, the native event
-				// object is reused and the type is changed. Therefore, we can't
-				// rely on the type being correct after the event finished
-				// bubbling, so we set it back to the previous value. (#8740)
-				if ( event ) {
-					event.type = eventType;
-				}
-				this._open( event, target, response );
-			});
-		});
-		if ( content ) {
-			this._open( event, target, content );
-		}
-	},
-
-	_open: function( event, target, content ) {
-		var tooltip, events, delayedShow,
-			positionOption = $.extend( {}, this.options.position );
-
-		if ( !content ) {
-			return;
-		}
-
-		// Content can be updated multiple times. If the tooltip already
-		// exists, then just update the content and bail.
-		tooltip = this._find( target );
-		if ( tooltip.length ) {
-			tooltip.find( ".ui-tooltip-content" ).html( content );
-			return;
-		}
-
-		// if we have a title, clear it to prevent the native tooltip
-		// we have to check first to avoid defining a title if none exists
-		// (we don't want to cause an element to start matching [title])
-		//
-		// We use removeAttr only for key events, to allow IE to export the correct
-		// accessible attributes. For mouse events, set to empty string to avoid
-		// native tooltip showing up (happens only when removing inside mouseover).
-		if ( target.is( "[title]" ) ) {
-			if ( event && event.type === "mouseover" ) {
-				target.attr( "title", "" );
-			} else {
-				target.removeAttr( "title" );
-			}
-		}
-
-		tooltip = this._tooltip( target );
-		addDescribedBy( target, tooltip.attr( "id" ) );
-		tooltip.find( ".ui-tooltip-content" ).html( content );
-
-		function position( event ) {
-			positionOption.of = event;
-			if ( tooltip.is( ":hidden" ) ) {
-				return;
-			}
-			tooltip.position( positionOption );
-		}
-		if ( this.options.track && event && /^mouse/.test( event.type ) ) {
-			this._on( this.document, {
-				mousemove: position
-			});
-			// trigger once to override element-relative positioning
-			position( event );
-		} else {
-			tooltip.position( $.extend({
-				of: target
-			}, this.options.position ) );
-		}
-
-		tooltip.hide();
-
-		this._show( tooltip, this.options.show );
-		// Handle tracking tooltips that are shown with a delay (#8644). As soon
-		// as the tooltip is visible, position the tooltip using the most recent
-		// event.
-		if ( this.options.show && this.options.show.delay ) {
-			delayedShow = setInterval(function() {
-				if ( tooltip.is( ":visible" ) ) {
-					position( positionOption.of );
-					clearInterval( delayedShow );
-				}
-			}, $.fx.interval );
-		}
-
-		this._trigger( "open", event, { tooltip: tooltip } );
-
-		events = {
-			keyup: function( event ) {
-				if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
-					var fakeEvent = $.Event(event);
-					fakeEvent.currentTarget = target[0];
-					this.close( fakeEvent, true );
-				}
-			},
-			remove: function() {
-				this._removeTooltip( tooltip );
-			}
-		};
-		if ( !event || event.type === "mouseover" ) {
-			events.mouseleave = "close";
-		}
-		if ( !event || event.type === "focusin" ) {
-			events.focusout = "close";
-		}
-		this._on( true, target, events );
-	},
-
-	close: function( event ) {
-		var that = this,
-			target = $( event ? event.currentTarget : this.element ),
-			tooltip = this._find( target );
-
-		// disabling closes the tooltip, so we need to track when we're closing
-		// to avoid an infinite loop in case the tooltip becomes disabled on close
-		if ( this.closing ) {
-			return;
-		}
-
-		// only set title if we had one before (see comment in _open())
-		if ( target.data( "ui-tooltip-title" ) ) {
-			target.attr( "title", target.data( "ui-tooltip-title" ) );
-		}
-
-		removeDescribedBy( target );
-
-		tooltip.stop( true );
-		this._hide( tooltip, this.options.hide, function() {
-			that._removeTooltip( $( this ) );
-		});
-
-		target.removeData( "ui-tooltip-open" );
-		this._off( target, "mouseleave focusout keyup" );
-		// Remove 'remove' binding only on delegated targets
-		if ( target[0] !== this.element[0] ) {
-			this._off( target, "remove" );
-		}
-		this._off( this.document, "mousemove" );
-
-		if ( event && event.type === "mouseleave" ) {
-			$.each( this.parents, function( id, parent ) {
-				$( parent.element ).attr( "title", parent.title );
-				delete that.parents[ id ];
-			});
-		}
-
-		this.closing = true;
-		this._trigger( "close", event, { tooltip: tooltip } );
-		this.closing = false;
-	},
-
-	_tooltip: function( element ) {
-		var id = "ui-tooltip-" + increments++,
-			tooltip = $( "<div>" )
-				.attr({
-					id: id,
-					role: "tooltip"
-				})
-				.addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " +
-					( this.options.tooltipClass || "" ) );
-		$( "<div>" )
-			.addClass( "ui-tooltip-content" )
-			.appendTo( tooltip );
-		tooltip.appendTo( this.document[0].body );
-		if ( $.fn.bgiframe ) {
-			tooltip.bgiframe();
-		}
-		this.tooltips[ id ] = element;
-		return tooltip;
-	},
-
-	_find: function( target ) {
-		var id = target.data( "ui-tooltip-id" );
-		return id ? $( "#" + id ) : $();
-	},
-
-	_removeTooltip: function( tooltip ) {
-		tooltip.remove();
-		delete this.tooltips[ tooltip.attr( "id" ) ];
-	},
-
-	_destroy: function() {
-		var that = this;
-
-		// close open tooltips
-		$.each( this.tooltips, function( id, element ) {
-			// Delegate to close method to handle common cleanup
-			var event = $.Event( "blur" );
-			event.target = event.currentTarget = element[0];
-			that.close( event, true );
-
-			// Remove immediately; destroying an open tooltip doesn't use the
-			// hide animation
-			$( "#" + id ).remove();
-
-			// Restore the title
-			if ( element.data( "ui-tooltip-title" ) ) {
-				element.attr( "title", element.data( "ui-tooltip-title" ) );
-				element.removeData( "ui-tooltip-title" );
-			}
-		});
-	}
-});
-
-}( jQuery ) );
-;(jQuery.effects || (function($, undefined) {
-
-var backCompat = $.uiBackCompat !== false,
-	// prefix used for storing data on .data()
-	dataSpace = "ui-effects-";
-
-$.effects = {
-	effect: {}
-};
-
-/*!
- * jQuery Color Animations v2.0.0
- * http://jquery.com/
- *
- * Copyright 2012 jQuery Foundation and other contributors
- * Released under the MIT license.
- * http://jquery.org/license
- *
- * Date: Mon Aug 13 13:41:02 2012 -0500
- */
-(function( jQuery, undefined ) {
-
-	var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor".split(" "),
-
-	// plusequals test for += 100 -= 100
-	rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
-	// a set of RE's that can match strings and generate color tuples.
-	stringParsers = [{
-			re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
-			parse: function( execResult ) {
-				return [
-					execResult[ 1 ],
-					execResult[ 2 ],
-					execResult[ 3 ],
-					execResult[ 4 ]
-				];
-			}
-		}, {
-			re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
-			parse: function( execResult ) {
-				return [
-					execResult[ 1 ] * 2.55,
-					execResult[ 2 ] * 2.55,
-					execResult[ 3 ] * 2.55,
-					execResult[ 4 ]
-				];
-			}
-		}, {
-			// this regex ignores A-F because it's compared against an already lowercased string
-			re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,
-			parse: function( execResult ) {
-				return [
-					parseInt( execResult[ 1 ], 16 ),
-					parseInt( execResult[ 2 ], 16 ),
-					parseInt( execResult[ 3 ], 16 )
-				];
-			}
-		}, {
-			// this regex ignores A-F because it's compared against an already lowercased string
-			re: /#([a-f0-9])([a-f0-9])([a-f0-9])/,
-			parse: function( execResult ) {
-				return [
-					parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
-					parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
-					parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
-				];
-			}
-		}, {
-			re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
-			space: "hsla",
-			parse: function( execResult ) {
-				return [
-					execResult[ 1 ],
-					execResult[ 2 ] / 100,
-					execResult[ 3 ] / 100,
-					execResult[ 4 ]
-				];
-			}
-		}],
-
-	// jQuery.Color( )
-	color = jQuery.Color = function( color, green, blue, alpha ) {
-		return new jQuery.Color.fn.parse( color, green, blue, alpha );
-	},
-	spaces = {
-		rgba: {
-			props: {
-				red: {
-					idx: 0,
-					type: "byte"
-				},
-				green: {
-					idx: 1,
-					type: "byte"
-				},
-				blue: {
-					idx: 2,
-					type: "byte"
-				}
-			}
-		},
-
-		hsla: {
-			props: {
-				hue: {
-					idx: 0,
-					type: "degrees"
-				},
-				saturation: {
-					idx: 1,
-					type: "percent"
-				},
-				lightness: {
-					idx: 2,
-					type: "percent"
-				}
-			}
-		}
-	},
-	propTypes = {
-		"byte": {
-			floor: true,
-			max: 255
-		},
-		"percent": {
-			max: 1
-		},
-		"degrees": {
-			mod: 360,
-			floor: true
-		}
-	},
-	support = color.support = {},
-
-	// element for support tests
-	supportElem = jQuery( "<p>" )[ 0 ],
-
-	// colors = jQuery.Color.names
-	colors,
-
-	// local aliases of functions called often
-	each = jQuery.each;
-
-// determine rgba support immediately
-supportElem.style.cssText = "background-color:rgba(1,1,1,.5)";
-support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1;
-
-// define cache name and alpha properties
-// for rgba and hsla spaces
-each( spaces, function( spaceName, space ) {
-	space.cache = "_" + spaceName;
-	space.props.alpha = {
-		idx: 3,
-		type: "percent",
-		def: 1
-	};
-});
-
-function clamp( value, prop, allowEmpty ) {
-	var type = propTypes[ prop.type ] || {};
-
-	if ( value == null ) {
-		return (allowEmpty || !prop.def) ? null : prop.def;
-	}
-
-	// ~~ is an short way of doing floor for positive numbers
-	value = type.floor ? ~~value : parseFloat( value );
-
-	// IE will pass in empty strings as value for alpha,
-	// which will hit this case
-	if ( isNaN( value ) ) {
-		return prop.def;
-	}
-
-	if ( type.mod ) {
-		// we add mod before modding to make sure that negatives values
-		// get converted properly: -10 -> 350
-		return (value + type.mod) % type.mod;
-	}
-
-	// for now all property types without mod have min and max
-	return 0 > value ? 0 : type.max < value ? type.max : value;
-}
-
-function stringParse( string ) {
-	var inst = color(),
-		rgba = inst._rgba = [];
-
-	string = string.toLowerCase();
-
-	each( stringParsers, function( i, parser ) {
-		var parsed,
-			match = parser.re.exec( string ),
-			values = match && parser.parse( match ),
-			spaceName = parser.space || "rgba";
-
-		if ( values ) {
-			parsed = inst[ spaceName ]( values );
-
-			// if this was an rgba parse the assignment might happen twice
-			// oh well....
-			inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
-			rgba = inst._rgba = parsed._rgba;
-
-			// exit each( stringParsers ) here because we matched
-			return false;
-		}
-	});
-
-	// Found a stringParser that handled it
-	if ( rgba.length ) {
-
-		// if this came from a parsed string, force "transparent" when alpha is 0
-		// chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
-		if ( rgba.join() === "0,0,0,0" ) {
-			jQuery.extend( rgba, colors.transparent );
-		}
-		return inst;
-	}
-
-	// named colors
-	return colors[ string ];
-}
-
-color.fn = jQuery.extend( color.prototype, {
-	parse: function( red, green, blue, alpha ) {
-		if ( red === undefined ) {
-			this._rgba = [ null, null, null, null ];
-			return this;
-		}
-		if ( red.jquery || red.nodeType ) {
-			red = jQuery( red ).css( green );
-			green = undefined;
-		}
-
-		var inst = this,
-			type = jQuery.type( red ),
-			rgba = this._rgba = [];
-
-		// more than 1 argument specified - assume ( red, green, blue, alpha )
-		if ( green !== undefined ) {
-			red = [ red, green, blue, alpha ];
-			type = "array";
-		}
-
-		if ( type === "string" ) {
-			return this.parse( stringParse( red ) || colors._default );
-		}
-
-		if ( type === "array" ) {
-			each( spaces.rgba.props, function( key, prop ) {
-				rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
-			});
-			return this;
-		}
-
-		if ( type === "object" ) {
-			if ( red instanceof color ) {
-				each( spaces, function( spaceName, space ) {
-					if ( red[ space.cache ] ) {
-						inst[ space.cache ] = red[ space.cache ].slice();
-					}
-				});
-			} else {
-				each( spaces, function( spaceName, space ) {
-					var cache = space.cache;
-					each( space.props, function( key, prop ) {
-
-						// if the cache doesn't exist, and we know how to convert
-						if ( !inst[ cache ] && space.to ) {
-
-							// if the value was null, we don't need to copy it
-							// if the key was alpha, we don't need to copy it either
-							if ( key === "alpha" || red[ key ] == null ) {
-								return;
-							}
-							inst[ cache ] = space.to( inst._rgba );
-						}
-
-						// this is the only case where we allow nulls for ALL properties.
-						// call clamp with alwaysAllowEmpty
-						inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
-					});
-
-					// everything defined but alpha?
-					if ( inst[ cache ] && $.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {
-						// use the default of 1
-						inst[ cache ][ 3 ] = 1;
-						if ( space.from ) {
-							inst._rgba = space.from( inst[ cache ] );
-						}
-					}
-				});
-			}
-			return this;
-		}
-	},
-	is: function( compare ) {
-		var is = color( compare ),
-			same = true,
-			inst = this;
-
-		each( spaces, function( _, space ) {
-			var localCache,
-				isCache = is[ space.cache ];
-			if (isCache) {
-				localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
-				each( space.props, function( _, prop ) {
-					if ( isCache[ prop.idx ] != null ) {
-						same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
-						return same;
-					}
-				});
-			}
-			return same;
-		});
-		return same;
-	},
-	_space: function() {
-		var used = [],
-			inst = this;
-		each( spaces, function( spaceName, space ) {
-			if ( inst[ space.cache ] ) {
-				used.push( spaceName );
-			}
-		});
-		return used.pop();
-	},
-	transition: function( other, distance ) {
-		var end = color( other ),
-			spaceName = end._space(),
-			space = spaces[ spaceName ],
-			startColor = this.alpha() === 0 ? color( "transparent" ) : this,
-			start = startColor[ space.cache ] || space.to( startColor._rgba ),
-			result = start.slice();
-
-		end = end[ space.cache ];
-		each( space.props, function( key, prop ) {
-			var index = prop.idx,
-				startValue = start[ index ],
-				endValue = end[ index ],
-				type = propTypes[ prop.type ] || {};
-
-			// if null, don't override start value
-			if ( endValue === null ) {
-				return;
-			}
-			// if null - use end
-			if ( startValue === null ) {
-				result[ index ] = endValue;
-			} else {
-				if ( type.mod ) {
-					if ( endValue - startValue > type.mod / 2 ) {
-						startValue += type.mod;
-					} else if ( startValue - endValue > type.mod / 2 ) {
-						startValue -= type.mod;
-					}
-				}
-				result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
-			}
-		});
-		return this[ spaceName ]( result );
-	},
-	blend: function( opaque ) {
-		// if we are already opaque - return ourself
-		if ( this._rgba[ 3 ] === 1 ) {
-			return this;
-		}
-
-		var rgb = this._rgba.slice(),
-			a = rgb.pop(),
-			blend = color( opaque )._rgba;
-
-		return color( jQuery.map( rgb, function( v, i ) {
-			return ( 1 - a ) * blend[ i ] + a * v;
-		}));
-	},
-	toRgbaString: function() {
-		var prefix = "rgba(",
-			rgba = jQuery.map( this._rgba, function( v, i ) {
-				return v == null ? ( i > 2 ? 1 : 0 ) : v;
-			});
-
-		if ( rgba[ 3 ] === 1 ) {
-			rgba.pop();
-			prefix = "rgb(";
-		}
-
-		return prefix + rgba.join() + ")";
-	},
-	toHslaString: function() {
-		var prefix = "hsla(",
-			hsla = jQuery.map( this.hsla(), function( v, i ) {
-				if ( v == null ) {
-					v = i > 2 ? 1 : 0;
-				}
-
-				// catch 1 and 2
-				if ( i && i < 3 ) {
-					v = Math.round( v * 100 ) + "%";
-				}
-				return v;
-			});
-
-		if ( hsla[ 3 ] === 1 ) {
-			hsla.pop();
-			prefix = "hsl(";
-		}
-		return prefix + hsla.join() + ")";
-	},
-	toHexString: function( includeAlpha ) {
-		var rgba = this._rgba.slice(),
-			alpha = rgba.pop();
-
-		if ( includeAlpha ) {
-			rgba.push( ~~( alpha * 255 ) );
-		}
-
-		return "#" + jQuery.map( rgba, function( v ) {
-
-			// default to 0 when nulls exist
-			v = ( v || 0 ).toString( 16 );
-			return v.length === 1 ? "0" + v : v;
-		}).join("");
-	},
-	toString: function() {
-		return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString();
-	}
-});
-color.fn.parse.prototype = color.fn;
-
-// hsla conversions adapted from:
-// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
-
-function hue2rgb( p, q, h ) {
-	h = ( h + 1 ) % 1;
-	if ( h * 6 < 1 ) {
-		return p + (q - p) * h * 6;
-	}
-	if ( h * 2 < 1) {
-		return q;
-	}
-	if ( h * 3 < 2 ) {
-		return p + (q - p) * ((2/3) - h) * 6;
-	}
-	return p;
-}
-
-spaces.hsla.to = function ( rgba ) {
-	if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
-		return [ null, null, null, rgba[ 3 ] ];
-	}
-	var r = rgba[ 0 ] / 255,
-		g = rgba[ 1 ] / 255,
-		b = rgba[ 2 ] / 255,
-		a = rgba[ 3 ],
-		max = Math.max( r, g, b ),
-		min = Math.min( r, g, b ),
-		diff = max - min,
-		add = max + min,
-		l = add * 0.5,
-		h, s;
-
-	if ( min === max ) {
-		h = 0;
-	} else if ( r === max ) {
-		h = ( 60 * ( g - b ) / diff ) + 360;
-	} else if ( g === max ) {
-		h = ( 60 * ( b - r ) / diff ) + 120;
-	} else {
-		h = ( 60 * ( r - g ) / diff ) + 240;
-	}
-
-	if ( l === 0 || l === 1 ) {
-		s = l;
-	} else if ( l <= 0.5 ) {
-		s = diff / add;
-	} else {
-		s = diff / ( 2 - add );
-	}
-	return [ Math.round(h) % 360, s, l, a == null ? 1 : a ];
-};
-
-spaces.hsla.from = function ( hsla ) {
-	if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
-		return [ null, null, null, hsla[ 3 ] ];
-	}
-	var h = hsla[ 0 ] / 360,
-		s = hsla[ 1 ],
-		l = hsla[ 2 ],
-		a = hsla[ 3 ],
-		q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
-		p = 2 * l - q;
-
-	return [
-		Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
-		Math.round( hue2rgb( p, q, h ) * 255 ),
-		Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
-		a
-	];
-};
-
-
-each( spaces, function( spaceName, space ) {
-	var props = space.props,
-		cache = space.cache,
-		to = space.to,
-		from = space.from;
-
-	// makes rgba() and hsla()
-	color.fn[ spaceName ] = function( value ) {
-
-		// generate a cache for this space if it doesn't exist
-		if ( to && !this[ cache ] ) {
-			this[ cache ] = to( this._rgba );
-		}
-		if ( value === undefined ) {
-			return this[ cache ].slice();
-		}
-
-		var ret,
-			type = jQuery.type( value ),
-			arr = ( type === "array" || type === "object" ) ? value : arguments,
-			local = this[ cache ].slice();
-
-		each( props, function( key, prop ) {
-			var val = arr[ type === "object" ? key : prop.idx ];
-			if ( val == null ) {
-				val = local[ prop.idx ];
-			}
-			local[ prop.idx ] = clamp( val, prop );
-		});
-
-		if ( from ) {
-			ret = color( from( local ) );
-			ret[ cache ] = local;
-			return ret;
-		} else {
-			return color( local );
-		}
-	};
-
-	// makes red() green() blue() alpha() hue() saturation() lightness()
-	each( props, function( key, prop ) {
-		// alpha is included in more than one space
-		if ( color.fn[ key ] ) {
-			return;
-		}
-		color.fn[ key ] = function( value ) {
-			var vtype = jQuery.type( value ),
-				fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ),
-				local = this[ fn ](),
-				cur = local[ prop.idx ],
-				match;
-
-			if ( vtype === "undefined" ) {
-				return cur;
-			}
-
-			if ( vtype === "function" ) {
-				value = value.call( this, cur );
-				vtype = jQuery.type( value );
-			}
-			if ( value == null && prop.empty ) {
-				return this;
-			}
-			if ( vtype === "string" ) {
-				match = rplusequals.exec( value );
-				if ( match ) {
-					value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
-				}
-			}
-			local[ prop.idx ] = value;
-			return this[ fn ]( local );
-		};
-	});
-});
-
-// add .fx.step functions
-each( stepHooks, function( i, hook ) {
-	jQuery.cssHooks[ hook ] = {
-		set: function( elem, value ) {
-			var parsed, curElem,
-				backgroundColor = "";
-
-			if ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) {
-				value = color( parsed || value );
-				if ( !support.rgba && value._rgba[ 3 ] !== 1 ) {
-					curElem = hook === "backgroundColor" ? elem.parentNode : elem;
-					while (
-						(backgroundColor === "" || backgroundColor === "transparent") &&
-						curElem && curElem.style
-					) {
-						try {
-							backgroundColor = jQuery.css( curElem, "backgroundColor" );
-							curElem = curElem.parentNode;
-						} catch ( e ) {
-						}
-					}
-
-					value = value.blend( backgroundColor && backgroundColor !== "transparent" ?
-						backgroundColor :
-						"_default" );
-				}
-
-				value = value.toRgbaString();
-			}
-			try {
-				elem.style[ hook ] = value;
-			} catch( error ) {
-				// wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit'
-			}
-		}
-	};
-	jQuery.fx.step[ hook ] = function( fx ) {
-		if ( !fx.colorInit ) {
-			fx.start = color( fx.elem, hook );
-			fx.end = color( fx.end );
-			fx.colorInit = true;
-		}
-		jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
-	};
-});
-
-jQuery.cssHooks.borderColor = {
-	expand: function( value ) {
-		var expanded = {};
-
-		each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) {
-			expanded[ "border" + part + "Color" ] = value;
-		});
-		return expanded;
-	}
-};
-
-// Basic color names only.
-// Usage of any of the other color names requires adding yourself or including
-// jquery.color.svg-names.js.
-colors = jQuery.Color.names = {
-	// 4.1. Basic color keywords
-	aqua: "#00ffff",
-	black: "#000000",
-	blue: "#0000ff",
-	fuchsia: "#ff00ff",
-	gray: "#808080",
-	green: "#008000",
-	lime: "#00ff00",
-	maroon: "#800000",
-	navy: "#000080",
-	olive: "#808000",
-	purple: "#800080",
-	red: "#ff0000",
-	silver: "#c0c0c0",
-	teal: "#008080",
-	white: "#ffffff",
-	yellow: "#ffff00",
-
-	// 4.2.3. "transparent" color keyword
-	transparent: [ null, null, null, 0 ],
-
-	_default: "#ffffff"
-};
-
-})( jQuery );
-
-
-
-/******************************************************************************/
-/****************************** CLASS ANIMATIONS ******************************/
-/******************************************************************************/
-(function() {
-
-var classAnimationActions = [ "add", "remove", "toggle" ],
-	shorthandStyles = {
-		border: 1,
-		borderBottom: 1,
-		borderColor: 1,
-		borderLeft: 1,
-		borderRight: 1,
-		borderTop: 1,
-		borderWidth: 1,
-		margin: 1,
-		padding: 1
-	};
-
-$.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) {
-	$.fx.step[ prop ] = function( fx ) {
-		if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
-			jQuery.style( fx.elem, prop, fx.end );
-			fx.setAttr = true;
-		}
-	};
-});
-
-function getElementStyles() {
-	var style = this.ownerDocument.defaultView ?
-			this.ownerDocument.defaultView.getComputedStyle( this, null ) :
-			this.currentStyle,
-		newStyle = {},
-		key,
-		len;
-
-	// webkit enumerates style porperties
-	if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
-		len = style.length;
-		while ( len-- ) {
-			key = style[ len ];
-			if ( typeof style[ key ] === "string" ) {
-				newStyle[ $.camelCase( key ) ] = style[ key ];
-			}
-		}
-	} else {
-		for ( key in style ) {
-			if ( typeof style[ key ] === "string" ) {
-				newStyle[ key ] = style[ key ];
-			}
-		}
-	}
-
-	return newStyle;
-}
-
-
-function styleDifference( oldStyle, newStyle ) {
-	var diff = {},
-		name, value;
-
-	for ( name in newStyle ) {
-		value = newStyle[ name ];
-		if ( oldStyle[ name ] !== value ) {
-			if ( !shorthandStyles[ name ] ) {
-				if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
-					diff[ name ] = value;
-				}
-			}
-		}
-	}
-
-	return diff;
-}
-
-$.effects.animateClass = function( value, duration, easing, callback ) {
-	var o = $.speed( duration, easing, callback );
-
-	return this.queue( function() {
-		var animated = $( this ),
-			baseClass = animated.attr( "class" ) || "",
-			applyClassChange,
-			allAnimations = o.children ? animated.find( "*" ).andSelf() : animated;
-
-		// map the animated objects to store the original styles.
-		allAnimations = allAnimations.map(function() {
-			var el = $( this );
-			return {
-				el: el,
-				start: getElementStyles.call( this )
-			};
-		});
-
-		// apply class change
-		applyClassChange = function() {
-			$.each( classAnimationActions, function(i, action) {
-				if ( value[ action ] ) {
-					animated[ action + "Class" ]( value[ action ] );
-				}
-			});
-		};
-		applyClassChange();
-
-		// map all animated objects again - calculate new styles and diff
-		allAnimations = allAnimations.map(function() {
-			this.end = getElementStyles.call( this.el[ 0 ] );
-			this.diff = styleDifference( this.start, this.end );
-			return this;
-		});
-
-		// apply original class
-		animated.attr( "class", baseClass );
-
-		// map all animated objects again - this time collecting a promise
-		allAnimations = allAnimations.map(function() {
-			var styleInfo = this,
-				dfd = $.Deferred(),
-				opts = jQuery.extend({}, o, {
-					queue: false,
-					complete: function() {
-						dfd.resolve( styleInfo );
-					}
-				});
-
-			this.el.animate( this.diff, opts );
-			return dfd.promise();
-		});
-
-		// once all animations have completed:
-		$.when.apply( $, allAnimations.get() ).done(function() {
-
-			// set the final class
-			applyClassChange();
-
-			// for each animated element,
-			// clear all css properties that were animated
-			$.each( arguments, function() {
-				var el = this.el;
-				$.each( this.diff, function(key) {
-					el.css( key, '' );
-				});
-			});
-
-			// this is guarnteed to be there if you use jQuery.speed()
-			// it also handles dequeuing the next anim...
-			o.complete.call( animated[ 0 ] );
-		});
-	});
-};
-
-$.fn.extend({
-	_addClass: $.fn.addClass,
-	addClass: function( classNames, speed, easing, callback ) {
-		return speed ?
-			$.effects.animateClass.call( this,
-				{ add: classNames }, speed, easing, callback ) :
-			this._addClass( classNames );
-	},
-
-	_removeClass: $.fn.removeClass,
-	removeClass: function( classNames, speed, easing, callback ) {
-		return speed ?
-			$.effects.animateClass.call( this,
-				{ remove: classNames }, speed, easing, callback ) :
-			this._removeClass( classNames );
-	},
-
-	_toggleClass: $.fn.toggleClass,
-	toggleClass: function( classNames, force, speed, easing, callback ) {
-		if ( typeof force === "boolean" || force === undefined ) {
-			if ( !speed ) {
-				// without speed parameter
-				return this._toggleClass( classNames, force );
-			} else {
-				return $.effects.animateClass.call( this,
-					(force ? { add: classNames } : { remove: classNames }),
-					speed, easing, callback );
-			}
-		} else {
-			// without force parameter
-			return $.effects.animateClass.call( this,
-				{ toggle: classNames }, force, speed, easing );
-		}
-	},
-
-	switchClass: function( remove, add, speed, easing, callback) {
-		return $.effects.animateClass.call( this, {
-			add: add,
-			remove: remove
-		}, speed, easing, callback );
-	}
-});
-
-})();
-
-/******************************************************************************/
-/*********************************** EFFECTS **********************************/
-/******************************************************************************/
-
-(function() {
-
-$.extend( $.effects, {
-	version: "1.9.2",
-
-	// Saves a set of properties in a data storage
-	save: function( element, set ) {
-		for( var i=0; i < set.length; i++ ) {
-			if ( set[ i ] !== null ) {
-				element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
-			}
-		}
-	},
-
-	// Restores a set of previously saved properties from a data storage
-	restore: function( element, set ) {
-		var val, i;
-		for( i=0; i < set.length; i++ ) {
-			if ( set[ i ] !== null ) {
-				val = element.data( dataSpace + set[ i ] );
-				// support: jQuery 1.6.2
-				// http://bugs.jquery.com/ticket/9917
-				// jQuery 1.6.2 incorrectly returns undefined for any falsy value.
-				// We can't differentiate between "" and 0 here, so we just assume
-				// empty string since it's likely to be a more common value...
-				if ( val === undefined ) {
-					val = "";
-				}
-				element.css( set[ i ], val );
-			}
-		}
-	},
-
-	setMode: function( el, mode ) {
-		if (mode === "toggle") {
-			mode = el.is( ":hidden" ) ? "show" : "hide";
-		}
-		return mode;
-	},
-
-	// Translates a [top,left] array into a baseline value
-	// this should be a little more flexible in the future to handle a string & hash
-	getBaseline: function( origin, original ) {
-		var y, x;
-		switch ( origin[ 0 ] ) {
-			case "top": y = 0; break;
-			case "middle": y = 0.5; break;
-			case "bottom": y = 1; break;
-			default: y = origin[ 0 ] / original.height;
-		}
-		switch ( origin[ 1 ] ) {
-			case "left": x = 0; break;
-			case "center": x = 0.5; break;
-			case "right": x = 1; break;
-			default: x = origin[ 1 ] / original.width;
-		}
-		return {
-			x: x,
-			y: y
-		};
-	},
-
-	// Wraps the element around a wrapper that copies position properties
-	createWrapper: function( element ) {
-
-		// if the element is already wrapped, return it
-		if ( element.parent().is( ".ui-effects-wrapper" )) {
-			return element.parent();
-		}
-
-		// wrap the element
-		var props = {
-				width: element.outerWidth(true),
-				height: element.outerHeight(true),
-				"float": element.css( "float" )
-			},
-			wrapper = $( "<div></div>" )
-				.addClass( "ui-effects-wrapper" )
-				.css({
-					fontSize: "100%",
-					background: "transparent",
-					border: "none",
-					margin: 0,
-					padding: 0
-				}),
-			// Store the size in case width/height are defined in % - Fixes #5245
-			size = {
-				width: element.width(),
-				height: element.height()
-			},
-			active = document.activeElement;
-
-		// support: Firefox
-		// Firefox incorrectly exposes anonymous content
-		// https://bugzilla.mozilla.org/show_bug.cgi?id=561664
-		try {
-			active.id;
-		} catch( e ) {
-			active = document.body;
-		}
-
-		element.wrap( wrapper );
-
-		// Fixes #7595 - Elements lose focus when wrapped.
-		if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
-			$( active ).focus();
-		}
-
-		wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element
-
-		// transfer positioning properties to the wrapper
-		if ( element.css( "position" ) === "static" ) {
-			wrapper.css({ position: "relative" });
-			element.css({ position: "relative" });
-		} else {
-			$.extend( props, {
-				position: element.css( "position" ),
-				zIndex: element.css( "z-index" )
-			});
-			$.each([ "top", "left", "bottom", "right" ], function(i, pos) {
-				props[ pos ] = element.css( pos );
-				if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
-					props[ pos ] = "auto";
-				}
-			});
-			element.css({
-				position: "relative",
-				top: 0,
-				left: 0,
-				right: "auto",
-				bottom: "auto"
-			});
-		}
-		element.css(size);
-
-		return wrapper.css( props ).show();
-	},
-
-	removeWrapper: function( element ) {
-		var active = document.activeElement;
-
-		if ( element.parent().is( ".ui-effects-wrapper" ) ) {
-			element.parent().replaceWith( element );
-
-			// Fixes #7595 - Elements lose focus when wrapped.
-			if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
-				$( active ).focus();
-			}
-		}
-
-
-		return element;
-	},
-
-	setTransition: function( element, list, factor, value ) {
-		value = value || {};
-		$.each( list, function( i, x ) {
-			var unit = element.cssUnit( x );
-			if ( unit[ 0 ] > 0 ) {
-				value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
-			}
-		});
-		return value;
-	}
-});
-
-// return an effect options object for the given parameters:
-function _normalizeArguments( effect, options, speed, callback ) {
-
-	// allow passing all options as the first parameter
-	if ( $.isPlainObject( effect ) ) {
-		options = effect;
-		effect = effect.effect;
-	}
-
-	// convert to an object
-	effect = { effect: effect };
-
-	// catch (effect, null, ...)
-	if ( options == null ) {
-		options = {};
-	}
-
-	// catch (effect, callback)
-	if ( $.isFunction( options ) ) {
-		callback = options;
-		speed = null;
-		options = {};
-	}
-
-	// catch (effect, speed, ?)
-	if ( typeof options === "number" || $.fx.speeds[ options ] ) {
-		callback = speed;
-		speed = options;
-		options = {};
-	}
-
-	// catch (effect, options, callback)
-	if ( $.isFunction( speed ) ) {
-		callback = speed;
-		speed = null;
-	}
-
-	// add options to effect
-	if ( options ) {
-		$.extend( effect, options );
-	}
-
-	speed = speed || options.duration;
-	effect.duration = $.fx.off ? 0 :
-		typeof speed === "number" ? speed :
-		speed in $.fx.speeds ? $.fx.speeds[ speed ] :
-		$.fx.speeds._default;
-
-	effect.complete = callback || options.complete;
-
-	return effect;
-}
-
-function standardSpeed( speed ) {
-	// valid standard speeds
-	if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
-		return true;
-	}
-
-	// invalid strings - treat as "normal" speed
-	if ( typeof speed === "string" && !$.effects.effect[ speed ] ) {
-		// TODO: remove in 2.0 (#7115)
-		if ( backCompat && $.effects[ speed ] ) {
-			return false;
-		}
-		return true;
-	}
-
-	return false;
-}
-
-$.fn.extend({
-	effect: function( /* effect, options, speed, callback */ ) {
-		var args = _normalizeArguments.apply( this, arguments ),
-			mode = args.mode,
-			queue = args.queue,
-			effectMethod = $.effects.effect[ args.effect ],
-
-			// DEPRECATED: remove in 2.0 (#7115)
-			oldEffectMethod = !effectMethod && backCompat && $.effects[ args.effect ];
-
-		if ( $.fx.off || !( effectMethod || oldEffectMethod ) ) {
-			// delegate to the original method (e.g., .show()) if possible
-			if ( mode ) {
-				return this[ mode ]( args.duration, args.complete );
-			} else {
-				return this.each( function() {
-					if ( args.complete ) {
-						args.complete.call( this );
-					}
-				});
-			}
-		}
-
-		function run( next ) {
-			var elem = $( this ),
-				complete = args.complete,
-				mode = args.mode;
-
-			function done() {
-				if ( $.isFunction( complete ) ) {
-					complete.call( elem[0] );
-				}
-				if ( $.isFunction( next ) ) {
-					next();
-				}
-			}
-
-			// if the element is hiddden and mode is hide,
-			// or element is visible and mode is show
-			if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
-				done();
-			} else {
-				effectMethod.call( elem[0], args, done );
-			}
-		}
-
-		// TODO: remove this check in 2.0, effectMethod will always be true
-		if ( effectMethod ) {
-			return queue === false ? this.each( run ) : this.queue( queue || "fx", run );
-		} else {
-			// DEPRECATED: remove in 2.0 (#7115)
-			return oldEffectMethod.call(this, {
-				options: args,
-				duration: args.duration,
-				callback: args.complete,
-				mode: args.mode
-			});
-		}
-	},
-
-	_show: $.fn.show,
-	show: function( speed ) {
-		if ( standardSpeed( speed ) ) {
-			return this._show.apply( this, arguments );
-		} else {
-			var args = _normalizeArguments.apply( this, arguments );
-			args.mode = "show";
-			return this.effect.call( this, args );
-		}
-	},
-
-	_hide: $.fn.hide,
-	hide: function( speed ) {
-		if ( standardSpeed( speed ) ) {
-			return this._hide.apply( this, arguments );
-		} else {
-			var args = _normalizeArguments.apply( this, arguments );
-			args.mode = "hide";
-			return this.effect.call( this, args );
-		}
-	},
-
-	// jQuery core overloads toggle and creates _toggle
-	__toggle: $.fn.toggle,
-	toggle: function( speed ) {
-		if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) {
-			return this.__toggle.apply( this, arguments );
-		} else {
-			var args = _normalizeArguments.apply( this, arguments );
-			args.mode = "toggle";
-			return this.effect.call( this, args );
-		}
-	},
-
-	// helper functions
-	cssUnit: function(key) {
-		var style = this.css( key ),
-			val = [];
-
-		$.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
-			if ( style.indexOf( unit ) > 0 ) {
-				val = [ parseFloat( style ), unit ];
-			}
-		});
-		return val;
-	}
-});
-
-})();
-
-/******************************************************************************/
-/*********************************** EASING ***********************************/
-/******************************************************************************/
-
-(function() {
-
-// based on easing equations from Robert Penner (http://www.robertpenner.com/easing)
-
-var baseEasings = {};
-
-$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
-	baseEasings[ name ] = function( p ) {
-		return Math.pow( p, i + 2 );
-	};
-});
-
-$.extend( baseEasings, {
-	Sine: function ( p ) {
-		return 1 - Math.cos( p * Math.PI / 2 );
-	},
-	Circ: function ( p ) {
-		return 1 - Math.sqrt( 1 - p * p );
-	},
-	Elastic: function( p ) {
-		return p === 0 || p === 1 ? p :
-			-Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 );
-	},
-	Back: function( p ) {
-		return p * p * ( 3 * p - 2 );
-	},
-	Bounce: function ( p ) {
-		var pow2,
-			bounce = 4;
-
-		while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
-		return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
-	}
-});
-
-$.each( baseEasings, function( name, easeIn ) {
-	$.easing[ "easeIn" + name ] = easeIn;
-	$.easing[ "easeOut" + name ] = function( p ) {
-		return 1 - easeIn( 1 - p );
-	};
-	$.easing[ "easeInOut" + name ] = function( p ) {
-		return p < 0.5 ?
-			easeIn( p * 2 ) / 2 :
-			1 - easeIn( p * -2 + 2 ) / 2;
-	};
-});
-
-})();
-
-})(jQuery));
-(function( $, undefined ) {
-
-var rvertical = /up|down|vertical/,
-	rpositivemotion = /up|left|vertical|horizontal/;
-
-$.effects.effect.blind = function( o, done ) {
-	// Create element
-	var el = $( this ),
-		props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
-		mode = $.effects.setMode( el, o.mode || "hide" ),
-		direction = o.direction || "up",
-		vertical = rvertical.test( direction ),
-		ref = vertical ? "height" : "width",
-		ref2 = vertical ? "top" : "left",
-		motion = rpositivemotion.test( direction ),
-		animation = {},
-		show = mode === "show",
-		wrapper, distance, margin;
-
-	// if already wrapped, the wrapper's properties are my property. #6245
-	if ( el.parent().is( ".ui-effects-wrapper" ) ) {
-		$.effects.save( el.parent(), props );
-	} else {
-		$.effects.save( el, props );
-	}
-	el.show();
-	wrapper = $.effects.createWrapper( el ).css({
-		overflow: "hidden"
-	});
-
-	distance = wrapper[ ref ]();
-	margin = parseFloat( wrapper.css( ref2 ) ) || 0;
-
-	animation[ ref ] = show ? distance : 0;
-	if ( !motion ) {
-		el
-			.css( vertical ? "bottom" : "right", 0 )
-			.css( vertical ? "top" : "left", "auto" )
-			.css({ position: "absolute" });
-
-		animation[ ref2 ] = show ? margin : distance + margin;
-	}
-
-	// start at 0 if we are showing
-	if ( show ) {
-		wrapper.css( ref, 0 );
-		if ( ! motion ) {
-			wrapper.css( ref2, margin + distance );
-		}
-	}
-
-	// Animate
-	wrapper.animate( animation, {
-		duration: o.duration,
-		easing: o.easing,
-		queue: false,
-		complete: function() {
-			if ( mode === "hide" ) {
-				el.hide();
-			}
-			$.effects.restore( el, props );
-			$.effects.removeWrapper( el );
-			done();
-		}
-	});
-
-};
-
-})(jQuery);
-(function( $, undefined ) {
-
-$.effects.effect.bounce = function( o, done ) {
-	var el = $( this ),
-		props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
-
-		// defaults:
-		mode = $.effects.setMode( el, o.mode || "effect" ),
-		hide = mode === "hide",
-		show = mode === "show",
-		direction = o.direction || "up",
-		distance = o.distance,
-		times = o.times || 5,
-
-		// number of internal animations
-		anims = times * 2 + ( show || hide ? 1 : 0 ),
-		speed = o.duration / anims,
-		easing = o.easing,
-
-		// utility:
-		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
-		motion = ( direction === "up" || direction === "left" ),
-		i,
-		upAnim,
-		downAnim,
-
-		// we will need to re-assemble the queue to stack our animations in place
-		queue = el.queue(),
-		queuelen = queue.length;
-
-	// Avoid touching opacity to prevent clearType and PNG issues in IE
-	if ( show || hide ) {
-		props.push( "opacity" );
-	}
-
-	$.effects.save( el, props );
-	el.show();
-	$.effects.createWrapper( el ); // Create Wrapper
-
-	// default distance for the BIGGEST bounce is the outer Distance / 3
-	if ( !distance ) {
-		distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
-	}
-
-	if ( show ) {
-		downAnim = { opacity: 1 };
-		downAnim[ ref ] = 0;
-
-		// if we are showing, force opacity 0 and set the initial position
-		// then do the "first" animation
-		el.css( "opacity", 0 )
-			.css( ref, motion ? -distance * 2 : distance * 2 )
-			.animate( downAnim, speed, easing );
-	}
-
-	// start at the smallest distance if we are hiding
-	if ( hide ) {
-		distance = distance / Math.pow( 2, times - 1 );
-	}
-
-	downAnim = {};
-	downAnim[ ref ] = 0;
-	// Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
-	for ( i = 0; i < times; i++ ) {
-		upAnim = {};
-		upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
-
-		el.animate( upAnim, speed, easing )
-			.animate( downAnim, speed, easing );
-
-		distance = hide ? distance * 2 : distance / 2;
-	}
-
-	// Last Bounce when Hiding
-	if ( hide ) {
-		upAnim = { opacity: 0 };
-		upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
-
-		el.animate( upAnim, speed, easing );
-	}
-
-	el.queue(function() {
-		if ( hide ) {
-			el.hide();
-		}
-		$.effects.restore( el, props );
-		$.effects.removeWrapper( el );
-		done();
-	});
-
-	// inject all the animations we just queued to be first in line (after "inprogress")
-	if ( queuelen > 1) {
-		queue.splice.apply( queue,
-			[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
-	}
-	el.dequeue();
-
-};
-
-})(jQuery);
-(function( $, undefined ) {
-
-$.effects.effect.clip = function( o, done ) {
-	// Create element
-	var el = $( this ),
-		props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
-		mode = $.effects.setMode( el, o.mode || "hide" ),
-		show = mode === "show",
-		direction = o.direction || "vertical",
-		vert = direction === "vertical",
-		size = vert ? "height" : "width",
-		position = vert ? "top" : "left",
-		animation = {},
-		wrapper, animate, distance;
-
-	// Save & Show
-	$.effects.save( el, props );
-	el.show();
-
-	// Create Wrapper
-	wrapper = $.effects.createWrapper( el ).css({
-		overflow: "hidden"
-	});
-	animate = ( el[0].tagName === "IMG" ) ? wrapper : el;
-	distance = animate[ size ]();
-
-	// Shift
-	if ( show ) {
-		animate.css( size, 0 );
-		animate.css( position, distance / 2 );
-	}
-
-	// Create Animation Object:
-	animation[ size ] = show ? distance : 0;
-	animation[ position ] = show ? 0 : distance / 2;
-
-	// Animate
-	animate.animate( animation, {
-		queue: false,
-		duration: o.duration,
-		easing: o.easing,
-		complete: function() {
-			if ( !show ) {
-				el.hide();
-			}
-			$.effects.restore( el, props );
-			$.effects.removeWrapper( el );
-			done();
-		}
-	});
-
-};
-
-})(jQuery);
-(function( $, undefined ) {
-
-$.effects.effect.drop = function( o, done ) {
-
-	var el = $( this ),
-		props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ],
-		mode = $.effects.setMode( el, o.mode || "hide" ),
-		show = mode === "show",
-		direction = o.direction || "left",
-		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
-		motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg",
-		animation = {
-			opacity: show ? 1 : 0
-		},
-		distance;
-
-	// Adjust
-	$.effects.save( el, props );
-	el.show();
-	$.effects.createWrapper( el );
-
-	distance = o.distance || el[ ref === "top" ? "outerHeight": "outerWidth" ]( true ) / 2;
-
-	if ( show ) {
-		el
-			.css( "opacity", 0 )
-			.css( ref, motion === "pos" ? -distance : distance );
-	}
-
-	// Animation
-	animation[ ref ] = ( show ?
-		( motion === "pos" ? "+=" : "-=" ) :
-		( motion === "pos" ? "-=" : "+=" ) ) +
-		distance;
-
-	// Animate
-	el.animate( animation, {
-		queue: false,
-		duration: o.duration,
-		easing: o.easing,
-		complete: function() {
-			if ( mode === "hide" ) {
-				el.hide();
-			}
-			$.effects.restore( el, props );
-			$.effects.removeWrapper( el );
-			done();
-		}
-	});
-};
-
-})(jQuery);
-(function( $, undefined ) {
-
-$.effects.effect.explode = function( o, done ) {
-
-	var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3,
-		cells = rows,
-		el = $( this ),
-		mode = $.effects.setMode( el, o.mode || "hide" ),
-		show = mode === "show",
-
-		// show and then visibility:hidden the element before calculating offset
-		offset = el.show().css( "visibility", "hidden" ).offset(),
-
-		// width and height of a piece
-		width = Math.ceil( el.outerWidth() / cells ),
-		height = Math.ceil( el.outerHeight() / rows ),
-		pieces = [],
-
-		// loop
-		i, j, left, top, mx, my;
-
-	// children animate complete:
-	function childComplete() {
-		pieces.push( this );
-		if ( pieces.length === rows * cells ) {
-			animComplete();
-		}
-	}
-
-	// clone the element for each row and cell.
-	for( i = 0; i < rows ; i++ ) { // ===>
-		top = offset.top + i * height;
-		my = i - ( rows - 1 ) / 2 ;
-
-		for( j = 0; j < cells ; j++ ) { // |||
-			left = offset.left + j * width;
-			mx = j - ( cells - 1 ) / 2 ;
-
-			// Create a clone of the now hidden main element that will be absolute positioned
-			// within a wrapper div off the -left and -top equal to size of our pieces
-			el
-				.clone()
-				.appendTo( "body" )
-				.wrap( "<div></div>" )
-				.css({
-					position: "absolute",
-					visibility: "visible",
-					left: -j * width,
-					top: -i * height
-				})
-
-			// select the wrapper - make it overflow: hidden and absolute positioned based on
-			// where the original was located +left and +top equal to the size of pieces
-				.parent()
-				.addClass( "ui-effects-explode" )
-				.css({
-					position: "absolute",
-					overflow: "hidden",
-					width: width,
-					height: height,
-					left: left + ( show ? mx * width : 0 ),
-					top: top + ( show ? my * height : 0 ),
-					opacity: show ? 0 : 1
-				}).animate({
-					left: left + ( show ? 0 : mx * width ),
-					top: top + ( show ? 0 : my * height ),
-					opacity: show ? 1 : 0
-				}, o.duration || 500, o.easing, childComplete );
-		}
-	}
-
-	function animComplete() {
-		el.css({
-			visibility: "visible"
-		});
-		$( pieces ).remove();
-		if ( !show ) {
-			el.hide();
-		}
-		done();
-	}
-};
-
-})(jQuery);
-(function( $, undefined ) {
-
-$.effects.effect.fade = function( o, done ) {
-	var el = $( this ),
-		mode = $.effects.setMode( el, o.mode || "toggle" );
-
-	el.animate({
-		opacity: mode
-	}, {
-		queue: false,
-		duration: o.duration,
-		easing: o.easing,
-		complete: done
-	});
-};
-
-})( jQuery );
-(function( $, undefined ) {
-
-$.effects.effect.fold = function( o, done ) {
-
-	// Create element
-	var el = $( this ),
-		props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
-		mode = $.effects.setMode( el, o.mode || "hide" ),
-		show = mode === "show",
-		hide = mode === "hide",
-		size = o.size || 15,
-		percent = /([0-9]+)%/.exec( size ),
-		horizFirst = !!o.horizFirst,
-		widthFirst = show !== horizFirst,
-		ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ],
-		duration = o.duration / 2,
-		wrapper, distance,
-		animation1 = {},
-		animation2 = {};
-
-	$.effects.save( el, props );
-	el.show();
-
-	// Create Wrapper
-	wrapper = $.effects.createWrapper( el ).css({
-		overflow: "hidden"
-	});
-	distance = widthFirst ?
-		[ wrapper.width(), wrapper.height() ] :
-		[ wrapper.height(), wrapper.width() ];
-
-	if ( percent ) {
-		size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
-	}
-	if ( show ) {
-		wrapper.css( horizFirst ? {
-			height: 0,
-			width: size
-		} : {
-			height: size,
-			width: 0
-		});
-	}
-
-	// Animation
-	animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size;
-	animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0;
-
-	// Animate
-	wrapper
-		.animate( animation1, duration, o.easing )
-		.animate( animation2, duration, o.easing, function() {
-			if ( hide ) {
-				el.hide();
-			}
-			$.effects.restore( el, props );
-			$.effects.removeWrapper( el );
-			done();
-		});
-
-};
-
-})(jQuery);
-(function( $, undefined ) {
-
-$.effects.effect.highlight = function( o, done ) {
-	var elem = $( this ),
-		props = [ "backgroundImage", "backgroundColor", "opacity" ],
-		mode = $.effects.setMode( elem, o.mode || "show" ),
-		animation = {
-			backgroundColor: elem.css( "backgroundColor" )
-		};
-
-	if (mode === "hide") {
-		animation.opacity = 0;
-	}
-
-	$.effects.save( elem, props );
-
-	elem
-		.show()
-		.css({
-			backgroundImage: "none",
-			backgroundColor: o.color || "#ffff99"
-		})
-		.animate( animation, {
-			queue: false,
-			duration: o.duration,
-			easing: o.easing,
-			complete: function() {
-				if ( mode === "hide" ) {
-					elem.hide();
-				}
-				$.effects.restore( elem, props );
-				done();
-			}
-		});
-};
-
-})(jQuery);
-(function( $, undefined ) {
-
-$.effects.effect.pulsate = function( o, done ) {
-	var elem = $( this ),
-		mode = $.effects.setMode( elem, o.mode || "show" ),
-		show = mode === "show",
-		hide = mode === "hide",
-		showhide = ( show || mode === "hide" ),
-
-		// showing or hiding leaves of the "last" animation
-		anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
-		duration = o.duration / anims,
-		animateTo = 0,
-		queue = elem.queue(),
-		queuelen = queue.length,
-		i;
-
-	if ( show || !elem.is(":visible")) {
-		elem.css( "opacity", 0 ).show();
-		animateTo = 1;
-	}
-
-	// anims - 1 opacity "toggles"
-	for ( i = 1; i < anims; i++ ) {
-		elem.animate({
-			opacity: animateTo
-		}, duration, o.easing );
-		animateTo = 1 - animateTo;
-	}
-
-	elem.animate({
-		opacity: animateTo
-	}, duration, o.easing);
-
-	elem.queue(function() {
-		if ( hide ) {
-			elem.hide();
-		}
-		done();
-	});
-
-	// We just queued up "anims" animations, we need to put them next in the queue
-	if ( queuelen > 1 ) {
-		queue.splice.apply( queue,
-			[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
-	}
-	elem.dequeue();
-};
-
-})(jQuery);
-(function( $, undefined ) {
-
-$.effects.effect.puff = function( o, done ) {
-	var elem = $( this ),
-		mode = $.effects.setMode( elem, o.mode || "hide" ),
-		hide = mode === "hide",
-		percent = parseInt( o.percent, 10 ) || 150,
-		factor = percent / 100,
-		original = {
-			height: elem.height(),
-			width: elem.width(),
-			outerHeight: elem.outerHeight(),
-			outerWidth: elem.outerWidth()
-		};
-
-	$.extend( o, {
-		effect: "scale",
-		queue: false,
-		fade: true,
-		mode: mode,
-		complete: done,
-		percent: hide ? percent : 100,
-		from: hide ?
-			original :
-			{
-				height: original.height * factor,
-				width: original.width * factor,
-				outerHeight: original.outerHeight * factor,
-				outerWidth: original.outerWidth * factor
-			}
-	});
-
-	elem.effect( o );
-};
-
-$.effects.effect.scale = function( o, done ) {
-
-	// Create element
-	var el = $( this ),
-		options = $.extend( true, {}, o ),
-		mode = $.effects.setMode( el, o.mode || "effect" ),
-		percent = parseInt( o.percent, 10 ) ||
-			( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ),
-		direction = o.direction || "both",
-		origin = o.origin,
-		original = {
-			height: el.height(),
-			width: el.width(),
-			outerHeight: el.outerHeight(),
-			outerWidth: el.outerWidth()
-		},
-		factor = {
-			y: direction !== "horizontal" ? (percent / 100) : 1,
-			x: direction !== "vertical" ? (percent / 100) : 1
-		};
-
-	// We are going to pass this effect to the size effect:
-	options.effect = "size";
-	options.queue = false;
-	options.complete = done;
-
-	// Set default origin and restore for show/hide
-	if ( mode !== "effect" ) {
-		options.origin = origin || ["middle","center"];
-		options.restore = true;
-	}
-
-	options.from = o.from || ( mode === "show" ? {
-		height: 0,
-		width: 0,
-		outerHeight: 0,
-		outerWidth: 0
-	} : original );
-	options.to = {
-		height: original.height * factor.y,
-		width: original.width * factor.x,
-		outerHeight: original.outerHeight * factor.y,
-		outerWidth: original.outerWidth * factor.x
-	};
-
-	// Fade option to support puff
-	if ( options.fade ) {
-		if ( mode === "show" ) {
-			options.from.opacity = 0;
-			options.to.opacity = 1;
-		}
-		if ( mode === "hide" ) {
-			options.from.opacity = 1;
-			options.to.opacity = 0;
-		}
-	}
-
-	// Animate
-	el.effect( options );
-
-};
-
-$.effects.effect.size = function( o, done ) {
-
-	// Create element
-	var original, baseline, factor,
-		el = $( this ),
-		props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ],
-
-		// Always restore
-		props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ],
-
-		// Copy for children
-		props2 = [ "width", "height", "overflow" ],
-		cProps = [ "fontSize" ],
-		vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
-		hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
-
-		// Set options
-		mode = $.effects.setMode( el, o.mode || "effect" ),
-		restore = o.restore || mode !== "effect",
-		scale = o.scale || "both",
-		origin = o.origin || [ "middle", "center" ],
-		position = el.css( "position" ),
-		props = restore ? props0 : props1,
-		zero = {
-			height: 0,
-			width: 0,
-			outerHeight: 0,
-			outerWidth: 0
-		};
-
-	if ( mode === "show" ) {
-		el.show();
-	}
-	original = {
-		height: el.height(),
-		width: el.width(),
-		outerHeight: el.outerHeight(),
-		outerWidth: el.outerWidth()
-	};
-
-	if ( o.mode === "toggle" && mode === "show" ) {
-		el.from = o.to || zero;
-		el.to = o.from || original;
-	} else {
-		el.from = o.from || ( mode === "show" ? zero : original );
-		el.to = o.to || ( mode === "hide" ? zero : original );
-	}
-
-	// Set scaling factor
-	factor = {
-		from: {
-			y: el.from.height / original.height,
-			x: el.from.width / original.width
-		},
-		to: {
-			y: el.to.height / original.height,
-			x: el.to.width / original.width
-		}
-	};
-
-	// Scale the css box
-	if ( scale === "box" || scale === "both" ) {
-
-		// Vertical props scaling
-		if ( factor.from.y !== factor.to.y ) {
-			props = props.concat( vProps );
-			el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from );
-			el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to );
-		}
-
-		// Horizontal props scaling
-		if ( factor.from.x !== factor.to.x ) {
-			props = props.concat( hProps );
-			el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from );
-			el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to );
-		}
-	}
-
-	// Scale the content
-	if ( scale === "content" || scale === "both" ) {
-
-		// Vertical props scaling
-		if ( factor.from.y !== factor.to.y ) {
-			props = props.concat( cProps ).concat( props2 );
-			el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from );
-			el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to );
-		}
-	}
-
-	$.effects.save( el, props );
-	el.show();
-	$.effects.createWrapper( el );
-	el.css( "overflow", "hidden" ).css( el.from );
-
-	// Adjust
-	if (origin) { // Calculate baseline shifts
-		baseline = $.effects.getBaseline( origin, original );
-		el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y;
-		el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x;
-		el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y;
-		el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x;
-	}
-	el.css( el.from ); // set top & left
-
-	// Animate
-	if ( scale === "content" || scale === "both" ) { // Scale the children
-
-		// Add margins/font-size
-		vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps);
-		hProps = hProps.concat([ "marginLeft", "marginRight" ]);
-		props2 = props0.concat(vProps).concat(hProps);
-
-		el.find( "*[width]" ).each( function(){
-			var child = $( this ),
-				c_original = {
-					height: child.height(),
-					width: child.width(),
-					outerHeight: child.outerHeight(),
-					outerWidth: child.outerWidth()
-				};
-			if (restore) {
-				$.effects.save(child, props2);
-			}
-
-			child.from = {
-				height: c_original.height * factor.from.y,
-				width: c_original.width * factor.from.x,
-				outerHeight: c_original.outerHeight * factor.from.y,
-				outerWidth: c_original.outerWidth * factor.from.x
-			};
-			child.to = {
-				height: c_original.height * factor.to.y,
-				width: c_original.width * factor.to.x,
-				outerHeight: c_original.height * factor.to.y,
-				outerWidth: c_original.width * factor.to.x
-			};
-
-			// Vertical props scaling
-			if ( factor.from.y !== factor.to.y ) {
-				child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from );
-				child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to );
-			}
-
-			// Horizontal props scaling
-			if ( factor.from.x !== factor.to.x ) {
-				child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from );
-				child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to );
-			}
-
-			// Animate children
-			child.css( child.from );
-			child.animate( child.to, o.duration, o.easing, function() {
-
-				// Restore children
-				if ( restore ) {
-					$.effects.restore( child, props2 );
-				}
-			});
-		});
-	}
-
-	// Animate
-	el.animate( el.to, {
-		queue: false,
-		duration: o.duration,
-		easing: o.easing,
-		complete: function() {
-			if ( el.to.opacity === 0 ) {
-				el.css( "opacity", el.from.opacity );
-			}
-			if( mode === "hide" ) {
-				el.hide();
-			}
-			$.effects.restore( el, props );
-			if ( !restore ) {
-
-				// we need to calculate our new positioning based on the scaling
-				if ( position === "static" ) {
-					el.css({
-						position: "relative",
-						top: el.to.top,
-						left: el.to.left
-					});
-				} else {
-					$.each([ "top", "left" ], function( idx, pos ) {
-						el.css( pos, function( _, str ) {
-							var val = parseInt( str, 10 ),
-								toRef = idx ? el.to.left : el.to.top;
-
-							// if original was "auto", recalculate the new value from wrapper
-							if ( str === "auto" ) {
-								return toRef + "px";
-							}
-
-							return val + toRef + "px";
-						});
-					});
-				}
-			}
-
-			$.effects.removeWrapper( el );
-			done();
-		}
-	});
-
-};
-
-})(jQuery);
-(function( $, undefined ) {
-
-$.effects.effect.shake = function( o, done ) {
-
-	var el = $( this ),
-		props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
-		mode = $.effects.setMode( el, o.mode || "effect" ),
-		direction = o.direction || "left",
-		distance = o.distance || 20,
-		times = o.times || 3,
-		anims = times * 2 + 1,
-		speed = Math.round(o.duration/anims),
-		ref = (direction === "up" || direction === "down") ? "top" : "left",
-		positiveMotion = (direction === "up" || direction === "left"),
-		animation = {},
-		animation1 = {},
-		animation2 = {},
-		i,
-
-		// we will need to re-assemble the queue to stack our animations in place
-		queue = el.queue(),
-		queuelen = queue.length;
-
-	$.effects.save( el, props );
-	el.show();
-	$.effects.createWrapper( el );
-
-	// Animation
-	animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
-	animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
-	animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
-
-	// Animate
-	el.animate( animation, speed, o.easing );
-
-	// Shakes
-	for ( i = 1; i < times; i++ ) {
-		el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing );
-	}
-	el
-		.animate( animation1, speed, o.easing )
-		.animate( animation, speed / 2, o.easing )
-		.queue(function() {
-			if ( mode === "hide" ) {
-				el.hide();
-			}
-			$.effects.restore( el, props );
-			$.effects.removeWrapper( el );
-			done();
-		});
-
-	// inject all the animations we just queued to be first in line (after "inprogress")
-	if ( queuelen > 1) {
-		queue.splice.apply( queue,
-			[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
-	}
-	el.dequeue();
-
-};
-
-})(jQuery);
-(function( $, undefined ) {
-
-$.effects.effect.slide = function( o, done ) {
-
-	// Create element
-	var el = $( this ),
-		props = [ "position", "top", "bottom", "left", "right", "width", "height" ],
-		mode = $.effects.setMode( el, o.mode || "show" ),
-		show = mode === "show",
-		direction = o.direction || "left",
-		ref = (direction === "up" || direction === "down") ? "top" : "left",
-		positiveMotion = (direction === "up" || direction === "left"),
-		distance,
-		animation = {};
-
-	// Adjust
-	$.effects.save( el, props );
-	el.show();
-	distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true );
-
-	$.effects.createWrapper( el ).css({
-		overflow: "hidden"
-	});
-
-	if ( show ) {
-		el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance );
-	}
-
-	// Animation
-	animation[ ref ] = ( show ?
-		( positiveMotion ? "+=" : "-=") :
-		( positiveMotion ? "-=" : "+=")) +
-		distance;
-
-	// Animate
-	el.animate( animation, {
-		queue: false,
-		duration: o.duration,
-		easing: o.easing,
-		complete: function() {
-			if ( mode === "hide" ) {
-				el.hide();
-			}
-			$.effects.restore( el, props );
-			$.effects.removeWrapper( el );
-			done();
-		}
-	});
-};
-
-})(jQuery);
-(function( $, undefined ) {
-
-$.effects.effect.transfer = function( o, done ) {
-	var elem = $( this ),
-		target = $( o.to ),
-		targetFixed = target.css( "position" ) === "fixed",
-		body = $("body"),
-		fixTop = targetFixed ? body.scrollTop() : 0,
-		fixLeft = targetFixed ? body.scrollLeft() : 0,
-		endPosition = target.offset(),
-		animation = {
-			top: endPosition.top - fixTop ,
-			left: endPosition.left - fixLeft ,
-			height: target.innerHeight(),
-			width: target.innerWidth()
-		},
-		startPosition = elem.offset(),
-		transfer = $( '<div class="ui-effects-transfer"></div>' )
-			.appendTo( document.body )
-			.addClass( o.className )
-			.css({
-				top: startPosition.top - fixTop ,
-				left: startPosition.left - fixLeft ,
-				height: elem.innerHeight(),
-				width: elem.innerWidth(),
-				position: targetFixed ? "fixed" : "absolute"
-			})
-			.animate( animation, o.duration, o.easing, function() {
-				transfer.remove();
-				done();
-			});
-};
-
-})(jQuery);
diff --git a/servers/admin/public/javascripts/vendors/jquery-ui-1.9.2.custom.min.js b/servers/admin/public/javascripts/vendors/jquery-ui-1.9.2.custom.min.js
deleted file mode 100755
index ecc7b8c..0000000
--- a/servers/admin/public/javascripts/vendors/jquery-ui-1.9.2.custom.min.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/*! jQuery UI - v1.9.2 - 2013-01-03
-* http://jqueryui.com
-* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.sortable.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.menu.js, jquery.ui.progressbar.js, jquery.ui.slider.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js, jquery.ui.effect.js, jquery.ui.effect-blind.js, jquery.ui.effect-bounce.js, jquery.ui.effect-clip.js, jquery.ui.effect-drop.js, jquery.ui.effect-explode.js, jquery.ui.effect-fade.js, jquery.ui.effect-fold.js, jquery.ui.effect-highlight.js, jquery.ui.effect-pulsate.js, jquery.ui.effect-scale.js, jquery.ui.effect-shake.js, jquery.ui.effect-slide.js, jquery.ui.effect-transfer.js
-* Copyright (c) 2013 jQuery Foundation and other contributors Licensed MIT */
-
-(function(e,t){function i(t,n){var r,i,o,u=t.nodeName.toLowerCase();return"area"===u?(r=t.parentNode,i=r.name,!t.href||!i||r.nodeName.toLowerCase()!=="map"?!1:(o=e("img[usemap=#"+i+"]")[0],!!o&&s(o))):(/input|select|textarea|button|object/.test(u)?!t.disabled:"a"===u?t.href||n:n)&&s(t)}function s(t){return e.expr.filters.visible(t)&&!e(t).parents().andSelf().filter(function(){return e.css(this,"visibility")==="hidden"}).length}var n=0,r=/^ui-id-\d+$/;e.ui=e.ui||{};if(e.ui.version)return;e.extend(e.ui,{version:"1.9.2",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({_focus:e.fn.focus,focus:function(t,n){return typeof t=="number"?this.each(function(){var r=this;setTimeout(function(){e(r).focus(),n&&n.call(r)},t)}):this._focus.apply(this,arguments)},scrollParent:function(){var t;return e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?t=this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):t=this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(n){if(n!==t)return this.css("zIndex",n);if(this.length){var r=e(this[0]),i,s;while(r.length&&r[0]!==document){i=r.css("position");if(i==="absolute"||i==="relative"||i==="fixed"){s=parseInt(r.css("zIndex"),10);if(!isNaN(s)&&s!==0)return s}r=r.parent()}}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++n)})},removeUniqueId:function(){return this.each(function(){r.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(n){return!!e.data(n,t)}}):function(t,n,r){return!!e.data(t,r[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var n=e.attr(t,"tabindex"),r=isNaN(n);return(r||n>=0)&&i(t,!r)}}),e(function(){var t=document.body,n=t.appendChild(n=document.createElement("div"));n.offsetHeight,e.extend(n.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0}),e.support.minHeight=n.offsetHeight===100,e.support.selectstart="onselectstart"in n,t.removeChild(n).style.display="none"}),e("<a>").outerWidth(1).jquery||e.each(["Width","Height"],function(n,r){function u(t,n,r,s){return e.each(i,function(){n-=parseFloat(e.css(t,"padding"+this))||0,r&&(n-=parseFloat(e.css(t,"border"+this+"Width"))||0),s&&(n-=parseFloat(e.css(t,"margin"+this))||0)}),n}var i=r==="Width"?["Left","Right"]:["Top","Bottom"],s=r.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+r]=function(n){return n===t?o["inner"+r].call(this):this.each(function(){e(this).css(s,u(this,n)+"px")})},e.fn["outer"+r]=function(t,n){return typeof t!="number"?o["outer"+r].call(this,t):this.each(function(){e(this).css(s,u(this,t,!0,n)+"px")})}}),e("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(n){return arguments.length?t.call(this,e.camelCase(n)):t.call(this)}}(e.fn.removeData)),function(){var t=/msie ([\w.]+)/.exec(navigator.userAgent.toLowerCase())||[];e.ui.ie=t.length?!0:!1,e.ui.ie6=parseFloat(t[1],10)===6}(),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,n,r){var i,s=e.ui[t].prototype;for(i in r)s.plugins[i]=s.plugins[i]||[],s.plugins[i].push([n,r[i]])},call:function(e,t,n){var r,i=e.plugins[t];if(!i||!e.element[0].parentNode||e.element[0].parentNode.nodeType===11)return;for(r=0;r<i.length;r++)e.options[i[r][0]]&&i[r][1].apply(e.element,n)}},contains:e.contains,hasScroll:function(t,n){if(e(t).css("overflow")==="hidden")return!1;var r=n&&n==="left"?"scrollLeft":"scrollTop",i=!1;return t[r]>0?!0:(t[r]=1,i=t[r]>0,t[r]=0,i)},isOverAxis:function(e,t,n){return e>t&&e<t+n},isOver:function(t,n,r,i,s,o){return e.ui.isOverAxis(t,r,s)&&e.ui.isOverAxis(n,i,o)}})})(jQuery);(function(e,t){var n=0,r=Array.prototype.slice,i=e.cleanData;e.cleanData=function(t){for(var n=0,r;(r=t[n])!=null;n++)try{e(r).triggerHandler("remove")}catch(s){}i(t)},e.widget=function(t,n,r){var i,s,o,u,a=t.split(".")[0];t=t.split(".")[1],i=a+"-"+t,r||(r=n,n=e.Widget),e.expr[":"][i.toLowerCase()]=function(t){return!!e.data(t,i)},e[a]=e[a]||{},s=e[a][t],o=e[a][t]=function(e,t){if(!this._createWidget)return new o(e,t);arguments.length&&this._createWidget(e,t)},e.extend(o,s,{version:r.version,_proto:e.extend({},r),_childConstructors:[]}),u=new n,u.options=e.widget.extend({},u.options),e.each(r,function(t,i){e.isFunction(i)&&(r[t]=function(){var e=function(){return n.prototype[t].apply(this,arguments)},r=function(e){return n.prototype[t].apply(this,e)};return function(){var t=this._super,n=this._superApply,s;return this._super=e,this._superApply=r,s=i.apply(this,arguments),this._super=t,this._superApply=n,s}}())}),o.prototype=e.widget.extend(u,{widgetEventPrefix:s?u.widgetEventPrefix:t},r,{constructor:o,namespace:a,widgetName:t,widgetBaseClass:i,widgetFullName:i}),s?(e.each(s._childConstructors,function(t,n){var r=n.prototype;e.widget(r.namespace+"."+r.widgetName,o,n._proto)}),delete s._childConstructors):n._childConstructors.push(o),e.widget.bridge(t,o)},e.widget.extend=function(n){var i=r.call(arguments,1),s=0,o=i.length,u,a;for(;s<o;s++)for(u in i[s])a=i[s][u],i[s].hasOwnProperty(u)&&a!==t&&(e.isPlainObject(a)?n[u]=e.isPlainObject(n[u])?e.widget.extend({},n[u],a):e.widget.extend({},a):n[u]=a);return n},e.widget.bridge=function(n,i){var s=i.prototype.widgetFullName||n;e.fn[n]=function(o){var u=typeof o=="string",a=r.call(arguments,1),f=this;return o=!u&&a.length?e.widget.extend.apply(null,[o].concat(a)):o,u?this.each(function(){var r,i=e.data(this,s);if(!i)return e.error("cannot call methods on "+n+" prior to initialization; "+"attempted to call method '"+o+"'");if(!e.isFunction(i[o])||o.charAt(0)==="_")return e.error("no such method '"+o+"' for "+n+" widget instance");r=i[o].apply(i,a);if(r!==i&&r!==t)return f=r&&r.jquery?f.pushStack(r.get()):r,!1}):this.each(function(){var t=e.data(this,s);t?t.option(o||{})._init():e.data(this,s,new i(o,this))}),f}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(t,r){r=e(r||this.defaultElement||this)[0],this.element=e(r),this.uuid=n++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),r!==this&&(e.data(r,this.widgetName,this),e.data(r,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===r&&this.destroy()}}),this.document=e(r.style?r.ownerDocument:r.document||r),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(n,r){var i=n,s,o,u;if(arguments.length===0)return e.widget.extend({},this.options);if(typeof n=="string"){i={},s=n.split("."),n=s.shift();if(s.length){o=i[n]=e.widget.extend({},this.options[n]);for(u=0;u<s.length-1;u++)o[s[u]]=o[s[u]]||{},o=o[s[u]];n=s.pop();if(r===t)return o[n]===t?null:o[n];o[n]=r}else{if(r===t)return this.options[n]===t?null:this.options[n];i[n]=r}}return this._setOptions(i),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,e==="disabled"&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!t).attr("aria-disabled",t),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(t,n,r){var i,s=this;typeof t!="boolean"&&(r=n,n=t,t=!1),r?(n=i=e(n),this.bindings=this.bindings.add(n)):(r=n,n=this.element,i=this.widget()),e.each(r,function(r,o){function u(){if(!t&&(s.options.disabled===!0||e(this).hasClass("ui-state-disabled")))return;return(typeof o=="string"?s[o]:o).apply(s,arguments)}typeof o!="string"&&(u.guid=o.guid=o.guid||u.guid||e.guid++);var a=r.match(/^(\w+)\s*(.*)$/),f=a[1]+s.eventNamespace,l=a[2];l?i.delegate(l,f,u):n.bind(f,u)})},_off:function(e,t){t=(t||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(t).undelegate(t)},_delay:function(e,t){function n(){return(typeof e=="string"?r[e]:e).apply(r,arguments)}var r=this;return setTimeout(n,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,n,r){var i,s,o=this.options[t];r=r||{},n=e.Event(n),n.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),n.target=this.element[0],s=n.originalEvent;if(s)for(i in s)i in n||(n[i]=s[i]);return this.element.trigger(n,r),!(e.isFunction(o)&&o.apply(this.element[0],[n].concat(r))===!1||n.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,n){e.Widget.prototype["_"+t]=function(r,i,s){typeof i=="string"&&(i={effect:i});var o,u=i?i===!0||typeof i=="number"?n:i.effect||n:t;i=i||{},typeof i=="number"&&(i={duration:i}),o=!e.isEmptyObject(i),i.complete=s,i.delay&&r.delay(i.delay),o&&e.effects&&(e.effects.effect[u]||e.uiBackCompat!==!1&&e.effects[u])?r[t](i):u!==t&&r[u]?r[u](i.duration,i.easing,s):r.queue(function(n){e(this)[t](),s&&s.call(r[0]),n()})}}),e.uiBackCompat!==!1&&(e.Widget.prototype._getCreateOptions=function(){return e.metadata&&e.metadata.get(this.element[0])[this.widgetName]})})(jQuery);(function(e,t){var n=!1;e(document).mouseup(function(e){n=!1}),e.widget("ui.mouse",{version:"1.9.2",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(n){if(!0===e.data(n.target,t.widgetName+".preventClickEvent"))return e.removeData(n.target,t.widgetName+".preventClickEvent"),n.stopImmediatePropagation(),!1}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(t){if(n)return;this._mouseStarted&&this._mouseUp(t),this._mouseDownEvent=t;var r=this,i=t.which===1,s=typeof this.options.cancel=="string"&&t.target.nodeName?e(t.target).closest(this.options.cancel).length:!1;if(!i||s||!this._mouseCapture(t))return!0;this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){r.mouseDelayMet=!0},this.options.delay));if(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)){this._mouseStarted=this._mouseStart(t)!==!1;if(!this._mouseStarted)return t.preventDefault(),!0}return!0===e.data(t.target,this.widgetName+".preventClickEvent")&&e.removeData(t.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return r._mouseMove(e)},this._mouseUpDelegate=function(e){return r._mouseUp(e)},e(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),t.preventDefault(),n=!0,!0},_mouseMove:function(t){return!e.ui.ie||document.documentMode>=9||!!t.button?this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted):this._mouseUp(t)},_mouseUp:function(t){return e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(e){return this.mouseDelayMet},_mouseStart:function(e){},_mouseDrag:function(e){},_mouseStop:function(e){},_mouseCapture:function(e){return!0}})})(jQuery);(function(e,t){function h(e,t,n){return[parseInt(e[0],10)*(l.test(e[0])?t/100:1),parseInt(e[1],10)*(l.test(e[1])?n/100:1)]}function p(t,n){return parseInt(e.css(t,n),10)||0}e.ui=e.ui||{};var n,r=Math.max,i=Math.abs,s=Math.round,o=/left|center|right/,u=/top|center|bottom/,a=/[\+\-]\d+%?/,f=/^\w+/,l=/%$/,c=e.fn.position;e.position={scrollbarWidth:function(){if(n!==t)return n;var r,i,s=e("<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>"),o=s.children()[0];return e("body").append(s),r=o.offsetWidth,s.css("overflow","scroll"),i=o.offsetWidth,r===i&&(i=s[0].clientWidth),s.remove(),n=r-i},getScrollInfo:function(t){var n=t.isWindow?"":t.element.css("overflow-x"),r=t.isWindow?"":t.element.css("overflow-y"),i=n==="scroll"||n==="auto"&&t.width<t.element[0].scrollWidth,s=r==="scroll"||r==="auto"&&t.height<t.element[0].scrollHeight;return{width:i?e.position.scrollbarWidth():0,height:s?e.position.scrollbarWidth():0}},getWithinInfo:function(t){var n=e(t||window),r=e.isWindow(n[0]);return{element:n,isWindow:r,offset:n.offset()||{left:0,top:0},scrollLeft:n.scrollLeft(),scrollTop:n.scrollTop(),width:r?n.width():n.outerWidth(),height:r?n.height():n.outerHeight()}}},e.fn.position=function(t){if(!t||!t.of)return c.apply(this,arguments);t=e.extend({},t);var n,l,d,v,m,g=e(t.of),y=e.position.getWithinInfo(t.within),b=e.position.getScrollInfo(y),w=g[0],E=(t.collision||"flip").split(" "),S={};return w.nodeType===9?(l=g.width(),d=g.height(),v={top:0,left:0}):e.isWindow(w)?(l=g.width(),d=g.height(),v={top:g.scrollTop(),left:g.scrollLeft()}):w.preventDefault?(t.at="left top",l=d=0,v={top:w.pageY,left:w.pageX}):(l=g.outerWidth(),d=g.outerHeight(),v=g.offset()),m=e.extend({},v),e.each(["my","at"],function(){var e=(t[this]||"").split(" "),n,r;e.length===1&&(e=o.test(e[0])?e.concat(["center"]):u.test(e[0])?["center"].concat(e):["center","center"]),e[0]=o.test(e[0])?e[0]:"center",e[1]=u.test(e[1])?e[1]:"center",n=a.exec(e[0]),r=a.exec(e[1]),S[this]=[n?n[0]:0,r?r[0]:0],t[this]=[f.exec(e[0])[0],f.exec(e[1])[0]]}),E.length===1&&(E[1]=E[0]),t.at[0]==="right"?m.left+=l:t.at[0]==="center"&&(m.left+=l/2),t.at[1]==="bottom"?m.top+=d:t.at[1]==="center"&&(m.top+=d/2),n=h(S.at,l,d),m.left+=n[0],m.top+=n[1],this.each(function(){var o,u,a=e(this),f=a.outerWidth(),c=a.outerHeight(),w=p(this,"marginLeft"),x=p(this,"marginTop"),T=f+w+p(this,"marginRight")+b.width,N=c+x+p(this,"marginBottom")+b.height,C=e.extend({},m),k=h(S.my,a.outerWidth(),a.outerHeight());t.my[0]==="right"?C.left-=f:t.my[0]==="center"&&(C.left-=f/2),t.my[1]==="bottom"?C.top-=c:t.my[1]==="center"&&(C.top-=c/2),C.left+=k[0],C.top+=k[1],e.support.offsetFractions||(C.left=s(C.left),C.top=s(C.top)),o={marginLeft:w,marginTop:x},e.each(["left","top"],function(r,i){e.ui.position[E[r]]&&e.ui.position[E[r]][i](C,{targetWidth:l,targetHeight:d,elemWidth:f,elemHeight:c,collisionPosition:o,collisionWidth:T,collisionHeight:N,offset:[n[0]+k[0],n[1]+k[1]],my:t.my,at:t.at,within:y,elem:a})}),e.fn.bgiframe&&a.bgiframe(),t.using&&(u=function(e){var n=v.left-C.left,s=n+l-f,o=v.top-C.top,u=o+d-c,h={target:{element:g,left:v.left,top:v.top,width:l,height:d},element:{element:a,left:C.left,top:C.top,width:f,height:c},horizontal:s<0?"left":n>0?"right":"center",vertical:u<0?"top":o>0?"bottom":"middle"};l<f&&i(n+s)<l&&(h.horizontal="center"),d<c&&i(o+u)<d&&(h.vertical="middle"),r(i(n),i(s))>r(i(o),i(u))?h.important="horizontal":h.important="vertical",t.using.call(this,e,h)}),a.offset(e.extend(C,{using:u}))})},e.ui.position={fit:{left:function(e,t){var n=t.within,i=n.isWindow?n.scrollLeft:n.offset.left,s=n.width,o=e.left-t.collisionPosition.marginLeft,u=i-o,a=o+t.collisionWidth-s-i,f;t.collisionWidth>s?u>0&&a<=0?(f=e.left+u+t.collisionWidth-s-i,e.left+=u-f):a>0&&u<=0?e.left=i:u>a?e.left=i+s-t.collisionWidth:e.left=i:u>0?e.left+=u:a>0?e.left-=a:e.left=r(e.left-o,e.left)},top:function(e,t){var n=t.within,i=n.isWindow?n.scrollTop:n.offset.top,s=t.within.height,o=e.top-t.collisionPosition.marginTop,u=i-o,a=o+t.collisionHeight-s-i,f;t.collisionHeight>s?u>0&&a<=0?(f=e.top+u+t.collisionHeight-s-i,e.top+=u-f):a>0&&u<=0?e.top=i:u>a?e.top=i+s-t.collisionHeight:e.top=i:u>0?e.top+=u:a>0?e.top-=a:e.top=r(e.top-o,e.top)}},flip:{left:function(e,t){var n=t.within,r=n.offset.left+n.scrollLeft,s=n.width,o=n.isWindow?n.scrollLeft:n.offset.left,u=e.left-t.collisionPosition.marginLeft,a=u-o,f=u+t.collisionWidth-s-o,l=t.my[0]==="left"?-t.elemWidth:t.my[0]==="right"?t.elemWidth:0,c=t.at[0]==="left"?t.targetWidth:t.at[0]==="right"?-t.targetWidth:0,h=-2*t.offset[0],p,d;if(a<0){p=e.left+l+c+h+t.collisionWidth-s-r;if(p<0||p<i(a))e.left+=l+c+h}else if(f>0){d=e.left-t.collisionPosition.marginLeft+l+c+h-o;if(d>0||i(d)<f)e.left+=l+c+h}},top:function(e,t){var n=t.within,r=n.offset.top+n.scrollTop,s=n.height,o=n.isWindow?n.scrollTop:n.offset.top,u=e.top-t.collisionPosition.marginTop,a=u-o,f=u+t.collisionHeight-s-o,l=t.my[1]==="top",c=l?-t.elemHeight:t.my[1]==="bottom"?t.elemHeight:0,h=t.at[1]==="top"?t.targetHeight:t.at[1]==="bottom"?-t.targetHeight:0,p=-2*t.offset[1],d,v;a<0?(v=e.top+c+h+p+t.collisionHeight-s-r,e.top+c+h+p>a&&(v<0||v<i(a))&&(e.top+=c+h+p)):f>0&&(d=e.top-t.collisionPosition.marginTop+c+h+p-o,e.top+c+h+p>f&&(d>0||i(d)<f)&&(e.top+=c+h+p))}},flipfit:{left:function(){e.ui.position.flip.left.apply(this,arguments),e.ui.position.fit.left.apply(this,arguments)},top:function(){e.ui.position.flip.top.apply(this,arguments),e.ui.position.fit.top.apply(this,arguments)}}},function(){var t,n,r,i,s,o=document.getElementsByTagName("body")[0],u=document.createElement("div");t=document.createElement(o?"div":"body"),r={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},o&&e.extend(r,{position:"absolute",left:"-1000px",top:"-1000px"});for(s in r)t.style[s]=r[s];t.appendChild(u),n=o||document.documentElement,n.insertBefore(t,n.firstChild),u.style.cssText="position: absolute; left: 10.7432222px;",i=e(u).offset().left,e.support.offsetFractions=i>10&&i<11,t.innerHTML="",n.removeChild(t)}(),e.uiBackCompat!==!1&&function(e){var n=e.fn.position;e.fn.position=function(r){if(!r||!r.offset)return n.call(this,r);var i=r.offset.split(" "),s=r.at.split(" ");return i.length===1&&(i[1]=i[0]),/^\d/.test(i[0])&&(i[0]="+"+i[0]),/^\d/.test(i[1])&&(i[1]="+"+i[1]),s.length===1&&(/left|center|right/.test(s[0])?s[1]="center":(s[1]=s[0],s[0]="center")),n.call(this,e.extend(r,{at:s[0]+i[0]+" "+s[1]+i[1],offset:t}))}}(jQuery)})(jQuery);(function(e,t){e.widget("ui.draggable",e.ui.mouse,{version:"1.9.2",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1},_create:function(){this.options.helper=="original"&&!/^(?:r|a|f)/.test(this.element.css("position"))&&(this.element[0].style.position="relative"),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._mouseInit()},_destroy:function(){this.element.removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._mouseDestroy()},_mouseCapture:function(t){var n=this.options;return this.helper||n.disabled||e(t.target).is(".ui-resizable-handle")?!1:(this.handle=this._getHandle(t),this.handle?(e(n.iframeFix===!0?"iframe":n.iframeFix).each(function(){e('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(e(this).offset()).appendTo("body")}),!0):!1)},_mouseStart:function(t){var n=this.options;return this.helper=this._createHelper(t),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),e.ui.ddmanager&&(e.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,n.cursorAt&&this._adjustOffsetFromHelper(n.cursorAt),n.containment&&this._setContainment(),this._trigger("start",t)===!1?(this._clear(),!1):(this._cacheHelperProportions(),e.ui.ddmanager&&!n.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this._mouseDrag(t,!0),e.ui.ddmanager&&e.ui.ddmanager.dragStart(this,t),!0)},_mouseDrag:function(t,n){this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute");if(!n){var r=this._uiHash();if(this._trigger("drag",t,r)===!1)return this._mouseUp({}),!1;this.position=r.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";return e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),!1},_mouseStop:function(t){var n=!1;e.ui.ddmanager&&!this.options.dropBehaviour&&(n=e.ui.ddmanager.drop(this,t)),this.dropped&&(n=this.dropped,this.dropped=!1);var r=this.element[0],i=!1;while(r&&(r=r.parentNode))r==document&&(i=!0);if(!i&&this.options.helper==="original")return!1;if(this.options.revert=="invalid"&&!n||this.options.revert=="valid"&&n||this.options.revert===!0||e.isFunction(this.options.revert)&&this.options.revert.call(this.element,n)){var s=this;e(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){s._trigger("stop",t)!==!1&&s._clear()})}else this._trigger("stop",t)!==!1&&this._clear();return!1},_mouseUp:function(t){return e("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),e.ui.ddmanager&&e.ui.ddmanager.dragStop(this,t),e.ui.mouse.prototype._mouseUp.call(this,t)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(t){var n=!this.options.handle||!e(this.options.handle,this.element).length?!0:!1;return e(this.options.handle,this.element).find("*").andSelf().each(function(){this==t.target&&(n=!0)}),n},_createHelper:function(t){var n=this.options,r=e.isFunction(n.helper)?e(n.helper.apply(this.element[0],[t])):n.helper=="clone"?this.element.clone().removeAttr("id"):this.element;return r.parents("body").length||r.appendTo(n.appendTo=="parent"?this.element[0].parentNode:n.appendTo),r[0]!=this.element[0]&&!/(fixed|absolute)/.test(r.css("position"))&&r.css("position","absolute"),r},_adjustOffsetFromHelper:function(t){typeof t=="string"&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var t=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&e.ui.ie)t={top:0,left:0};return{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var e=this.element.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t=this.options;t.containment=="parent"&&(t.containment=this.helper[0].parentNode);if(t.containment=="document"||t.containment=="window")this.containment=[t.containment=="document"?0:e(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,t.containment=="document"?0:e(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,(t.containment=="document"?0:e(window).scrollLeft())+e(t.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(t.containment=="document"?0:e(window).scrollTop())+(e(t.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(t.containment)&&t.containment.constructor!=Array){var n=e(t.containment),r=n[0];if(!r)return;var i=n.offset(),s=e(r).css("overflow")!="hidden";this.containment=[(parseInt(e(r).css("borderLeftWidth"),10)||0)+(parseInt(e(r).css("paddingLeft"),10)||0),(parseInt(e(r).css("borderTopWidth"),10)||0)+(parseInt(e(r).css("paddingTop"),10)||0),(s?Math.max(r.scrollWidth,r.offsetWidth):r.offsetWidth)-(parseInt(e(r).css("borderLeftWidth"),10)||0)-(parseInt(e(r).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(s?Math.max(r.scrollHeight,r.offsetHeight):r.offsetHeight)-(parseInt(e(r).css("borderTopWidth"),10)||0)-(parseInt(e(r).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=n}else t.containment.constructor==Array&&(this.containment=t.containment)},_convertPositionTo:function(t,n){n||(n=this.position);var r=t=="absolute"?1:-1,i=this.options,s=this.cssPosition!="absolute"||this.scrollParent[0]!=document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,o=/(html|body)/i.test(s[0].tagName);return{top:n.top+this.offset.relative.top*r+this.offset.parent.top*r-(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():o?0:s.scrollTop())*r,left:n.left+this.offset.relative.left*r+this.offset.parent.left*r-(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():o?0:s.scrollLeft())*r}},_generatePosition:function(t){var n=this.options,r=this.cssPosition!="absolute"||this.scrollParent[0]!=document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,i=/(html|body)/i.test(r[0].tagName),s=t.pageX,o=t.pageY;if(this.originalPosition){var u;if(this.containment){if(this.relative_container){var a=this.relative_container.offset();u=[this.containment[0]+a.left,this.containment[1]+a.top,this.containment[2]+a.left,this.containment[3]+a.top]}else u=this.containment;t.pageX-this.offset.click.left<u[0]&&(s=u[0]+this.offset.click.left),t.pageY-this.offset.click.top<u[1]&&(o=u[1]+this.offset.click.top),t.pageX-this.offset.click.left>u[2]&&(s=u[2]+this.offset.click.left),t.pageY-this.offset.click.top>u[3]&&(o=u[3]+this.offset.click.top)}if(n.grid){var f=n.grid[1]?this.originalPageY+Math.round((o-this.originalPageY)/n.grid[1])*n.grid[1]:this.originalPageY;o=u?f-this.offset.click.top<u[1]||f-this.offset.click.top>u[3]?f-this.offset.click.top<u[1]?f+n.grid[1]:f-n.grid[1]:f:f;var l=n.grid[0]?this.originalPageX+Math.round((s-this.originalPageX)/n.grid[0])*n.grid[0]:this.originalPageX;s=u?l-this.offset.click.left<u[0]||l-this.offset.click.left>u[2]?l-this.offset.click.left<u[0]?l+n.grid[0]:l-n.grid[0]:l:l}}return{top:o-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():i?0:r.scrollTop()),left:s-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():i?0:r.scrollLeft())}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]!=this.element[0]&&!this.cancelHelperRemoval&&this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1},_trigger:function(t,n,r){return r=r||this._uiHash(),e.ui.plugin.call(this,t,[n,r]),t=="drag"&&(this.positionAbs=this._convertPositionTo("absolute")),e.Widget.prototype._trigger.call(this,t,n,r)},plugins:{},_uiHash:function(e){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),e.ui.plugin.add("draggable","connectToSortable",{start:function(t,n){var r=e(this).data("draggable"),i=r.options,s=e.extend({},n,{item:r.element});r.sortables=[],e(i.connectToSortable).each(function(){var n=e.data(this,"sortable");n&&!n.options.disabled&&(r.sortables.push({instance:n,shouldRevert:n.options.revert}),n.refreshPositions(),n._trigger("activate",t,s))})},stop:function(t,n){var r=e(this).data("draggable"),i=e.extend({},n,{item:r.element});e.each(r.sortables,function(){this.instance.isOver?(this.instance.isOver=0,r.cancelHelperRemoval=!0,this.instance.cancelHelperRemoval=!1,this.shouldRevert&&(this.instance.options.revert=!0),this.instance._mouseStop(t),this.instance.options.helper=this.instance.options._helper,r.options.helper=="original"&&this.instance.currentItem.css({top:"auto",left:"auto"})):(this.instance.cancelHelperRemoval=!1,this.instance._trigger("deactivate",t,i))})},drag:function(t,n){var r=e(this).data("draggable"),i=this,s=function(t){var n=this.offset.click.top,r=this.offset.click.left,i=this.positionAbs.top,s=this.positionAbs.left,o=t.height,u=t.width,a=t.top,f=t.left;return e.ui.isOver(i+n,s+r,a,f,o,u)};e.each(r.sortables,function(s){var o=!1,u=this;this.instance.positionAbs=r.positionAbs,this.instance.helperProportions=r.helperProportions,this.instance.offset.click=r.offset.click,this.instance._intersectsWith(this.instance.containerCache)&&(o=!0,e.each(r.sortables,function(){return this.instance.positionAbs=r.positionAbs,this.instance.helperProportions=r.helperProportions,this.instance.offset.click=r.offset.click,this!=u&&this.instance._intersectsWith(this.instance.containerCache)&&e.ui.contains(u.instance.element[0],this.instance.element[0])&&(o=!1),o})),o?(this.instance.isOver||(this.instance.isOver=1,this.instance.currentItem=e(i).clone().removeAttr("id").appendTo(this.instance.element).data("sortable-item",!0),this.instance.options._helper=this.instance.options.helper,this.instance.options.helper=function(){return n.helper[0]},t.target=this.instance.currentItem[0],this.instance._mouseCapture(t,!0),this.instance._mouseStart(t,!0,!0),this.instance.offset.click.top=r.offset.click.top,this.instance.offset.click.left=r.offset.click.left,this.instance.offset.parent.left-=r.offset.parent.left-this.instance.offset.parent.left,this.instance.offset.parent.top-=r.offset.parent.top-this.instance.offset.parent.top,r._trigger("toSortable",t),r.dropped=this.instance.element,r.currentItem=r.element,this.instance.fromOutside=r),this.instance.currentItem&&this.instance._mouseDrag(t)):this.instance.isOver&&(this.instance.isOver=0,this.instance.cancelHelperRemoval=!0,this.instance.options.revert=!1,this.instance._trigger("out",t,this.instance._uiHash(this.instance)),this.instance._mouseStop(t,!0),this.instance.options.helper=this.instance.options._helper,this.instance.currentItem.remove(),this.instance.placeholder&&this.instance.placeholder.remove(),r._trigger("fromSortable",t),r.dropped=!1)})}}),e.ui.plugin.add("draggable","cursor",{start:function(t,n){var r=e("body"),i=e(this).data("draggable").options;r.css("cursor")&&(i._cursor=r.css("cursor")),r.css("cursor",i.cursor)},stop:function(t,n){var r=e(this).data("draggable").options;r._cursor&&e("body").css("cursor",r._cursor)}}),e.ui.plugin.add("draggable","opacity",{start:function(t,n){var r=e(n.helper),i=e(this).data("draggable").options;r.css("opacity")&&(i._opacity=r.css("opacity")),r.css("opacity",i.opacity)},stop:function(t,n){var r=e(this).data("draggable").options;r._opacity&&e(n.helper).css("opacity",r._opacity)}}),e.ui.plugin.add("draggable","scroll",{start:function(t,n){var r=e(this).data("draggable");r.scrollParent[0]!=document&&r.scrollParent[0].tagName!="HTML"&&(r.overflowOffset=r.scrollParent.offset())},drag:function(t,n){var r=e(this).data("draggable"),i=r.options,s=!1;if(r.scrollParent[0]!=document&&r.scrollParent[0].tagName!="HTML"){if(!i.axis||i.axis!="x")r.overflowOffset.top+r.scrollParent[0].offsetHeight-t.pageY<i.scrollSensitivity?r.scrollParent[0].scrollTop=s=r.scrollParent[0].scrollTop+i.scrollSpeed:t.pageY-r.overflowOffset.top<i.scrollSensitivity&&(r.scrollParent[0].scrollTop=s=r.scrollParent[0].scrollTop-i.scrollSpeed);if(!i.axis||i.axis!="y")r.overflowOffset.left+r.scrollParent[0].offsetWidth-t.pageX<i.scrollSensitivity?r.scrollParent[0].scrollLeft=s=r.scrollParent[0].scrollLeft+i.scrollSpeed:t.pageX-r.overflowOffset.left<i.scrollSensitivity&&(r.scrollParent[0].scrollLeft=s=r.scrollParent[0].scrollLeft-i.scrollSpeed)}else{if(!i.axis||i.axis!="x")t.pageY-e(document).scrollTop()<i.scrollSensitivity?s=e(document).scrollTop(e(document).scrollTop()-i.scrollSpeed):e(window).height()-(t.pageY-e(document).scrollTop())<i.scrollSensitivity&&(s=e(document).scrollTop(e(document).scrollTop()+i.scrollSpeed));if(!i.axis||i.axis!="y")t.pageX-e(document).scrollLeft()<i.scrollSensitivity?s=e(document).scrollLeft(e(document).scrollLeft()-i.scrollSpeed):e(window).width()-(t.pageX-e(document).scrollLeft())<i.scrollSensitivity&&(s=e(document).scrollLeft(e(document).scrollLeft()+i.scrollSpeed))}s!==!1&&e.ui.ddmanager&&!i.dropBehaviour&&e.ui.ddmanager.prepareOffsets(r,t)}}),e.ui.plugin.add("draggable","snap",{start:function(t,n){var r=e(this).data("draggable"),i=r.options;r.snapElements=[],e(i.snap.constructor!=String?i.snap.items||":data(draggable)":i.snap).each(function(){var t=e(this),n=t.offset();this!=r.element[0]&&r.snapElements.push({item:this,width:t.outerWidth(),height:t.outerHeight(),top:n.top,left:n.left})})},drag:function(t,n){var r=e(this).data("draggable"),i=r.options,s=i.snapTolerance,o=n.offset.left,u=o+r.helperProportions.width,a=n.offset.top,f=a+r.helperProportions.height;for(var l=r.snapElements.length-1;l>=0;l--){var c=r.snapElements[l].left,h=c+r.snapElements[l].width,p=r.snapElements[l].top,d=p+r.snapElements[l].height;if(!(c-s<o&&o<h+s&&p-s<a&&a<d+s||c-s<o&&o<h+s&&p-s<f&&f<d+s||c-s<u&&u<h+s&&p-s<a&&a<d+s||c-s<u&&u<h+s&&p-s<f&&f<d+s)){r.snapElements[l].snapping&&r.options.snap.release&&r.options.snap.release.call(r.element,t,e.extend(r._uiHash(),{snapItem:r.snapElements[l].item})),r.snapElements[l].snapping=!1;continue}if(i.snapMode!="inner"){var v=Math.abs(p-f)<=s,m=Math.abs(d-a)<=s,g=Math.abs(c-u)<=s,y=Math.abs(h-o)<=s;v&&(n.position.top=r._convertPositionTo("relative",{top:p-r.helperProportions.height,left:0}).top-r.margins.top),m&&(n.position.top=r._convertPositionTo("relative",{top:d,left:0}).top-r.margins.top),g&&(n.position.left=r._convertPositionTo("relative",{top:0,left:c-r.helperProportions.width}).left-r.margins.left),y&&(n.position.left=r._convertPositionTo("relative",{top:0,left:h}).left-r.margins.left)}var b=v||m||g||y;if(i.snapMode!="outer"){var v=Math.abs(p-a)<=s,m=Math.abs(d-f)<=s,g=Math.abs(c-o)<=s,y=Math.abs(h-u)<=s;v&&(n.position.top=r._convertPositionTo("relative",{top:p,left:0}).top-r.margins.top),m&&(n.position.top=r._convertPositionTo("relative",{top:d-r.helperProportions.height,left:0}).top-r.margins.top),g&&(n.position.left=r._convertPositionTo("relative",{top:0,left:c}).left-r.margins.left),y&&(n.position.left=r._convertPositionTo("relative",{top:0,left:h-r.helperProportions.width}).left-r.margins.left)}!r.snapElements[l].snapping&&(v||m||g||y||b)&&r.options.snap.snap&&r.options.snap.snap.call(r.element,t,e.extend(r._uiHash(),{snapItem:r.snapElements[l].item})),r.snapElements[l].snapping=v||m||g||y||b}}}),e.ui.plugin.add("draggable","stack",{start:function(t,n){var r=e(this).data("draggable").options,i=e.makeArray(e(r.stack)).sort(function(t,n){return(parseInt(e(t).css("zIndex"),10)||0)-(parseInt(e(n).css("zIndex"),10)||0)});if(!i.length)return;var s=parseInt(i[0].style.zIndex)||0;e(i).each(function(e){this.style.zIndex=s+e}),this[0].style.zIndex=s+i.length}}),e.ui.plugin.add("draggable","zIndex",{start:function(t,n){var r=e(n.helper),i=e(this).data("draggable").options;r.css("zIndex")&&(i._zIndex=r.css("zIndex")),r.css("zIndex",i.zIndex)},stop:function(t,n){var r=e(this).data("draggable").options;r._zIndex&&e(n.helper).css("zIndex",r._zIndex)}})})(jQuery);(function(e,t){e.widget("ui.droppable",{version:"1.9.2",widgetEventPrefix:"drop",options:{accept:"*",activeClass:!1,addClasses:!0,greedy:!1,hoverClass:!1,scope:"default",tolerance:"intersect"},_create:function(){var t=this.options,n=t.accept;this.isover=0,this.isout=1,this.accept=e.isFunction(n)?n:function(e){return e.is(n)},this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight},e.ui.ddmanager.droppables[t.scope]=e.ui.ddmanager.droppables[t.scope]||[],e.ui.ddmanager.droppables[t.scope].push(this),t.addClasses&&this.element.addClass("ui-droppable")},_destroy:function(){var t=e.ui.ddmanager.droppables[this.options.scope];for(var n=0;n<t.length;n++)t[n]==this&&t.splice(n,1);this.element.removeClass("ui-droppable ui-droppable-disabled")},_setOption:function(t,n){t=="accept"&&(this.accept=e.isFunction(n)?n:function(e){return e.is(n)}),e.Widget.prototype._setOption.apply(this,arguments)},_activate:function(t){var n=e.ui.ddmanager.current;this.options.activeClass&&this.element.addClass(this.options.activeClass),n&&this._trigger("activate",t,this.ui(n))},_deactivate:function(t){var n=e.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass),n&&this._trigger("deactivate",t,this.ui(n))},_over:function(t){var n=e.ui.ddmanager.current;if(!n||(n.currentItem||n.element)[0]==this.element[0])return;this.accept.call(this.element[0],n.currentItem||n.element)&&(this.options.hoverClass&&this.element.addClass(this.options.hoverClass),this._trigger("over",t,this.ui(n)))},_out:function(t){var n=e.ui.ddmanager.current;if(!n||(n.currentItem||n.element)[0]==this.element[0])return;this.accept.call(this.element[0],n.currentItem||n.element)&&(this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("out",t,this.ui(n)))},_drop:function(t,n){var r=n||e.ui.ddmanager.current;if(!r||(r.currentItem||r.element)[0]==this.element[0])return!1;var i=!1;return this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function(){var t=e.data(this,"droppable");if(t.options.greedy&&!t.options.disabled&&t.options.scope==r.options.scope&&t.accept.call(t.element[0],r.currentItem||r.element)&&e.ui.intersect(r,e.extend(t,{offset:t.element.offset()}),t.options.tolerance))return i=!0,!1}),i?!1:this.accept.call(this.element[0],r.currentItem||r.element)?(this.options.activeClass&&this.element.removeClass(this.options.activeClass),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("drop",t,this.ui(r)),this.element):!1},ui:function(e){return{draggable:e.currentItem||e.element,helper:e.helper,position:e.position,offset:e.positionAbs}}}),e.ui.intersect=function(t,n,r){if(!n.offset)return!1;var i=(t.positionAbs||t.position.absolute).left,s=i+t.helperProportions.width,o=(t.positionAbs||t.position.absolute).top,u=o+t.helperProportions.height,a=n.offset.left,f=a+n.proportions.width,l=n.offset.top,c=l+n.proportions.height;switch(r){case"fit":return a<=i&&s<=f&&l<=o&&u<=c;case"intersect":return a<i+t.helperProportions.width/2&&s-t.helperProportions.width/2<f&&l<o+t.helperProportions.height/2&&u-t.helperProportions.height/2<c;case"pointer":var h=(t.positionAbs||t.position.absolute).left+(t.clickOffset||t.offset.click).left,p=(t.positionAbs||t.position.absolute).top+(t.clickOffset||t.offset.click).top,d=e.ui.isOver(p,h,l,a,n.proportions.height,n.proportions.width);return d;case"touch":return(o>=l&&o<=c||u>=l&&u<=c||o<l&&u>c)&&(i>=a&&i<=f||s>=a&&s<=f||i<a&&s>f);default:return!1}},e.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(t,n){var r=e.ui.ddmanager.droppables[t.options.scope]||[],i=n?n.type:null,s=(t.currentItem||t.element).find(":data(droppable)").andSelf();e:for(var o=0;o<r.length;o++){if(r[o].options.disabled||t&&!r[o].accept.call(r[o].element[0],t.currentItem||t.element))continue;for(var u=0;u<s.length;u++)if(s[u]==r[o].element[0]){r[o].proportions.height=0;continue e}r[o].visible=r[o].element.css("display")!="none";if(!r[o].visible)continue;i=="mousedown"&&r[o]._activate.call(r[o],n),r[o].offset=r[o].element.offset(),r[o].proportions={width:r[o].element[0].offsetWidth,height:r[o].element[0].offsetHeight}}},drop:function(t,n){var r=!1;return e.each(e.ui.ddmanager.droppables[t.options.scope]||[],function(){if(!this.options)return;!this.options.disabled&&this.visible&&e.ui.intersect(t,this,this.options.tolerance)&&(r=this._drop.call(this,n)||r),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],t.currentItem||t.element)&&(this.isout=1,this.isover=0,this._deactivate.call(this,n))}),r},dragStart:function(t,n){t.element.parentsUntil("body").bind("scroll.droppable",function(){t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,n)})},drag:function(t,n){t.options.refreshPositions&&e.ui.ddmanager.prepareOffsets(t,n),e.each(e.ui.ddmanager.droppables[t.options.scope]||[],function(){if(this.options.disabled||this.greedyChild||!this.visible)return;var r=e.ui.intersect(t,this,this.options.tolerance),i=!r&&this.isover==1?"isout":r&&this.isover==0?"isover":null;if(!i)return;var s;if(this.options.greedy){var o=this.options.scope,u=this.element.parents(":data(droppable)").filter(function(){return e.data(this,"droppable").options.scope===o});u.length&&(s=e.data(u[0],"droppable"),s.greedyChild=i=="isover"?1:0)}s&&i=="isover"&&(s.isover=0,s.isout=1,s._out.call(s,n)),this[i]=1,this[i=="isout"?"isover":"isout"]=0,this[i=="isover"?"_over":"_out"].call(this,n),s&&i=="isout"&&(s.isout=0,s.isover=1,s._over.call(s,n))})},dragStop:function(t,n){t.element.parentsUntil("body").unbind("scroll.droppable"),t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,n)}}})(jQuery);(function(e,t){e.widget("ui.resizable",e.ui.mouse,{version:"1.9.2",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1e3},_create:function(){var t=this,n=this.options;this.element.addClass("ui-resizable"),e.extend(this,{_aspectRatio:!!n.aspectRatio,aspectRatio:n.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:n.helper||n.ghost||n.animate?n.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(e('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("resizable",this.element.data("resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=n.handles||(e(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se");if(this.handles.constructor==String){this.handles=="all"&&(this.handles="n,e,s,w,se,sw,ne,nw");var r=this.handles.split(",");this.handles={};for(var i=0;i<r.length;i++){var s=e.trim(r[i]),o="ui-resizable-"+s,u=e('<div class="ui-resizable-handle '+o+'"></div>');u.css({zIndex:n.zIndex}),"se"==s&&u.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(u)}}this._renderAxis=function(t){t=t||this.element;for(var n in this.handles){this.handles[n].constructor==String&&(this.handles[n]=e(this.handles[n],this.element).show());if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var r=e(this.handles[n],this.element),i=0;i=/sw|ne|nw|se|n|s/.test(n)?r.outerHeight():r.outerWidth();var s=["padding",/ne|nw|n/.test(n)?"Top":/se|sw|s/.test(n)?"Bottom":/^e$/.test(n)?"Right":"Left"].join("");t.css(s,i),this._proportionallyResize()}if(!e(this.handles[n]).length)continue}},this._renderAxis(this.element),this._handles=e(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){if(!t.resizing){if(this.className)var e=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);t.axis=e&&e[1]?e[1]:"se"}}),n.autoHide&&(this._handles.hide(),e(this.element).addClass("ui-resizable-autohide").mouseenter(function(){if(n.disabled)return;e(this).removeClass("ui-resizable-autohide"),t._handles.show()}).mouseleave(function(){if(n.disabled)return;t.resizing||(e(this).addClass("ui-resizable-autohide"),t._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t=function(t){e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){t(this.element);var n=this.element;this.originalElement.css({position:n.css("position"),width:n.outerWidth(),height:n.outerHeight(),top:n.css("top"),left:n.css("left")}).insertAfter(n),n.remove()}return this.originalElement.css("resize",this.originalResizeStyle),t(this.originalElement),this},_mouseCapture:function(t){var n=!1;for(var r in this.handles)e(this.handles[r])[0]==t.target&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(t){var r=this.options,i=this.element.position(),s=this.element;this.resizing=!0,this.documentScroll={top:e(document).scrollTop(),left:e(document).scrollLeft()},(s.is(".ui-draggable")||/absolute/.test(s.css("position")))&&s.css({position:"absolute",top:i.top,left:i.left}),this._renderProxy();var o=n(this.helper.css("left")),u=n(this.helper.css("top"));r.containment&&(o+=e(r.containment).scrollLeft()||0,u+=e(r.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:o,top:u},this.size=this._helper?{width:s.outerWidth(),height:s.outerHeight()}:{width:s.width(),height:s.height()},this.originalSize=this._helper?{width:s.outerWidth(),height:s.outerHeight()}:{width:s.width(),height:s.height()},this.originalPosition={left:o,top:u},this.sizeDiff={width:s.outerWidth()-s.width(),height:s.outerHeight()-s.height()},this.originalMousePosition={left:t.pageX,top:t.pageY},this.aspectRatio=typeof r.aspectRatio=="number"?r.aspectRatio:this.originalSize.width/this.originalSize.height||1;var a=e(".ui-resizable-"+this.axis).css("cursor");return e("body").css("cursor",a=="auto"?this.axis+"-resize":a),s.addClass("ui-resizable-resizing"),this._propagate("start",t),!0},_mouseDrag:function(e){var t=this.helper,n=this.options,r={},i=this,s=this.originalMousePosition,o=this.axis,u=e.pageX-s.left||0,a=e.pageY-s.top||0,f=this._change[o];if(!f)return!1;var l=f.apply(this,[e,u,a]);this._updateVirtualBoundaries(e.shiftKey);if(this._aspectRatio||e.shiftKey)l=this._updateRatio(l,e);return l=this._respectSize(l,e),this._propagate("resize",e),t.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"}),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),this._updateCache(l),this._trigger("resize",e,this.ui()),!1},_mouseStop:function(t){this.resizing=!1;var n=this.options,r=this;if(this._helper){var i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),o=s&&e.ui.hasScroll(i[0],"left")?0:r.sizeDiff.height,u=s?0:r.sizeDiff.width,a={width:r.helper.width()-u,height:r.helper.height()-o},f=parseInt(r.element.css("left"),10)+(r.position.left-r.originalPosition.left)||null,l=parseInt(r.element.css("top"),10)+(r.position.top-r.originalPosition.top)||null;n.animate||this.element.css(e.extend(a,{top:l,left:f})),r.helper.height(r.size.height),r.helper.width(r.size.width),this._helper&&!n.animate&&this._proportionallyResize()}return e("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(e){var t=this.options,n,i,s,o,u;u={minWidth:r(t.minWidth)?t.minWidth:0,maxWidth:r(t.maxWidth)?t.maxWidth:Infinity,minHeight:r(t.minHeight)?t.minHeight:0,maxHeight:r(t.maxHeight)?t.maxHeight:Infinity};if(this._aspectRatio||e)n=u.minHeight*this.aspectRatio,s=u.minWidth/this.aspectRatio,i=u.maxHeight*this.aspectRatio,o=u.maxWidth/this.aspectRatio,n>u.minWidth&&(u.minWidth=n),s>u.minHeight&&(u.minHeight=s),i<u.maxWidth&&(u.maxWidth=i),o<u.maxHeight&&(u.maxHeight=o);this._vBoundaries=u},_updateCache:function(e){var t=this.options;this.offset=this.helper.offset(),r(e.left)&&(this.position.left=e.left),r(e.top)&&(this.position.top=e.top),r(e.height)&&(this.size.height=e.height),r(e.width)&&(this.size.width=e.width)},_updateRatio:function(e,t){var n=this.options,i=this.position,s=this.size,o=this.axis;return r(e.height)?e.width=e.height*this.aspectRatio:r(e.width)&&(e.height=e.width/this.aspectRatio),o=="sw"&&(e.left=i.left+(s.width-e.width),e.top=null),o=="nw"&&(e.top=i.top+(s.height-e.height),e.left=i.left+(s.width-e.width)),e},_respectSize:function(e,t){var n=this.helper,i=this._vBoundaries,s=this._aspectRatio||t.shiftKey,o=this.axis,u=r(e.width)&&i.maxWidth&&i.maxWidth<e.width,a=r(e.height)&&i.maxHeight&&i.maxHeight<e.height,f=r(e.width)&&i.minWidth&&i.minWidth>e.width,l=r(e.height)&&i.minHeight&&i.minHeight>e.height;f&&(e.width=i.minWidth),l&&(e.height=i.minHeight),u&&(e.width=i.maxWidth),a&&(e.height=i.maxHeight);var c=this.originalPosition.left+this.originalSize.width,h=this.position.top+this.size.height,p=/sw|nw|w/.test(o),d=/nw|ne|n/.test(o);f&&p&&(e.left=c-i.minWidth),u&&p&&(e.left=c-i.maxWidth),l&&d&&(e.top=h-i.minHeight),a&&d&&(e.top=h-i.maxHeight);var v=!e.width&&!e.height;return v&&!e.left&&e.top?e.top=null:v&&!e.top&&e.left&&(e.left=null),e},_proportionallyResize:function(){var t=this.options;if(!this._proportionallyResizeElements.length)return;var n=this.helper||this.element;for(var r=0;r<this._proportionallyResizeElements.length;r++){var i=this._proportionallyResizeElements[r];if(!this.borderDif){var s=[i.css("borderTopWidth"),i.css("borderRightWidth"),i.css("borderBottomWidth"),i.css("borderLeftWidth")],o=[i.css("paddingTop"),i.css("paddingRight"),i.css("paddingBottom"),i.css("paddingLeft")];this.borderDif=e.map(s,function(e,t){var n=parseInt(e,10)||0,r=parseInt(o[t],10)||0;return n+r})}i.css({height:n.height()-this.borderDif[0]-this.borderDif[2]||0,width:n.width()-this.borderDif[1]-this.borderDif[3]||0})}},_renderProxy:function(){var t=this.element,n=this.options;this.elementOffset=t.offset();if(this._helper){this.helper=this.helper||e('<div style="overflow:hidden;"></div>');var r=e.ui.ie6?1:0,i=e.ui.ie6?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+i,height:this.element.outerHeight()+i,position:"absolute",left:this.elementOffset.left-r+"px",top:this.elementOffset.top-r+"px",zIndex:++n.zIndex}),this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(e,t,n){return{width:this.originalSize.width+t}},w:function(e,t,n){var r=this.options,i=this.originalSize,s=this.originalPosition;return{left:s.left+t,width:i.width-t}},n:function(e,t,n){var r=this.options,i=this.originalSize,s=this.originalPosition;return{top:s.top+n,height:i.height-n}},s:function(e,t,n){return{height:this.originalSize.height+n}},se:function(t,n,r){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,n,r]))},sw:function(t,n,r){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,n,r]))},ne:function(t,n,r){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,n,r]))},nw:function(t,n,r){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,n,r]))}},_propagate:function(t,n){e.ui.plugin.call(this,t,[n,this.ui()]),t!="resize"&&this._trigger(t,n,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),e.ui.plugin.add("resizable","alsoResize",{start:function(t,n){var r=e(this).data("resizable"),i=r.options,s=function(t){e(t).each(function(){var t=e(this);t.data("resizable-alsoresize",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css("left"),10),top:parseInt(t.css("top"),10)})})};typeof i.alsoResize=="object"&&!i.alsoResize.parentNode?i.alsoResize.length?(i.alsoResize=i.alsoResize[0],s(i.alsoResize)):e.each(i.alsoResize,function(e){s(e)}):s(i.alsoResize)},resize:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.originalSize,o=r.originalPosition,u={height:r.size.height-s.height||0,width:r.size.width-s.width||0,top:r.position.top-o.top||0,left:r.position.left-o.left||0},a=function(t,r){e(t).each(function(){var t=e(this),i=e(this).data("resizable-alsoresize"),s={},o=r&&r.length?r:t.parents(n.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(o,function(e,t){var n=(i[t]||0)+(u[t]||0);n&&n>=0&&(s[t]=n||null)}),t.css(s)})};typeof i.alsoResize=="object"&&!i.alsoResize.nodeType?e.each(i.alsoResize,function(e,t){a(e,t)}):a(i.alsoResize)},stop:function(t,n){e(this).removeData("resizable-alsoresize")}}),e.ui.plugin.add("resizable","animate",{stop:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r._proportionallyResizeElements,o=s.length&&/textarea/i.test(s[0].nodeName),u=o&&e.ui.hasScroll(s[0],"left")?0:r.sizeDiff.height,a=o?0:r.sizeDiff.width,f={width:r.size.width-a,height:r.size.height-u},l=parseInt(r.element.css("left"),10)+(r.position.left-r.originalPosition.left)||null,c=parseInt(r.element.css("top"),10)+(r.position.top-r.originalPosition.top)||null;r.element.animate(e.extend(f,c&&l?{top:c,left:l}:{}),{duration:i.animateDuration,easing:i.animateEasing,step:function(){var n={width:parseInt(r.element.css("width"),10),height:parseInt(r.element.css("height"),10),top:parseInt(r.element.css("top"),10),left:parseInt(r.element.css("left"),10)};s&&s.length&&e(s[0]).css({width:n.width,height:n.height}),r._updateCache(n),r._propagate("resize",t)}})}}),e.ui.plugin.add("resizable","containment",{start:function(t,r){var i=e(this).data("resizable"),s=i.options,o=i.element,u=s.containment,a=u instanceof e?u.get(0):/parent/.test(u)?o.parent().get(0):u;if(!a)return;i.containerElement=e(a);if(/document/.test(u)||u==document)i.containerOffset={left:0,top:0},i.containerPosition={left:0,top:0},i.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight};else{var f=e(a),l=[];e(["Top","Right","Left","Bottom"]).each(function(e,t){l[e]=n(f.css("padding"+t))}),i.containerOffset=f.offset(),i.containerPosition=f.position(),i.containerSize={height:f.innerHeight()-l[3],width:f.innerWidth()-l[1]};var c=i.containerOffset,h=i.containerSize.height,p=i.containerSize.width,d=e.ui.hasScroll(a,"left")?a.scrollWidth:p,v=e.ui.hasScroll(a)?a.scrollHeight:h;i.parentData={element:a,left:c.left,top:c.top,width:d,height:v}}},resize:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.containerSize,o=r.containerOffset,u=r.size,a=r.position,f=r._aspectRatio||t.shiftKey,l={top:0,left:0},c=r.containerElement;c[0]!=document&&/static/.test(c.css("position"))&&(l=o),a.left<(r._helper?o.left:0)&&(r.size.width=r.size.width+(r._helper?r.position.left-o.left:r.position.left-l.left),f&&(r.size.height=r.size.width/r.aspectRatio),r.position.left=i.helper?o.left:0),a.top<(r._helper?o.top:0)&&(r.size.height=r.size.height+(r._helper?r.position.top-o.top:r.position.top),f&&(r.size.width=r.size.height*r.aspectRatio),r.position.top=r._helper?o.top:0),r.offset.left=r.parentData.left+r.position.left,r.offset.top=r.parentData.top+r.position.top;var h=Math.abs((r._helper?r.offset.left-l.left:r.offset.left-l.left)+r.sizeDiff.width),p=Math.abs((r._helper?r.offset.top-l.top:r.offset.top-o.top)+r.sizeDiff.height),d=r.containerElement.get(0)==r.element.parent().get(0),v=/relative|absolute/.test(r.containerElement.css("position"));d&&v&&(h-=r.parentData.left),h+r.size.width>=r.parentData.width&&(r.size.width=r.parentData.width-h,f&&(r.size.height=r.size.width/r.aspectRatio)),p+r.size.height>=r.parentData.height&&(r.size.height=r.parentData.height-p,f&&(r.size.width=r.size.height*r.aspectRatio))},stop:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.position,o=r.containerOffset,u=r.containerPosition,a=r.containerElement,f=e(r.helper),l=f.offset(),c=f.outerWidth()-r.sizeDiff.width,h=f.outerHeight()-r.sizeDiff.height;r._helper&&!i.animate&&/relative/.test(a.css("position"))&&e(this).css({left:l.left-u.left-o.left,width:c,height:h}),r._helper&&!i.animate&&/static/.test(a.css("position"))&&e(this).css({left:l.left-u.left-o.left,width:c,height:h})}}),e.ui.plugin.add("resizable","ghost",{start:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.size;r.ghost=r.originalElement.clone(),r.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof i.ghost=="string"?i.ghost:""),r.ghost.appendTo(r.helper)},resize:function(t,n){var r=e(this).data("resizable"),i=r.options;r.ghost&&r.ghost.css({position:"relative",height:r.size.height,width:r.size.width})},stop:function(t,n){var r=e(this).data("resizable"),i=r.options;r.ghost&&r.helper&&r.helper.get(0).removeChild(r.ghost.get(0))}}),e.ui.plugin.add("resizable","grid",{resize:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.size,o=r.originalSize,u=r.originalPosition,a=r.axis,f=i._aspectRatio||t.shiftKey;i.grid=typeof i.grid=="number"?[i.grid,i.grid]:i.grid;var l=Math.round((s.width-o.width)/(i.grid[0]||1))*(i.grid[0]||1),c=Math.round((s.height-o.height)/(i.grid[1]||1))*(i.grid[1]||1);/^(se|s|e)$/.test(a)?(r.size.width=o.width+l,r.size.height=o.height+c):/^(ne)$/.test(a)?(r.size.width=o.width+l,r.size.height=o.height+c,r.position.top=u.top-c):/^(sw)$/.test(a)?(r.size.width=o.width+l,r.size.height=o.height+c,r.position.left=u.left-l):(r.size.width=o.width+l,r.size.height=o.height+c,r.position.top=u.top-c,r.position.left=u.left-l)}});var n=function(e){return parseInt(e,10)||0},r=function(e){return!isNaN(parseInt(e,10))}})(jQuery);(function(e,t){e.widget("ui.selectable",e.ui.mouse,{version:"1.9.2",options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch"},_create:function(){var t=this;this.element.addClass("ui-selectable"),this.dragged=!1;var n;this.refresh=function(){n=e(t.options.filter,t.element[0]),n.addClass("ui-selectee"),n.each(function(){var t=e(this),n=t.offset();e.data(this,"selectable-item",{element:this,$element:t,left:n.left,top:n.top,right:n.left+t.outerWidth(),bottom:n.top+t.outerHeight(),startselected:!1,selected:t.hasClass("ui-selected"),selecting:t.hasClass("ui-selecting"),unselecting:t.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=n.addClass("ui-selectee"),this._mouseInit(),this.helper=e("<div class='ui-selectable-helper'></div>")},_destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled"),this._mouseDestroy()},_mouseStart:function(t){var n=this;this.opos=[t.pageX,t.pageY];if(this.options.disabled)return;var r=this.options;this.selectees=e(r.filter,this.element[0]),this._trigger("start",t),e(r.appendTo).append(this.helper),this.helper.css({left:t.clientX,top:t.clientY,width:0,height:0}),r.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var r=e.data(this,"selectable-item");r.startselected=!0,!t.metaKey&&!t.ctrlKey&&(r.$element.removeClass("ui-selected"),r.selected=!1,r.$element.addClass("ui-unselecting"),r.unselecting=!0,n._trigger("unselecting",t,{unselecting:r.element}))}),e(t.target).parents().andSelf().each(function(){var r=e.data(this,"selectable-item");if(r){var i=!t.metaKey&&!t.ctrlKey||!r.$element.hasClass("ui-selected");return r.$element.removeClass(i?"ui-unselecting":"ui-selected").addClass(i?"ui-selecting":"ui-unselecting"),r.unselecting=!i,r.selecting=i,r.selected=i,i?n._trigger("selecting",t,{selecting:r.element}):n._trigger("unselecting",t,{unselecting:r.element}),!1}})},_mouseDrag:function(t){var n=this;this.dragged=!0;if(this.options.disabled)return;var r=this.options,i=this.opos[0],s=this.opos[1],o=t.pageX,u=t.pageY;if(i>o){var a=o;o=i,i=a}if(s>u){var a=u;u=s,s=a}return this.helper.css({left:i,top:s,width:o-i,height:u-s}),this.selectees.each(function(){var a=e.data(this,"selectable-item");if(!a||a.element==n.element[0])return;var f=!1;r.tolerance=="touch"?f=!(a.left>o||a.right<i||a.top>u||a.bottom<s):r.tolerance=="fit"&&(f=a.left>i&&a.right<o&&a.top>s&&a.bottom<u),f?(a.selected&&(a.$element.removeClass("ui-selected"),a.selected=!1),a.unselecting&&(a.$element.removeClass("ui-unselecting"),a.unselecting=!1),a.selecting||(a.$element.addClass("ui-selecting"),a.selecting=!0,n._trigger("selecting",t,{selecting:a.element}))):(a.selecting&&((t.metaKey||t.ctrlKey)&&a.startselected?(a.$element.removeClass("ui-selecting"),a.selecting=!1,a.$element.addClass("ui-selected"),a.selected=!0):(a.$element.removeClass("ui-selecting"),a.selecting=!1,a.startselected&&(a.$element.addClass("ui-unselecting"),a.unselecting=!0),n._trigger("unselecting",t,{unselecting:a.element}))),a.selected&&!t.metaKey&&!t.ctrlKey&&!a.startselected&&(a.$element.removeClass("ui-selected"),a.selected=!1,a.$element.addClass("ui-unselecting"),a.unselecting=!0,n._trigger("unselecting",t,{unselecting:a.element})))}),!1},_mouseStop:function(t){var n=this;this.dragged=!1;var r=this.options;return e(".ui-unselecting",this.element[0]).each(function(){var r=e.data(this,"selectable-item");r.$element.removeClass("ui-unselecting"),r.unselecting=!1,r.startselected=!1,n._trigger("unselected",t,{unselected:r.element})}),e(".ui-selecting",this.element[0]).each(function(){var r=e.data(this,"selectable-item");r.$element.removeClass("ui-selecting").addClass("ui-selected"),r.selecting=!1,r.selected=!0,r.startselected=!0,n._trigger("selected",t,{selected:r.element})}),this._trigger("stop",t),this.helper.remove(),!1}})})(jQuery);(function(e,t){e.widget("ui.sortable",e.ui.mouse,{version:"1.9.2",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3},_create:function(){var e=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?e.axis==="x"||/left|right/.test(this.items[0].item.css("float"))||/inline|table-cell/.test(this.items[0].item.css("display")):!1,this.offset=this.element.offset(),this._mouseInit(),this.ready=!0},_destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled"),this._mouseDestroy();for(var e=this.items.length-1;e>=0;e--)this.items[e].item.removeData(this.widgetName+"-item");return this},_setOption:function(t,n){t==="disabled"?(this.options[t]=n,this.widget().toggleClass("ui-sortable-disabled",!!n)):e.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(t,n){var r=this;if(this.reverting)return!1;if(this.options.disabled||this.options.type=="static")return!1;this._refreshItems(t);var i=null,s=e(t.target).parents().each(function(){if(e.data(this,r.widgetName+"-item")==r)return i=e(this),!1});e.data(t.target,r.widgetName+"-item")==r&&(i=e(t.target));if(!i)return!1;if(this.options.handle&&!n){var o=!1;e(this.options.handle,i).find("*").andSelf().each(function(){this==t.target&&(o=!0)});if(!o)return!1}return this.currentItem=i,this._removeCurrentsFromItems(),!0},_mouseStart:function(t,n,r){var i=this.options;this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(t),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!=this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),i.containment&&this._setContainment(),i.cursor&&(e("body").css("cursor")&&(this._storedCursor=e("body").css("cursor")),e("body").css("cursor",i.cursor)),i.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",i.opacity)),i.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",i.zIndex)),this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",t,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions();if(!r)for(var s=this.containers.length-1;s>=0;s--)this.containers[s]._trigger("activate",t,this._uiHash(this));return e.ui.ddmanager&&(e.ui.ddmanager.current=this),e.ui.ddmanager&&!i.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(t),!0},_mouseDrag:function(t){this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs);if(this.options.scroll){var n=this.options,r=!1;this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-t.pageY<n.scrollSensitivity?this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop+n.scrollSpeed:t.pageY-this.overflowOffset.top<n.scrollSensitivity&&(this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop-n.scrollSpeed),this.overflowOffset.left+this.scrollParent[0].offsetWidth-t.pageX<n.scrollSensitivity?this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft+n.scrollSpeed:t.pageX-this.overflowOffset.left<n.scrollSensitivity&&(this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft-n.scrollSpeed)):(t.pageY-e(document).scrollTop()<n.scrollSensitivity?r=e(document).scrollTop(e(document).scrollTop()-n.scrollSpeed):e(window).height()-(t.pageY-e(document).scrollTop())<n.scrollSensitivity&&(r=e(document).scrollTop(e(document).scrollTop()+n.scrollSpeed)),t.pageX-e(document).scrollLeft()<n.scrollSensitivity?r=e(document).scrollLeft(e(document).scrollLeft()-n.scrollSpeed):e(window).width()-(t.pageX-e(document).scrollLeft())<n.scrollSensitivity&&(r=e(document).scrollLeft(e(document).scrollLeft()+n.scrollSpeed))),r!==!1&&e.ui.ddmanager&&!n.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t)}this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";for(var i=this.items.length-1;i>=0;i--){var s=this.items[i],o=s.item[0],u=this._intersectsWithPointer(s);if(!u)continue;if(s.instance!==this.currentContainer)continue;if(o!=this.currentItem[0]&&this.placeholder[u==1?"next":"prev"]()[0]!=o&&!e.contains(this.placeholder[0],o)&&(this.options.type=="semi-dynamic"?!e.contains(this.element[0],o):!0)){this.direction=u==1?"down":"up";if(this.options.tolerance!="pointer"&&!this._intersectsWithSides(s))break;this._rearrange(t,s),this._trigger("change",t,this._uiHash());break}}return this._contactContainers(t),e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),this._trigger("sort",t,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(t,n){if(!t)return;e.ui.ddmanager&&!this.options.dropBehaviour&&e.ui.ddmanager.drop(this,t);if(this.options.revert){var r=this,i=this.placeholder.offset();this.reverting=!0,e(this.helper).animate({left:i.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:i.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){r._clear(t)})}else this._clear(t,n);return!1},cancel:function(){if(this.dragging){this._mouseUp({target:null}),this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var t=this.containers.length-1;t>=0;t--)this.containers[t]._trigger("deactivate",null,this._uiHash(this)),this.containers[t].containerCache.over&&(this.containers[t]._trigger("out",null,this._uiHash(this)),this.containers[t].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),e.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?e(this.domPosition.prev).after(this.currentItem):e(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(t){var n=this._getItemsAsjQuery(t&&t.connected),r=[];return t=t||{},e(n).each(function(){var n=(e(t.item||this).attr(t.attribute||"id")||"").match(t.expression||/(.+)[-=_](.+)/);n&&r.push((t.key||n[1]+"[]")+"="+(t.key&&t.expression?n[1]:n[2]))}),!r.length&&t.key&&r.push(t.key+"="),r.join("&")},toArray:function(t){var n=this._getItemsAsjQuery(t&&t.connected),r=[];return t=t||{},n.each(function(){r.push(e(t.item||this).attr(t.attribute||"id")||"")}),r},_intersectsWith:function(e){var t=this.positionAbs.left,n=t+this.helperProportions.width,r=this.positionAbs.top,i=r+this.helperProportions.height,s=e.left,o=s+e.width,u=e.top,a=u+e.height,f=this.offset.click.top,l=this.offset.click.left,c=r+f>u&&r+f<a&&t+l>s&&t+l<o;return this.options.tolerance=="pointer"||this.options.forcePointerForContainers||this.options.tolerance!="pointer"&&this.helperProportions[this.floating?"width":"height"]>e[this.floating?"width":"height"]?c:s<t+this.helperProportions.width/2&&n-this.helperProportions.width/2<o&&u<r+this.helperProportions.height/2&&i-this.helperProportions.height/2<a},_intersectsWithPointer:function(t){var n=this.options.axis==="x"||e.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,t.top,t.height),r=this.options.axis==="y"||e.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,t.left,t.width),i=n&&r,s=this._getDragVerticalDirection(),o=this._getDragHorizontalDirection();return i?this.floating?o&&o=="right"||s=="down"?2:1:s&&(s=="down"?2:1):!1},_intersectsWithSides:function(t){var n=e.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,t.top+t.height/2,t.height),r=e.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,t.left+t.width/2,t.width),i=this._getDragVerticalDirection(),s=this._getDragHorizontalDirection();return this.floating&&s?s=="right"&&r||s=="left"&&!r:i&&(i=="down"&&n||i=="up"&&!n)},_getDragVerticalDirection:function(){var e=this.positionAbs.top-this.lastPositionAbs.top;return e!=0&&(e>0?"down":"up")},_getDragHorizontalDirection:function(){var e=this.positionAbs.left-this.lastPositionAbs.left;return e!=0&&(e>0?"right":"left")},refresh:function(e){return this._refreshItems(e),this.refreshPositions(),this},_connectWith:function(){var e=this.options;return e.connectWith.constructor==String?[e.connectWith]:e.connectWith},_getItemsAsjQuery:function(t){var n=[],r=[],i=this._connectWith();if(i&&t)for(var s=i.length-1;s>=0;s--){var o=e(i[s]);for(var u=o.length-1;u>=0;u--){var a=e.data(o[u],this.widgetName);a&&a!=this&&!a.options.disabled&&r.push([e.isFunction(a.options.items)?a.options.items.call(a.element):e(a.options.items,a.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),a])}}r.push([e.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):e(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(var s=r.length-1;s>=0;s--)r[s][0].each(function(){n.push(this)});return e(n)},_removeCurrentsFromItems:function(){var t=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=e.grep(this.items,function(e){for(var n=0;n<t.length;n++)if(t[n]==e.item[0])return!1;return!0})},_refreshItems:function(t){this.items=[],this.containers=[this];var n=this.items,r=[[e.isFunction(this.options.items)?this.options.items.call(this.element[0],t,{item:this.currentItem}):e(this.options.items,this.element),this]],i=this._connectWith();if(i&&this.ready)for(var s=i.length-1;s>=0;s--){var o=e(i[s]);for(var u=o.length-1;u>=0;u--){var a=e.data(o[u],this.widgetName);a&&a!=this&&!a.options.disabled&&(r.push([e.isFunction(a.options.items)?a.options.items.call(a.element[0],t,{item:this.currentItem}):e(a.options.items,a.element),a]),this.containers.push(a))}}for(var s=r.length-1;s>=0;s--){var f=r[s][1],l=r[s][0];for(var u=0,c=l.length;u<c;u++){var h=e(l[u]);h.data(this.widgetName+"-item",f),n.push({item:h,instance:f,width:0,height:0,left:0,top:0})}}},refreshPositions:function(t){this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());for(var n=this.items.length-1;n>=0;n--){var r=this.items[n];if(r.instance!=this.currentContainer&&this.currentContainer&&r.item[0]!=this.currentItem[0])continue;var i=this.options.toleranceElement?e(this.options.toleranceElement,r.item):r.item;t||(r.width=i.outerWidth(),r.height=i.outerHeight());var s=i.offset();r.left=s.left,r.top=s.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(var n=this.containers.length-1;n>=0;n--){var s=this.containers[n].element.offset();this.containers[n].containerCache.left=s.left,this.containers[n].containerCache.top=s.top,this.containers[n].containerCache.width=this.containers[n].element.outerWidth(),this.containers[n].containerCache.height=this.containers[n].element.outerHeight()}return this},_createPlaceholder:function(t){t=t||this;var n=t.options;if(!n.placeholder||n.placeholder.constructor==String){var r=n.placeholder;n.placeholder={element:function(){var n=e(document.createElement(t.currentItem[0].nodeName)).addClass(r||t.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];return r||(n.style.visibility="hidden"),n},update:function(e,i){if(r&&!n.forcePlaceholderSize)return;i.height()||i.height(t.currentItem.innerHeight()-parseInt(t.currentItem.css("paddingTop")||0,10)-parseInt(t.currentItem.css("paddingBottom")||0,10)),i.width()||i.width(t.currentItem.innerWidth()-parseInt(t.currentItem.css("paddingLeft")||0,10)-parseInt(t.currentItem.css("paddingRight")||0,10))}}}t.placeholder=e(n.placeholder.element.call(t.element,t.currentItem)),t.currentItem.after(t.placeholder),n.placeholder.update(t,t.placeholder)},_contactContainers:function(t){var n=null,r=null;for(var i=this.containers.length-1;i>=0;i--){if(e.contains(this.currentItem[0],this.containers[i].element[0]))continue;if(this._intersectsWith(this.containers[i].containerCache)){if(n&&e.contains(this.containers[i].element[0],n.element[0]))continue;n=this.containers[i],r=i}else this.containers[i].containerCache.over&&(this.containers[i]._trigger("out",t,this._uiHash(this)),this.containers[i].containerCache.over=0)}if(!n)return;if(this.containers.length===1)this.containers[r]._trigger("over",t,this._uiHash(this)),this.containers[r].containerCache.over=1;else{var s=1e4,o=null,u=this.containers[r].floating?"left":"top",a=this.containers[r].floating?"width":"height",f=this.positionAbs[u]+this.offset.click[u];for(var l=this.items.length-1;l>=0;l--){if(!e.contains(this.containers[r].element[0],this.items[l].item[0]))continue;if(this.items[l].item[0]==this.currentItem[0])continue;var c=this.items[l].item.offset()[u],h=!1;Math.abs(c-f)>Math.abs(c+this.items[l][a]-f)&&(h=!0,c+=this.items[l][a]),Math.abs(c-f)<s&&(s=Math.abs(c-f),o=this.items[l],this.direction=h?"up":"down")}if(!o&&!this.options.dropOnEmpty)return;this.currentContainer=this.containers[r],o?this._rearrange(t,o,null,!0):this._rearrange(t,null,this.containers[r].element,!0),this._trigger("change",t,this._uiHash()),this.containers[r]._trigger("change",t,this._uiHash(this)),this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[r]._trigger("over",t,this._uiHash(this)),this.containers[r].containerCache.over=1}},_createHelper:function(t){var n=this.options,r=e.isFunction(n.helper)?e(n.helper.apply(this.element[0],[t,this.currentItem])):n.helper=="clone"?this.currentItem.clone():this.currentItem;return r.parents("body").length||e(n.appendTo!="parent"?n.appendTo:this.currentItem[0].parentNode)[0].appendChild(r[0]),r[0]==this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(r[0].style.width==""||n.forceHelperSize)&&r.width(this.currentItem.width()),(r[0].style.height==""||n.forceHelperSize)&&r.height(this.currentItem.height()),r},_adjustOffsetFromHelper:function(t){typeof t=="string"&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var t=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&e.ui.ie)t={top:0,left:0};return{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var e=this.currentItem.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t=this.options;t.containment=="parent"&&(t.containment=this.helper[0].parentNode);if(t.containment=="document"||t.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,e(t.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(e(t.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(t.containment)){var n=e(t.containment)[0],r=e(t.containment).offset(),i=e(n).css("overflow")!="hidden";this.containment=[r.left+(parseInt(e(n).css("borderLeftWidth"),10)||0)+(parseInt(e(n).css("paddingLeft"),10)||0)-this.margins.left,r.top+(parseInt(e(n).css("borderTopWidth"),10)||0)+(parseInt(e(n).css("paddingTop"),10)||0)-this.margins.top,r.left+(i?Math.max(n.scrollWidth,n.offsetWidth):n.offsetWidth)-(parseInt(e(n).css("borderLeftWidth"),10)||0)-(parseInt(e(n).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,r.top+(i?Math.max(n.scrollHeight,n.offsetHeight):n.offsetHeight)-(parseInt(e(n).css("borderTopWidth"),10)||0)-(parseInt(e(n).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(t,n){n||(n=this.position);var r=t=="absolute"?1:-1,i=this.options,s=this.cssPosition!="absolute"||this.scrollParent[0]!=document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,o=/(html|body)/i.test(s[0].tagName);return{top:n.top+this.offset.relative.top*r+this.offset.parent.top*r-(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():o?0:s.scrollTop())*r,left:n.left+this.offset.relative.left*r+this.offset.parent.left*r-(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():o?0:s.scrollLeft())*r}},_generatePosition:function(t){var n=this.options,r=this.cssPosition!="absolute"||this.scrollParent[0]!=document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,i=/(html|body)/i.test(r[0].tagName);this.cssPosition=="relative"&&(this.scrollParent[0]==document||this.scrollParent[0]==this.offsetParent[0])&&(this.offset.relative=this._getRelativeOffset());var s=t.pageX,o=t.pageY;if(this.originalPosition){this.containment&&(t.pageX-this.offset.click.left<this.containment[0]&&(s=this.containment[0]+this.offset.click.left),t.pageY-this.offset.click.top<this.containment[1]&&(o=this.containment[1]+this.offset.click.top),t.pageX-this.offset.click.left>this.containment[2]&&(s=this.containment[2]+this.offset.click.left),t.pageY-this.offset.click.top>this.containment[3]&&(o=this.containment[3]+this.offset.click.top));if(n.grid){var u=this.originalPageY+Math.round((o-this.originalPageY)/n.grid[1])*n.grid[1];o=this.containment?u-this.offset.click.top<this.containment[1]||u-this.offset.click.top>this.containment[3]?u-this.offset.click.top<this.containment[1]?u+n.grid[1]:u-n.grid[1]:u:u;var a=this.originalPageX+Math.round((s-this.originalPageX)/n.grid[0])*n.grid[0];s=this.containment?a-this.offset.click.left<this.containment[0]||a-this.offset.click.left>this.containment[2]?a-this.offset.click.left<this.containment[0]?a+n.grid[0]:a-n.grid[0]:a:a}}return{top:o-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():i?0:r.scrollTop()),left:s-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():i?0:r.scrollLeft())}},_rearrange:function(e,t,n,r){n?n[0].appendChild(this.placeholder[0]):t.item[0].parentNode.insertBefore(this.placeholder[0],this.direction=="down"?t.item[0]:t.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var i=this.counter;this._delay(function(){i==this.counter&&this.refreshPositions(!r)})},_clear:function(t,n){this.reverting=!1;var r=[];!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null;if(this.helper[0]==this.currentItem[0]){for(var i in this._storedCSS)if(this._storedCSS[i]=="auto"||this._storedCSS[i]=="static")this._storedCSS[i]="";this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();this.fromOutside&&!n&&r.push(function(e){this._trigger("receive",e,this._uiHash(this.fromOutside))}),(this.fromOutside||this.domPosition.prev!=this.currentItem.prev().not(".ui-sortable-helper")[0]||this.domPosition.parent!=this.currentItem.parent()[0])&&!n&&r.push(function(e){this._trigger("update",e,this._uiHash())}),this!==this.currentContainer&&(n||(r.push(function(e){this._trigger("remove",e,this._uiHash())}),r.push(function(e){return function(t){e._trigger("receive",t,this._uiHash(this))}}.call(this,this.currentContainer)),r.push(function(e){return function(t){e._trigger("update",t,this._uiHash(this))}}.call(this,this.currentContainer))));for(var i=this.containers.length-1;i>=0;i--)n||r.push(function(e){return function(t){e._trigger("deactivate",t,this._uiHash(this))}}.call(this,this.containers[i])),this.containers[i].containerCache.over&&(r.push(function(e){return function(t){e._trigger("out",t,this._uiHash(this))}}.call(this,this.containers[i])),this.containers[i].containerCache.over=0);this._storedCursor&&e("body").css("cursor",this._storedCursor),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex),this.dragging=!1;if(this.cancelHelperRemoval){if(!n){this._trigger("beforeStop",t,this._uiHash());for(var i=0;i<r.length;i++)r[i].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!1}n||this._trigger("beforeStop",t,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.helper[0]!=this.currentItem[0]&&this.helper.remove(),this.helper=null;if(!n){for(var i=0;i<r.length;i++)r[i].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!0},_trigger:function(){e.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(t){var n=t||this;return{helper:n.helper,placeholder:n.placeholder||e([]),position:n.position,originalPosition:n.originalPosition,offset:n.positionAbs,item:n.currentItem,sender:t?t.element:null}}})})(jQuery);(function(e,t){var n=0,r={},i={};r.height=r.paddingTop=r.paddingBottom=r.borderTopWidth=r.borderBottomWidth="hide",i.height=i.paddingTop=i.paddingBottom=i.borderTopWidth=i.borderBottomWidth="show",e.widget("ui.accordion",{version:"1.9.2",options:{active:0,animate:{},collapsible:!1,event:"click",header:"> li > :first-child,> :not(li):even",heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},_create:function(){var t=this.accordionId="ui-accordion-"+(this.element.attr("id")||++n),r=this.options;this.prevShow=this.prevHide=e(),this.element.addClass("ui-accordion ui-widget ui-helper-reset"),this.headers=this.element.find(r.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all"),this._hoverable(this.headers),this._focusable(this.headers),this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom").hide(),!r.collapsible&&(r.active===!1||r.active==null)&&(r.active=0),r.active<0&&(r.active+=this.headers.length),this.active=this._findActive(r.active).addClass("ui-accordion-header-active ui-state-active").toggleClass("ui-corner-all ui-corner-top"),this.active.next().addClass("ui-accordion-content-active").show(),this._createIcons(),this.refresh(),this.element.attr("role","tablist"),this.headers.attr("role","tab").each(function(n){var r=e(this),i=r.attr("id"),s=r.next(),o=s.attr("id");i||(i=t+"-header-"+n,r.attr("id",i)),o||(o=t+"-panel-"+n,s.attr("id",o)),r.attr("aria-controls",o),s.attr("aria-labelledby",i)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false",tabIndex:-1}).next().attr({"aria-expanded":"false","aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true",tabIndex:0}).next().attr({"aria-expanded":"true","aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._on(this.headers,{keydown:"_keydown"}),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._setupEvents(r.event)},_getCreateEventData:function(){return{header:this.active,content:this.active.length?this.active.next():e()}},_createIcons:function(){var t=this.options.icons;t&&(e("<span>").addClass("ui-accordion-header-icon ui-icon "+t.header).prependTo(this.headers),this.active.children(".ui-accordion-header-icon").removeClass(t.header).addClass(t.activeHeader),this.headers.addClass("ui-accordion-icons"))},_destroyIcons:function(){this.headers.removeClass("ui-accordion-icons").children(".ui-accordion-header-icon").remove()},_destroy:function(){var e;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role"),this.headers.removeClass("ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-selected").removeAttr("aria-controls").removeAttr("tabIndex").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),this._destroyIcons(),e=this.headers.next().css("display","").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),this.options.heightStyle!=="content"&&e.css("height","")},_setOption:function(e,t){if(e==="active"){this._activate(t);return}e==="event"&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(t)),this._super(e,t),e==="collapsible"&&!t&&this.options.active===!1&&this._activate(0),e==="icons"&&(this._destroyIcons(),t&&this._createIcons()),e==="disabled"&&this.headers.add(this.headers.next()).toggleClass("ui-state-disabled",!!t)},_keydown:function(t){if(t.altKey||t.ctrlKey)return;var n=e.ui.keyCode,r=this.headers.length,i=this.headers.index(t.target),s=!1;switch(t.keyCode){case n.RIGHT:case n.DOWN:s=this.headers[(i+1)%r];break;case n.LEFT:case n.UP:s=this.headers[(i-1+r)%r];break;case n.SPACE:case n.ENTER:this._eventHandler(t);break;case n.HOME:s=this.headers[0];break;case n.END:s=this.headers[r-1]}s&&(e(t.target).attr("tabIndex",-1),e(s).attr("tabIndex",0),s.focus(),t.preventDefault())},_panelKeyDown:function(t){t.keyCode===e.ui.keyCode.UP&&t.ctrlKey&&e(t.currentTarget).prev().focus()},refresh:function(){var t,n,r=this.options.heightStyle,i=this.element.parent();r==="fill"?(e.support.minHeight||(n=i.css("overflow"),i.css("overflow","hidden")),t=i.height(),this.element.siblings(":visible").each(function(){var n=e(this),r=n.css("position");if(r==="absolute"||r==="fixed")return;t-=n.outerHeight(!0)}),n&&i.css("overflow",n),this.headers.each(function(){t-=e(this).outerHeight(!0)}),this.headers.next().each(function(){e(this).height(Math.max(0,t-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):r==="auto"&&(t=0,this.headers.next().each(function(){t=Math.max(t,e(this).css("height","").height())}).height(t))},_activate:function(t){var n=this._findActive(t)[0];if(n===this.active[0])return;n=n||this.active[0],this._eventHandler({target:n,currentTarget:n,preventDefault:e.noop})},_findActive:function(t){return typeof t=="number"?this.headers.eq(t):e()},_setupEvents:function(t){var n={};if(!t)return;e.each(t.split(" "),function(e,t){n[t]="_eventHandler"}),this._on(this.headers,n)},_eventHandler:function(t){var n=this.options,r=this.active,i=e(t.currentTarget),s=i[0]===r[0],o=s&&n.collapsible,u=o?e():i.next(),a=r.next(),f={oldHeader:r,oldPanel:a,newHeader:o?e():i,newPanel:u};t.preventDefault();if(s&&!n.collapsible||this._trigger("beforeActivate",t,f)===!1)return;n.active=o?!1:this.headers.index(i),this.active=s?e():i,this._toggle(f),r.removeClass("ui-accordion-header-active ui-state-active"),n.icons&&r.children(".ui-accordion-header-icon").removeClass(n.icons.activeHeader).addClass(n.icons.header),s||(i.removeClass("ui-corner-all").addClass("ui-accordion-header-active ui-state-active ui-corner-top"),n.icons&&i.children(".ui-accordion-header-icon").removeClass(n.icons.header).addClass(n.icons.activeHeader),i.next().addClass("ui-accordion-content-active"))},_toggle:function(t){var n=t.newPanel,r=this.prevShow.length?this.prevShow:t.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=n,this.prevHide=r,this.options.animate?this._animate(n,r,t):(r.hide(),n.show(),this._toggleComplete(t)),r.attr({"aria-expanded":"false","aria-hidden":"true"}),r.prev().attr("aria-selected","false"),n.length&&r.length?r.prev().attr("tabIndex",-1):n.length&&this.headers.filter(function(){return e(this).attr("tabIndex")===0}).attr("tabIndex",-1),n.attr({"aria-expanded":"true","aria-hidden":"false"}).prev().attr({"aria-selected":"true",tabIndex:0})},_animate:function(e,t,n){var s,o,u,a=this,f=0,l=e.length&&(!t.length||e.index()<t.index()),c=this.options.animate||{},h=l&&c.down||c,p=function(){a._toggleComplete(n)};typeof h=="number"&&(u=h),typeof h=="string"&&(o=h),o=o||h.easing||c.easing,u=u||h.duration||c.duration;if(!t.length)return e.animate(i,u,o,p);if(!e.length)return t.animate(r,u,o,p);s=e.show().outerHeight(),t.animate(r,{duration:u,easing:o,step:function(e,t){t.now=Math.round(e)}}),e.hide().animate(i,{duration:u,easing:o,complete:p,step:function(e,n){n.now=Math.round(e),n.prop!=="height"?f+=n.now:a.options.heightStyle!=="content"&&(n.now=Math.round(s-t.outerHeight()-f),f=0)}})},_toggleComplete:function(e){var t=e.oldPanel;t.removeClass("ui-accordion-content-active").prev().removeClass("ui-corner-top").addClass("ui-corner-all"),t.length&&(t.parent()[0].className=t.parent()[0].className),this._trigger("activate",null,e)}}),e.uiBackCompat!==!1&&(function(e,t){e.extend(t.options,{navigation:!1,navigationFilter:function(){return this.href.toLowerCase()===location.href.toLowerCase()}});var n=t._create;t._create=function(){if(this.options.navigation){var t=this,r=this.element.find(this.options.header),i=r.next(),s=r.add(i).find("a").filter(this.options.navigationFilter)[0];s&&r.add(i).each(function(n){if(e.contains(this,s))return t.options.active=Math.floor(n/2),!1})}n.call(this)}}(jQuery,jQuery.ui.accordion.prototype),function(e,t){e.extend(t.options,{heightStyle:null,autoHeight:!0,clearStyle:!1,fillSpace:!1});var n=t._create,r=t._setOption;e.extend(t,{_create:function(){this.options.heightStyle=this.options.heightStyle||this._mergeHeightStyle(),n.call(this)},_setOption:function(e){if(e==="autoHeight"||e==="clearStyle"||e==="fillSpace")this.options.heightStyle=this._mergeHeightStyle();r.apply(this,arguments)},_mergeHeightStyle:function(){var e=this.options;if(e.fillSpace)return"fill";if(e.clearStyle)return"content";if(e.autoHeight)return"auto"}})}(jQuery,jQuery.ui.accordion.prototype),function(e,t){e.extend(t.options.icons,{activeHeader:null,headerSelected:"ui-icon-triangle-1-s"});var n=t._createIcons;t._createIcons=function(){this.options.icons&&(this.options.icons.activeHeader=this.options.icons.activeHeader||this.options.icons.headerSelected),n.call(this)}}(jQuery,jQuery.ui.accordion.prototype),function(e,t){t.activate=t._activate;var n=t._findActive;t._findActive=function(e){return e===-1&&(e=!1),e&&typeof e!="number"&&(e=this.headers.index(this.headers.filter(e)),e===-1&&(e=!1)),n.call(this,e)}}(jQuery,jQuery.ui.accordion.prototype),jQuery.ui.accordion.prototype.resize=jQuery.ui.accordion.prototype.refresh,function(e,t){e.extend(t.options,{change:null,changestart:null});var n=t._trigger;t._trigger=function(e,t,r){var i=n.apply(this,arguments);return i?(e==="beforeActivate"?i=n.call(this,"changestart",t,{oldHeader:r.oldHeader,oldContent:r.oldPanel,newHeader:r.newHeader,newContent:r.newPanel}):e==="activate"&&(i=n.call(this,"change",t,{oldHeader:r.oldHeader,oldContent:r.oldPanel,newHeader:r.newHeader,newContent:r.newPanel})),i):!1}}(jQuery,jQuery.ui.accordion.prototype),function(e,t){e.extend(t.options,{animate:null,animated:"slide"});var n=t._create;t._create=function(){var e=this.options;e.animate===null&&(e.animated?e.animated==="slide"?e.animate=300:e.animated==="bounceslide"?e.animate={duration:200,down:{easing:"easeOutBounce",duration:1e3}}:e.animate=e.animated:e.animate=!1),n.call(this)}}(jQuery,jQuery.ui.accordion.prototype))})(jQuery);(function(e,t){var n=0;e.widget("ui.autocomplete",{version:"1.9.2",defaultElement:"<input>",options:{appendTo:"body",autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},pending:0,_create:function(){var t,n,r;this.isMultiLine=this._isMultiLine(),this.valueMethod=this.element[this.element.is("input,textarea")?"val":"text"],this.isNewMenu=!0,this.element.addClass("ui-autocomplete-input").attr("autocomplete","off"),this._on(this.element,{keydown:function(i){if(this.element.prop("readOnly")){t=!0,r=!0,n=!0;return}t=!1,r=!1,n=!1;var s=e.ui.keyCode;switch(i.keyCode){case s.PAGE_UP:t=!0,this._move("previousPage",i);break;case s.PAGE_DOWN:t=!0,this._move("nextPage",i);break;case s.UP:t=!0,this._keyEvent("previous",i);break;case s.DOWN:t=!0,this._keyEvent("next",i);break;case s.ENTER:case s.NUMPAD_ENTER:this.menu.active&&(t=!0,i.preventDefault(),this.menu.select(i));break;case s.TAB:this.menu.active&&this.menu.select(i);break;case s.ESCAPE:this.menu.element.is(":visible")&&(this._value(this.term),this.close(i),i.preventDefault());break;default:n=!0,this._searchTimeout(i)}},keypress:function(r){if(t){t=!1,r.preventDefault();return}if(n)return;var i=e.ui.keyCode;switch(r.keyCode){case i.PAGE_UP:this._move("previousPage",r);break;case i.PAGE_DOWN:this._move("nextPage",r);break;case i.UP:this._keyEvent("previous",r);break;case i.DOWN:this._keyEvent("next",r)}},input:function(e){if(r){r=!1,e.preventDefault();return}this._searchTimeout(e)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(e){if(this.cancelBlur){delete this.cancelBlur;return}clearTimeout(this.searching),this.close(e),this._change(e)}}),this._initSource(),this.menu=e("<ul>").addClass("ui-autocomplete").appendTo(this.document.find(this.options.appendTo||"body")[0]).menu({input:e(),role:null}).zIndex(this.element.zIndex()+1).hide().data("menu"),this._on(this.menu.element,{mousedown:function(t){t.preventDefault(),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur});var n=this.menu.element[0];e(t.target).closest(".ui-menu-item").length||this._delay(function(){var t=this;this.document.one("mousedown",function(r){r.target!==t.element[0]&&r.target!==n&&!e.contains(n,r.target)&&t.close()})})},menufocus:function(t,n){if(this.isNewMenu){this.isNewMenu=!1;if(t.originalEvent&&/^mouse/.test(t.originalEvent.type)){this.menu.blur(),this.document.one("mousemove",function(){e(t.target).trigger(t.originalEvent)});return}}var r=n.item.data("ui-autocomplete-item")||n.item.data("item.autocomplete");!1!==this._trigger("focus",t,{item:r})?t.originalEvent&&/^key/.test(t.originalEvent.type)&&this._value(r.value):this.liveRegion.text(r.value)},menuselect:function(e,t){var n=t.item.data("ui-autocomplete-item")||t.item.data("item.autocomplete"),r=this.previous;this.element[0]!==this.document[0].activeElement&&(this.element.focus(),this.previous=r,this._delay(function(){this.previous=r,this.selectedItem=n})),!1!==this._trigger("select",e,{item:n})&&this._value(n.value),this.term=this._value(),this.close(e),this.selectedItem=n}}),this.liveRegion=e("<span>",{role:"status","aria-live":"polite"}).addClass("ui-helper-hidden-accessible").insertAfter(this.element),e.fn.bgiframe&&this.menu.element.bgiframe(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(e,t){this._super(e,t),e==="source"&&this._initSource(),e==="appendTo"&&this.menu.element.appendTo(this.document.find(t||"body")[0]),e==="disabled"&&t&&this.xhr&&this.xhr.abort()},_isMultiLine:function(){return this.element.is("textarea")?!0:this.element.is("input")?!1:this.element.prop("isContentEditable")},_initSource:function(){var t,n,r=this;e.isArray(this.options.source)?(t=this.options.source,this.source=function(n,r){r(e.ui.autocomplete.filter(t,n.term))}):typeof this.options.source=="string"?(n=this.options.source,this.source=function(t,i){r.xhr&&r.xhr.abort(),r.xhr=e.ajax({url:n,data:t,dataType:"json",success:function(e){i(e)},error:function(){i([])}})}):this.source=this.options.source},_searchTimeout:function(e){clearTimeout(this.searching),this.searching=this._delay(function(){this.term!==this._value()&&(this.selectedItem=null,this.search(null,e))},this.options.delay)},search:function(e,t){e=e!=null?e:this._value(),this.term=this._value();if(e.length<this.options.minLength)return this.close(t);if(this._trigger("search",t)===!1)return;return this._search(e)},_search:function(e){this.pending++,this.element.addClass("ui-autocomplete-loading"),this.cancelSearch=!1,this.source({term:e},this._response())},_response:function(){var e=this,t=++n;return function(r){t===n&&e.__response(r),e.pending--,e.pending||e.element.removeClass("ui-autocomplete-loading")}},__response:function(e){e&&(e=this._normalize(e)),this._trigger("response",null,{content:e}),!this.options.disabled&&e&&e.length&&!this.cancelSearch?(this._suggest(e),this._trigger("open")):this._close()},close:function(e){this.cancelSearch=!0,this._close(e)},_close:function(e){this.menu.element.is(":visible")&&(this.menu.element.hide(),this.menu.blur(),this.isNewMenu=!0,this._trigger("close",e))},_change:function(e){this.previous!==this._value()&&this._trigger("change",e,{item:this.selectedItem})},_normalize:function(t){return t.length&&t[0].label&&t[0].value?t:e.map(t,function(t){return typeof t=="string"?{label:t,value:t}:e.extend({label:t.label||t.value,value:t.value||t.label},t)})},_suggest:function(t){var n=this.menu.element.empty().zIndex(this.element.zIndex()+1);this._renderMenu(n,t),this.menu.refresh(),n.show(),this._resizeMenu(),n.position(e.extend({of:this.element},this.options.position)),this.options.autoFocus&&this.menu.next()},_resizeMenu:function(){var e=this.menu.element;e.outerWidth(Math.max(e.width("").outerWidth()+1,this.element.outerWidth()))},_renderMenu:function(t,n){var r=this;e.each(n,function(e,n){r._renderItemData(t,n)})},_renderItemData:function(e,t){return this._renderItem(e,t).data("ui-autocomplete-item",t)},_renderItem:function(t,n){return e("<li>").append(e("<a>").text(n.label)).appendTo(t)},_move:function(e,t){if(!this.menu.element.is(":visible")){this.search(null,t);return}if(this.menu.isFirstItem()&&/^previous/.test(e)||this.menu.isLastItem()&&/^next/.test(e)){this._value(this.term),this.menu.blur();return}this.menu[e](t)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(e,t){if(!this.isMultiLine||this.menu.element.is(":visible"))this._move(e,t),t.preventDefault()}}),e.extend(e.ui.autocomplete,{escapeRegex:function(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(t,n){var r=new RegExp(e.ui.autocomplete.escapeRegex(n),"i");return e.grep(t,function(e){return r.test(e.label||e.value||e)})}}),e.widget("ui.autocomplete",e.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(e){return e+(e>1?" results are":" result is")+" available, use up and down arrow keys to navigate."}}},__response:function(e){var t;this._superApply(arguments);if(this.options.disabled||this.cancelSearch)return;e&&e.length?t=this.options.messages.results(e.length):t=this.options.messages.noResults,this.liveRegion.text(t)}})})(jQuery);(function(e,t){var n,r,i,s,o="ui-button ui-widget ui-state-default ui-corner-all",u="ui-state-hover ui-state-active ",a="ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",f=function(){var t=e(this).find(":ui-button");setTimeout(function(){t.button("refresh")},1)},l=function(t){var n=t.name,r=t.form,i=e([]);return n&&(r?i=e(r).find("[name='"+n+"']"):i=e("[name='"+n+"']",t.ownerDocument).filter(function(){return!this.form})),i};e.widget("ui.button",{version:"1.9.2",defaultElement:"<button>",options:{disabled:null,text:!0,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset"+this.eventNamespace).bind("reset"+this.eventNamespace,f),typeof this.options.disabled!="boolean"?this.options.disabled=!!this.element.prop("disabled"):this.element.prop("disabled",this.options.disabled),this._determineButtonType(),this.hasTitle=!!this.buttonElement.attr("title");var t=this,u=this.options,a=this.type==="checkbox"||this.type==="radio",c=a?"":"ui-state-active",h="ui-state-focus";u.label===null&&(u.label=this.type==="input"?this.buttonElement.val():this.buttonElement.html()),this._hoverable(this.buttonElement),this.buttonElement.addClass(o).attr("role","button").bind("mouseenter"+this.eventNamespace,function(){if(u.disabled)return;this===n&&e(this).addClass("ui-state-active")}).bind("mouseleave"+this.eventNamespace,function(){if(u.disabled)return;e(this).removeClass(c)}).bind("click"+this.eventNamespace,function(e){u.disabled&&(e.preventDefault(),e.stopImmediatePropagation())}),this.element.bind("focus"+this.eventNamespace,function(){t.buttonElement.addClass(h)}).bind("blur"+this.eventNamespace,function(){t.buttonElement.removeClass(h)}),a&&(this.element.bind("change"+this.eventNamespace,function(){if(s)return;t.refresh()}),this.buttonElement.bind("mousedown"+this.eventNamespace,function(e){if(u.disabled)return;s=!1,r=e.pageX,i=e.pageY}).bind("mouseup"+this.eventNamespace,function(e){if(u.disabled)return;if(r!==e.pageX||i!==e.pageY)s=!0})),this.type==="checkbox"?this.buttonElement.bind("click"+this.eventNamespace,function(){if(u.disabled||s)return!1;e(this).toggleClass("ui-state-active"),t.buttonElement.attr("aria-pressed",t.element[0].checked)}):this.type==="radio"?this.buttonElement.bind("click"+this.eventNamespace,function(){if(u.disabled||s)return!1;e(this).addClass("ui-state-active"),t.buttonElement.attr("aria-pressed","true");var n=t.element[0];l(n).not(n).map(function(){return e(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed","false")}):(this.buttonElement.bind("mousedown"+this.eventNamespace,function(){if(u.disabled)return!1;e(this).addClass("ui-state-active"),n=this,t.document.one("mouseup",function(){n=null})}).bind("mouseup"+this.eventNamespace,function(){if(u.disabled)return!1;e(this).removeClass("ui-state-active")}).bind("keydown"+this.eventNamespace,function(t){if(u.disabled)return!1;(t.keyCode===e.ui.keyCode.SPACE||t.keyCode===e.ui.keyCode.ENTER)&&e(this).addClass("ui-state-active")}).bind("keyup"+this.eventNamespace,function(){e(this).removeClass("ui-state-active")}),this.buttonElement.is("a")&&this.buttonElement.keyup(function(t){t.keyCode===e.ui.keyCode.SPACE&&e(this).click()})),this._setOption("disabled",u.disabled),this._resetButton()},_determineButtonType:function(){var e,t,n;this.element.is("[type=checkbox]")?this.type="checkbox":this.element.is("[type=radio]")?this.type="radio":this.element.is("input")?this.type="input":this.type="button",this.type==="checkbox"||this.type==="radio"?(e=this.element.parents().last(),t="label[for='"+this.element.attr("id")+"']",this.buttonElement=e.find(t),this.buttonElement.length||(e=e.length?e.siblings():this.element.siblings(),this.buttonElement=e.filter(t),this.buttonElement.length||(this.buttonElement=e.find(t))),this.element.addClass("ui-helper-hidden-accessible"),n=this.element.is(":checked"),n&&this.buttonElement.addClass("ui-state-active"),this.buttonElement.prop("aria-pressed",n)):this.buttonElement=this.element},widget:function(){return this.buttonElement},_destroy:function(){this.element.removeClass("ui-helper-hidden-accessible"),this.buttonElement.removeClass(o+" "+u+" "+a).removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html()),this.hasTitle||this.buttonElement.removeAttr("title")},_setOption:function(e,t){this._super(e,t);if(e==="disabled"){t?this.element.prop("disabled",!0):this.element.prop("disabled",!1);return}this._resetButton()},refresh:function(){var t=this.element.is("input, button")?this.element.is(":disabled"):this.element.hasClass("ui-button-disabled");t!==this.options.disabled&&this._setOption("disabled",t),this.type==="radio"?l(this.element[0]).each(function(){e(this).is(":checked")?e(this).button("widget").addClass("ui-state-active").attr("aria-pressed","true"):e(this).button("widget").removeClass("ui-state-active").attr("aria-pressed","false")}):this.type==="checkbox"&&(this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed","true"):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed","false"))},_resetButton:function(){if(this.type==="input"){this.options.label&&this.element.val(this.options.label);return}var t=this.buttonElement.removeClass(a),n=e("<span></span>",this.document[0]).addClass("ui-button-text").html(this.options.label).appendTo(t.empty()).text(),r=this.options.icons,i=r.primary&&r.secondary,s=[];r.primary||r.secondary?(this.options.text&&s.push("ui-button-text-icon"+(i?"s":r.primary?"-primary":"-secondary")),r.primary&&t.prepend("<span class='ui-button-icon-primary ui-icon "+r.primary+"'></span>"),r.secondary&&t.append("<span class='ui-button-icon-secondary ui-icon "+r.secondary+"'></span>"),this.options.text||(s.push(i?"ui-button-icons-only":"ui-button-icon-only"),this.hasTitle||t.attr("title",e.trim(n)))):s.push("ui-button-text-only"),t.addClass(s.join(" "))}}),e.widget("ui.buttonset",{version:"1.9.2",options:{items:"button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(e,t){e==="disabled"&&this.buttons.button("option",e,t),this._super(e,t)},refresh:function(){var t=this.element.css("direction")==="rtl";this.buttons=this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return e(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass(t?"ui-corner-right":"ui-corner-left").end().filter(":last").addClass(t?"ui-corner-left":"ui-corner-right").end().end()},_destroy:function(){this.element.removeClass("ui-buttonset"),this.buttons.map(function(){return e(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy")}})})(jQuery);(function($,undefined){function Datepicker(){this.debug=!1,this._curInst=null,this._keyEvent=!1,this._disabledInputs=[],this._datepickerShowing=!1,this._inDialog=!1,this._mainDivId="ui-datepicker-div",this._inlineClass="ui-datepicker-inline",this._appendClass="ui-datepicker-append",this._triggerClass="ui-datepicker-trigger",this._dialogClass="ui-datepicker-dialog",this._disableClass="ui-datepicker-disabled",this._unselectableClass="ui-datepicker-unselectable",this._currentClass="ui-datepicker-current-day",this._dayOverClass="ui-datepicker-days-cell-over",this.regional=[],this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""},this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:!1,hideIfNoPrevNext:!1,navigationAsDateFormat:!1,gotoCurrent:!1,changeMonth:!1,changeYear:!1,yearRange:"c-10:c+10",showOtherMonths:!1,selectOtherMonths:!1,showWeek:!1,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:!0,showButtonPanel:!1,autoSize:!1,disabled:!1},$.extend(this._defaults,this.regional[""]),this.dpDiv=bindHover($('<div id="'+this._mainDivId+'" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))}function bindHover(e){var t="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return e.delegate(t,"mouseout",function(){$(this).removeClass("ui-state-hover"),this.className.indexOf("ui-datepicker-prev")!=-1&&$(this).removeClass("ui-datepicker-prev-hover"),this.className.indexOf("ui-datepicker-next")!=-1&&$(this).removeClass("ui-datepicker-next-hover")}).delegate(t,"mouseover",function(){$.datepicker._isDisabledDatepicker(instActive.inline?e.parent()[0]:instActive.input[0])||($(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),$(this).addClass("ui-state-hover"),this.className.indexOf("ui-datepicker-prev")!=-1&&$(this).addClass("ui-datepicker-prev-hover"),this.className.indexOf("ui-datepicker-next")!=-1&&$(this).addClass("ui-datepicker-next-hover"))})}function extendRemove(e,t){$.extend(e,t);for(var n in t)if(t[n]==null||t[n]==undefined)e[n]=t[n];return e}$.extend($.ui,{datepicker:{version:"1.9.2"}});var PROP_NAME="datepicker",dpuuid=(new Date).getTime(),instActive;$.extend(Datepicker.prototype,{markerClassName:"hasDatepicker",maxRows:4,log:function(){this.debug&&console.log.apply("",arguments)},_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(e){return extendRemove(this._defaults,e||{}),this},_attachDatepicker:function(target,settings){var inlineSettings=null;for(var attrName in this._defaults){var attrValue=target.getAttribute("date:"+attrName);if(attrValue){inlineSettings=inlineSettings||{};try{inlineSettings[attrName]=eval(attrValue)}catch(err){inlineSettings[attrName]=attrValue}}}var nodeName=target.nodeName.toLowerCase(),inline=nodeName=="div"||nodeName=="span";target.id||(this.uuid+=1,target.id="dp"+this.uuid);var inst=this._newInst($(target),inline);inst.settings=$.extend({},settings||{},inlineSettings||{}),nodeName=="input"?this._connectDatepicker(target,inst):inline&&this._inlineDatepicker(target,inst)},_newInst:function(e,t){var n=e[0].id.replace(/([^A-Za-z0-9_-])/g,"\\\\$1");return{id:n,input:e,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:t,dpDiv:t?bindHover($('<div class="'+this._inlineClass+' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')):this.dpDiv}},_connectDatepicker:function(e,t){var n=$(e);t.append=$([]),t.trigger=$([]);if(n.hasClass(this.markerClassName))return;this._attachments(n,t),n.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp).bind("setData.datepicker",function(e,n,r){t.settings[n]=r}).bind("getData.datepicker",function(e,n){return this._get(t,n)}),this._autoSize(t),$.data(e,PROP_NAME,t),t.settings.disabled&&this._disableDatepicker(e)},_attachments:function(e,t){var n=this._get(t,"appendText"),r=this._get(t,"isRTL");t.append&&t.append.remove(),n&&(t.append=$('<span class="'+this._appendClass+'">'+n+"</span>"),e[r?"before":"after"](t.append)),e.unbind("focus",this._showDatepicker),t.trigger&&t.trigger.remove();var i=this._get(t,"showOn");(i=="focus"||i=="both")&&e.focus(this._showDatepicker);if(i=="button"||i=="both"){var s=this._get(t,"buttonText"),o=this._get(t,"buttonImage");t.trigger=$(this._get(t,"buttonImageOnly")?$("<img/>").addClass(this._triggerClass).attr({src:o,alt:s,title:s}):$('<button type="button"></button>').addClass(this._triggerClass).html(o==""?s:$("<img/>").attr({src:o,alt:s,title:s}))),e[r?"before":"after"](t.trigger),t.trigger.click(function(){return $.datepicker._datepickerShowing&&$.datepicker._lastInput==e[0]?$.datepicker._hideDatepicker():$.datepicker._datepickerShowing&&$.datepicker._lastInput!=e[0]?($.datepicker._hideDatepicker(),$.datepicker._showDatepicker(e[0])):$.datepicker._showDatepicker(e[0]),!1})}},_autoSize:function(e){if(this._get(e,"autoSize")&&!e.inline){var t=new Date(2009,11,20),n=this._get(e,"dateFormat");if(n.match(/[DM]/)){var r=function(e){var t=0,n=0;for(var r=0;r<e.length;r++)e[r].length>t&&(t=e[r].length,n=r);return n};t.setMonth(r(this._get(e,n.match(/MM/)?"monthNames":"monthNamesShort"))),t.setDate(r(this._get(e,n.match(/DD/)?"dayNames":"dayNamesShort"))+20-t.getDay())}e.input.attr("size",this._formatDate(e,t).length)}},_inlineDatepicker:function(e,t){var n=$(e);if(n.hasClass(this.markerClassName))return;n.addClass(this.markerClassName).append(t.dpDiv).bind("setData.datepicker",function(e,n,r){t.settings[n]=r}).bind("getData.datepicker",function(e,n){return this._get(t,n)}),$.data(e,PROP_NAME,t),this._setDate(t,this._getDefaultDate(t),!0),this._updateDatepicker(t),this._updateAlternate(t),t.settings.disabled&&this._disableDatepicker(e),t.dpDiv.css("display","block")},_dialogDatepicker:function(e,t,n,r,i){var s=this._dialogInst;if(!s){this.uuid+=1;var o="dp"+this.uuid;this._dialogInput=$('<input type="text" id="'+o+'" style="position: absolute; top: -100px; width: 0px;"/>'),this._dialogInput.keydown(this._doKeyDown),$("body").append(this._dialogInput),s=this._dialogInst=this._newInst(this._dialogInput,!1),s.settings={},$.data(this._dialogInput[0],PROP_NAME,s)}extendRemove(s.settings,r||{}),t=t&&t.constructor==Date?this._formatDate(s,t):t,this._dialogInput.val(t),this._pos=i?i.length?i:[i.pageX,i.pageY]:null;if(!this._pos){var u=document.documentElement.clientWidth,a=document.documentElement.clientHeight,f=document.documentElement.scrollLeft||document.body.scrollLeft,l=document.documentElement.scrollTop||document.body.scrollTop;this._pos=[u/2-100+f,a/2-150+l]}return this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px"),s.settings.onSelect=n,this._inDialog=!0,this.dpDiv.addClass(this._dialogClass),this._showDatepicker(this._dialogInput[0]),$.blockUI&&$.blockUI(this.dpDiv),$.data(this._dialogInput[0],PROP_NAME,s),this},_destroyDatepicker:function(e){var t=$(e),n=$.data(e,PROP_NAME);if(!t.hasClass(this.markerClassName))return;var r=e.nodeName.toLowerCase();$.removeData(e,PROP_NAME),r=="input"?(n.append.remove(),n.trigger.remove(),t.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)):(r=="div"||r=="span")&&t.removeClass(this.markerClassName).empty()},_enableDatepicker:function(e){var t=$(e),n=$.data(e,PROP_NAME);if(!t.hasClass(this.markerClassName))return;var r=e.nodeName.toLowerCase();if(r=="input")e.disabled=!1,n.trigger.filter("button").each(function(){this.disabled=!1}).end().filter("img").css({opacity:"1.0",cursor:""});else if(r=="div"||r=="span"){var i=t.children("."+this._inlineClass);i.children().removeClass("ui-state-disabled"),i.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!1)}this._disabledInputs=$.map(this._disabledInputs,function(t){return t==e?null:t})},_disableDatepicker:function(e){var t=$(e),n=$.data(e,PROP_NAME);if(!t.hasClass(this.markerClassName))return;var r=e.nodeName.toLowerCase();if(r=="input")e.disabled=!0,n.trigger.filter("button").each(function(){this.disabled=!0}).end().filter("img").css({opacity:"0.5",cursor:"default"});else if(r=="div"||r=="span"){var i=t.children("."+this._inlineClass);i.children().addClass("ui-state-disabled"),i.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!0)}this._disabledInputs=$.map(this._disabledInputs,function(t){return t==e?null:t}),this._disabledInputs[this._disabledInputs.length]=e},_isDisabledDatepicker:function(e){if(!e)return!1;for(var t=0;t<this._disabledInputs.length;t++)if(this._disabledInputs[t]==e)return!0;return!1},_getInst:function(e){try{return $.data(e,PROP_NAME)}catch(t){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(e,t,n){var r=this._getInst(e);if(arguments.length==2&&typeof t=="string")return t=="defaults"?$.extend({},$.datepicker._defaults):r?t=="all"?$.extend({},r.settings):this._get(r,t):null;var i=t||{};typeof t=="string"&&(i={},i[t]=n);if(r){this._curInst==r&&this._hideDatepicker();var s=this._getDateDatepicker(e,!0),o=this._getMinMaxDate(r,"min"),u=this._getMinMaxDate(r,"max");extendRemove(r.settings,i),o!==null&&i.dateFormat!==undefined&&i.minDate===undefined&&(r.settings.minDate=this._formatDate(r,o)),u!==null&&i.dateFormat!==undefined&&i.maxDate===undefined&&(r.settings.maxDate=this._formatDate(r,u)),this._attachments($(e),r),this._autoSize(r),this._setDate(r,s),this._updateAlternate(r),this._updateDatepicker(r)}},_changeDatepicker:function(e,t,n){this._optionDatepicker(e,t,n)},_refreshDatepicker:function(e){var t=this._getInst(e);t&&this._updateDatepicker(t)},_setDateDatepicker:function(e,t){var n=this._getInst(e);n&&(this._setDate(n,t),this._updateDatepicker(n),this._updateAlternate(n))},_getDateDatepicker:function(e,t){var n=this._getInst(e);return n&&!n.inline&&this._setDateFromField(n,t),n?this._getDate(n):null},_doKeyDown:function(e){var t=$.datepicker._getInst(e.target),n=!0,r=t.dpDiv.is(".ui-datepicker-rtl");t._keyEvent=!0;if($.datepicker._datepickerShowing)switch(e.keyCode){case 9:$.datepicker._hideDatepicker(),n=!1;break;case 13:var i=$("td."+$.datepicker._dayOverClass+":not(."+$.datepicker._currentClass+")",t.dpDiv);i[0]&&$.datepicker._selectDay(e.target,t.selectedMonth,t.selectedYear,i[0]);var s=$.datepicker._get(t,"onSelect");if(s){var o=$.datepicker._formatDate(t);s.apply(t.input?t.input[0]:null,[o,t])}else $.datepicker._hideDatepicker();return!1;case 27:$.datepicker._hideDatepicker();break;case 33:$.datepicker._adjustDate(e.target,e.ctrlKey?-$.datepicker._get(t,"stepBigMonths"):-$.datepicker._get(t,"stepMonths"),"M");break;case 34:$.datepicker._adjustDate(e.target,e.ctrlKey?+$.datepicker._get(t,"stepBigMonths"):+$.datepicker._get(t,"stepMonths"),"M");break;case 35:(e.ctrlKey||e.metaKey)&&$.datepicker._clearDate(e.target),n=e.ctrlKey||e.metaKey;break;case 36:(e.ctrlKey||e.metaKey)&&$.datepicker._gotoToday(e.target),n=e.ctrlKey||e.metaKey;break;case 37:(e.ctrlKey||e.metaKey)&&$.datepicker._adjustDate(e.target,r?1:-1,"D"),n=e.ctrlKey||e.metaKey,e.originalEvent.altKey&&$.datepicker._adjustDate(e.target,e.ctrlKey?-$.datepicker._get(t,"stepBigMonths"):-$.datepicker._get(t,"stepMonths"),"M");break;case 38:(e.ctrlKey||e.metaKey)&&$.datepicker._adjustDate(e.target,-7,"D"),n=e.ctrlKey||e.metaKey;break;case 39:(e.ctrlKey||e.metaKey)&&$.datepicker._adjustDate(e.target,r?-1:1,"D"),n=e.ctrlKey||e.metaKey,e.originalEvent.altKey&&$.datepicker._adjustDate(e.target,e.ctrlKey?+$.datepicker._get(t,"stepBigMonths"):+$.datepicker._get(t,"stepMonths"),"M");break;case 40:(e.ctrlKey||e.metaKey)&&$.datepicker._adjustDate(e.target,7,"D"),n=e.ctrlKey||e.metaKey;break;default:n=!1}else e.keyCode==36&&e.ctrlKey?$.datepicker._showDatepicker(this):n=!1;n&&(e.preventDefault(),e.stopPropagation())},_doKeyPress:function(e){var t=$.datepicker._getInst(e.target);if($.datepicker._get(t,"constrainInput")){var n=$.datepicker._possibleChars($.datepicker._get(t,"dateFormat")),r=String.fromCharCode(e.charCode==undefined?e.keyCode:e.charCode);return e.ctrlKey||e.metaKey||r<" "||!n||n.indexOf(r)>-1}},_doKeyUp:function(e){var t=$.datepicker._getInst(e.target);if(t.input.val()!=t.lastVal)try{var n=$.datepicker.parseDate($.datepicker._get(t,"dateFormat"),t.input?t.input.val():null,$.datepicker._getFormatConfig(t));n&&($.datepicker._setDateFromField(t),$.datepicker._updateAlternate(t),$.datepicker._updateDatepicker(t))}catch(r){$.datepicker.log(r)}return!0},_showDatepicker:function(e){e=e.target||e,e.nodeName.toLowerCase()!="input"&&(e=$("input",e.parentNode)[0]);if($.datepicker._isDisabledDatepicker(e)||$.datepicker._lastInput==e)return;var t=$.datepicker._getInst(e);$.datepicker._curInst&&$.datepicker._curInst!=t&&($.datepicker._curInst.dpDiv.stop(!0,!0),t&&$.datepicker._datepickerShowing&&$.datepicker._hideDatepicker($.datepicker._curInst.input[0]));var n=$.datepicker._get(t,"beforeShow"),r=n?n.apply(e,[e,t]):{};if(r===!1)return;extendRemove(t.settings,r),t.lastVal=null,$.datepicker._lastInput=e,$.datepicker._setDateFromField(t),$.datepicker._inDialog&&(e.value=""),$.datepicker._pos||($.datepicker._pos=$.datepicker._findPos(e),$.datepicker._pos[1]+=e.offsetHeight);var i=!1;$(e).parents().each(function(){return i|=$(this).css("position")=="fixed",!i});var s={left:$.datepicker._pos[0],top:$.datepicker._pos[1]};$.datepicker._pos=null,t.dpDiv.empty(),t.dpDiv.css({position:"absolute",display:"block",top:"-1000px"}),$.datepicker._updateDatepicker(t),s=$.datepicker._checkOffset(t,s,i),t.dpDiv.css({position:$.datepicker._inDialog&&$.blockUI?"static":i?"fixed":"absolute",display:"none",left:s.left+"px",top:s.top+"px"});if(!t.inline){var o=$.datepicker._get(t,"showAnim"),u=$.datepicker._get(t,"duration"),a=function(){var e=t.dpDiv.find("iframe.ui-datepicker-cover");if(!!e.length){var n=$.datepicker._getBorders(t.dpDiv);e.css({left:-n[0],top:-n[1],width:t.dpDiv.outerWidth(),height:t.dpDiv.outerHeight()})}};t.dpDiv.zIndex($(e).zIndex()+1),$.datepicker._datepickerShowing=!0,$.effects&&($.effects.effect[o]||$.effects[o])?t.dpDiv.show(o,$.datepicker._get(t,"showOptions"),u,a):t.dpDiv[o||"show"](o?u:null,a),(!o||!u)&&a(),t.input.is(":visible")&&!t.input.is(":disabled")&&t.input.focus(),$.datepicker._curInst=t}},_updateDatepicker:function(e){this.maxRows=4;var t=$.datepicker._getBorders(e.dpDiv);instActive=e,e.dpDiv.empty().append(this._generateHTML(e)),this._attachHandlers(e);var n=e.dpDiv.find("iframe.ui-datepicker-cover");!n.length||n.css({left:-t[0],top:-t[1],width:e.dpDiv.outerWidth(),height:e.dpDiv.outerHeight()}),e.dpDiv.find("."+this._dayOverClass+" a").mouseover();var r=this._getNumberOfMonths(e),i=r[1],s=17;e.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""),i>1&&e.dpDiv.addClass("ui-datepicker-multi-"+i).css("width",s*i+"em"),e.dpDiv[(r[0]!=1||r[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi"),e.dpDiv[(this._get(e,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"),e==$.datepicker._curInst&&$.datepicker._datepickerShowing&&e.input&&e.input.is(":visible")&&!e.input.is(":disabled")&&e.input[0]!=document.activeElement&&e.input.focus();if(e.yearshtml){var o=e.yearshtml;setTimeout(function(){o===e.yearshtml&&e.yearshtml&&e.dpDiv.find("select.ui-datepicker-year:first").replaceWith(e.yearshtml),o=e.yearshtml=null},0)}},_getBorders:function(e){var t=function(e){return{thin:1,medium:2,thick:3}[e]||e};return[parseFloat(t(e.css("border-left-width"))),parseFloat(t(e.css("border-top-width")))]},_checkOffset:function(e,t,n){var r=e.dpDiv.outerWidth(),i=e.dpDiv.outerHeight(),s=e.input?e.input.outerWidth():0,o=e.input?e.input.outerHeight():0,u=document.documentElement.clientWidth+(n?0:$(document).scrollLeft()),a=document.documentElement.clientHeight+(n?0:$(document).scrollTop());return t.left-=this._get(e,"isRTL")?r-s:0,t.left-=n&&t.left==e.input.offset().left?$(document).scrollLeft():0,t.top-=n&&t.top==e.input.offset().top+o?$(document).scrollTop():0,t.left-=Math.min(t.left,t.left+r>u&&u>r?Math.abs(t.left+r-u):0),t.top-=Math.min(t.top,t.top+i>a&&a>i?Math.abs(i+o):0),t},_findPos:function(e){var t=this._getInst(e),n=this._get(t,"isRTL");while(e&&(e.type=="hidden"||e.nodeType!=1||$.expr.filters.hidden(e)))e=e[n?"previousSibling":"nextSibling"];var r=$(e).offset();return[r.left,r.top]},_hideDatepicker:function(e){var t=this._curInst;if(!t||e&&t!=$.data(e,PROP_NAME))return;if(this._datepickerShowing){var n=this._get(t,"showAnim"),r=this._get(t,"duration"),i=function(){$.datepicker._tidyDialog(t)};$.effects&&($.effects.effect[n]||$.effects[n])?t.dpDiv.hide(n,$.datepicker._get(t,"showOptions"),r,i):t.dpDiv[n=="slideDown"?"slideUp":n=="fadeIn"?"fadeOut":"hide"](n?r:null,i),n||i(),this._datepickerShowing=!1;var s=this._get(t,"onClose");s&&s.apply(t.input?t.input[0]:null,[t.input?t.input.val():"",t]),this._lastInput=null,this._inDialog&&(this._dialogInput.css({position:"absolute",left:"0",top:"-100px"}),$.blockUI&&($.unblockUI(),$("body").append(this.dpDiv))),this._inDialog=!1}},_tidyDialog:function(e){e.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(e){if(!$.datepicker._curInst)return;var t=$(e.target),n=$.datepicker._getInst(t[0]);(t[0].id!=$.datepicker._mainDivId&&t.parents("#"+$.datepicker._mainDivId).length==0&&!t.hasClass($.datepicker.markerClassName)&&!t.closest("."+$.datepicker._triggerClass).length&&$.datepicker._datepickerShowing&&(!$.datepicker._inDialog||!$.blockUI)||t.hasClass($.datepicker.markerClassName)&&$.datepicker._curInst!=n)&&$.datepicker._hideDatepicker()},_adjustDate:function(e,t,n){var r=$(e),i=this._getInst(r[0]);if(this._isDisabledDatepicker(r[0]))return;this._adjustInstDate(i,t+(n=="M"?this._get(i,"showCurrentAtPos"):0),n),this._updateDatepicker(i)},_gotoToday:function(e){var t=$(e),n=this._getInst(t[0]);if(this._get(n,"gotoCurrent")&&n.currentDay)n.selectedDay=n.currentDay,n.drawMonth=n.selectedMonth=n.currentMonth,n.drawYear=n.selectedYear=n.currentYear;else{var r=new Date;n.selectedDay=r.getDate(),n.drawMonth=n.selectedMonth=r.getMonth(),n.drawYear=n.selectedYear=r.getFullYear()}this._notifyChange(n),this._adjustDate(t)},_selectMonthYear:function(e,t,n){var r=$(e),i=this._getInst(r[0]);i["selected"+(n=="M"?"Month":"Year")]=i["draw"+(n=="M"?"Month":"Year")]=parseInt(t.options[t.selectedIndex].value,10),this._notifyChange(i),this._adjustDate(r)},_selectDay:function(e,t,n,r){var i=$(e);if($(r).hasClass(this._unselectableClass)||this._isDisabledDatepicker(i[0]))return;var s=this._getInst(i[0]);s.selectedDay=s.currentDay=$("a",r).html(),s.selectedMonth=s.currentMonth=t,s.selectedYear=s.currentYear=n,this._selectDate(e,this._formatDate(s,s.currentDay,s.currentMonth,s.currentYear))},_clearDate:function(e){var t=$(e),n=this._getInst(t[0]);this._selectDate(t,"")},_selectDate:function(e,t){var n=$(e),r=this._getInst(n[0]);t=t!=null?t:this._formatDate(r),r.input&&r.input.val(t),this._updateAlternate(r);var i=this._get(r,"onSelect");i?i.apply(r.input?r.input[0]:null,[t,r]):r.input&&r.input.trigger("change"),r.inline?this._updateDatepicker(r):(this._hideDatepicker(),this._lastInput=r.input[0],typeof r.input[0]!="object"&&r.input.focus(),this._lastInput=null)},_updateAlternate:function(e){var t=this._get(e,"altField");if(t){var n=this._get(e,"altFormat")||this._get(e,"dateFormat"),r=this._getDate(e),i=this.formatDate(n,r,this._getFormatConfig(e));$(t).each(function(){$(this).val(i)})}},noWeekends:function(e){var t=e.getDay();return[t>0&&t<6,""]},iso8601Week:function(e){var t=new Date(e.getTime());t.setDate(t.getDate()+4-(t.getDay()||7));var n=t.getTime();return t.setMonth(0),t.setDate(1),Math.floor(Math.round((n-t)/864e5)/7)+1},parseDate:function(e,t,n){if(e==null||t==null)throw"Invalid arguments";t=typeof t=="object"?t.toString():t+"";if(t=="")return null;var r=(n?n.shortYearCutoff:null)||this._defaults.shortYearCutoff;r=typeof r!="string"?r:(new Date).getFullYear()%100+parseInt(r,10);var i=(n?n.dayNamesShort:null)||this._defaults.dayNamesShort,s=(n?n.dayNames:null)||this._defaults.dayNames,o=(n?n.monthNamesShort:null)||this._defaults.monthNamesShort,u=(n?n.monthNames:null)||this._defaults.monthNames,a=-1,f=-1,l=-1,c=-1,h=!1,p=function(t){var n=y+1<e.length&&e.charAt(y+1)==t;return n&&y++,n},d=function(e){var n=p(e),r=e=="@"?14:e=="!"?20:e=="y"&&n?4:e=="o"?3:2,i=new RegExp("^\\d{1,"+r+"}"),s=t.substring(g).match(i);if(!s)throw"Missing number at position "+g;return g+=s[0].length,parseInt(s[0],10)},v=function(e,n,r){var i=$.map(p(e)?r:n,function(e,t){return[[t,e]]}).sort(function(e,t){return-(e[1].length-t[1].length)}),s=-1;$.each(i,function(e,n){var r=n[1];if(t.substr(g,r.length).toLowerCase()==r.toLowerCase())return s=n[0],g+=r.length,!1});if(s!=-1)return s+1;throw"Unknown name at position "+g},m=function(){if(t.charAt(g)!=e.charAt(y))throw"Unexpected literal at position "+g;g++},g=0;for(var y=0;y<e.length;y++)if(h)e.charAt(y)=="'"&&!p("'")?h=!1:m();else switch(e.charAt(y)){case"d":l=d("d");break;case"D":v("D",i,s);break;case"o":c=d("o");break;case"m":f=d("m");break;case"M":f=v("M",o,u);break;case"y":a=d("y");break;case"@":var b=new Date(d("@"));a=b.getFullYear(),f=b.getMonth()+1,l=b.getDate();break;case"!":var b=new Date((d("!")-this._ticksTo1970)/1e4);a=b.getFullYear(),f=b.getMonth()+1,l=b.getDate();break;case"'":p("'")?m():h=!0;break;default:m()}if(g<t.length){var w=t.substr(g);if(!/^\s+/.test(w))throw"Extra/unparsed characters found in date: "+w}a==-1?a=(new Date).getFullYear():a<100&&(a+=(new Date).getFullYear()-(new Date).getFullYear()%100+(a<=r?0:-100));if(c>-1){f=1,l=c;do{var E=this._getDaysInMonth(a,f-1);if(l<=E)break;f++,l-=E}while(!0)}var b=this._daylightSavingAdjust(new Date(a,f-1,l));if(b.getFullYear()!=a||b.getMonth()+1!=f||b.getDate()!=l)throw"Invalid date";return b},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*24*60*60*1e7,formatDate:function(e,t,n){if(!t)return"";var r=(n?n.dayNamesShort:null)||this._defaults.dayNamesShort,i=(n?n.dayNames:null)||this._defaults.dayNames,s=(n?n.monthNamesShort:null)||this._defaults.monthNamesShort,o=(n?n.monthNames:null)||this._defaults.monthNames,u=function(t){var n=h+1<e.length&&e.charAt(h+1)==t;return n&&h++,n},a=function(e,t,n){var r=""+t;if(u(e))while(r.length<n)r="0"+r;return r},f=function(e,t,n,r){return u(e)?r[t]:n[t]},l="",c=!1;if(t)for(var h=0;h<e.length;h++)if(c)e.charAt(h)=="'"&&!u("'")?c=!1:l+=e.charAt(h);else switch(e.charAt(h)){case"d":l+=a("d",t.getDate(),2);break;case"D":l+=f("D",t.getDay(),r,i);break;case"o":l+=a("o",Math.round(((new Date(t.getFullYear(),t.getMonth(),t.getDate())).getTime()-(new Date(t.getFullYear(),0,0)).getTime())/864e5),3);break;case"m":l+=a("m",t.getMonth()+1,2);break;case"M":l+=f("M",t.getMonth(),s,o);break;case"y":l+=u("y")?t.getFullYear():(t.getYear()%100<10?"0":"")+t.getYear()%100;break;case"@":l+=t.getTime();break;case"!":l+=t.getTime()*1e4+this._ticksTo1970;break;case"'":u("'")?l+="'":c=!0;break;default:l+=e.charAt(h)}return l},_possibleChars:function(e){var t="",n=!1,r=function(t){var n=i+1<e.length&&e.charAt(i+1)==t;return n&&i++,n};for(var i=0;i<e.length;i++)if(n)e.charAt(i)=="'"&&!r("'")?n=!1:t+=e.charAt(i);else switch(e.charAt(i)){case"d":case"m":case"y":case"@":t+="0123456789";break;case"D":case"M":return null;case"'":r("'")?t+="'":n=!0;break;default:t+=e.charAt(i)}return t},_get:function(e,t){return e.settings[t]!==undefined?e.settings[t]:this._defaults[t]},_setDateFromField:function(e,t){if(e.input.val()==e.lastVal)return;var n=this._get(e,"dateFormat"),r=e.lastVal=e.input?e.input.val():null,i,s;i=s=this._getDefaultDate(e);var o=this._getFormatConfig(e);try{i=this.parseDate(n,r,o)||s}catch(u){this.log(u),r=t?"":r}e.selectedDay=i.getDate(),e.drawMonth=e.selectedMonth=i.getMonth(),e.drawYear=e.selectedYear=i.getFullYear(),e.currentDay=r?i.getDate():0,e.currentMonth=r?i.getMonth():0,e.currentYear=r?i.getFullYear():0,this._adjustInstDate(e)},_getDefaultDate:function(e){return this._restrictMinMax(e,this._determineDate(e,this._get(e,"defaultDate"),new Date))},_determineDate:function(e,t,n){var r=function(e){var t=new Date;return t.setDate(t.getDate()+e),t},i=function(t){try{return $.datepicker.parseDate($.datepicker._get(e,"dateFormat"),t,$.datepicker._getFormatConfig(e))}catch(n){}var r=(t.toLowerCase().match(/^c/)?$.datepicker._getDate(e):null)||new Date,i=r.getFullYear(),s=r.getMonth(),o=r.getDate(),u=/([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,a=u.exec(t);while(a){switch(a[2]||"d"){case"d":case"D":o+=parseInt(a[1],10);break;case"w":case"W":o+=parseInt(a[1],10)*7;break;case"m":case"M":s+=parseInt(a[1],10),o=Math.min(o,$.datepicker._getDaysInMonth(i,s));break;case"y":case"Y":i+=parseInt(a[1],10),o=Math.min(o,$.datepicker._getDaysInMonth(i,s))}a=u.exec(t)}return new Date(i,s,o)},s=t==null||t===""?n:typeof t=="string"?i(t):typeof t=="number"?isNaN(t)?n:r(t):new Date(t.getTime());return s=s&&s.toString()=="Invalid Date"?n:s,s&&(s.setHours(0),s.setMinutes(0),s.setSeconds(0),s.setMilliseconds(0)),this._daylightSavingAdjust(s)},_daylightSavingAdjust:function(e){return e?(e.setHours(e.getHours()>12?e.getHours()+2:0),e):null},_setDate:function(e,t,n){var r=!t,i=e.selectedMonth,s=e.selectedYear,o=this._restrictMinMax(e,this._determineDate(e,t,new Date));e.selectedDay=e.currentDay=o.getDate(),e.drawMonth=e.selectedMonth=e.currentMonth=o.getMonth(),e.drawYear=e.selectedYear=e.currentYear=o.getFullYear(),(i!=e.selectedMonth||s!=e.selectedYear)&&!n&&this._notifyChange(e),this._adjustInstDate(e),e.input&&e.input.val(r?"":this._formatDate(e))},_getDate:function(e){var t=!e.currentYear||e.input&&e.input.val()==""?null:this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return t},_attachHandlers:function(e){var t=this._get(e,"stepMonths"),n="#"+e.id.replace(/\\\\/g,"\\");e.dpDiv.find("[data-handler]").map(function(){var e={prev:function(){window["DP_jQuery_"+dpuuid].datepicker._adjustDate(n,-t,"M")},next:function(){window["DP_jQuery_"+dpuuid].datepicker._adjustDate(n,+t,"M")},hide:function(){window["DP_jQuery_"+dpuuid].datepicker._hideDatepicker()},today:function(){window["DP_jQuery_"+dpuuid].datepicker._gotoToday(n)},selectDay:function(){return window["DP_jQuery_"+dpuuid].datepicker._selectDay(n,+this.getAttribute("data-month"),+this.getAttribute("data-year"),this),!1},selectMonth:function(){return window["DP_jQuery_"+dpuuid].datepicker._selectMonthYear(n,this,"M"),!1},selectYear:function(){return window["DP_jQuery_"+dpuuid].datepicker._selectMonthYear(n,this,"Y"),!1}};$(this).bind(this.getAttribute("data-event"),e[this.getAttribute("data-handler")])})},_generateHTML:function(e){var t=new Date;t=this._daylightSavingAdjust(new Date(t.getFullYear(),t.getMonth(),t.getDate()));var n=this._get(e,"isRTL"),r=this._get(e,"showButtonPanel"),i=this._get(e,"hideIfNoPrevNext"),s=this._get(e,"navigationAsDateFormat"),o=this._getNumberOfMonths(e),u=this._get(e,"showCurrentAtPos"),a=this._get(e,"stepMonths"),f=o[0]!=1||o[1]!=1,l=this._daylightSavingAdjust(e.currentDay?new Date(e.currentYear,e.currentMonth,e.currentDay):new Date(9999,9,9)),c=this._getMinMaxDate(e,"min"),h=this._getMinMaxDate(e,"max"),p=e.drawMonth-u,d=e.drawYear;p<0&&(p+=12,d--);if(h){var v=this._daylightSavingAdjust(new Date(h.getFullYear(),h.getMonth()-o[0]*o[1]+1,h.getDate()));v=c&&v<c?c:v;while(this._daylightSavingAdjust(new Date(d,p,1))>v)p--,p<0&&(p=11,d--)}e.drawMonth=p,e.drawYear=d;var m=this._get(e,"prevText");m=s?this.formatDate(m,this._daylightSavingAdjust(new Date(d,p-a,1)),this._getFormatConfig(e)):m;var g=this._canAdjustMonth(e,-1,d,p)?'<a class="ui-datepicker-prev ui-corner-all" data-handler="prev" data-event="click" title="'+m+'"><span class="ui-icon ui-icon-circle-triangle-'+(n?"e":"w")+'">'+m+"</span></a>":i?"":'<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+m+'"><span class="ui-icon ui-icon-circle-triangle-'+(n?"e":"w")+'">'+m+"</span></a>",y=this._get(e,"nextText");y=s?this.formatDate(y,this._daylightSavingAdjust(new Date(d,p+a,1)),this._getFormatConfig(e)):y;var b=this._canAdjustMonth(e,1,d,p)?'<a class="ui-datepicker-next ui-corner-all" data-handler="next" data-event="click" title="'+y+'"><span class="ui-icon ui-icon-circle-triangle-'+(n?"w":"e")+'">'+y+"</span></a>":i?"":'<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+y+'"><span class="ui-icon ui-icon-circle-triangle-'+(n?"w":"e")+'">'+y+"</span></a>",w=this._get(e,"currentText"),E=this._get(e,"gotoCurrent")&&e.currentDay?l:t;w=s?this.formatDate(w,E,this._getFormatConfig(e)):w;var S=e.inline?"":'<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" data-handler="hide" data-event="click">'+this._get(e,"closeText")+"</button>",x=r?'<div class="ui-datepicker-buttonpane ui-widget-content">'+(n?S:"")+(this._isInRange(e,E)?'<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" data-handler="today" data-event="click">'+w+"</button>":"")+(n?"":S)+"</div>":"",T=parseInt(this._get(e,"firstDay"),10);T=isNaN(T)?0:T;var N=this._get(e,"showWeek"),C=this._get(e,"dayNames"),k=this._get(e,"dayNamesShort"),L=this._get(e,"dayNamesMin"),A=this._get(e,"monthNames"),O=this._get(e,"monthNamesShort"),M=this._get(e,"beforeShowDay"),_=this._get(e,"showOtherMonths"),D=this._get(e,"selectOtherMonths"),P=this._get(e,"calculateWeek")||this.iso8601Week,H=this._getDefaultDate(e),B="";for(var j=0;j<o[0];j++){var F="";this.maxRows=4;for(var I=0;I<o[1];I++){var q=this._daylightSavingAdjust(new Date(d,p,e.selectedDay)),R=" ui-corner-all",U="";if(f){U+='<div class="ui-datepicker-group';if(o[1]>1)switch(I){case 0:U+=" ui-datepicker-group-first",R=" ui-corner-"+(n?"right":"left");break;case o[1]-1:U+=" ui-datepicker-group-last",R=" ui-corner-"+(n?"left":"right");break;default:U+=" ui-datepicker-group-middle",R=""}U+='">'}U+='<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix'+R+'">'+(/all|left/.test(R)&&j==0?n?b:g:"")+(/all|right/.test(R)&&j==0?n?g:b:"")+this._generateMonthYearHeader(e,p,d,c,h,j>0||I>0,A,O)+'</div><table class="ui-datepicker-calendar"><thead>'+"<tr>";var z=N?'<th class="ui-datepicker-week-col">'+this._get(e,"weekHeader")+"</th>":"";for(var W=0;W<7;W++){var X=(W+T)%7;z+="<th"+((W+T+6)%7>=5?' class="ui-datepicker-week-end"':"")+">"+'<span title="'+C[X]+'">'+L[X]+"</span></th>"}U+=z+"</tr></thead><tbody>";var V=this._getDaysInMonth(d,p);d==e.selectedYear&&p==e.selectedMonth&&(e.selectedDay=Math.min(e.selectedDay,V));var J=(this._getFirstDayOfMonth(d,p)-T+7)%7,K=Math.ceil((J+V)/7),Q=f?this.maxRows>K?this.maxRows:K:K;this.maxRows=Q;var G=this._daylightSavingAdjust(new Date(d,p,1-J));for(var Y=0;Y<Q;Y++){U+="<tr>";var Z=N?'<td class="ui-datepicker-week-col">'+this._get(e,"calculateWeek")(G)+"</td>":"";for(var W=0;W<7;W++){var et=M?M.apply(e.input?e.input[0]:null,[G]):[!0,""],tt=G.getMonth()!=p,nt=tt&&!D||!et[0]||c&&G<c||h&&G>h;Z+='<td class="'+((W+T+6)%7>=5?" ui-datepicker-week-end":"")+(tt?" ui-datepicker-other-month":"")+(G.getTime()==q.getTime()&&p==e.selectedMonth&&e._keyEvent||H.getTime()==G.getTime()&&H.getTime()==q.getTime()?" "+this._dayOverClass:"")+(nt?" "+this._unselectableClass+" ui-state-disabled":"")+(tt&&!_?"":" "+et[1]+(G.getTime()==l.getTime()?" "+this._currentClass:"")+(G.getTime()==t.getTime()?" ui-datepicker-today":""))+'"'+((!tt||_)&&et[2]?' title="'+et[2]+'"':"")+(nt?"":' data-handler="selectDay" data-event="click" data-month="'+G.getMonth()+'" data-year="'+G.getFullYear()+'"')+">"+(tt&&!_?"&#xa0;":nt?'<span class="ui-state-default">'+G.getDate()+"</span>":'<a class="ui-state-default'+(G.getTime()==t.getTime()?" ui-state-highlight":"")+(G.getTime()==l.getTime()?" ui-state-active":"")+(tt?" ui-priority-secondary":"")+'" href="#">'+G.getDate()+"</a>")+"</td>",G.setDate(G.getDate()+1),G=this._daylightSavingAdjust(G)}U+=Z+"</tr>"}p++,p>11&&(p=0,d++),U+="</tbody></table>"+(f?"</div>"+(o[0]>0&&I==o[1]-1?'<div class="ui-datepicker-row-break"></div>':""):""),F+=U}B+=F}return B+=x+($.ui.ie6&&!e.inline?'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>':""),e._keyEvent=!1,B},_generateMonthYearHeader:function(e,t,n,r,i,s,o,u){var a=this._get(e,"changeMonth"),f=this._get(e,"changeYear"),l=this._get(e,"showMonthAfterYear"),c='<div class="ui-datepicker-title">',h="";if(s||!a)h+='<span class="ui-datepicker-month">'+o[t]+"</span>";else{var p=r&&r.getFullYear()==n,d=i&&i.getFullYear()==n;h+='<select class="ui-datepicker-month" data-handler="selectMonth" data-event="change">';for(var v=0;v<12;v++)(!p||v>=r.getMonth())&&(!d||v<=i.getMonth())&&(h+='<option value="'+v+'"'+(v==t?' selected="selected"':"")+">"+u[v]+"</option>");h+="</select>"}l||(c+=h+(s||!a||!f?"&#xa0;":""));if(!e.yearshtml){e.yearshtml="";if(s||!f)c+='<span class="ui-datepicker-year">'+n+"</span>";else{var m=this._get(e,"yearRange").split(":"),g=(new Date).getFullYear(),y=function(e){var t=e.match(/c[+-].*/)?n+parseInt(e.substring(1),10):e.match(/[+-].*/)?g+parseInt(e,10):parseInt(e,10);return isNaN(t)?g:t},b=y(m[0]),w=Math.max(b,y(m[1]||""));b=r?Math.max(b,r.getFullYear()):b,w=i?Math.min(w,i.getFullYear()):w,e.yearshtml+='<select class="ui-datepicker-year" data-handler="selectYear" data-event="change">';for(;b<=w;b++)e.yearshtml+='<option value="'+b+'"'+(b==n?' selected="selected"':"")+">"+b+"</option>";e.yearshtml+="</select>",c+=e.yearshtml,e.yearshtml=null}}return c+=this._get(e,"yearSuffix"),l&&(c+=(s||!a||!f?"&#xa0;":"")+h),c+="</div>",c},_adjustInstDate:function(e,t,n){var r=e.drawYear+(n=="Y"?t:0),i=e.drawMonth+(n=="M"?t:0),s=Math.min(e.selectedDay,this._getDaysInMonth(r,i))+(n=="D"?t:0),o=this._restrictMinMax(e,this._daylightSavingAdjust(new Date(r,i,s)));e.selectedDay=o.getDate(),e.drawMonth=e.selectedMonth=o.getMonth(),e.drawYear=e.selectedYear=o.getFullYear(),(n=="M"||n=="Y")&&this._notifyChange(e)},_restrictMinMax:function(e,t){var n=this._getMinMaxDate(e,"min"),r=this._getMinMaxDate(e,"max"),i=n&&t<n?n:t;return i=r&&i>r?r:i,i},_notifyChange:function(e){var t=this._get(e,"onChangeMonthYear");t&&t.apply(e.input?e.input[0]:null,[e.selectedYear,e.selectedMonth+1,e])},_getNumberOfMonths:function(e){var t=this._get(e,"numberOfMonths");return t==null?[1,1]:typeof t=="number"?[1,t]:t},_getMinMaxDate:function(e,t){return this._determineDate(e,this._get(e,t+"Date"),null)},_getDaysInMonth:function(e,t){return 32-this._daylightSavingAdjust(new Date(e,t,32)).getDate()},_getFirstDayOfMonth:function(e,t){return(new Date(e,t,1)).getDay()},_canAdjustMonth:function(e,t,n,r){var i=this._getNumberOfMonths(e),s=this._daylightSavingAdjust(new Date(n,r+(t<0?t:i[0]*i[1]),1));return t<0&&s.setDate(this._getDaysInMonth(s.getFullYear(),s.getMonth())),this._isInRange(e,s)},_isInRange:function(e,t){var n=this._getMinMaxDate(e,"min"),r=this._getMinMaxDate(e,"max");return(!n||t.getTime()>=n.getTime())&&(!r||t.getTime()<=r.getTime())},_getFormatConfig:function(e){var t=this._get(e,"shortYearCutoff");return t=typeof t!="string"?t:(new Date).getFullYear()%100+parseInt(t,10),{shortYearCutoff:t,dayNamesShort:this._get(e,"dayNamesShort"),dayNames:this._get(e,"dayNames"),monthNamesShort:this._get(e,"monthNamesShort"),monthNames:this._get(e,"monthNames")}},_formatDate:function(e,t,n,r){t||(e.currentDay=e.selectedDay,e.currentMonth=e.selectedMonth,e.currentYear=e.selectedYear);var i=t?typeof t=="object"?t:this._daylightSavingAdjust(new Date(r,n,t)):this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return this.formatDate(this._get(e,"dateFormat"),i,this._getFormatConfig(e))}}),$.fn.datepicker=function(e){if(!this.length)return this;$.datepicker.initialized||($(document).mousedown($.datepicker._checkExternalClick).find(document.body).append($.datepicker.dpDiv),$.datepicker.initialized=!0);var t=Array.prototype.slice.call(arguments,1);return typeof e!="string"||e!="isDisabled"&&e!="getDate"&&e!="widget"?e=="option"&&arguments.length==2&&typeof arguments[1]=="string"?$.datepicker["_"+e+"Datepicker"].apply($.datepicker,[this[0]].concat(t)):this.each(function(){typeof e=="string"?$.datepicker["_"+e+"Datepicker"].apply($.datepicker,[this].concat(t)):$.datepicker._attachDatepicker(this,e)}):$.datepicker["_"+e+"Datepicker"].apply($.datepicker,[this[0]].concat(t))},$.datepicker=new Datepicker,$.datepicker.initialized=!1,$.datepicker.uuid=(new Date).getTime(),$.datepicker.version="1.9.2",window["DP_jQuery_"+dpuuid]=$})(jQuery);(function(e,t){var n="ui-dialog ui-widget ui-widget-content ui-corner-all ",r={buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},i={maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0};e.widget("ui.dialog",{version:"1.9.2",options:{autoOpen:!0,buttons:{},closeOnEscape:!0,closeText:"close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:!1,maxWidth:!1,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",of:window,collision:"fit",using:function(t){var n=e(this).css(t).offset().top;n<0&&e(this).css("top",t.top-n)}},resizable:!0,show:null,stack:!0,title:"",width:300,zIndex:1e3},_create:function(){this.originalTitle=this.element.attr("title"),typeof this.originalTitle!="string"&&(this.originalTitle=""),this.oldPosition={parent:this.element.parent(),index:this.element.parent().children().index(this.element)},this.options.title=this.options.title||this.originalTitle;var t=this,r=this.options,i=r.title||"&#160;",s,o,u,a,f;s=(this.uiDialog=e("<div>")).addClass(n+r.dialogClass).css({display:"none",outline:0,zIndex:r.zIndex}).attr("tabIndex",-1).keydown(function(n){r.closeOnEscape&&!n.isDefaultPrevented()&&n.keyCode&&n.keyCode===e.ui.keyCode.ESCAPE&&(t.close(n),n.preventDefault())}).mousedown(function(e){t.moveToTop(!1,e)}).appendTo("body"),this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(s),o=(this.uiDialogTitlebar=e("<div>")).addClass("ui-dialog-titlebar  ui-widget-header  ui-corner-all  ui-helper-clearfix").bind("mousedown",function(){s.focus()}).prependTo(s),u=e("<a href='#'></a>").addClass("ui-dialog-titlebar-close  ui-corner-all").attr("role","button").click(function(e){e.preventDefault(),t.close(e)}).appendTo(o),(this.uiDialogTitlebarCloseText=e("<span>")).addClass("ui-icon ui-icon-closethick").text(r.closeText).appendTo(u),a=e("<span>").uniqueId().addClass("ui-dialog-title").html(i).prependTo(o),f=(this.uiDialogButtonPane=e("<div>")).addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),(this.uiButtonSet=e("<div>")).addClass("ui-dialog-buttonset").appendTo(f),s.attr({role:"dialog","aria-labelledby":a.attr("id")}),o.find("*").add(o).disableSelection(),this._hoverable(u),this._focusable(u),r.draggable&&e.fn.draggable&&this._makeDraggable(),r.resizable&&e.fn.resizable&&this._makeResizable(),this._createButtons(r.buttons),this._isOpen=!1,e.fn.bgiframe&&s.bgiframe(),this._on(s,{keydown:function(t){if(!r.modal||t.keyCode!==e.ui.keyCode.TAB)return;var n=e(":tabbable",s),i=n.filter(":first"),o=n.filter(":last");if(t.target===o[0]&&!t.shiftKey)return i.focus(1),!1;if(t.target===i[0]&&t.shiftKey)return o.focus(1),!1}})},_init:function(){this.options.autoOpen&&this.open()},_destroy:function(){var e,t=this.oldPosition;this.overlay&&this.overlay.destroy(),this.uiDialog.hide(),this.element.removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body"),this.uiDialog.remove(),this.originalTitle&&this.element.attr("title",this.originalTitle),e=t.parent.children().eq(t.index),e.length&&e[0]!==this.element[0]?e.before(this.element):t.parent.append(this.element)},widget:function(){return this.uiDialog},close:function(t){var n=this,r,i;if(!this._isOpen)return;if(!1===this._trigger("beforeClose",t))return;return this._isOpen=!1,this.overlay&&this.overlay.destroy(),this.options.hide?this._hide(this.uiDialog,this.options.hide,function(){n._trigger("close",t)}):(this.uiDialog.hide(),this._trigger("close",t)),e.ui.dialog.overlay.resize(),this.options.modal&&(r=0,e(".ui-dialog").each(function(){this!==n.uiDialog[0]&&(i=e(this).css("z-index"),isNaN(i)||(r=Math.max(r,i)))}),e.ui.dialog.maxZ=r),this},isOpen:function(){return this._isOpen},moveToTop:function(t,n){var r=this.options,i;return r.modal&&!t||!r.stack&&!r.modal?this._trigger("focus",n):(r.zIndex>e.ui.dialog.maxZ&&(e.ui.dialog.maxZ=r.zIndex),this.overlay&&(e.ui.dialog.maxZ+=1,e.ui.dialog.overlay.maxZ=e.ui.dialog.maxZ,this.overlay.$el.css("z-index",e.ui.dialog.overlay.maxZ)),i={scrollTop:this.element.scrollTop(),scrollLeft:this.element.scrollLeft()},e.ui.dialog.maxZ+=1,this.uiDialog.css("z-index",e.ui.dialog.maxZ),this.element.attr(i),this._trigger("focus",n),this)},open:function(){if(this._isOpen)return;var t,n=this.options,r=this.uiDialog;return this._size(),this._position(n.position),r.show(n.show),this.overlay=n.modal?new e.ui.dialog.overlay(this):null,this.moveToTop(!0),t=this.element.find(":tabbable"),t.length||(t=this.uiDialogButtonPane.find(":tabbable"),t.length||(t=r)),t.eq(0).focus(),this._isOpen=!0,this._trigger("open"),this},_createButtons:function(t){var n=this,r=!1;this.uiDialogButtonPane.remove(),this.uiButtonSet.empty(),typeof t=="object"&&t!==null&&e.each(t,function(){return!(r=!0)}),r?(e.each(t,function(t,r){var i,s;r=e.isFunction(r)?{click:r,text:t}:r,r=e.extend({type:"button"},r),s=r.click,r.click=function(){s.apply(n.element[0],arguments)},i=e("<button></button>",r).appendTo(n.uiButtonSet),e.fn.button&&i.button()}),this.uiDialog.addClass("ui-dialog-buttons"),this.uiDialogButtonPane.appendTo(this.uiDialog)):this.uiDialog.removeClass("ui-dialog-buttons")},_makeDraggable:function(){function r(e){return{position:e.position,offset:e.offset}}var t=this,n=this.options;this.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(n,i){e(this).addClass("ui-dialog-dragging"),t._trigger("dragStart",n,r(i))},drag:function(e,n){t._trigger("drag",e,r(n))},stop:function(i,s){n.position=[s.position.left-t.document.scrollLeft(),s.position.top-t.document.scrollTop()],e(this).removeClass("ui-dialog-dragging"),t._trigger("dragStop",i,r(s)),e.ui.dialog.overlay.resize()}})},_makeResizable:function(n){function u(e){return{originalPosition:e.originalPosition,originalSize:e.originalSize,position:e.position,size:e.size}}n=n===t?this.options.resizable:n;var r=this,i=this.options,s=this.uiDialog.css("position"),o=typeof n=="string"?n:"n,e,s,w,se,sw,ne,nw";this.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:this.element,maxWidth:i.maxWidth,maxHeight:i.maxHeight,minWidth:i.minWidth,minHeight:this._minHeight(),handles:o,start:function(t,n){e(this).addClass("ui-dialog-resizing"),r._trigger("resizeStart",t,u(n))},resize:function(e,t){r._trigger("resize",e,u(t))},stop:function(t,n){e(this).removeClass("ui-dialog-resizing"),i.height=e(this).height(),i.width=e(this).width(),r._trigger("resizeStop",t,u(n)),e.ui.dialog.overlay.resize()}}).css("position",s).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var e=this.options;return e.height==="auto"?e.minHeight:Math.min(e.minHeight,e.height)},_position:function(t){var n=[],r=[0,0],i;if(t){if(typeof t=="string"||typeof t=="object"&&"0"in t)n=t.split?t.split(" "):[t[0],t[1]],n.length===1&&(n[1]=n[0]),e.each(["left","top"],function(e,t){+n[e]===n[e]&&(r[e]=n[e],n[e]=t)}),t={my:n[0]+(r[0]<0?r[0]:"+"+r[0])+" "+n[1]+(r[1]<0?r[1]:"+"+r[1]),at:n.join(" ")};t=e.extend({},e.ui.dialog.prototype.options.position,t)}else t=e.ui.dialog.prototype.options.position;i=this.uiDialog.is(":visible"),i||this.uiDialog.show(),this.uiDialog.position(t),i||this.uiDialog.hide()},_setOptions:function(t){var n=this,s={},o=!1;e.each(t,function(e,t){n._setOption(e,t),e in r&&(o=!0),e in i&&(s[e]=t)}),o&&this._size(),this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option",s)},_setOption:function(t,r){var i,s,o=this.uiDialog;switch(t){case"buttons":this._createButtons(r);break;case"closeText":this.uiDialogTitlebarCloseText.text(""+r);break;case"dialogClass":o.removeClass(this.options.dialogClass).addClass(n+r);break;case"disabled":r?o.addClass("ui-dialog-disabled"):o.removeClass("ui-dialog-disabled");break;case"draggable":i=o.is(":data(draggable)"),i&&!r&&o.draggable("destroy"),!i&&r&&this._makeDraggable();break;case"position":this._position(r);break;case"resizable":s=o.is(":data(resizable)"),s&&!r&&o.resizable("destroy"),s&&typeof r=="string"&&o.resizable("option","handles",r),!s&&r!==!1&&this._makeResizable(r);break;case"title":e(".ui-dialog-title",this.uiDialogTitlebar).html(""+(r||"&#160;"))}this._super(t,r)},_size:function(){var t,n,r,i=this.options,s=this.uiDialog.is(":visible");this.element.show().css({width:"auto",minHeight:0,height:0}),i.minWidth>i.width&&(i.width=i.minWidth),t=this.uiDialog.css({height:"auto",width:i.width}).outerHeight(),n=Math.max(0,i.minHeight-t),i.height==="auto"?e.support.minHeight?this.element.css({minHeight:n,height:"auto"}):(this.uiDialog.show(),r=this.element.css("height","auto").height(),s||this.uiDialog.hide(),this.element.height(Math.max(r,n))):this.element.height(Math.max(i.height-t,0)),this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())}}),e.extend(e.ui.dialog,{uuid:0,maxZ:0,getTitleId:function(e){var t=e.attr("id");return t||(this.uuid+=1,t=this.uuid),"ui-dialog-title-"+t},overlay:function(t){this.$el=e.ui.dialog.overlay.create(t)}}),e.extend(e.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:e.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(e){return e+".dialog-overlay"}).join(" "),create:function(t){this.instances.length===0&&(setTimeout(function(){e.ui.dialog.overlay.instances.length&&e(document).bind(e.ui.dialog.overlay.events,function(t){if(e(t.target).zIndex()<e.ui.dialog.overlay.maxZ)return!1})},1),e(window).bind("resize.dialog-overlay",e.ui.dialog.overlay.resize));var n=this.oldInstances.pop()||e("<div>").addClass("ui-widget-overlay");return e(document).bind("keydown.dialog-overlay",function(r){var i=e.ui.dialog.overlay.instances;i.length!==0&&i[i.length-1]===n&&t.options.closeOnEscape&&!r.isDefaultPrevented()&&r.keyCode&&r.keyCode===e.ui.keyCode.ESCAPE&&(t.close(r),r.preventDefault())}),n.appendTo(document.body).css({width:this.width(),height:this.height()}),e.fn.bgiframe&&n.bgiframe(),this.instances.push(n),n},destroy:function(t){var n=e.inArray(t,this.instances),r=0;n!==-1&&this.oldInstances.push(this.instances.splice(n,1)[0]),this.instances.length===0&&e([document,window]).unbind(".dialog-overlay"),t.height(0).width(0).remove(),e.each(this.instances,function(){r=Math.max(r,this.css("z-index"))}),this.maxZ=r},height:function(){var t,n;return e.ui.ie?(t=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight),n=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight),t<n?e(window).height()+"px":t+"px"):e(document).height()+"px"},width:function(){var t,n;return e.ui.ie?(t=Math.max(document.documentElement.scrollWidth,document.body.scrollWidth),n=Math.max(document.documentElement.offsetWidth,document.body.offsetWidth),t<n?e(window).width()+"px":t+"px"):e(document).width()+"px"},resize:function(){var t=e([]);e.each(e.ui.dialog.overlay.instances,function(){t=t.add(this)}),t.css({width:0,height:0}).css({width:e.ui.dialog.overlay.width(),height:e.ui.dialog.overlay.height()})}}),e.extend(e.ui.dialog.overlay.prototype,{destroy:function(){e.ui.dialog.overlay.destroy(this.$el)}})})(jQuery);(function(e,t){var n=!1;e.widget("ui.menu",{version:"1.9.2",defaultElement:"<ul>",delay:300,options:{icons:{submenu:"ui-icon-carat-1-e"},menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.element.uniqueId().addClass("ui-menu ui-widget ui-widget-content ui-corner-all").toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length).attr({role:this.options.role,tabIndex:0}).bind("click"+this.eventNamespace,e.proxy(function(e){this.options.disabled&&e.preventDefault()},this)),this.options.disabled&&this.element.addClass("ui-state-disabled").attr("aria-disabled","true"),this._on({"mousedown .ui-menu-item > a":function(e){e.preventDefault()},"click .ui-state-disabled > a":function(e){e.preventDefault()},"click .ui-menu-item:has(a)":function(t){var r=e(t.target).closest(".ui-menu-item");!n&&r.not(".ui-state-disabled").length&&(n=!0,this.select(t),r.has(".ui-menu").length?this.expand(t):this.element.is(":focus")||(this.element.trigger("focus",[!0]),this.active&&this.active.parents(".ui-menu").length===1&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(t){var n=e(t.currentTarget);n.siblings().children(".ui-state-active").removeClass("ui-state-active"),this.focus(t,n)},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(e,t){var n=this.active||this.element.children(".ui-menu-item").eq(0);t||this.focus(e,n)},blur:function(t){this._delay(function(){e.contains(this.element[0],this.document[0].activeElement)||this.collapseAll(t)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(t){e(t.target).closest(".ui-menu").length||this.collapseAll(t),n=!1}})},_destroy:function(){this.element.removeAttr("aria-activedescendant").find(".ui-menu").andSelf().removeClass("ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons").removeAttr("role").removeAttr("tabIndex").removeAttr("aria-labelledby").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-disabled").removeUniqueId().show(),this.element.find(".ui-menu-item").removeClass("ui-menu-item").removeAttr("role").removeAttr("aria-disabled").children("a").removeUniqueId().removeClass("ui-corner-all ui-state-hover").removeAttr("tabIndex").removeAttr("role").removeAttr("aria-haspopup").children().each(function(){var t=e(this);t.data("ui-menu-submenu-carat")&&t.remove()}),this.element.find(".ui-menu-divider").removeClass("ui-menu-divider ui-widget-content")},_keydown:function(t){function a(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}var n,r,i,s,o,u=!0;switch(t.keyCode){case e.ui.keyCode.PAGE_UP:this.previousPage(t);break;case e.ui.keyCode.PAGE_DOWN:this.nextPage(t);break;case e.ui.keyCode.HOME:this._move("first","first",t);break;case e.ui.keyCode.END:this._move("last","last",t);break;case e.ui.keyCode.UP:this.previous(t);break;case e.ui.keyCode.DOWN:this.next(t);break;case e.ui.keyCode.LEFT:this.collapse(t);break;case e.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(t);break;case e.ui.keyCode.ENTER:case e.ui.keyCode.SPACE:this._activate(t);break;case e.ui.keyCode.ESCAPE:this.collapse(t);break;default:u=!1,r=this.previousFilter||"",i=String.fromCharCode(t.keyCode),s=!1,clearTimeout(this.filterTimer),i===r?s=!0:i=r+i,o=new RegExp("^"+a(i),"i"),n=this.activeMenu.children(".ui-menu-item").filter(function(){return o.test(e(this).children("a").text())}),n=s&&n.index(this.active.next())!==-1?this.active.nextAll(".ui-menu-item"):n,n.length||(i=String.fromCharCode(t.keyCode),o=new RegExp("^"+a(i),"i"),n=this.activeMenu.children(".ui-menu-item").filter(function(){return o.test(e(this).children("a").text())})),n.length?(this.focus(t,n),n.length>1?(this.previousFilter=i,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter):delete this.previousFilter}u&&t.preventDefault()},_activate:function(e){this.active.is(".ui-state-disabled")||(this.active.children("a[aria-haspopup='true']").length?this.expand(e):this.select(e))},refresh:function(){var t,n=this.options.icons.submenu,r=this.element.find(this.options.menus);r.filter(":not(.ui-menu)").addClass("ui-menu ui-widget ui-widget-content ui-corner-all").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var t=e(this),r=t.prev("a"),i=e("<span>").addClass("ui-menu-icon ui-icon "+n).data("ui-menu-submenu-carat",!0);r.attr("aria-haspopup","true").prepend(i),t.attr("aria-labelledby",r.attr("id"))}),t=r.add(this.element),t.children(":not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","presentation").children("a").uniqueId().addClass("ui-corner-all").attr({tabIndex:-1,role:this._itemRole()}),t.children(":not(.ui-menu-item)").each(function(){var t=e(this);/[^\-—–\s]/.test(t.text())||t.addClass("ui-widget-content ui-menu-divider")}),t.children(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!e.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},focus:function(e,t){var n,r;this.blur(e,e&&e.type==="focus"),this._scrollIntoView(t),this.active=t.first(),r=this.active.children("a").addClass("ui-state-focus"),this.options.role&&this.element.attr("aria-activedescendant",r.attr("id")),this.active.parent().closest(".ui-menu-item").children("a:first").addClass("ui-state-active"),e&&e.type==="keydown"?this._close():this.timer=this._delay(function(){this._close()},this.delay),n=t.children(".ui-menu"),n.length&&/^mouse/.test(e.type)&&this._startOpening(n),this.activeMenu=t.parent(),this._trigger("focus",e,{item:t})},_scrollIntoView:function(t){var n,r,i,s,o,u;this._hasScroll()&&(n=parseFloat(e.css(this.activeMenu[0],"borderTopWidth"))||0,r=parseFloat(e.css(this.activeMenu[0],"paddingTop"))||0,i=t.offset().top-this.activeMenu.offset().top-n-r,s=this.activeMenu.scrollTop(),o=this.activeMenu.height(),u=t.height(),i<0?this.activeMenu.scrollTop(s+i):i+u>o&&this.activeMenu.scrollTop(s+i-o+u))},blur:function(e,t){t||clearTimeout(this.timer);if(!this.active)return;this.active.children("a").removeClass("ui-state-focus"),this.active=null,this._trigger("blur",e,{item:this.active})},_startOpening:function(e){clearTimeout(this.timer);if(e.attr("aria-hidden")!=="true")return;this.timer=this._delay(function(){this._close(),this._open(e)},this.delay)},_open:function(t){var n=e.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(t.parents(".ui-menu")).hide().attr("aria-hidden","true"),t.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(n)},collapseAll:function(t,n){clearTimeout(this.timer),this.timer=this._delay(function(){var r=n?this.element:e(t&&t.target).closest(this.element.find(".ui-menu"));r.length||(r=this.element),this._close(r),this.blur(t),this.activeMenu=r},this.delay)},_close:function(e){e||(e=this.active?this.active.parent():this.element),e.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false").end().find("a.ui-state-active").removeClass("ui-state-active")},collapse:function(e){var t=this.active&&this.active.parent().closest(".ui-menu-item",this.element);t&&t.length&&(this._close(),this.focus(e,t))},expand:function(e){var t=this.active&&this.active.children(".ui-menu ").children(".ui-menu-item").first();t&&t.length&&(this._open(t.parent()),this._delay(function(){this.focus(e,t)}))},next:function(e){this._move("next","first",e)},previous:function(e){this._move("prev","last",e)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_move:function(e,t,n){var r;this.active&&(e==="first"||e==="last"?r=this.active[e==="first"?"prevAll":"nextAll"](".ui-menu-item").eq(-1):r=this.active[e+"All"](".ui-menu-item").eq(0));if(!r||!r.length||!this.active)r=this.activeMenu.children(".ui-menu-item")[t]();this.focus(n,r)},nextPage:function(t){var n,r,i;if(!this.active){this.next(t);return}if(this.isLastItem())return;this._hasScroll()?(r=this.active.offset().top,i=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return n=e(this),n.offset().top-r-i<0}),this.focus(t,n)):this.focus(t,this.activeMenu.children(".ui-menu-item")[this.active?"last":"first"]())},previousPage:function(t){var n,r,i;if(!this.active){this.next(t);return}if(this.isFirstItem())return;this._hasScroll()?(r=this.active.offset().top,i=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return n=e(this),n.offset().top-r+i>0}),this.focus(t,n)):this.focus(t,this.activeMenu.children(".ui-menu-item").first())},_hasScroll:function(){return this.element.outerHeight()<this.element.prop("scrollHeight")},select:function(t){this.active=this.active||e(t.target).closest(".ui-menu-item");var n={item:this.active};this.active.has(".ui-menu").length||this.collapseAll(t,!0),this._trigger("select",t,n)}})})(jQuery);(function(e,t){e.widget("ui.progressbar",{version:"1.9.2",options:{value:0,max:100},min:0,_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min,"aria-valuemax":this.options.max,"aria-valuenow":this._value()}),this.valueDiv=e("<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>").appendTo(this.element),this.oldValue=this._value(),this._refreshValue()},_destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove()},value:function(e){return e===t?this._value():(this._setOption("value",e),this)},_setOption:function(e,t){e==="value"&&(this.options.value=t,this._refreshValue(),this._value()===this.options.max&&this._trigger("complete")),this._super(e,t)},_value:function(){var e=this.options.value;return typeof e!="number"&&(e=0),Math.min(this.options.max,Math.max(this.min,e))},_percentage:function(){return 100*this._value()/this.options.max},_refreshValue:function(){var e=this.value(),t=this._percentage();this.oldValue!==e&&(this.oldValue=e,this._trigger("change")),this.valueDiv.toggle(e>this.min).toggleClass("ui-corner-right",e===this.options.max).width(t.toFixed(0)+"%"),this.element.attr("aria-valuenow",e)}})})(jQuery);(function(e,t){var n=5;e.widget("ui.slider",e.ui.mouse,{version:"1.9.2",widgetEventPrefix:"slide",options:{animate:!1,distance:0,max:100,min:0,orientation:"horizontal",range:!1,step:1,value:0,values:null},_create:function(){var t,r,i=this.options,s=this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),o="<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",u=[];this._keySliding=!1,this._mouseSliding=!1,this._animateOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget"+" ui-widget-content"+" ui-corner-all"+(i.disabled?" ui-slider-disabled ui-disabled":"")),this.range=e([]),i.range&&(i.range===!0&&(i.values||(i.values=[this._valueMin(),this._valueMin()]),i.values.length&&i.values.length!==2&&(i.values=[i.values[0],i.values[0]])),this.range=e("<div></div>").appendTo(this.element).addClass("ui-slider-range ui-widget-header"+(i.range==="min"||i.range==="max"?" ui-slider-range-"+i.range:""))),r=i.values&&i.values.length||1;for(t=s.length;t<r;t++)u.push(o);this.handles=s.add(e(u.join("")).appendTo(this.element)),this.handle=this.handles.eq(0),this.handles.add(this.range).filter("a").click(function(e){e.preventDefault()}).mouseenter(function(){i.disabled||e(this).addClass("ui-state-hover")}).mouseleave(function(){e(this).removeClass("ui-state-hover")}).focus(function(){i.disabled?e(this).blur():(e(".ui-slider .ui-state-focus").removeClass("ui-state-focus"),e(this).addClass("ui-state-focus"))}).blur(function(){e(this).removeClass("ui-state-focus")}),this.handles.each(function(t){e(this).data("ui-slider-handle-index",t)}),this._on(this.handles,{keydown:function(t){var r,i,s,o,u=e(t.target).data("ui-slider-handle-index");switch(t.keyCode){case e.ui.keyCode.HOME:case e.ui.keyCode.END:case e.ui.keyCode.PAGE_UP:case e.ui.keyCode.PAGE_DOWN:case e.ui.keyCode.UP:case e.ui.keyCode.RIGHT:case e.ui.keyCode.DOWN:case e.ui.keyCode.LEFT:t.preventDefault();if(!this._keySliding){this._keySliding=!0,e(t.target).addClass("ui-state-active"),r=this._start(t,u);if(r===!1)return}}o=this.options.step,this.options.values&&this.options.values.length?i=s=this.values(u):i=s=this.value();switch(t.keyCode){case e.ui.keyCode.HOME:s=this._valueMin();break;case e.ui.keyCode.END:s=this._valueMax();break;case e.ui.keyCode.PAGE_UP:s=this._trimAlignValue(i+(this._valueMax()-this._valueMin())/n);break;case e.ui.keyCode.PAGE_DOWN:s=this._trimAlignValue(i-(this._valueMax()-this._valueMin())/n);break;case e.ui.keyCode.UP:case e.ui.keyCode.RIGHT:if(i===this._valueMax())return;s=this._trimAlignValue(i+o);break;case e.ui.keyCode.DOWN:case e.ui.keyCode.LEFT:if(i===this._valueMin())return;s=this._trimAlignValue(i-o)}this._slide(t,u,s)},keyup:function(t){var n=e(t.target).data("ui-slider-handle-index");this._keySliding&&(this._keySliding=!1,this._stop(t,n),this._change(t,n),e(t.target).removeClass("ui-state-active"))}}),this._refreshValue(),this._animateOff=!1},_destroy:function(){this.handles.remove(),this.range.remove(),this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all"),this._mouseDestroy()},_mouseCapture:function(t){var n,r,i,s,o,u,a,f,l=this,c=this.options;return c.disabled?!1:(this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()},this.elementOffset=this.element.offset(),n={x:t.pageX,y:t.pageY},r=this._normValueFromMouse(n),i=this._valueMax()-this._valueMin()+1,this.handles.each(function(t){var n=Math.abs(r-l.values(t));i>n&&(i=n,s=e(this),o=t)}),c.range===!0&&this.values(1)===c.min&&(o+=1,s=e(this.handles[o])),u=this._start(t,o),u===!1?!1:(this._mouseSliding=!0,this._handleIndex=o,s.addClass("ui-state-active").focus(),a=s.offset(),f=!e(t.target).parents().andSelf().is(".ui-slider-handle"),this._clickOffset=f?{left:0,top:0}:{left:t.pageX-a.left-s.width()/2,top:t.pageY-a.top-s.height()/2-(parseInt(s.css("borderTopWidth"),10)||0)-(parseInt(s.css("borderBottomWidth"),10)||0)+(parseInt(s.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(t,o,r),this._animateOff=!0,!0))},_mouseStart:function(){return!0},_mouseDrag:function(e){var t={x:e.pageX,y:e.pageY},n=this._normValueFromMouse(t);return this._slide(e,this._handleIndex,n),!1},_mouseStop:function(e){return this.handles.removeClass("ui-state-active"),this._mouseSliding=!1,this._stop(e,this._handleIndex),this._change(e,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1,!1},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(e){var t,n,r,i,s;return this.orientation==="horizontal"?(t=this.elementSize.width,n=e.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(t=this.elementSize.height,n=e.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),r=n/t,r>1&&(r=1),r<0&&(r=0),this.orientation==="vertical"&&(r=1-r),i=this._valueMax()-this._valueMin(),s=this._valueMin()+r*i,this._trimAlignValue(s)},_start:function(e,t){var n={handle:this.handles[t],value:this.value()};return this.options.values&&this.options.values.length&&(n.value=this.values(t),n.values=this.values()),this._trigger("start",e,n)},_slide:function(e,t,n){var r,i,s;this.options.values&&this.options.values.length?(r=this.values(t?0:1),this.options.values.length===2&&this.options.range===!0&&(t===0&&n>r||t===1&&n<r)&&(n=r),n!==this.values(t)&&(i=this.values(),i[t]=n,s=this._trigger("slide",e,{handle:this.handles[t],value:n,values:i}),r=this.values(t?0:1),s!==!1&&this.values(t,n,!0))):n!==this.value()&&(s=this._trigger("slide",e,{handle:this.handles[t],value:n}),s!==!1&&this.value(n))},_stop:function(e,t){var n={handle:this.handles[t],value:this.value()};this.options.values&&this.options.values.length&&(n.value=this.values(t),n.values=this.values()),this._trigger("stop",e,n)},_change:function(e,t){if(!this._keySliding&&!this._mouseSliding){var n={handle:this.handles[t],value:this.value()};this.options.values&&this.options.values.length&&(n.value=this.values(t),n.values=this.values()),this._trigger("change",e,n)}},value:function(e){if(arguments.length){this.options.value=this._trimAlignValue(e),this._refreshValue(),this._change(null,0);return}return this._value()},values:function(t,n){var r,i,s;if(arguments.length>1){this.options.values[t]=this._trimAlignValue(n),this._refreshValue(),this._change(null,t);return}if(!arguments.length)return this._values();if(!e.isArray(arguments[0]))return this.options.values&&this.options.values.length?this._values(t):this.value();r=this.options.values,i=arguments[0];for(s=0;s<r.length;s+=1)r[s]=this._trimAlignValue(i[s]),this._change(null,s);this._refreshValue()},_setOption:function(t,n){var r,i=0;e.isArray(this.options.values)&&(i=this.options.values.length),e.Widget.prototype._setOption.apply(this,arguments);switch(t){case"disabled":n?(this.handles.filter(".ui-state-focus").blur(),this.handles.removeClass("ui-state-hover"),this.handles.prop("disabled",!0),this.element.addClass("ui-disabled")):(this.handles.prop("disabled",!1),this.element.removeClass("ui-disabled"));break;case"orientation":this._detectOrientation(),this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation),this._refreshValue();break;case"value":this._animateOff=!0,this._refreshValue(),this._change(null,0),this._animateOff=!1;break;case"values":this._animateOff=!0,this._refreshValue();for(r=0;r<i;r+=1)this._change(null,r);this._animateOff=!1;break;case"min":case"max":this._animateOff=!0,this._refreshValue(),this._animateOff=!1}},_value:function(){var e=this.options.value;return e=this._trimAlignValue(e),e},_values:function(e){var t,n,r;if(arguments.length)return t=this.options.values[e],t=this._trimAlignValue(t),t;n=this.options.values.slice();for(r=0;r<n.length;r+=1)n[r]=this._trimAlignValue(n[r]);return n},_trimAlignValue:function(e){if(e<=this._valueMin())return this._valueMin();if(e>=this._valueMax())return this._valueMax();var t=this.options.step>0?this.options.step:1,n=(e-this._valueMin())%t,r=e-n;return Math.abs(n)*2>=t&&(r+=n>0?t:-t),parseFloat(r.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var t,n,r,i,s,o=this.options.range,u=this.options,a=this,f=this._animateOff?!1:u.animate,l={};this.options.values&&this.options.values.length?this.handles.each(function(r){n=(a.values(r)-a._valueMin())/(a._valueMax()-a._valueMin())*100,l[a.orientation==="horizontal"?"left":"bottom"]=n+"%",e(this).stop(1,1)[f?"animate":"css"](l,u.animate),a.options.range===!0&&(a.orientation==="horizontal"?(r===0&&a.range.stop(1,1)[f?"animate":"css"]({left:n+"%"},u.animate),r===1&&a.range[f?"animate":"css"]({width:n-t+"%"},{queue:!1,duration:u.animate})):(r===0&&a.range.stop(1,1)[f?"animate":"css"]({bottom:n+"%"},u.animate),r===1&&a.range[f?"animate":"css"]({height:n-t+"%"},{queue:!1,duration:u.animate}))),t=n}):(r=this.value(),i=this._valueMin(),s=this._valueMax(),n=s!==i?(r-i)/(s-i)*100:0,l[this.orientation==="horizontal"?"left":"bottom"]=n+"%",this.handle.stop(1,1)[f?"animate":"css"](l,u.animate),o==="min"&&this.orientation==="horizontal"&&this.range.stop(1,1)[f?"animate":"css"]({width:n+"%"},u.animate),o==="max"&&this.orientation==="horizontal"&&this.range[f?"animate":"css"]({width:100-n+"%"},{queue:!1,duration:u.animate}),o==="min"&&this.orientation==="vertical"&&this.range.stop(1,1)[f?"animate":"css"]({height:n+"%"},u.animate),o==="max"&&this.orientation==="vertical"&&this.range[f?"animate":"css"]({height:100-n+"%"},{queue:!1,duration:u.animate}))}})})(jQuery);(function(e){function t(e){return function(){var t=this.element.val();e.apply(this,arguments),this._refresh(),t!==this.element.val()&&this._trigger("change")}}e.widget("ui.spinner",{version:"1.9.2",defaultElement:"<input>",widgetEventPrefix:"spin",options:{culture:null,icons:{down:"ui-icon-triangle-1-s",up:"ui-icon-triangle-1-n"},incremental:!0,max:null,min:null,numberFormat:null,page:10,step:1,change:null,spin:null,start:null,stop:null},_create:function(){this._setOption("max",this.options.max),this._setOption("min",this.options.min),this._setOption("step",this.options.step),this._value(this.element.val(),!0),this._draw(),this._on(this._events),this._refresh(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_getCreateOptions:function(){var t={},n=this.element;return e.each(["min","max","step"],function(e,r){var i=n.attr(r);i!==undefined&&i.length&&(t[r]=i)}),t},_events:{keydown:function(e){this._start(e)&&this._keydown(e)&&e.preventDefault()},keyup:"_stop",focus:function(){this.previous=this.element.val()},blur:function(e){if(this.cancelBlur){delete this.cancelBlur;return}this._refresh(),this.previous!==this.element.val()&&this._trigger("change",e)},mousewheel:function(e,t){if(!t)return;if(!this.spinning&&!this._start(e))return!1;this._spin((t>0?1:-1)*this.options.step,e),clearTimeout(this.mousewheelTimer),this.mousewheelTimer=this._delay(function(){this.spinning&&this._stop(e)},100),e.preventDefault()},"mousedown .ui-spinner-button":function(t){function r(){var e=this.element[0]===this.document[0].activeElement;e||(this.element.focus(),this.previous=n,this._delay(function(){this.previous=n}))}var n;n=this.element[0]===this.document[0].activeElement?this.previous:this.element.val(),t.preventDefault(),r.call(this),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,r.call(this)});if(this._start(t)===!1)return;this._repeat(null,e(t.currentTarget).hasClass("ui-spinner-up")?1:-1,t)},"mouseup .ui-spinner-button":"_stop","mouseenter .ui-spinner-button":function(t){if(!e(t.currentTarget).hasClass("ui-state-active"))return;if(this._start(t)===!1)return!1;this._repeat(null,e(t.currentTarget).hasClass("ui-spinner-up")?1:-1,t)},"mouseleave .ui-spinner-button":"_stop"},_draw:function(){var e=this.uiSpinner=this.element.addClass("ui-spinner-input").attr("autocomplete","off").wrap(this._uiSpinnerHtml()).parent().append(this._buttonHtml());this.element.attr("role","spinbutton"),this.buttons=e.find(".ui-spinner-button").attr("tabIndex",-1).button().removeClass("ui-corner-all"),this.buttons.height()>Math.ceil(e.height()*.5)&&e.height()>0&&e.height(e.height()),this.options.disabled&&this.disable()},_keydown:function(t){var n=this.options,r=e.ui.keyCode;switch(t.keyCode){case r.UP:return this._repeat(null,1,t),!0;case r.DOWN:return this._repeat(null,-1,t),!0;case r.PAGE_UP:return this._repeat(null,n.page,t),!0;case r.PAGE_DOWN:return this._repeat(null,-n.page,t),!0}return!1},_uiSpinnerHtml:function(){return"<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>"},_buttonHtml:function(){return"<a class='ui-spinner-button ui-spinner-up ui-corner-tr'><span class='ui-icon "+this.options.icons.up+"'>&#9650;</span>"+"</a>"+"<a class='ui-spinner-button ui-spinner-down ui-corner-br'>"+"<span class='ui-icon "+this.options.icons.down+"'>&#9660;</span>"+"</a>"},_start:function(e){return!this.spinning&&this._trigger("start",e)===!1?!1:(this.counter||(this.counter=1),this.spinning=!0,!0)},_repeat:function(e,t,n){e=e||500,clearTimeout(this.timer),this.timer=this._delay(function(){this._repeat(40,t,n)},e),this._spin(t*this.options.step,n)},_spin:function(e,t){var n=this.value()||0;this.counter||(this.counter=1),n=this._adjustValue(n+e*this._increment(this.counter));if(!this.spinning||this._trigger("spin",t,{value:n})!==!1)this._value(n),this.counter++},_increment:function(t){var n=this.options.incremental;return n?e.isFunction(n)?n(t):Math.floor(t*t*t/5e4-t*t/500+17*t/200+1):1},_precision:function(){var e=this._precisionOf(this.options.step);return this.options.min!==null&&(e=Math.max(e,this._precisionOf(this.options.min))),e},_precisionOf:function(e){var t=e.toString(),n=t.indexOf(".");return n===-1?0:t.length-n-1},_adjustValue:function(e){var t,n,r=this.options;return t=r.min!==null?r.min:0,n=e-t,n=Math.round(n/r.step)*r.step,e=t+n,e=parseFloat(e.toFixed(this._precision())),r.max!==null&&e>r.max?r.max:r.min!==null&&e<r.min?r.min:e},_stop:function(e){if(!this.spinning)return;clearTimeout(this.timer),clearTimeout(this.mousewheelTimer),this.counter=0,this.spinning=!1,this._trigger("stop",e)},_setOption:function(e,t){if(e==="culture"||e==="numberFormat"){var n=this._parse(this.element.val());this.options[e]=t,this.element.val(this._format(n));return}(e==="max"||e==="min"||e==="step")&&typeof t=="string"&&(t=this._parse(t)),this._super(e,t),e==="disabled"&&(t?(this.element.prop("disabled",!0),this.buttons.button("disable")):(this.element.prop("disabled",!1),this.buttons.button("enable")))},_setOptions:t(function(e){this._super(e),this._value(this.element.val())}),_parse:function(e){return typeof e=="string"&&e!==""&&(e=window.Globalize&&this.options.numberFormat?Globalize.parseFloat(e,10,this.options.culture):+e),e===""||isNaN(e)?null:e},_format:function(e){return e===""?"":window.Globalize&&this.options.numberFormat?Globalize.format(e,this.options.numberFormat,this.options.culture):e},_refresh:function(){this.element.attr({"aria-valuemin":this.options.min,"aria-valuemax":this.options.max,"aria-valuenow":this._parse(this.element.val())})},_value:function(e,t){var n;e!==""&&(n=this._parse(e),n!==null&&(t||(n=this._adjustValue(n)),e=this._format(n))),this.element.val(e),this._refresh()},_destroy:function(){this.element.removeClass("ui-spinner-input").prop("disabled",!1).removeAttr("autocomplete").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.uiSpinner.replaceWith(this.element)},stepUp:t(function(e){this._stepUp(e)}),_stepUp:function(e){this._spin((e||1)*this.options.step)},stepDown:t(function(e){this._stepDown(e)}),_stepDown:function(e){this._spin((e||1)*-this.options.step)},pageUp:t(function(e){this._stepUp((e||1)*this.options.page)}),pageDown:t(function(e){this._stepDown((e||1)*this.options.page)}),value:function(e){if(!arguments.length)return this._parse(this.element.val());t(this._value).call(this,e)},widget:function(){return this.uiSpinner}})})(jQuery);(function(e,t){function i(){return++n}function s(e){return e.hash.length>1&&e.href.replace(r,"")===location.href.replace(r,"").replace(/\s/g,"%20")}var n=0,r=/#.*$/;e.widget("ui.tabs",{version:"1.9.2",delay:300,options:{active:null,collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_create:function(){var t=this,n=this.options,r=n.active,i=location.hash.substring(1);this.running=!1,this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible",n.collapsible).delegate(".ui-tabs-nav > li","mousedown"+this.eventNamespace,function(t){e(this).is(".ui-state-disabled")&&t.preventDefault()}).delegate(".ui-tabs-anchor","focus"+this.eventNamespace,function(){e(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this._processTabs();if(r===null){i&&this.tabs.each(function(t,n){if(e(n).attr("aria-controls")===i)return r=t,!1}),r===null&&(r=this.tabs.index(this.tabs.filter(".ui-tabs-active")));if(r===null||r===-1)r=this.tabs.length?0:!1}r!==!1&&(r=this.tabs.index(this.tabs.eq(r)),r===-1&&(r=n.collapsible?!1:0)),n.active=r,!n.collapsible&&n.active===!1&&this.anchors.length&&(n.active=0),e.isArray(n.disabled)&&(n.disabled=e.unique(n.disabled.concat(e.map(this.tabs.filter(".ui-state-disabled"),function(e){return t.tabs.index(e)}))).sort()),this.options.active!==!1&&this.anchors.length?this.active=this._findActive(this.options.active):this.active=e(),this._refresh(),this.active.length&&this.load(n.active)},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):e()}},_tabKeydown:function(t){var n=e(this.document[0].activeElement).closest("li"),r=this.tabs.index(n),i=!0;if(this._handlePageNav(t))return;switch(t.keyCode){case e.ui.keyCode.RIGHT:case e.ui.keyCode.DOWN:r++;break;case e.ui.keyCode.UP:case e.ui.keyCode.LEFT:i=!1,r--;break;case e.ui.keyCode.END:r=this.anchors.length-1;break;case e.ui.keyCode.HOME:r=0;break;case e.ui.keyCode.SPACE:t.preventDefault(),clearTimeout(this.activating),this._activate(r);return;case e.ui.keyCode.ENTER:t.preventDefault(),clearTimeout(this.activating),this._activate(r===this.options.active?!1:r);return;default:return}t.preventDefault(),clearTimeout(this.activating),r=this._focusNextTab(r,i),t.ctrlKey||(n.attr("aria-selected","false"),this.tabs.eq(r).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",r)},this.delay))},_panelKeydown:function(t){if(this._handlePageNav(t))return;t.ctrlKey&&t.keyCode===e.ui.keyCode.UP&&(t.preventDefault(),this.active.focus())},_handlePageNav:function(t){if(t.altKey&&t.keyCode===e.ui.keyCode.PAGE_UP)return this._activate(this._focusNextTab(this.options.active-1,!1)),!0;if(t.altKey&&t.keyCode===e.ui.keyCode.PAGE_DOWN)return this._activate(this._focusNextTab(this.options.active+1,!0)),!0},_findNextTab:function(t,n){function i(){return t>r&&(t=0),t<0&&(t=r),t}var r=this.tabs.length-1;while(e.inArray(i(),this.options.disabled)!==-1)t=n?t+1:t-1;return t},_focusNextTab:function(e,t){return e=this._findNextTab(e,t),this.tabs.eq(e).focus(),e},_setOption:function(e,t){if(e==="active"){this._activate(t);return}if(e==="disabled"){this._setupDisabled(t);return}this._super(e,t),e==="collapsible"&&(this.element.toggleClass("ui-tabs-collapsible",t),!t&&this.options.active===!1&&this._activate(0)),e==="event"&&this._setupEvents(t),e==="heightStyle"&&this._setupHeightStyle(t)},_tabId:function(e){return e.attr("aria-controls")||"ui-tabs-"+i()},_sanitizeSelector:function(e){return e?e.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var t=this.options,n=this.tablist.children(":has(a[href])");t.disabled=e.map(n.filter(".ui-state-disabled"),function(e){return n.index(e)}),this._processTabs(),t.active===!1||!this.anchors.length?(t.active=!1,this.active=e()):this.active.length&&!e.contains(this.tablist[0],this.active[0])?this.tabs.length===t.disabled.length?(t.active=!1,this.active=e()):this._activate(this._findNextTab(Math.max(0,t.active-1),!1)):t.active=this.tabs.index(this.active),this._refresh()},_refresh:function(){this._setupDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-expanded":"false","aria-hidden":"true"}),this.active.length?(this.active.addClass("ui-tabs-active ui-state-active").attr({"aria-selected":"true",tabIndex:0}),this._getPanelForTab(this.active).show().attr({"aria-expanded":"true","aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var t=this;this.tablist=this._getList().addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").attr("role","tablist"),this.tabs=this.tablist.find("> li:has(a[href])").addClass("ui-state-default ui-corner-top").attr({role:"tab",tabIndex:-1}),this.anchors=this.tabs.map(function(){return e("a",this)[0]}).addClass("ui-tabs-anchor").attr({role:"presentation",tabIndex:-1}),this.panels=e(),this.anchors.each(function(n,r){var i,o,u,a=e(r).uniqueId().attr("id"),f=e(r).closest("li"),l=f.attr("aria-controls");s(r)?(i=r.hash,o=t.element.find(t._sanitizeSelector(i))):(u=t._tabId(f),i="#"+u,o=t.element.find(i),o.length||(o=t._createPanel(u),o.insertAfter(t.panels[n-1]||t.tablist)),o.attr("aria-live","polite")),o.length&&(t.panels=t.panels.add(o)),l&&f.data("ui-tabs-aria-controls",l),f.attr({"aria-controls":i.substring(1),"aria-labelledby":a}),o.attr("aria-labelledby",a)}),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role","tabpanel")},_getList:function(){return this.element.find("ol,ul").eq(0)},_createPanel:function(t){return e("<div>").attr("id",t).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)},_setupDisabled:function(t){e.isArray(t)&&(t.length?t.length===this.anchors.length&&(t=!0):t=!1);for(var n=0,r;r=this.tabs[n];n++)t===!0||e.inArray(n,t)!==-1?e(r).addClass("ui-state-disabled").attr("aria-disabled","true"):e(r).removeClass("ui-state-disabled").removeAttr("aria-disabled");this.options.disabled=t},_setupEvents:function(t){var n={click:function(e){e.preventDefault()}};t&&e.each(t.split(" "),function(e,t){n[t]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(this.anchors,n),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(t){var n,r,i=this.element.parent();t==="fill"?(e.support.minHeight||(r=i.css("overflow"),i.css("overflow","hidden")),n=i.height(),this.element.siblings(":visible").each(function(){var t=e(this),r=t.css("position");if(r==="absolute"||r==="fixed")return;n-=t.outerHeight(!0)}),r&&i.css("overflow",r),this.element.children().not(this.panels).each(function(){n-=e(this).outerHeight(!0)}),this.panels.each(function(){e(this).height(Math.max(0,n-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):t==="auto"&&(n=0,this.panels.each(function(){n=Math.max(n,e(this).height("").height())}).height(n))},_eventHandler:function(t){var n=this.options,r=this.active,i=e(t.currentTarget),s=i.closest("li"),o=s[0]===r[0],u=o&&n.collapsible,a=u?e():this._getPanelForTab(s),f=r.length?this._getPanelForTab(r):e(),l={oldTab:r,oldPanel:f,newTab:u?e():s,newPanel:a};t.preventDefault();if(s.hasClass("ui-state-disabled")||s.hasClass("ui-tabs-loading")||this.running||o&&!n.collapsible||this._trigger("beforeActivate",t,l)===!1)return;n.active=u?!1:this.tabs.index(s),this.active=o?e():s,this.xhr&&this.xhr.abort(),!f.length&&!a.length&&e.error("jQuery UI Tabs: Mismatching fragment identifier."),a.length&&this.load(this.tabs.index(s),t),this._toggle(t,l)},_toggle:function(t,n){function o(){r.running=!1,r._trigger("activate",t,n)}function u(){n.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),i.length&&r.options.show?r._show(i,r.options.show,o):(i.show(),o())}var r=this,i=n.newPanel,s=n.oldPanel;this.running=!0,s.length&&this.options.hide?this._hide(s,this.options.hide,function(){n.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),u()}):(n.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),s.hide(),u()),s.attr({"aria-expanded":"false","aria-hidden":"true"}),n.oldTab.attr("aria-selected","false"),i.length&&s.length?n.oldTab.attr("tabIndex",-1):i.length&&this.tabs.filter(function(){return e(this).attr("tabIndex")===0}).attr("tabIndex",-1),i.attr({"aria-expanded":"true","aria-hidden":"false"}),n.newTab.attr({"aria-selected":"true",tabIndex:0})},_activate:function(t){var n,r=this._findActive(t);if(r[0]===this.active[0])return;r.length||(r=this.active),n=r.find(".ui-tabs-anchor")[0],this._eventHandler({target:n,currentTarget:n,preventDefault:e.noop})},_findActive:function(t){return t===!1?e():this.tabs.eq(t)},_getIndex:function(e){return typeof e=="string"&&(e=this.anchors.index(this.anchors.filter("[href$='"+e+"']"))),e},_destroy:function(){this.xhr&&this.xhr.abort(),this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible"),this.tablist.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").removeAttr("role"),this.anchors.removeClass("ui-tabs-anchor").removeAttr("role").removeAttr("tabIndex").removeData("href.tabs").removeData("load.tabs").removeUniqueId(),this.tabs.add(this.panels).each(function(){e.data(this,"ui-tabs-destroy")?e(this).remove():e(this).removeClass("ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel").removeAttr("tabIndex").removeAttr("aria-live").removeAttr("aria-busy").removeAttr("aria-selected").removeAttr("aria-labelledby").removeAttr("aria-hidden").removeAttr("aria-expanded").removeAttr("role")}),this.tabs.each(function(){var t=e(this),n=t.data("ui-tabs-aria-controls");n?t.attr("aria-controls",n):t.removeAttr("aria-controls")}),this.panels.show(),this.options.heightStyle!=="content"&&this.panels.css("height","")},enable:function(n){var r=this.options.disabled;if(r===!1)return;n===t?r=!1:(n=this._getIndex(n),e.isArray(r)?r=e.map(r,function(e){return e!==n?e:null}):r=e.map(this.tabs,function(e,t){return t!==n?t:null})),this._setupDisabled(r)},disable:function(n){var r=this.options.disabled;if(r===!0)return;if(n===t)r=!0;else{n=this._getIndex(n);if(e.inArray(n,r)!==-1)return;e.isArray(r)?r=e.merge([n],r).sort():r=[n]}this._setupDisabled(r)},load:function(t,n){t=this._getIndex(t);var r=this,i=this.tabs.eq(t),o=i.find(".ui-tabs-anchor"),u=this._getPanelForTab(i),a={tab:i,panel:u};if(s(o[0]))return;this.xhr=e.ajax(this._ajaxSettings(o,n,a)),this.xhr&&this.xhr.statusText!=="canceled"&&(i.addClass("ui-tabs-loading"),u.attr("aria-busy","true"),this.xhr.success(function(e){setTimeout(function(){u.html(e),r._trigger("load",n,a)},1)}).complete(function(e,t){setTimeout(function(){t==="abort"&&r.panels.stop(!1,!0),i.removeClass("ui-tabs-loading"),u.removeAttr("aria-busy"),e===r.xhr&&delete r.xhr},1)}))},_ajaxSettings:function(t,n,r){var i=this;return{url:t.attr("href"),beforeSend:function(t,s){return i._trigger("beforeLoad",n,e.extend({jqXHR:t,ajaxSettings:s},r))}}},_getPanelForTab:function(t){var n=e(t).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+n))}}),e.uiBackCompat!==!1&&(e.ui.tabs.prototype._ui=function(e,t){return{tab:e,panel:t,index:this.anchors.index(e)}},e.widget("ui.tabs",e.ui.tabs,{url:function(e,t){this.anchors.eq(e).attr("href",t)}}),e.widget("ui.tabs",e.ui.tabs,{options:{ajaxOptions:null,cache:!1},_create:function(){this._super();var t=this;this._on({tabsbeforeload:function(n,r){if(e.data(r.tab[0],"cache.tabs")){n.preventDefault();return}r.jqXHR.success(function(){t.options.cache&&e.data(r.tab[0],"cache.tabs",!0)})}})},_ajaxSettings:function(t,n,r){var i=this.options.ajaxOptions;return e.extend({},i,{error:function(e,t){try{i.error(e,t,r.tab.closest("li").index(),r.tab[0])}catch(n){}}},this._superApply(arguments))},_setOption:function(e,t){e==="cache"&&t===!1&&this.anchors.removeData("cache.tabs"),this._super(e,t)},_destroy:function(){this.anchors.removeData("cache.tabs"),this._super()},url:function(e){this.anchors.eq(e).removeData("cache.tabs"),this._superApply(arguments)}}),e.widget("ui.tabs",e.ui.tabs,{abort:function(){this.xhr&&this.xhr.abort()}}),e.widget("ui.tabs",e.ui.tabs,{options:{spinner:"<em>Loading&#8230;</em>"},_create:function(){this._super(),this._on({tabsbeforeload:function(e,t){if(e.target!==this.element[0]||!this.options.spinner)return;var n=t.tab.find("span"),r=n.html();n.html(this.options.spinner),t.jqXHR.complete(function(){n.html(r)})}})}}),e.widget("ui.tabs",e.ui.tabs,{options:{enable:null,disable:null},enable:function(t){var n=this.options,r;if(t&&n.disabled===!0||e.isArray(n.disabled)&&e.inArray(t,n.disabled)!==-1)r=!0;this._superApply(arguments),r&&this._trigger("enable",null,this._ui(this.anchors[t],this.panels[t]))},disable:function(t){var n=this.options,r;if(t&&n.disabled===!1||e.isArray(n.disabled)&&e.inArray(t,n.disabled)===-1)r=!0;this._superApply(arguments),r&&this._trigger("disable",null,this._ui(this.anchors[t],this.panels[t]))}}),e.widget("ui.tabs",e.ui.tabs,{options:{add:null,remove:null,tabTemplate:"<li><a href='#{href}'><span>#{label}</span></a></li>"},add:function(n,r,i){i===t&&(i=this.anchors.length);var s,o,u=this.options,a=e(u.tabTemplate.replace(/#\{href\}/g,n).replace(/#\{label\}/g,r)),f=n.indexOf("#")?this._tabId(a):n.replace("#","");return a.addClass("ui-state-default ui-corner-top").data("ui-tabs-destroy",!0),a.attr("aria-controls",f),s=i>=this.tabs.length,o=this.element.find("#"+f),o.length||(o=this._createPanel(f),s?i>0?o.insertAfter(this.panels.eq(-1)):o.appendTo(this.element):o.insertBefore(this.panels[i])),o.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").hide(),s?a.appendTo(this.tablist):a.insertBefore(this.tabs[i]),u.disabled=e.map(u.disabled,function(e){return e>=i?++e:e}),this.refresh(),this.tabs.length===1&&u.active===!1&&this.option("active",0),this._trigger("add",null,this._ui(this.anchors[i],this.panels[i])),this},remove:function(t){t=this._getIndex(t);var n=this.options,r=this.tabs.eq(t).remove(),i=this._getPanelForTab(r).remove();return r.hasClass("ui-tabs-active")&&this.anchors.length>2&&this._activate(t+(t+1<this.anchors.length?1:-1)),n.disabled=e.map(e.grep(n.disabled,function(e){return e!==t}),function(e){return e>=t?--e:e}),this.refresh(),this._trigger("remove",null,this._ui(r.find("a")[0],i[0])),this}}),e.widget("ui.tabs",e.ui.tabs,{length:function(){return this.anchors.length}}),e.widget("ui.tabs",e.ui.tabs,{options:{idPrefix:"ui-tabs-"},_tabId:function(t){var n=t.is("li")?t.find("a[href]"):t;return n=n[0],e(n).closest("li").attr("aria-controls")||n.title&&n.title.replace(/\s/g,"_").replace(/[^\w\u00c0-\uFFFF\-]/g,"")||this.options.idPrefix+i()}}),e.widget("ui.tabs",e.ui.tabs,{options:{panelTemplate:"<div></div>"},_createPanel:function(t){return e(this.options.panelTemplate).attr("id",t).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)}}),e.widget("ui.tabs",e.ui.tabs,{_create:function(){var e=this.options;e.active===null&&e.selected!==t&&(e.active=e.selected===-1?!1:e.selected),this._super(),e.selected=e.active,e.selected===!1&&(e.selected=-1)},_setOption:function(e,t){if(e!=="selected")return this._super(e,t);var n=this.options;this._super("active",t===-1?!1:t),n.selected=n.active,n.selected===!1&&(n.selected=-1)},_eventHandler:function(){this._superApply(arguments),this.options.selected=this.options.active,this.options.selected===!1&&(this.options.selected=-1)}}),e.widget("ui.tabs",e.ui.tabs,{options:{show:null,select:null},_create:function(){this._super(),this.options.active!==!1&&this._trigger("show",null,this._ui(this.active.find(".ui-tabs-anchor")[0],this._getPanelForTab(this.active)[0]))},_trigger:function(e,t,n){var r,i,s=this._superApply(arguments);return s?(e==="beforeActivate"?(r=n.newTab.length?n.newTab:n.oldTab,i=n.newPanel.length?n.newPanel:n.oldPanel,s=this._super("select",t,{tab:r.find(".ui-tabs-anchor")[0],panel:i[0],index:r.closest("li").index()})):e==="activate"&&n.newTab.length&&(s=this._super("show",t,{tab:n.newTab.find(".ui-tabs-anchor")[0],panel:n.newPanel[0],index:n.newTab.closest("li").index()})),s):!1}}),e.widget("ui.tabs",e.ui.tabs,{select:function(e){e=this._getIndex(e);if(e===-1){if(!this.options.collapsible||this.options.selected===-1)return;e=this.options.selected}this.anchors.eq(e).trigger(this.options.event+this.eventNamespace)}}),function(){var t=0;e.widget("ui.tabs",e.ui.tabs,{options:{cookie:null},_create:function(){var e=this.options,t;e.active==null&&e.cookie&&(t=parseInt(this._cookie(),10),t===-1&&(t=!1),e.active=t),this._super()},_cookie:function(n){var r=[this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+ ++t)];return arguments.length&&(r.push(n===!1?-1:n),r.push(this.options.cookie)),e.cookie.apply(null,r)},_refresh:function(){this._super(),this.options.cookie&&this._cookie(this.options.active,this.options.cookie)},_eventHandler:function(){this._superApply(arguments),this.options.cookie&&this._cookie(this.options.active,this.options.cookie)},_destroy:function(){this._super(),this.options.cookie&&this._cookie(null,this.options.cookie)}})}(),e.widget("ui.tabs",e.ui.tabs,{_trigger:function(t,n,r){var i=e.extend({},r);return t==="load"&&(i.panel=i.panel[0],i.tab=i.tab.find(".ui-tabs-anchor")[0]),this._super(t,n,i)}}),e.widget("ui.tabs",e.ui.tabs,{options:{fx:null},_getFx:function(){var t,n,r=this.options.fx;return r&&(e.isArray(r)?(t=r[0],n=r[1]):t=n=r),r?{show:n,hide:t}:null},_toggle:function(e,t){function o(){n.running=!1,n._trigger("activate",e,t)}function u(){t.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),r.length&&s.show?r.animate(s.show,s.show.duration,function(){o()}):(r.show(),o())}var n=this,r=t.newPanel,i=t.oldPanel,s=this._getFx();if(!s)return this._super(e,t);n.running=!0,i.length&&s.hide?i.animate(s.hide,s.hide.duration,function(){t.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),u()}):(t.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),i.hide(),u())}}))})(jQuery);(function(e){function n(t,n){var r=(t.attr("aria-describedby")||"").split(/\s+/);r.push(n),t.data("ui-tooltip-id",n).attr("aria-describedby",e.trim(r.join(" ")))}function r(t){var n=t.data("ui-tooltip-id"),r=(t.attr("aria-describedby")||"").split(/\s+/),i=e.inArray(n,r);i!==-1&&r.splice(i,1),t.removeData("ui-tooltip-id"),r=e.trim(r.join(" ")),r?t.attr("aria-describedby",r):t.removeAttr("aria-describedby")}var t=0;e.widget("ui.tooltip",{version:"1.9.2",options:{content:function(){return e(this).attr("title")},hide:!0,items:"[title]:not([disabled])",position:{my:"left top+15",at:"left bottom",collision:"flipfit flip"},show:!0,tooltipClass:null,track:!1,close:null,open:null},_create:function(){this._on({mouseover:"open",focusin:"open"}),this.tooltips={},this.parents={},this.options.disabled&&this._disable()},_setOption:function(t,n){var r=this;if(t==="disabled"){this[n?"_disable":"_enable"](),this.options[t]=n;return}this._super(t,n),t==="content"&&e.each(this.tooltips,function(e,t){r._updateContent(t)})},_disable:function(){var t=this;e.each(this.tooltips,function(n,r){var i=e.Event("blur");i.target=i.currentTarget=r[0],t.close(i,!0)}),this.element.find(this.options.items).andSelf().each(function(){var t=e(this);t.is("[title]")&&t.data("ui-tooltip-title",t.attr("title")).attr("title","")})},_enable:function(){this.element.find(this.options.items).andSelf().each(function(){var t=e(this);t.data("ui-tooltip-title")&&t.attr("title",t.data("ui-tooltip-title"))})},open:function(t){var n=this,r=e(t?t.target:this.element).closest(this.options.items);if(!r.length||r.data("ui-tooltip-id"))return;r.attr("title")&&r.data("ui-tooltip-title",r.attr("title")),r.data("ui-tooltip-open",!0),t&&t.type==="mouseover"&&r.parents().each(function(){var t=e(this),r;t.data("ui-tooltip-open")&&(r=e.Event("blur"),r.target=r.currentTarget=this,n.close(r,!0)),t.attr("title")&&(t.uniqueId(),n.parents[this.id]={element:this,title:t.attr("title")},t.attr("title",""))}),this._updateContent(r,t)},_updateContent:function(e,t){var n,r=this.options.content,i=this,s=t?t.type:null;if(typeof r=="string")return this._open(t,e,r);n=r.call(e[0],function(n){if(!e.data("ui-tooltip-open"))return;i._delay(function(){t&&(t.type=s),this._open(t,e,n)})}),n&&this._open(t,e,n)},_open:function(t,r,i){function f(e){a.of=e;if(s.is(":hidden"))return;s.position(a)}var s,o,u,a=e.extend({},this.options.position);if(!i)return;s=this._find(r);if(s.length){s.find(".ui-tooltip-content").html(i);return}r.is("[title]")&&(t&&t.type==="mouseover"?r.attr("title",""):r.removeAttr("title")),s=this._tooltip(r),n(r,s.attr("id")),s.find(".ui-tooltip-content").html(i),this.options.track&&t&&/^mouse/.test(t.type)?(this._on(this.document,{mousemove:f}),f(t)):s.position(e.extend({of:r},this.options.position)),s.hide(),this._show(s,this.options.show),this.options.show&&this.options.show.delay&&(u=setInterval(function(){s.is(":visible")&&(f(a.of),clearInterval(u))},e.fx.interval)),this._trigger("open",t,{tooltip:s}),o={keyup:function(t){if(t.keyCode===e.ui.keyCode.ESCAPE){var n=e.Event(t);n.currentTarget=r[0],this.close(n,!0)}},remove:function(){this._removeTooltip(s)}};if(!t||t.type==="mouseover")o.mouseleave="close";if(!t||t.type==="focusin")o.focusout="close";this._on(!0,r,o)},close:function(t){var n=this,i=e(t?t.currentTarget:this.element),s=this._find(i);if(this.closing)return;i.data("ui-tooltip-title")&&i.attr("title",i.data("ui-tooltip-title")),r(i),s.stop(!0),this._hide(s,this.options.hide,function(){n._removeTooltip(e(this))}),i.removeData("ui-tooltip-open"),this._off(i,"mouseleave focusout keyup"),i[0]!==this.element[0]&&this._off(i,"remove"),this._off(this.document,"mousemove"),t&&t.type==="mouseleave"&&e.each(this.parents,function(t,r){e(r.element).attr("title",r.title),delete n.parents[t]}),this.closing=!0,this._trigger("close",t,{tooltip:s}),this.closing=!1},_tooltip:function(n){var r="ui-tooltip-"+t++,i=e("<div>").attr({id:r,role:"tooltip"}).addClass("ui-tooltip ui-widget ui-corner-all ui-widget-content "+(this.options.tooltipClass||""));return e("<div>").addClass("ui-tooltip-content").appendTo(i),i.appendTo(this.document[0].body),e.fn.bgiframe&&i.bgiframe(),this.tooltips[r]=n,i},_find:function(t){var n=t.data("ui-tooltip-id");return n?e("#"+n):e()},_removeTooltip:function(e){e.remove(),delete this.tooltips[e.attr("id")]},_destroy:function(){var t=this;e.each(this.tooltips,function(n,r){var i=e.Event("blur");i.target=i.currentTarget=r[0],t.close(i,!0),e("#"+n).remove(),r.data("ui-tooltip-title")&&(r.attr("title",r.data("ui-tooltip-title")),r.removeData("ui-tooltip-title"))})}})})(jQuery);jQuery.effects||function(e,t){var n=e.uiBackCompat!==!1,r="ui-effects-";e.effects={effect:{}},function(t,n){function p(e,t,n){var r=a[t.type]||{};return e==null?n||!t.def?null:t.def:(e=r.floor?~~e:parseFloat(e),isNaN(e)?t.def:r.mod?(e+r.mod)%r.mod:0>e?0:r.max<e?r.max:e)}function d(e){var n=o(),r=n._rgba=[];return e=e.toLowerCase(),h(s,function(t,i){var s,o=i.re.exec(e),a=o&&i.parse(o),f=i.space||"rgba";if(a)return s=n[f](a),n[u[f].cache]=s[u[f].cache],r=n._rgba=s._rgba,!1}),r.length?(r.join()==="0,0,0,0"&&t.extend(r,c.transparent),n):c[e]}function v(e,t,n){return n=(n+1)%1,n*6<1?e+(t-e)*n*6:n*2<1?t:n*3<2?e+(t-e)*(2/3-n)*6:e}var r="backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor".split(" "),i=/^([\-+])=\s*(\d+\.?\d*)/,s=[{re:/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,parse:function(e){return[e[1],e[2],e[3],e[4]]}},{re:/rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,parse:function(e){return[e[1]*2.55,e[2]*2.55,e[3]*2.55,e[4]]}},{re:/#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,parse:function(e){return[parseInt(e[1],16),parseInt(e[2],16),parseInt(e[3],16)]}},{re:/#([a-f0-9])([a-f0-9])([a-f0-9])/,parse:function(e){return[parseInt(e[1]+e[1],16),parseInt(e[2]+e[2],16),parseInt(e[3]+e[3],16)]}},{re:/hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,space:"hsla",parse:function(e){return[e[1],e[2]/100,e[3]/100,e[4]]}}],o=t.Color=function(e,n,r,i){return new t.Color.fn.parse(e,n,r,i)},u={rgba:{props:{red:{idx:0,type:"byte"},green:{idx:1,type:"byte"},blue:{idx:2,type:"byte"}}},hsla:{props:{hue:{idx:0,type:"degrees"},saturation:{idx:1,type:"percent"},lightness:{idx:2,type:"percent"}}}},a={"byte":{floor:!0,max:255},percent:{max:1},degrees:{mod:360,floor:!0}},f=o.support={},l=t("<p>")[0],c,h=t.each;l.style.cssText="background-color:rgba(1,1,1,.5)",f.rgba=l.style.backgroundColor.indexOf("rgba")>-1,h(u,function(e,t){t.cache="_"+e,t.props.alpha={idx:3,type:"percent",def:1}}),o.fn=t.extend(o.prototype,{parse:function(r,i,s,a){if(r===n)return this._rgba=[null,null,null,null],this;if(r.jquery||r.nodeType)r=t(r).css(i),i=n;var f=this,l=t.type(r),v=this._rgba=[];i!==n&&(r=[r,i,s,a],l="array");if(l==="string")return this.parse(d(r)||c._default);if(l==="array")return h(u.rgba.props,function(e,t){v[t.idx]=p(r[t.idx],t)}),this;if(l==="object")return r instanceof o?h(u,function(e,t){r[t.cache]&&(f[t.cache]=r[t.cache].slice())}):h(u,function(t,n){var i=n.cache;h(n.props,function(e,t){if(!f[i]&&n.to){if(e==="alpha"||r[e]==null)return;f[i]=n.to(f._rgba)}f[i][t.idx]=p(r[e],t,!0)}),f[i]&&e.inArray(null,f[i].slice(0,3))<0&&(f[i][3]=1,n.from&&(f._rgba=n.from(f[i])))}),this},is:function(e){var t=o(e),n=!0,r=this;return h(u,function(e,i){var s,o=t[i.cache];return o&&(s=r[i.cache]||i.to&&i.to(r._rgba)||[],h(i.props,function(e,t){if(o[t.idx]!=null)return n=o[t.idx]===s[t.idx],n})),n}),n},_space:function(){var e=[],t=this;return h(u,function(n,r){t[r.cache]&&e.push(n)}),e.pop()},transition:function(e,t){var n=o(e),r=n._space(),i=u[r],s=this.alpha()===0?o("transparent"):this,f=s[i.cache]||i.to(s._rgba),l=f.slice();return n=n[i.cache],h(i.props,function(e,r){var i=r.idx,s=f[i],o=n[i],u=a[r.type]||{};if(o===null)return;s===null?l[i]=o:(u.mod&&(o-s>u.mod/2?s+=u.mod:s-o>u.mod/2&&(s-=u.mod)),l[i]=p((o-s)*t+s,r))}),this[r](l)},blend:function(e){if(this._rgba[3]===1)return this;var n=this._rgba.slice(),r=n.pop(),i=o(e)._rgba;return o(t.map(n,function(e,t){return(1-r)*i[t]+r*e}))},toRgbaString:function(){var e="rgba(",n=t.map(this._rgba,function(e,t){return e==null?t>2?1:0:e});return n[3]===1&&(n.pop(),e="rgb("),e+n.join()+")"},toHslaString:function(){var e="hsla(",n=t.map(this.hsla(),function(e,t){return e==null&&(e=t>2?1:0),t&&t<3&&(e=Math.round(e*100)+"%"),e});return n[3]===1&&(n.pop(),e="hsl("),e+n.join()+")"},toHexString:function(e){var n=this._rgba.slice(),r=n.pop();return e&&n.push(~~(r*255)),"#"+t.map(n,function(e){return e=(e||0).toString(16),e.length===1?"0"+e:e}).join("")},toString:function(){return this._rgba[3]===0?"transparent":this.toRgbaString()}}),o.fn.parse.prototype=o.fn,u.hsla.to=function(e){if(e[0]==null||e[1]==null||e[2]==null)return[null,null,null,e[3]];var t=e[0]/255,n=e[1]/255,r=e[2]/255,i=e[3],s=Math.max(t,n,r),o=Math.min(t,n,r),u=s-o,a=s+o,f=a*.5,l,c;return o===s?l=0:t===s?l=60*(n-r)/u+360:n===s?l=60*(r-t)/u+120:l=60*(t-n)/u+240,f===0||f===1?c=f:f<=.5?c=u/a:c=u/(2-a),[Math.round(l)%360,c,f,i==null?1:i]},u.hsla.from=function(e){if(e[0]==null||e[1]==null||e[2]==null)return[null,null,null,e[3]];var t=e[0]/360,n=e[1],r=e[2],i=e[3],s=r<=.5?r*(1+n):r+n-r*n,o=2*r-s;return[Math.round(v(o,s,t+1/3)*255),Math.round(v(o,s,t)*255),Math.round(v(o,s,t-1/3)*255),i]},h(u,function(e,r){var s=r.props,u=r.cache,a=r.to,f=r.from;o.fn[e]=function(e){a&&!this[u]&&(this[u]=a(this._rgba));if(e===n)return this[u].slice();var r,i=t.type(e),l=i==="array"||i==="object"?e:arguments,c=this[u].slice();return h(s,function(e,t){var n=l[i==="object"?e:t.idx];n==null&&(n=c[t.idx]),c[t.idx]=p(n,t)}),f?(r=o(f(c)),r[u]=c,r):o(c)},h(s,function(n,r){if(o.fn[n])return;o.fn[n]=function(s){var o=t.type(s),u=n==="alpha"?this._hsla?"hsla":"rgba":e,a=this[u](),f=a[r.idx],l;return o==="undefined"?f:(o==="function"&&(s=s.call(this,f),o=t.type(s)),s==null&&r.empty?this:(o==="string"&&(l=i.exec(s),l&&(s=f+parseFloat(l[2])*(l[1]==="+"?1:-1))),a[r.idx]=s,this[u](a)))}})}),h(r,function(e,n){t.cssHooks[n]={set:function(e,r){var i,s,u="";if(t.type(r)!=="string"||(i=d(r))){r=o(i||r);if(!f.rgba&&r._rgba[3]!==1){s=n==="backgroundColor"?e.parentNode:e;while((u===""||u==="transparent")&&s&&s.style)try{u=t.css(s,"backgroundColor"),s=s.parentNode}catch(a){}r=r.blend(u&&u!=="transparent"?u:"_default")}r=r.toRgbaString()}try{e.style[n]=r}catch(l){}}},t.fx.step[n]=function(e){e.colorInit||(e.start=o(e.elem,n),e.end=o(e.end),e.colorInit=!0),t.cssHooks[n].set(e.elem,e.start.transition(e.end,e.pos))}}),t.cssHooks.borderColor={expand:function(e){var t={};return h(["Top","Right","Bottom","Left"],function(n,r){t["border"+r+"Color"]=e}),t}},c=t.Color.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00",transparent:[null,null,null,0],_default:"#ffffff"}}(jQuery),function(){function i(){var t=this.ownerDocument.defaultView?this.ownerDocument.defaultView.getComputedStyle(this,null):this.currentStyle,n={},r,i;if(t&&t.length&&t[0]&&t[t[0]]){i=t.length;while(i--)r=t[i],typeof t[r]=="string"&&(n[e.camelCase(r)]=t[r])}else for(r in t)typeof t[r]=="string"&&(n[r]=t[r]);return n}function s(t,n){var i={},s,o;for(s in n)o=n[s],t[s]!==o&&!r[s]&&(e.fx.step[s]||!isNaN(parseFloat(o)))&&(i[s]=o);return i}var n=["add","remove","toggle"],r={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};e.each(["borderLeftStyle","borderRightStyle","borderBottomStyle","borderTopStyle"],function(t,n){e.fx.step[n]=function(e){if(e.end!=="none"&&!e.setAttr||e.pos===1&&!e.setAttr)jQuery.style(e.elem,n,e.end),e.setAttr=!0}}),e.effects.animateClass=function(t,r,o,u){var a=e.speed(r,o,u);return this.queue(function(){var r=e(this),o=r.attr("class")||"",u,f=a.children?r.find("*").andSelf():r;f=f.map(function(){var t=e(this);return{el:t,start:i.call(this)}}),u=function(){e.each(n,function(e,n){t[n]&&r[n+"Class"](t[n])})},u(),f=f.map(function(){return this.end=i.call(this.el[0]),this.diff=s(this.start,this.end),this}),r.attr("class",o),f=f.map(function(){var t=this,n=e.Deferred(),r=jQuery.extend({},a,{queue:!1,complete:function(){n.resolve(t)}});return this.el.animate(this.diff,r),n.promise()}),e.when.apply(e,f.get()).done(function(){u(),e.each(arguments,function(){var t=this.el;e.each(this.diff,function(e){t.css(e,"")})}),a.complete.call(r[0])})})},e.fn.extend({_addClass:e.fn.addClass,addClass:function(t,n,r,i){return n?e.effects.animateClass.call(this,{add:t},n,r,i):this._addClass(t)},_removeClass:e.fn.removeClass,removeClass:function(t,n,r,i){return n?e.effects.animateClass.call(this,{remove:t},n,r,i):this._removeClass(t)},_toggleClass:e.fn.toggleClass,toggleClass:function(n,r,i,s,o){return typeof r=="boolean"||r===t?i?e.effects.animateClass.call(this,r?{add:n}:{remove:n},i,s,o):this._toggleClass(n,r):e.effects.animateClass.call(this,{toggle:n},r,i,s)},switchClass:function(t,n,r,i,s){return e.effects.animateClass.call(this,{add:n,remove:t},r,i,s)}})}(),function(){function i(t,n,r,i){e.isPlainObject(t)&&(n=t,t=t.effect),t={effect:t},n==null&&(n={}),e.isFunction(n)&&(i=n,r=null,n={});if(typeof n=="number"||e.fx.speeds[n])i=r,r=n,n={};return e.isFunction(r)&&(i=r,r=null),n&&e.extend(t,n),r=r||n.duration,t.duration=e.fx.off?0:typeof r=="number"?r:r in e.fx.speeds?e.fx.speeds[r]:e.fx.speeds._default,t.complete=i||n.complete,t}function s(t){return!t||typeof t=="number"||e.fx.speeds[t]?!0:typeof t=="string"&&!e.effects.effect[t]?n&&e.effects[t]?!1:!0:!1}e.extend(e.effects,{version:"1.9.2",save:function(e,t){for(var n=0;n<t.length;n++)t[n]!==null&&e.data(r+t[n],e[0].style[t[n]])},restore:function(e,n){var i,s;for(s=0;s<n.length;s++)n[s]!==null&&(i=e.data(r+n[s]),i===t&&(i=""),e.css(n[s],i))},setMode:function(e,t){return t==="toggle"&&(t=e.is(":hidden")?"show":"hide"),t},getBaseline:function(e,t){var n,r;switch(e[0]){case"top":n=0;break;case"middle":n=.5;break;case"bottom":n=1;break;default:n=e[0]/t.height}switch(e[1]){case"left":r=0;break;case"center":r=.5;break;case"right":r=1;break;default:r=e[1]/t.width}return{x:r,y:n}},createWrapper:function(t){if(t.parent().is(".ui-effects-wrapper"))return t.parent();var n={width:t.outerWidth(!0),height:t.outerHeight(!0),"float":t.css("float")},r=e("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),i={width:t.width(),height:t.height()},s=document.activeElement;try{s.id}catch(o){s=document.body}return t.wrap(r),(t[0]===s||e.contains(t[0],s))&&e(s).focus(),r=t.parent(),t.css("position")==="static"?(r.css({position:"relative"}),t.css({position:"relative"})):(e.extend(n,{position:t.css("position"),zIndex:t.css("z-index")}),e.each(["top","left","bottom","right"],function(e,r){n[r]=t.css(r),isNaN(parseInt(n[r],10))&&(n[r]="auto")}),t.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),t.css(i),r.css(n).show()},removeWrapper:function(t){var n=document.activeElement;return t.parent().is(".ui-effects-wrapper")&&(t.parent().replaceWith(t),(t[0]===n||e.contains(t[0],n))&&e(n).focus()),t},setTransition:function(t,n,r,i){return i=i||{},e.each(n,function(e,n){var s=t.cssUnit(n);s[0]>0&&(i[n]=s[0]*r+s[1])}),i}}),e.fn.extend({effect:function(){function a(n){function u(){e.isFunction(i)&&i.call(r[0]),e.isFunction(n)&&n()}var r=e(this),i=t.complete,s=t.mode;(r.is(":hidden")?s==="hide":s==="show")?u():o.call(r[0],t,u)}var t=i.apply(this,arguments),r=t.mode,s=t.queue,o=e.effects.effect[t.effect],u=!o&&n&&e.effects[t.effect];return e.fx.off||!o&&!u?r?this[r](t.duration,t.complete):this.each(function(){t.complete&&t.complete.call(this)}):o?s===!1?this.each(a):this.queue(s||"fx",a):u.call(this,{options:t,duration:t.duration,callback:t.complete,mode:t.mode})},_show:e.fn.show,show:function(e){if(s(e))return this._show.apply(this,arguments);var t=i.apply(this,arguments);return t.mode="show",this.effect.call(this,t)},_hide:e.fn.hide,hide:function(e){if(s(e))return this._hide.apply(this,arguments);var t=i.apply(this,arguments);return t.mode="hide",this.effect.call(this,t)},__toggle:e.fn.toggle,toggle:function(t){if(s(t)||typeof t=="boolean"||e.isFunction(t))return this.__toggle.apply(this,arguments);var n=i.apply(this,arguments);return n.mode="toggle",this.effect.call(this,n)},cssUnit:function(t){var n=this.css(t),r=[];return e.each(["em","px","%","pt"],function(e,t){n.indexOf(t)>0&&(r=[parseFloat(n),t])}),r}})}(),function(){var t={};e.each(["Quad","Cubic","Quart","Quint","Expo"],function(e,n){t[n]=function(t){return Math.pow(t,e+2)}}),e.extend(t,{Sine:function(e){return 1-Math.cos(e*Math.PI/2)},Circ:function(e){return 1-Math.sqrt(1-e*e)},Elastic:function(e){return e===0||e===1?e:-Math.pow(2,8*(e-1))*Math.sin(((e-1)*80-7.5)*Math.PI/15)},Back:function(e){return e*e*(3*e-2)},Bounce:function(e){var t,n=4;while(e<((t=Math.pow(2,--n))-1)/11);return 1/Math.pow(4,3-n)-7.5625*Math.pow((t*3-2)/22-e,2)}}),e.each(t,function(t,n){e.easing["easeIn"+t]=n,e.easing["easeOut"+t]=function(e){return 1-n(1-e)},e.easing["easeInOut"+t]=function(e){return e<.5?n(e*2)/2:1-n(e*-2+2)/2}})}()}(jQuery);(function(e,t){var n=/up|down|vertical/,r=/up|left|vertical|horizontal/;e.effects.effect.blind=function(t,i){var s=e(this),o=["position","top","bottom","left","right","height","width"],u=e.effects.setMode(s,t.mode||"hide"),a=t.direction||"up",f=n.test(a),l=f?"height":"width",c=f?"top":"left",h=r.test(a),p={},d=u==="show",v,m,g;s.parent().is(".ui-effects-wrapper")?e.effects.save(s.parent(),o):e.effects.save(s,o),s.show(),v=e.effects.createWrapper(s).css({overflow:"hidden"}),m=v[l](),g=parseFloat(v.css(c))||0,p[l]=d?m:0,h||(s.css(f?"bottom":"right",0).css(f?"top":"left","auto").css({position:"absolute"}),p[c]=d?g:m+g),d&&(v.css(l,0),h||v.css(c,g+m)),v.animate(p,{duration:t.duration,easing:t.easing,queue:!1,complete:function(){u==="hide"&&s.hide(),e.effects.restore(s,o),e.effects.removeWrapper(s),i()}})}})(jQuery);(function(e,t){e.effects.effect.bounce=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"effect"),o=s==="hide",u=s==="show",a=t.direction||"up",f=t.distance,l=t.times||5,c=l*2+(u||o?1:0),h=t.duration/c,p=t.easing,d=a==="up"||a==="down"?"top":"left",v=a==="up"||a==="left",m,g,y,b=r.queue(),w=b.length;(u||o)&&i.push("opacity"),e.effects.save(r,i),r.show(),e.effects.createWrapper(r),f||(f=r[d==="top"?"outerHeight":"outerWidth"]()/3),u&&(y={opacity:1},y[d]=0,r.css("opacity",0).css(d,v?-f*2:f*2).animate(y,h,p)),o&&(f/=Math.pow(2,l-1)),y={},y[d]=0;for(m=0;m<l;m++)g={},g[d]=(v?"-=":"+=")+f,r.animate(g,h,p).animate(y,h,p),f=o?f*2:f/2;o&&(g={opacity:0},g[d]=(v?"-=":"+=")+f,r.animate(g,h,p)),r.queue(function(){o&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}),w>1&&b.splice.apply(b,[1,0].concat(b.splice(w,c+1))),r.dequeue()}})(jQuery);(function(e,t){e.effects.effect.clip=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"hide"),o=s==="show",u=t.direction||"vertical",a=u==="vertical",f=a?"height":"width",l=a?"top":"left",c={},h,p,d;e.effects.save(r,i),r.show(),h=e.effects.createWrapper(r).css({overflow:"hidden"}),p=r[0].tagName==="IMG"?h:r,d=p[f](),o&&(p.css(f,0),p.css(l,d/2)),c[f]=o?d:0,c[l]=o?0:d/2,p.animate(c,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){o||r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}})}})(jQuery);(function(e,t){e.effects.effect.drop=function(t,n){var r=e(this),i=["position","top","bottom","left","right","opacity","height","width"],s=e.effects.setMode(r,t.mode||"hide"),o=s==="show",u=t.direction||"left",a=u==="up"||u==="down"?"top":"left",f=u==="up"||u==="left"?"pos":"neg",l={opacity:o?1:0},c;e.effects.save(r,i),r.show(),e.effects.createWrapper(r),c=t.distance||r[a==="top"?"outerHeight":"outerWidth"](!0)/2,o&&r.css("opacity",0).css(a,f==="pos"?-c:c),l[a]=(o?f==="pos"?"+=":"-=":f==="pos"?"-=":"+=")+c,r.animate(l,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){s==="hide"&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}})}})(jQuery);(function(e,t){e.effects.effect.explode=function(t,n){function y(){c.push(this),c.length===r*i&&b()}function b(){s.css({visibility:"visible"}),e(c).remove(),u||s.hide(),n()}var r=t.pieces?Math.round(Math.sqrt(t.pieces)):3,i=r,s=e(this),o=e.effects.setMode(s,t.mode||"hide"),u=o==="show",a=s.show().css("visibility","hidden").offset(),f=Math.ceil(s.outerWidth()/i),l=Math.ceil(s.outerHeight()/r),c=[],h,p,d,v,m,g;for(h=0;h<r;h++){v=a.top+h*l,g=h-(r-1)/2;for(p=0;p<i;p++)d=a.left+p*f,m=p-(i-1)/2,s.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-p*f,top:-h*l}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:f,height:l,left:d+(u?m*f:0),top:v+(u?g*l:0),opacity:u?0:1}).animate({left:d+(u?0:m*f),top:v+(u?0:g*l),opacity:u?1:0},t.duration||500,t.easing,y)}}})(jQuery);(function(e,t){e.effects.effect.fade=function(t,n){var r=e(this),i=e.effects.setMode(r,t.mode||"toggle");r.animate({opacity:i},{queue:!1,duration:t.duration,easing:t.easing,complete:n})}})(jQuery);(function(e,t){e.effects.effect.fold=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"hide"),o=s==="show",u=s==="hide",a=t.size||15,f=/([0-9]+)%/.exec(a),l=!!t.horizFirst,c=o!==l,h=c?["width","height"]:["height","width"],p=t.duration/2,d,v,m={},g={};e.effects.save(r,i),r.show(),d=e.effects.createWrapper(r).css({overflow:"hidden"}),v=c?[d.width(),d.height()]:[d.height(),d.width()],f&&(a=parseInt(f[1],10)/100*v[u?0:1]),o&&d.css(l?{height:0,width:a}:{height:a,width:0}),m[h[0]]=o?v[0]:a,g[h[1]]=o?v[1]:0,d.animate(m,p,t.easing).animate(g,p,t.easing,function(){u&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()})}})(jQuery);(function(e,t){e.effects.effect.highlight=function(t,n){var r=e(this),i=["backgroundImage","backgroundColor","opacity"],s=e.effects.setMode(r,t.mode||"show"),o={backgroundColor:r.css("backgroundColor")};s==="hide"&&(o.opacity=0),e.effects.save(r,i),r.show().css({backgroundImage:"none",backgroundColor:t.color||"#ffff99"}).animate(o,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){s==="hide"&&r.hide(),e.effects.restore(r,i),n()}})}})(jQuery);(function(e,t){e.effects.effect.pulsate=function(t,n){var r=e(this),i=e.effects.setMode(r,t.mode||"show"),s=i==="show",o=i==="hide",u=s||i==="hide",a=(t.times||5)*2+(u?1:0),f=t.duration/a,l=0,c=r.queue(),h=c.length,p;if(s||!r.is(":visible"))r.css("opacity",0).show(),l=1;for(p=1;p<a;p++)r.animate({opacity:l},f,t.easing),l=1-l;r.animate({opacity:l},f,t.easing),r.queue(function(){o&&r.hide(),n()}),h>1&&c.splice.apply(c,[1,0].concat(c.splice(h,a+1))),r.dequeue()}})(jQuery);(function(e,t){e.effects.effect.puff=function(t,n){var r=e(this),i=e.effects.setMode(r,t.mode||"hide"),s=i==="hide",o=parseInt(t.percent,10)||150,u=o/100,a={height:r.height(),width:r.width(),outerHeight:r.outerHeight(),outerWidth:r.outerWidth()};e.extend(t,{effect:"scale",queue:!1,fade:!0,mode:i,complete:n,percent:s?o:100,from:s?a:{height:a.height*u,width:a.width*u,outerHeight:a.outerHeight*u,outerWidth:a.outerWidth*u}}),r.effect(t)},e.effects.effect.scale=function(t,n){var r=e(this),i=e.extend(!0,{},t),s=e.effects.setMode(r,t.mode||"effect"),o=parseInt(t.percent,10)||(parseInt(t.percent,10)===0?0:s==="hide"?0:100),u=t.direction||"both",a=t.origin,f={height:r.height(),width:r.width(),outerHeight:r.outerHeight(),outerWidth:r.outerWidth()},l={y:u!=="horizontal"?o/100:1,x:u!=="vertical"?o/100:1};i.effect="size",i.queue=!1,i.complete=n,s!=="effect"&&(i.origin=a||["middle","center"],i.restore=!0),i.from=t.from||(s==="show"?{height:0,width:0,outerHeight:0,outerWidth:0}:f),i.to={height:f.height*l.y,width:f.width*l.x,outerHeight:f.outerHeight*l.y,outerWidth:f.outerWidth*l.x},i.fade&&(s==="show"&&(i.from.opacity=0,i.to.opacity=1),s==="hide"&&(i.from.opacity=1,i.to.opacity=0)),r.effect(i)},e.effects.effect.size=function(t,n){var r,i,s,o=e(this),u=["position","top","bottom","left","right","width","height","overflow","opacity"],a=["position","top","bottom","left","right","overflow","opacity"],f=["width","height","overflow"],l=["fontSize"],c=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],h=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],p=e.effects.setMode(o,t.mode||"effect"),d=t.restore||p!=="effect",v=t.scale||"both",m=t.origin||["middle","center"],g=o.css("position"),y=d?u:a,b={height:0,width:0,outerHeight:0,outerWidth:0};p==="show"&&o.show(),r={height:o.height(),width:o.width(),outerHeight:o.outerHeight(),outerWidth:o.outerWidth()},t.mode==="toggle"&&p==="show"?(o.from=t.to||b,o.to=t.from||r):(o.from=t.from||(p==="show"?b:r),o.to=t.to||(p==="hide"?b:r)),s={from:{y:o.from.height/r.height,x:o.from.width/r.width},to:{y:o.to.height/r.height,x:o.to.width/r.width}};if(v==="box"||v==="both")s.from.y!==s.to.y&&(y=y.concat(c),o.from=e.effects.setTransition(o,c,s.from.y,o.from),o.to=e.effects.setTransition(o,c,s.to.y,o.to)),s.from.x!==s.to.x&&(y=y.concat(h),o.from=e.effects.setTransition(o,h,s.from.x,o.from),o.to=e.effects.setTransition(o,h,s.to.x,o.to));(v==="content"||v==="both")&&s.from.y!==s.to.y&&(y=y.concat(l).concat(f),o.from=e.effects.setTransition(o,l,s.from.y,o.from),o.to=e.effects.setTransition(o,l,s.to.y,o.to)),e.effects.save(o,y),o.show(),e.effects.createWrapper(o),o.css("overflow","hidden").css(o.from),m&&(i=e.effects.getBaseline(m,r),o.from.top=(r.outerHeight-o.outerHeight())*i.y,o.from.left=(r.outerWidth-o.outerWidth())*i.x,o.to.top=(r.outerHeight-o.to.outerHeight)*i.y,o.to.left=(r.outerWidth-o.to.outerWidth)*i.x),o.css(o.from);if(v==="content"||v==="both")c=c.concat(["marginTop","marginBottom"]).concat(l),h=h.concat(["marginLeft","marginRight"]),f=u.concat(c).concat(h),o.find("*[width]").each(function(){var n=e(this),r={height:n.height(),width:n.width(),outerHeight:n.outerHeight(),outerWidth:n.outerWidth()};d&&e.effects.save(n,f),n.from={height:r.height*s.from.y,width:r.width*s.from.x,outerHeight:r.outerHeight*s.from.y,outerWidth:r.outerWidth*s.from.x},n.to={height:r.height*s.to.y,width:r.width*s.to.x,outerHeight:r.height*s.to.y,outerWidth:r.width*s.to.x},s.from.y!==s.to.y&&(n.from=e.effects.setTransition(n,c,s.from.y,n.from),n.to=e.effects.setTransition(n,c,s.to.y,n.to)),s.from.x!==s.to.x&&(n.from=e.effects.setTransition(n,h,s.from.x,n.from),n.to=e.effects.setTransition(n,h,s.to.x,n.to)),n.css(n.from),n.animate(n.to,t.duration,t.easing,function(){d&&e.effects.restore(n,f)})});o.animate(o.to,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){o.to.opacity===0&&o.css("opacity",o.from.opacity),p==="hide"&&o.hide(),e.effects.restore(o,y),d||(g==="static"?o.css({position:"relative",top:o.to.top,left:o.to.left}):e.each(["top","left"],function(e,t){o.css(t,function(t,n){var r=parseInt(n,10),i=e?o.to.left:o.to.top;return n==="auto"?i+"px":r+i+"px"})})),e.effects.removeWrapper(o),n()}})}})(jQuery);(function(e,t){e.effects.effect.shake=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"effect"),o=t.direction||"left",u=t.distance||20,a=t.times||3,f=a*2+1,l=Math.round(t.duration/f),c=o==="up"||o==="down"?"top":"left",h=o==="up"||o==="left",p={},d={},v={},m,g=r.queue(),y=g.length;e.effects.save(r,i),r.show(),e.effects.createWrapper(r),p[c]=(h?"-=":"+=")+u,d[c]=(h?"+=":"-=")+u*2,v[c]=(h?"-=":"+=")+u*2,r.animate(p,l,t.easing);for(m=1;m<a;m++)r.animate(d,l,t.easing).animate(v,l,t.easing);r.animate(d,l,t.easing).animate(p,l/2,t.easing).queue(function(){s==="hide"&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}),y>1&&g.splice.apply(g,[1,0].concat(g.splice(y,f+1))),r.dequeue()}})(jQuery);(function(e,t){e.effects.effect.slide=function(t,n){var r=e(this),i=["position","top","bottom","left","right","width","height"],s=e.effects.setMode(r,t.mode||"show"),o=s==="show",u=t.direction||"left",a=u==="up"||u==="down"?"top":"left",f=u==="up"||u==="left",l,c={};e.effects.save(r,i),r.show(),l=t.distance||r[a==="top"?"outerHeight":"outerWidth"](!0),e.effects.createWrapper(r).css({overflow:"hidden"}),o&&r.css(a,f?isNaN(l)?"-"+l:-l:l),c[a]=(o?f?"+=":"-=":f?"-=":"+=")+l,r.animate(c,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){s==="hide"&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}})}})(jQuery);(function(e,t){e.effects.effect.transfer=function(t,n){var r=e(this),i=e(t.to),s=i.css("position")==="fixed",o=e("body"),u=s?o.scrollTop():0,a=s?o.scrollLeft():0,f=i.offset(),l={top:f.top-u,left:f.left-a,height:i.innerHeight(),width:i.innerWidth()},c=r.offset(),h=e('<div class="ui-effects-transfer"></div>').appendTo(document.body).addClass(t.className).css({top:c.top-u,left:c.left-a,height:r.innerHeight(),width:r.innerWidth(),position:s?"fixed":"absolute"}).animate(l,t.duration,t.easing,function(){h.remove(),n()})}})(jQuery);
\ No newline at end of file
diff --git a/servers/admin/public/javascripts/vendors/json2.js b/servers/admin/public/javascripts/vendors/json2.js
deleted file mode 100644
index c7745df..0000000
--- a/servers/admin/public/javascripts/vendors/json2.js
+++ /dev/null
@@ -1,486 +0,0 @@
-/*
-    json2.js
-    2012-10-08
-
-    Public Domain.
-
-    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
-
-    See http://www.JSON.org/js.html
-
-
-    This code should be minified before deployment.
-    See http://javascript.crockford.com/jsmin.html
-
-    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
-    NOT CONTROL.
-
-
-    This file creates a global JSON object containing two methods: stringify
-    and parse.
-
-        JSON.stringify(value, replacer, space)
-            value       any JavaScript value, usually an object or array.
-
-            replacer    an optional parameter that determines how object
-                        values are stringified for objects. It can be a
-                        function or an array of strings.
-
-            space       an optional parameter that specifies the indentation
-                        of nested structures. If it is omitted, the text will
-                        be packed without extra whitespace. If it is a number,
-                        it will specify the number of spaces to indent at each
-                        level. If it is a string (such as '\t' or '&nbsp;'),
-                        it contains the characters used to indent at each level.
-
-            This method produces a JSON text from a JavaScript value.
-
-            When an object value is found, if the object contains a toJSON
-            method, its toJSON method will be called and the result will be
-            stringified. A toJSON method does not serialize: it returns the
-            value represented by the name/value pair that should be serialized,
-            or undefined if nothing should be serialized. The toJSON method
-            will be passed the key associated with the value, and this will be
-            bound to the value
-
-            For example, this would serialize Dates as ISO strings.
-
-                Date.prototype.toJSON = function (key) {
-                    function f(n) {
-                        // Format integers to have at least two digits.
-                        return n < 10 ? '0' + n : n;
-                    }
-
-                    return this.getUTCFullYear()   + '-' +
-                         f(this.getUTCMonth() + 1) + '-' +
-                         f(this.getUTCDate())      + 'T' +
-                         f(this.getUTCHours())     + ':' +
-                         f(this.getUTCMinutes())   + ':' +
-                         f(this.getUTCSeconds())   + 'Z';
-                };
-
-            You can provide an optional replacer method. It will be passed the
-            key and value of each member, with this bound to the containing
-            object. The value that is returned from your method will be
-            serialized. If your method returns undefined, then the member will
-            be excluded from the serialization.
-
-            If the replacer parameter is an array of strings, then it will be
-            used to select the members to be serialized. It filters the results
-            such that only members with keys listed in the replacer array are
-            stringified.
-
-            Values that do not have JSON representations, such as undefined or
-            functions, will not be serialized. Such values in objects will be
-            dropped; in arrays they will be replaced with null. You can use
-            a replacer function to replace those with JSON values.
-            JSON.stringify(undefined) returns undefined.
-
-            The optional space parameter produces a stringification of the
-            value that is filled with line breaks and indentation to make it
-            easier to read.
-
-            If the space parameter is a non-empty string, then that string will
-            be used for indentation. If the space parameter is a number, then
-            the indentation will be that many spaces.
-
-            Example:
-
-            text = JSON.stringify(['e', {pluribus: 'unum'}]);
-            // text is '["e",{"pluribus":"unum"}]'
-
-
-            text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
-            // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
-
-            text = JSON.stringify([new Date()], function (key, value) {
-                return this[key] instanceof Date ?
-                    'Date(' + this[key] + ')' : value;
-            });
-            // text is '["Date(---current time---)"]'
-
-
-        JSON.parse(text, reviver)
-            This method parses a JSON text to produce an object or array.
-            It can throw a SyntaxError exception.
-
-            The optional reviver parameter is a function that can filter and
-            transform the results. It receives each of the keys and values,
-            and its return value is used instead of the original value.
-            If it returns what it received, then the structure is not modified.
-            If it returns undefined then the member is deleted.
-
-            Example:
-
-            // Parse the text. Values that look like ISO date strings will
-            // be converted to Date objects.
-
-            myData = JSON.parse(text, function (key, value) {
-                var a;
-                if (typeof value === 'string') {
-                    a =
-/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
-                    if (a) {
-                        return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
-                            +a[5], +a[6]));
-                    }
-                }
-                return value;
-            });
-
-            myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
-                var d;
-                if (typeof value === 'string' &&
-                        value.slice(0, 5) === 'Date(' &&
-                        value.slice(-1) === ')') {
-                    d = new Date(value.slice(5, -1));
-                    if (d) {
-                        return d;
-                    }
-                }
-                return value;
-            });
-
-
-    This is a reference implementation. You are free to copy, modify, or
-    redistribute.
-*/
-
-/*jslint evil: true, regexp: true */
-
-/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
-    call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
-    getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
-    lastIndex, length, parse, prototype, push, replace, slice, stringify,
-    test, toJSON, toString, valueOf
-*/
-
-
-// Create a JSON object only if one does not already exist. We create the
-// methods in a closure to avoid creating global variables.
-
-if (typeof JSON !== 'object') {
-    JSON = {};
-}
-
-(function () {
-    'use strict';
-
-    function f(n) {
-        // Format integers to have at least two digits.
-        return n < 10 ? '0' + n : n;
-    }
-
-    if (typeof Date.prototype.toJSON !== 'function') {
-
-        Date.prototype.toJSON = function (key) {
-
-            return isFinite(this.valueOf())
-                ? this.getUTCFullYear()     + '-' +
-                    f(this.getUTCMonth() + 1) + '-' +
-                    f(this.getUTCDate())      + 'T' +
-                    f(this.getUTCHours())     + ':' +
-                    f(this.getUTCMinutes())   + ':' +
-                    f(this.getUTCSeconds())   + 'Z'
-                : null;
-        };
-
-        String.prototype.toJSON      =
-            Number.prototype.toJSON  =
-            Boolean.prototype.toJSON = function (key) {
-                return this.valueOf();
-            };
-    }
-
-    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
-        escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
-        gap,
-        indent,
-        meta = {    // table of character substitutions
-            '\b': '\\b',
-            '\t': '\\t',
-            '\n': '\\n',
-            '\f': '\\f',
-            '\r': '\\r',
-            '"' : '\\"',
-            '\\': '\\\\'
-        },
-        rep;
-
-
-    function quote(string) {
-
-// If the string contains no control characters, no quote characters, and no
-// backslash characters, then we can safely slap some quotes around it.
-// Otherwise we must also replace the offending characters with safe escape
-// sequences.
-
-        escapable.lastIndex = 0;
-        return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
-            var c = meta[a];
-            return typeof c === 'string'
-                ? c
-                : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
-        }) + '"' : '"' + string + '"';
-    }
-
-
-    function str(key, holder) {
-
-// Produce a string from holder[key].
-
-        var i,          // The loop counter.
-            k,          // The member key.
-            v,          // The member value.
-            length,
-            mind = gap,
-            partial,
-            value = holder[key];
-
-// If the value has a toJSON method, call it to obtain a replacement value.
-
-        if (value && typeof value === 'object' &&
-                typeof value.toJSON === 'function') {
-            value = value.toJSON(key);
-        }
-
-// If we were called with a replacer function, then call the replacer to
-// obtain a replacement value.
-
-        if (typeof rep === 'function') {
-            value = rep.call(holder, key, value);
-        }
-
-// What happens next depends on the value's type.
-
-        switch (typeof value) {
-        case 'string':
-            return quote(value);
-
-        case 'number':
-
-// JSON numbers must be finite. Encode non-finite numbers as null.
-
-            return isFinite(value) ? String(value) : 'null';
-
-        case 'boolean':
-        case 'null':
-
-// If the value is a boolean or null, convert it to a string. Note:
-// typeof null does not produce 'null'. The case is included here in
-// the remote chance that this gets fixed someday.
-
-            return String(value);
-
-// If the type is 'object', we might be dealing with an object or an array or
-// null.
-
-        case 'object':
-
-// Due to a specification blunder in ECMAScript, typeof null is 'object',
-// so watch out for that case.
-
-            if (!value) {
-                return 'null';
-            }
-
-// Make an array to hold the partial results of stringifying this object value.
-
-            gap += indent;
-            partial = [];
-
-// Is the value an array?
-
-            if (Object.prototype.toString.apply(value) === '[object Array]') {
-
-// The value is an array. Stringify every element. Use null as a placeholder
-// for non-JSON values.
-
-                length = value.length;
-                for (i = 0; i < length; i += 1) {
-                    partial[i] = str(i, value) || 'null';
-                }
-
-// Join all of the elements together, separated with commas, and wrap them in
-// brackets.
-
-                v = partial.length === 0
-                    ? '[]'
-                    : gap
-                    ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
-                    : '[' + partial.join(',') + ']';
-                gap = mind;
-                return v;
-            }
-
-// If the replacer is an array, use it to select the members to be stringified.
-
-            if (rep && typeof rep === 'object') {
-                length = rep.length;
-                for (i = 0; i < length; i += 1) {
-                    if (typeof rep[i] === 'string') {
-                        k = rep[i];
-                        v = str(k, value);
-                        if (v) {
-                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
-                        }
-                    }
-                }
-            } else {
-
-// Otherwise, iterate through all of the keys in the object.
-
-                for (k in value) {
-                    if (Object.prototype.hasOwnProperty.call(value, k)) {
-                        v = str(k, value);
-                        if (v) {
-                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
-                        }
-                    }
-                }
-            }
-
-// Join all of the member texts together, separated with commas,
-// and wrap them in braces.
-
-            v = partial.length === 0
-                ? '{}'
-                : gap
-                ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
-                : '{' + partial.join(',') + '}';
-            gap = mind;
-            return v;
-        }
-    }
-
-// If the JSON object does not yet have a stringify method, give it one.
-
-    if (typeof JSON.stringify !== 'function') {
-        JSON.stringify = function (value, replacer, space) {
-
-// The stringify method takes a value and an optional replacer, and an optional
-// space parameter, and returns a JSON text. The replacer can be a function
-// that can replace values, or an array of strings that will select the keys.
-// A default replacer method can be provided. Use of the space parameter can
-// produce text that is more easily readable.
-
-            var i;
-            gap = '';
-            indent = '';
-
-// If the space parameter is a number, make an indent string containing that
-// many spaces.
-
-            if (typeof space === 'number') {
-                for (i = 0; i < space; i += 1) {
-                    indent += ' ';
-                }
-
-// If the space parameter is a string, it will be used as the indent string.
-
-            } else if (typeof space === 'string') {
-                indent = space;
-            }
-
-// If there is a replacer, it must be a function or an array.
-// Otherwise, throw an error.
-
-            rep = replacer;
-            if (replacer && typeof replacer !== 'function' &&
-                    (typeof replacer !== 'object' ||
-                    typeof replacer.length !== 'number')) {
-                throw new Error('JSON.stringify');
-            }
-
-// Make a fake root object containing our value under the key of ''.
-// Return the result of stringifying the value.
-
-            return str('', {'': value});
-        };
-    }
-
-
-// If the JSON object does not yet have a parse method, give it one.
-
-    if (typeof JSON.parse !== 'function') {
-        JSON.parse = function (text, reviver) {
-
-// The parse method takes a text and an optional reviver function, and returns
-// a JavaScript value if the text is a valid JSON text.
-
-            var j;
-
-            function walk(holder, key) {
-
-// The walk method is used to recursively walk the resulting structure so
-// that modifications can be made.
-
-                var k, v, value = holder[key];
-                if (value && typeof value === 'object') {
-                    for (k in value) {
-                        if (Object.prototype.hasOwnProperty.call(value, k)) {
-                            v = walk(value, k);
-                            if (v !== undefined) {
-                                value[k] = v;
-                            } else {
-                                delete value[k];
-                            }
-                        }
-                    }
-                }
-                return reviver.call(holder, key, value);
-            }
-
-
-// Parsing happens in four stages. In the first stage, we replace certain
-// Unicode characters with escape sequences. JavaScript handles many characters
-// incorrectly, either silently deleting them, or treating them as line endings.
-
-            text = String(text);
-            cx.lastIndex = 0;
-            if (cx.test(text)) {
-                text = text.replace(cx, function (a) {
-                    return '\\u' +
-                        ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
-                });
-            }
-
-// In the second stage, we run the text against regular expressions that look
-// for non-JSON patterns. We are especially concerned with '()' and 'new'
-// because they can cause invocation, and '=' because it can cause mutation.
-// But just to be safe, we want to reject all unexpected forms.
-
-// We split the second stage into 4 regexp operations in order to work around
-// crippling inefficiencies in IE's and Safari's regexp engines. First we
-// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
-// replace all simple value tokens with ']' characters. Third, we delete all
-// open brackets that follow a colon or comma or that begin the text. Finally,
-// we look to see that the remaining characters are only whitespace or ']' or
-// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
-
-            if (/^[\],:{}\s]*$/
-                    .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
-                        .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
-                        .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
-
-// In the third stage we use the eval function to compile the text into a
-// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
-// in JavaScript: it can begin a block or an object literal. We wrap the text
-// in parens to eliminate the ambiguity.
-
-                j = eval('(' + text + ')');
-
-// In the optional fourth stage, we recursively walk the new structure, passing
-// each name/value pair to a reviver function for possible transformation.
-
-                return typeof reviver === 'function'
-                    ? walk({'': j}, '')
-                    : j;
-            }
-
-// If the text is not JSON parseable, then a SyntaxError is thrown.
-
-            throw new SyntaxError('JSON.parse');
-        };
-    }
-}());
diff --git a/servers/admin/public/javascripts/vendors/modernizr-2.6.2-respond-1.1.0.min.js b/servers/admin/public/javascripts/vendors/modernizr-2.6.2-respond-1.1.0.min.js
deleted file mode 100755
index 302f461..0000000
--- a/servers/admin/public/javascripts/vendors/modernizr-2.6.2-respond-1.1.0.min.js
+++ /dev/null
@@ -1,11 +0,0 @@
-/* Modernizr 2.6.2 (Custom Build) | MIT & BSD
- * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-mq-cssclasses-addtest-prefixed-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load
- */
-;window.Modernizr=function(a,b,c){function D(a){j.cssText=a}function E(a,b){return D(n.join(a+";")+(b||""))}function F(a,b){return typeof a===b}function G(a,b){return!!~(""+a).indexOf(b)}function H(a,b){for(var d in a){var e=a[d];if(!G(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function I(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:F(f,"function")?f.bind(d||b):f}return!1}function J(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+p.join(d+" ")+d).split(" ");return F(b,"string")||F(b,"undefined")?H(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),I(e,b,c))}function K(){e.input=function(c){for(var d=0,e=c.length;d<e;d++)u[c[d]]=c[d]in k;return u.list&&(u.list=!!b.createElement("datalist")&&!!a.HTMLDataListElement),u}("autocomplete autofocus list placeholder max min multiple pattern required step".split(" ")),e.inputtypes=function(a){for(var d=0,e,f,h,i=a.length;d<i;d++)k.setAttribute("type",f=a[d]),e=k.type!=="text",e&&(k.value=l,k.style.cssText="position:absolute;visibility:hidden;",/^range$/.test(f)&&k.style.WebkitAppearance!==c?(g.appendChild(k),h=b.defaultView,e=h.getComputedStyle&&h.getComputedStyle(k,null).WebkitAppearance!=="textfield"&&k.offsetHeight!==0,g.removeChild(k)):/^(search|tel)$/.test(f)||(/^(url|email)$/.test(f)?e=k.checkValidity&&k.checkValidity()===!1:e=k.value!=l)),t[a[d]]=!!e;return t}("search tel url email datetime date month week time datetime-local number range color".split(" "))}var d="2.6.2",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k=b.createElement("input"),l=":)",m={}.toString,n=" -webkit- -moz- -o- -ms- ".split(" "),o="Webkit Moz O ms",p=o.split(" "),q=o.toLowerCase().split(" "),r={svg:"http://www.w3.org/2000/svg"},s={},t={},u={},v=[],w=v.slice,x,y=function(a,c,d,e){var f,i,j,k,l=b.createElement("div"),m=b.body,n=m||b.createElement("body");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:h+(d+1),l.appendChild(j);return f=["&#173;",'<style id="s',h,'">',a,"</style>"].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return y("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},A=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=F(e[d],"function"),F(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),B={}.hasOwnProperty,C;!F(B,"undefined")&&!F(B.call,"undefined")?C=function(a,b){return B.call(a,b)}:C=function(a,b){return b in a&&F(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return J("flexWrap")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!F(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){return!!a.WebGLRenderingContext},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.postmessage=function(){return!!a.postMessage},s.websqldatabase=function(){return!!a.openDatabase},s.indexedDB=function(){return!!J("indexedDB",a)},s.hashchange=function(){return A("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},s.history=function(){return!!a.history&&!!history.pushState},s.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},s.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},s.rgba=function(){return D("background-color:rgba(150,255,150,.5)"),G(j.backgroundColor,"rgba")},s.hsla=function(){return D("background-color:hsla(120,40%,100%,.5)"),G(j.backgroundColor,"rgba")||G(j.backgroundColor,"hsla")},s.multiplebgs=function(){return D("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return J("backgroundSize")},s.borderimage=function(){return J("borderImage")},s.borderradius=function(){return J("borderRadius")},s.boxshadow=function(){return J("boxShadow")},s.textshadow=function(){return b.createElement("div").style.textShadow===""},s.opacity=function(){return E("opacity:.55"),/^0.55$/.test(j.opacity)},s.cssanimations=function(){return J("animationName")},s.csscolumns=function(){return J("columnCount")},s.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return D((a+"-webkit- ".split(" ").join(b+a)+n.join(c+a)).slice(0,-a.length)),G(j.backgroundImage,"gradient")},s.cssreflections=function(){return J("boxReflect")},s.csstransforms=function(){return!!J("transform")},s.csstransforms3d=function(){var a=!!J("perspective");return a&&"webkitPerspective"in g.style&&y("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},s.csstransitions=function(){return J("transition")},s.fontface=function(){var a;return y('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&g.indexOf(d.split(" ")[0])===0}),a},s.generatedcontent=function(){var a;return y(["#",h,"{font:0/0 a}#",h,':after{content:"',l,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},s.video=function(){var a=b.createElement("video"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),c.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,"")}catch(d){}return c},s.audio=function(){var a=b.createElement("audio"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),c.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),c.wav=a.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),c.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,"")}catch(d){}return c},s.localstorage=function(){try{return localStorage.setItem(h,h),localStorage.removeItem(h),!0}catch(a){return!1}},s.sessionstorage=function(){try{return sessionStorage.setItem(h,h),sessionStorage.removeItem(h),!0}catch(a){return!1}},s.webworkers=function(){return!!a.Worker},s.applicationcache=function(){return!!a.applicationCache},s.svg=function(){return!!b.createElementNS&&!!b.createElementNS(r.svg,"svg").createSVGRect},s.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML="<svg/>",(a.firstChild&&a.firstChild.namespaceURI)==r.svg},s.smil=function(){return!!b.createElementNS&&/SVGAnimate/.test(m.call(b.createElementNS(r.svg,"animate")))},s.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(m.call(b.createElementNS(r.svg,"clipPath")))};for(var L in s)C(s,L)&&(x=L.toLowerCase(),e[x]=s[L](),v.push((e[x]?"":"no-")+x));return e.input||K(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)C(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},D(""),i=k=null,function(a,b){function k(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function l(){var a=r.elements;return typeof a=="string"?a.split(" "):a}function m(a){var b=i[a[g]];return b||(b={},h++,a[g]=h,i[h]=b),b}function n(a,c,f){c||(c=b);if(j)return c.createElement(a);f||(f=m(c));var g;return f.cache[a]?g=f.cache[a].cloneNode():e.test(a)?g=(f.cache[a]=f.createElem(a)).cloneNode():g=f.createElem(a),g.canHaveChildren&&!d.test(a)?f.frag.appendChild(g):g}function o(a,c){a||(a=b);if(j)return a.createDocumentFragment();c=c||m(a);var d=c.frag.cloneNode(),e=0,f=l(),g=f.length;for(;e<g;e++)d.createElement(f[e]);return d}function p(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return r.shivMethods?n(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+l().join().replace(/\w+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(r,b.frag)}function q(a){a||(a=b);var c=m(a);return r.shivCSS&&!f&&!c.hasCSS&&(c.hasCSS=!!k(a,"article,aside,figcaption,figure,footer,header,hgroup,nav,section{display:block}mark{background:#FF0;color:#000}")),j||p(a,c),a}var c=a.html5||{},d=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,e=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,f,g="_html5shiv",h=0,i={},j;(function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",f="hidden"in a,j=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){f=!0,j=!0}})();var r={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,supportsUnknownElements:j,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:q,createElement:n,createDocumentFragment:o};a.html5=r,q(b)}(this,b),e._version=d,e._prefixes=n,e._domPrefixes=q,e._cssomPrefixes=p,e.mq=z,e.hasEvent=A,e.testProp=function(a){return H([a])},e.testAllProps=J,e.testStyles=y,e.prefixed=function(a,b,c){return b?J(a,b,c):J(a,"pfx")},g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+v.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f<d;f++)g=a[f].split("="),(e=z[g.shift()])&&(c=e(c,g));for(f=0;f<b;f++)c=x[f](c);return c}function g(a,e,f,g,h){var i=b(a),j=i.autoCallback;i.url.split(".").pop().split("?").shift(),i.bypass||(e&&(e=d(e)?e:e[a]||e[g]||e[a.split("/").pop().split("?")[0]]),i.instead?i.instead(a,e,f,g,h):(y[i.url]?i.noexec=!0:y[i.url]=1,f.load(i.url,i.forceCSS||!i.forceJS&&"css"==i.url.split(".").pop().split("?").shift()?"c":c,i.noexec,i.attrs,i.timeout),(d(e)||d(j))&&f.load(function(){k(),e&&e(i.origUrl,h,g),j&&j(i.origUrl,h,g),y[i.url]=2})))}function h(a,b){function c(a,c){if(a){if(e(a))c||(j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}),g(a,j,b,0,h);else if(Object(a)===a)for(n in m=function(){var b=0,c;for(c in a)a.hasOwnProperty(c)&&b++;return b}(),a)a.hasOwnProperty(n)&&(!c&&!--m&&(d(j)?j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}:j[n]=function(a){return function(){var b=[].slice.call(arguments);a&&a.apply(this,b),l()}}(k[n])),g(a[n],j,b,n,h))}else!c&&l()}var h=!!a.test,i=a.load||a.both,j=a.callback||f,k=j,l=a.complete||f,m,n;c(h?a.yep:a.nope,!!i),i&&c(i)}var i,j,l=this.yepnope.loader;if(e(a))g(a,0,l,0);else if(w(a))for(i=0;i<a.length;i++)j=a[i],e(j)?g(j,0,l,0):w(j)?B(j):Object(j)===j&&h(j,l);else Object(a)===a&&h(a,l)},B.addPrefix=function(a,b){z[a]=b},B.addFilter=function(a){x.push(a)},B.errorTimeout=1e4,null==b.readyState&&b.addEventListener&&(b.readyState="loading",b.addEventListener("DOMContentLoaded",A=function(){b.removeEventListener("DOMContentLoaded",A,0),b.readyState="complete"},0)),a.yepnope=k(),a.yepnope.executeStack=h,a.yepnope.injectJs=function(a,c,d,e,i,j){var k=b.createElement("script"),l,o,e=e||B.errorTimeout;k.src=a;for(o in d)k.setAttribute(o,d[o]);c=j?h:c||f,k.onreadystatechange=k.onload=function(){!l&&g(k.readyState)&&(l=1,c(),k.onload=k.onreadystatechange=null)},m(function(){l||(l=1,c(1))},e),i?k.onload():n.parentNode.insertBefore(k,n)},a.yepnope.injectCss=function(a,c,d,e,g,i){var e=b.createElement("link"),j,c=i?h:c||f;e.href=a,e.rel="stylesheet",e.type="text/css";for(j in d)e.setAttribute(j,d[j]);g||(n.parentNode.insertBefore(e,n),m(c,0))}}(this,document),Modernizr.load=function(){yepnope.apply(window,[].slice.call(arguments,0))};
-
-/*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */
-/*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */
-window.matchMedia=window.matchMedia||(function(e,f){var c,a=e.documentElement,b=a.firstElementChild||a.firstChild,d=e.createElement("body"),g=e.createElement("div");g.id="mq-test-1";g.style.cssText="position:absolute;top:-100em";d.style.background="none";d.appendChild(g);return function(h){g.innerHTML='&shy;<style media="'+h+'"> #mq-test-1 { width: 42px; }</style>';a.insertBefore(d,b);c=g.offsetWidth==42;a.removeChild(d);return{matches:c,media:h}}})(document);
-
-/*! Respond.js v1.1.0: min/max-width media query polyfill. (c) Scott Jehl. MIT/GPLv2 Lic. j.mp/respondjs  */
-(function(e){e.respond={};respond.update=function(){};respond.mediaQueriesSupported=e.matchMedia&&e.matchMedia("only all").matches;if(respond.mediaQueriesSupported){return}var w=e.document,s=w.documentElement,i=[],k=[],q=[],o={},h=30,f=w.getElementsByTagName("head")[0]||s,g=w.getElementsByTagName("base")[0],b=f.getElementsByTagName("link"),d=[],a=function(){var D=b,y=D.length,B=0,A,z,C,x;for(;B<y;B++){A=D[B],z=A.href,C=A.media,x=A.rel&&A.rel.toLowerCase()==="stylesheet";if(!!z&&x&&!o[z]){if(A.styleSheet&&A.styleSheet.rawCssText){m(A.styleSheet.rawCssText,z,C);o[z]=true}else{if((!/^([a-zA-Z:]*\/\/)/.test(z)&&!g)||z.replace(RegExp.$1,"").split("/")[0]===e.location.host){d.push({href:z,media:C})}}}}u()},u=function(){if(d.length){var x=d.shift();n(x.href,function(y){m(y,x.href,x.media);o[x.href]=true;u()})}},m=function(I,x,z){var G=I.match(/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi),J=G&&G.length||0,x=x.substring(0,x.lastIndexOf("/")),y=function(K){return K.replace(/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,"$1"+x+"$2$3")},A=!J&&z,D=0,C,E,F,B,H;if(x.length){x+="/"}if(A){J=1}for(;D<J;D++){C=0;if(A){E=z;k.push(y(I))}else{E=G[D].match(/@media *([^\{]+)\{([\S\s]+?)$/)&&RegExp.$1;k.push(RegExp.$2&&y(RegExp.$2))}B=E.split(",");H=B.length;for(;C<H;C++){F=B[C];i.push({media:F.split("(")[0].match(/(only\s+)?([a-zA-Z]+)\s?/)&&RegExp.$2||"all",rules:k.length-1,hasquery:F.indexOf("(")>-1,minw:F.match(/\(min\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:F.match(/\(max\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}}j()},l,r,v=function(){var z,A=w.createElement("div"),x=w.body,y=false;A.style.cssText="position:absolute;font-size:1em;width:1em";if(!x){x=y=w.createElement("body");x.style.background="none"}x.appendChild(A);s.insertBefore(x,s.firstChild);z=A.offsetWidth;if(y){s.removeChild(x)}else{x.removeChild(A)}z=p=parseFloat(z);return z},p,j=function(I){var x="clientWidth",B=s[x],H=w.compatMode==="CSS1Compat"&&B||w.body[x]||B,D={},G=b[b.length-1],z=(new Date()).getTime();if(I&&l&&z-l<h){clearTimeout(r);r=setTimeout(j,h);return}else{l=z}for(var E in i){var K=i[E],C=K.minw,J=K.maxw,A=C===null,L=J===null,y="em";if(!!C){C=parseFloat(C)*(C.indexOf(y)>-1?(p||v()):1)}if(!!J){J=parseFloat(J)*(J.indexOf(y)>-1?(p||v()):1)}if(!K.hasquery||(!A||!L)&&(A||H>=C)&&(L||H<=J)){if(!D[K.media]){D[K.media]=[]}D[K.media].push(k[K.rules])}}for(var E in q){if(q[E]&&q[E].parentNode===f){f.removeChild(q[E])}}for(var E in D){var M=w.createElement("style"),F=D[E].join("\n");M.type="text/css";M.media=E;f.insertBefore(M,G.nextSibling);if(M.styleSheet){M.styleSheet.cssText=F}else{M.appendChild(w.createTextNode(F))}q.push(M)}},n=function(x,z){var y=c();if(!y){return}y.open("GET",x,true);y.onreadystatechange=function(){if(y.readyState!=4||y.status!=200&&y.status!=304){return}z(y.responseText)};if(y.readyState==4){return}y.send(null)},c=(function(){var x=false;try{x=new XMLHttpRequest()}catch(y){x=new ActiveXObject("Microsoft.XMLHTTP")}return function(){return x}})();a();respond.update=a;function t(){j(true)}if(e.addEventListener){e.addEventListener("resize",t,false)}else{if(e.attachEvent){e.attachEvent("onresize",t)}}})(this);
\ No newline at end of file
diff --git a/servers/admin/public/javascripts/vendors/toastr-1.2.2.js b/servers/admin/public/javascripts/vendors/toastr-1.2.2.js
deleted file mode 100644
index 9ca4c40..0000000
--- a/servers/admin/public/javascripts/vendors/toastr-1.2.2.js
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright 2012 John Papa and Hans Fjällemark.  
- * All Rights Reserved.  
- * Use, reproduction, distribution, and modification of this code is subject to the terms and 
- * conditions of the MIT license, available at http://www.opensource.org/licenses/mit-license.php
- *
- * Author: John Papa and Hans Fjällemark
- * Project: https://github.com/CodeSeven/toastr
- */
-; (function (define) {
-    define(['jquery'], function ($) {
-        return (function () {
-            var $container,
-
-                defaults = {
-                    tapToDismiss: true,
-                    toastClass: 'toast',
-                    containerId: 'toast-container',
-                    debug: false,
-                    fadeIn: 300,
-                    fadeOut: 1000,
-                    extendedTimeOut: 1000,
-                    iconClasses: {
-                        error: 'toast-error',
-                        info: 'toast-info',
-                        success: 'toast-success',
-                        warning: 'toast-warning'
-                    },
-                    iconClass: 'toast-info',
-                    positionClass: 'toast-top-right',
-                    timeOut: 5000, // Set timeOut to 0 to make it sticky
-                    titleClass: 'toast-title',
-                    messageClass: 'toast-message',
-                    target: 'body'
-                },
-
-                error = function (message, title, optionsOverride) {
-                    return notify({
-                        iconClass: getOptions().iconClasses.error,
-                        message: message,
-                        optionsOverride: optionsOverride,
-                        title: title
-                    });
-                },
-
-                info = function (message, title, optionsOverride) {
-                    return notify({
-                        iconClass: getOptions().iconClasses.info,
-                        message: message,
-                        optionsOverride: optionsOverride,
-                        title: title
-                    });
-                },
-
-                notify = function (map) {
-                    var
-                        options = getOptions(),
-                        iconClass = map.iconClass || options.iconClass;
-
-                    if (typeof (map.optionsOverride) !== 'undefined') {
-                        options = $.extend(options, map.optionsOverride);
-                        iconClass = map.optionsOverride.iconClass || iconClass;
-                    }
-
-                    var
-                        intervalId = null,
-                        $container = getContainer(options),
-                        $toastElement = $('<div/>'),
-                        $titleElement = $('<div/>'),
-                        $messageElement = $('<div/>'),
-                        response = { options: options, map: map };
-
-                    if (map.iconClass) {
-                        $toastElement.addClass(options.toastClass).addClass(iconClass);
-                    }
-
-                    if (map.title) {
-                        $titleElement.append(map.title).addClass(options.titleClass);
-                        $toastElement.append($titleElement);
-                    }
-
-                    if (map.message) {
-                        $messageElement.append(map.message).addClass(options.messageClass);
-                        $toastElement.append($messageElement);
-                    }
-
-                    $toastElement.hide();
-                    $container.prepend($toastElement);
-                    $toastElement.fadeIn(options.fadeIn);
-                    if (options.timeOut > 0) {
-                        intervalId = setTimeout(fadeAway, options.timeOut);
-                    }
-
-                    $toastElement.hover(stickAround, delayedFadeAway);
-                    if (!options.onclick && options.tapToDismiss) {
-                        $toastElement.click(fadeAway);
-                    }
-
-                    if (options.onclick) {
-                        $toastElement.click(function () {
-                            options.onclick() && fadeAway();
-                        });
-                    }
-
-                    if (options.debug && console) {
-                        console.log(response);
-                    }
-
-                    return $toastElement;
-
-                    function fadeAway() {
-                        if ($(':focus', $toastElement).length > 0) {
-                            return;
-                        }
-                        return $toastElement.fadeOut(options.fadeOut, function () {
-                            removeToast($toastElement);
-                        });
-                    }
-
-                    function delayedFadeAway() {
-                        if (options.timeOut > 0 || options.extendedTimeOut > 0) {
-                            intervalId = setTimeout(fadeAway, options.extendedTimeOut);
-                        }
-                    }
-
-                    function stickAround() {
-                        clearTimeout(intervalId);
-                        $toastElement.stop(true, true).fadeIn(options.fadeIn);
-                    }
-                },
-
-                success = function (message, title, optionsOverride) {
-                    return notify({
-                        iconClass: getOptions().iconClasses.success,
-                        message: message,
-                        optionsOverride: optionsOverride,
-                        title: title
-                    });
-                },
-
-                warning = function (message, title, optionsOverride) {
-                    return notify({
-                        iconClass: getOptions().iconClasses.warning,
-                        message: message,
-                        optionsOverride: optionsOverride,
-                        title: title
-                    });
-                },
-
-                clear = function ($toastElement) {
-                    var options = getOptions();
-                    if (!$container) { getContainer(options) };
-                    if ($toastElement && $(':focus', $toastElement).length === 0) {
-                        $toastElement.fadeOut(options.fadeOut, function () {
-                            removeToast($toastElement);
-                        });
-                        return;
-                    }
-                    if ($container.children().length) {
-                        $container.fadeOut(options.fadeOut, function () {
-                            $container.remove();
-                        });
-                    }
-                };
-
-            var toastr = {
-                clear: clear,
-                error: error,
-                getContainer: getContainer,
-                info: info,
-                options: {},
-                success: success,
-                version: '1.2.2',
-                warning: warning
-            };
-
-            return toastr;
-
-            //#region Internal Methods
-
-            function getContainer(options) {
-                if (!options) { options = getOptions(); }
-                container = $('#' + options.containerId);
-                if (container.children().length) {
-                    return container;
-                }
-                container = $('<div/>')
-                    .attr('id', options.containerId)
-                    .addClass(options.positionClass);
-                container.appendTo($(options.target));
-                $container = container;
-                return container;
-            };
-
-            function getOptions() {
-                return $.extend({}, defaults, toastr.options);
-            };
-
-            function removeToast($toastElement) {
-                if (!$container) { $container = getContainer(); }
-                if ($toastElement.is(':visible')) {
-                    return;
-                }
-                $toastElement.remove();
-                $toastElement = null;
-                if ($container.children().length === 0) {
-                    $container.remove();
-                }
-            }
-            //#endregion
-
-        })();
-    });
-}(typeof define === 'function' && define.amd ? define : function (deps, factory) {
-    if (typeof module !== 'undefined' && module.exports) { //Node
-        module.exports = factory(require(deps[0]));
-    } else {
-        window['toastr'] = factory(window['jQuery']);
-    }
-}));
diff --git a/servers/admin/public/javascripts/vendors/toastr-1.2.2.min.js b/servers/admin/public/javascripts/vendors/toastr-1.2.2.min.js
deleted file mode 100644
index 2d1a4a7..0000000
--- a/servers/admin/public/javascripts/vendors/toastr-1.2.2.min.js
+++ /dev/null
@@ -1 +0,0 @@
-(function(n){n(["jquery"],function(n){return function(){function u(r){return(r||(r=i()),container=n("#"+r.containerId),container.children().length)?container:(container=n("<div/>").attr("id",r.containerId).addClass(r.positionClass),container.appendTo(n(r.target)),t=container,container)}function i(){return n.extend({},o,f.options)}function e(n){(t||(t=u()),n.is(":visible"))||(n.remove(),n=null,t.children().length===0&&t.remove())}var t,o={tapToDismiss:!0,toastClass:"toast",containerId:"toast-container",debug:!1,fadeIn:300,fadeOut:1e3,extendedTimeOut:1e3,iconClasses:{error:"toast-error",info:"toast-info",success:"toast-success",warning:"toast-warning"},iconClass:"toast-info",positionClass:"toast-top-right",timeOut:5e3,titleClass:"toast-title",messageClass:"toast-message",target:"body"},s=function(n,t,u){return r({iconClass:i().iconClasses.error,message:n,optionsOverride:u,title:t})},h=function(n,t,u){return r({iconClass:i().iconClasses.info,message:n,optionsOverride:u,title:t})},r=function(t){function o(){if(!(n(":focus",f).length>0))return f.fadeOut(r.fadeOut,function(){e(f)})}function y(){(r.timeOut>0||r.extendedTimeOut>0)&&(h=setTimeout(o,r.extendedTimeOut))}function p(){clearTimeout(h),f.stop(!0,!0).fadeIn(r.fadeIn)}var r=i(),s=t.iconClass||r.iconClass;typeof t.optionsOverride!="undefined"&&(r=n.extend(r,t.optionsOverride),s=t.optionsOverride.iconClass||s);var h=null,a=u(r),f=n("<div/>"),c=n("<div/>"),l=n("<div/>"),v={options:r,map:t};return t.iconClass&&f.addClass(r.toastClass).addClass(s),t.title&&(c.append(t.title).addClass(r.titleClass),f.append(c)),t.message&&(l.append(t.message).addClass(r.messageClass),f.append(l)),f.hide(),a.prepend(f),f.fadeIn(r.fadeIn),r.timeOut>0&&(h=setTimeout(o,r.timeOut)),f.hover(p,y),!r.onclick&&r.tapToDismiss&&f.click(o),r.onclick&&f.click(function(){r.onclick()&&o()}),r.debug&&console&&console.log(v),f},c=function(n,t,u){return r({iconClass:i().iconClasses.success,message:n,optionsOverride:u,title:t})},l=function(n,t,u){return r({iconClass:i().iconClasses.warning,message:n,optionsOverride:u,title:t})},a=function(r){var f=i();if(t||u(f),r&&n(":focus",r).length===0){r.fadeOut(f.fadeOut,function(){e(r)});return}t.children().length&&t.fadeOut(f.fadeOut,function(){t.remove()})},f={clear:a,error:s,getContainer:u,info:h,options:{},success:c,version:"1.2.2",warning:l};return f}()})})(typeof define=="function"&&define.amd?define:function(n,t){typeof module!="undefined"&&module.exports?module.exports=t(require(n[0])):window.toastr=t(window.jQuery)})
\ No newline at end of file
diff --git a/servers/admin/public/javascripts/vendors/underscore-min.js b/servers/admin/public/javascripts/vendors/underscore-min.js
deleted file mode 100644
index 7ed6e52..0000000
--- a/servers/admin/public/javascripts/vendors/underscore-min.js
+++ /dev/null
@@ -1 +0,0 @@
-(function(){var n=this,t=n._,r={},e=Array.prototype,u=Object.prototype,i=Function.prototype,a=e.push,o=e.slice,c=e.concat,l=u.toString,f=u.hasOwnProperty,s=e.forEach,p=e.map,v=e.reduce,h=e.reduceRight,g=e.filter,d=e.every,m=e.some,y=e.indexOf,b=e.lastIndexOf,x=Array.isArray,_=Object.keys,j=i.bind,w=function(n){return n instanceof w?n:this instanceof w?(this._wrapped=n,void 0):new w(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=w),exports._=w):n._=w,w.VERSION="1.4.3";var A=w.each=w.forEach=function(n,t,e){if(null!=n)if(s&&n.forEach===s)n.forEach(t,e);else if(n.length===+n.length){for(var u=0,i=n.length;i>u;u++)if(t.call(e,n[u],u,n)===r)return}else for(var a in n)if(w.has(n,a)&&t.call(e,n[a],a,n)===r)return};w.map=w.collect=function(n,t,r){var e=[];return null==n?e:p&&n.map===p?n.map(t,r):(A(n,function(n,u,i){e[e.length]=t.call(r,n,u,i)}),e)};var O="Reduce of empty array with no initial value";w.reduce=w.foldl=w.inject=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),v&&n.reduce===v)return e&&(t=w.bind(t,e)),u?n.reduce(t,r):n.reduce(t);if(A(n,function(n,i,a){u?r=t.call(e,r,n,i,a):(r=n,u=!0)}),!u)throw new TypeError(O);return r},w.reduceRight=w.foldr=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),h&&n.reduceRight===h)return e&&(t=w.bind(t,e)),u?n.reduceRight(t,r):n.reduceRight(t);var i=n.length;if(i!==+i){var a=w.keys(n);i=a.length}if(A(n,function(o,c,l){c=a?a[--i]:--i,u?r=t.call(e,r,n[c],c,l):(r=n[c],u=!0)}),!u)throw new TypeError(O);return r},w.find=w.detect=function(n,t,r){var e;return E(n,function(n,u,i){return t.call(r,n,u,i)?(e=n,!0):void 0}),e},w.filter=w.select=function(n,t,r){var e=[];return null==n?e:g&&n.filter===g?n.filter(t,r):(A(n,function(n,u,i){t.call(r,n,u,i)&&(e[e.length]=n)}),e)},w.reject=function(n,t,r){return w.filter(n,function(n,e,u){return!t.call(r,n,e,u)},r)},w.every=w.all=function(n,t,e){t||(t=w.identity);var u=!0;return null==n?u:d&&n.every===d?n.every(t,e):(A(n,function(n,i,a){return(u=u&&t.call(e,n,i,a))?void 0:r}),!!u)};var E=w.some=w.any=function(n,t,e){t||(t=w.identity);var u=!1;return null==n?u:m&&n.some===m?n.some(t,e):(A(n,function(n,i,a){return u||(u=t.call(e,n,i,a))?r:void 0}),!!u)};w.contains=w.include=function(n,t){return null==n?!1:y&&n.indexOf===y?-1!=n.indexOf(t):E(n,function(n){return n===t})},w.invoke=function(n,t){var r=o.call(arguments,2);return w.map(n,function(n){return(w.isFunction(t)?t:n[t]).apply(n,r)})},w.pluck=function(n,t){return w.map(n,function(n){return n[t]})},w.where=function(n,t){return w.isEmpty(t)?[]:w.filter(n,function(n){for(var r in t)if(t[r]!==n[r])return!1;return!0})},w.max=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.max.apply(Math,n);if(!t&&w.isEmpty(n))return-1/0;var e={computed:-1/0,value:-1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;a>=e.computed&&(e={value:n,computed:a})}),e.value},w.min=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.min.apply(Math,n);if(!t&&w.isEmpty(n))return 1/0;var e={computed:1/0,value:1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;e.computed>a&&(e={value:n,computed:a})}),e.value},w.shuffle=function(n){var t,r=0,e=[];return A(n,function(n){t=w.random(r++),e[r-1]=e[t],e[t]=n}),e};var F=function(n){return w.isFunction(n)?n:function(t){return t[n]}};w.sortBy=function(n,t,r){var e=F(t);return w.pluck(w.map(n,function(n,t,u){return{value:n,index:t,criteria:e.call(r,n,t,u)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||void 0===r)return 1;if(e>r||void 0===e)return-1}return n.index<t.index?-1:1}),"value")};var k=function(n,t,r,e){var u={},i=F(t||w.identity);return A(n,function(t,a){var o=i.call(r,t,a,n);e(u,o,t)}),u};w.groupBy=function(n,t,r){return k(n,t,r,function(n,t,r){(w.has(n,t)?n[t]:n[t]=[]).push(r)})},w.countBy=function(n,t,r){return k(n,t,r,function(n,t){w.has(n,t)||(n[t]=0),n[t]++})},w.sortedIndex=function(n,t,r,e){r=null==r?w.identity:F(r);for(var u=r.call(e,t),i=0,a=n.length;a>i;){var o=i+a>>>1;u>r.call(e,n[o])?i=o+1:a=o}return i},w.toArray=function(n){return n?w.isArray(n)?o.call(n):n.length===+n.length?w.map(n,w.identity):w.values(n):[]},w.size=function(n){return null==n?0:n.length===+n.length?n.length:w.keys(n).length},w.first=w.head=w.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:o.call(n,0,t)},w.initial=function(n,t,r){return o.call(n,0,n.length-(null==t||r?1:t))},w.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:o.call(n,Math.max(n.length-t,0))},w.rest=w.tail=w.drop=function(n,t,r){return o.call(n,null==t||r?1:t)},w.compact=function(n){return w.filter(n,w.identity)};var R=function(n,t,r){return A(n,function(n){w.isArray(n)?t?a.apply(r,n):R(n,t,r):r.push(n)}),r};w.flatten=function(n,t){return R(n,t,[])},w.without=function(n){return w.difference(n,o.call(arguments,1))},w.uniq=w.unique=function(n,t,r,e){w.isFunction(t)&&(e=r,r=t,t=!1);var u=r?w.map(n,r,e):n,i=[],a=[];return A(u,function(r,e){(t?e&&a[a.length-1]===r:w.contains(a,r))||(a.push(r),i.push(n[e]))}),i},w.union=function(){return w.uniq(c.apply(e,arguments))},w.intersection=function(n){var t=o.call(arguments,1);return w.filter(w.uniq(n),function(n){return w.every(t,function(t){return w.indexOf(t,n)>=0})})},w.difference=function(n){var t=c.apply(e,o.call(arguments,1));return w.filter(n,function(n){return!w.contains(t,n)})},w.zip=function(){for(var n=o.call(arguments),t=w.max(w.pluck(n,"length")),r=Array(t),e=0;t>e;e++)r[e]=w.pluck(n,""+e);return r},w.object=function(n,t){if(null==n)return{};for(var r={},e=0,u=n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},w.indexOf=function(n,t,r){if(null==n)return-1;var e=0,u=n.length;if(r){if("number"!=typeof r)return e=w.sortedIndex(n,t),n[e]===t?e:-1;e=0>r?Math.max(0,u+r):r}if(y&&n.indexOf===y)return n.indexOf(t,r);for(;u>e;e++)if(n[e]===t)return e;return-1},w.lastIndexOf=function(n,t,r){if(null==n)return-1;var e=null!=r;if(b&&n.lastIndexOf===b)return e?n.lastIndexOf(t,r):n.lastIndexOf(t);for(var u=e?r:n.length;u--;)if(n[u]===t)return u;return-1},w.range=function(n,t,r){1>=arguments.length&&(t=n||0,n=0),r=arguments[2]||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=0,i=Array(e);e>u;)i[u++]=n,n+=r;return i};var I=function(){};w.bind=function(n,t){var r,e;if(n.bind===j&&j)return j.apply(n,o.call(arguments,1));if(!w.isFunction(n))throw new TypeError;return r=o.call(arguments,2),e=function(){if(!(this instanceof e))return n.apply(t,r.concat(o.call(arguments)));I.prototype=n.prototype;var u=new I;I.prototype=null;var i=n.apply(u,r.concat(o.call(arguments)));return Object(i)===i?i:u}},w.bindAll=function(n){var t=o.call(arguments,1);return 0==t.length&&(t=w.functions(n)),A(t,function(t){n[t]=w.bind(n[t],n)}),n},w.memoize=function(n,t){var r={};return t||(t=w.identity),function(){var e=t.apply(this,arguments);return w.has(r,e)?r[e]:r[e]=n.apply(this,arguments)}},w.delay=function(n,t){var r=o.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},w.defer=function(n){return w.delay.apply(w,[n,1].concat(o.call(arguments,1)))},w.throttle=function(n,t){var r,e,u,i,a=0,o=function(){a=new Date,u=null,i=n.apply(r,e)};return function(){var c=new Date,l=t-(c-a);return r=this,e=arguments,0>=l?(clearTimeout(u),u=null,a=c,i=n.apply(r,e)):u||(u=setTimeout(o,l)),i}},w.debounce=function(n,t,r){var e,u;return function(){var i=this,a=arguments,o=function(){e=null,r||(u=n.apply(i,a))},c=r&&!e;return clearTimeout(e),e=setTimeout(o,t),c&&(u=n.apply(i,a)),u}},w.once=function(n){var t,r=!1;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}},w.wrap=function(n,t){return function(){var r=[n];return a.apply(r,arguments),t.apply(this,r)}},w.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length-1;r>=0;r--)t=[n[r].apply(this,t)];return t[0]}},w.after=function(n,t){return 0>=n?t():function(){return 1>--n?t.apply(this,arguments):void 0}},w.keys=_||function(n){if(n!==Object(n))throw new TypeError("Invalid object");var t=[];for(var r in n)w.has(n,r)&&(t[t.length]=r);return t},w.values=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push(n[r]);return t},w.pairs=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push([r,n[r]]);return t},w.invert=function(n){var t={};for(var r in n)w.has(n,r)&&(t[n[r]]=r);return t},w.functions=w.methods=function(n){var t=[];for(var r in n)w.isFunction(n[r])&&t.push(r);return t.sort()},w.extend=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]=t[r]}),n},w.pick=function(n){var t={},r=c.apply(e,o.call(arguments,1));return A(r,function(r){r in n&&(t[r]=n[r])}),t},w.omit=function(n){var t={},r=c.apply(e,o.call(arguments,1));for(var u in n)w.contains(r,u)||(t[u]=n[u]);return t},w.defaults=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)null==n[r]&&(n[r]=t[r])}),n},w.clone=function(n){return w.isObject(n)?w.isArray(n)?n.slice():w.extend({},n):n},w.tap=function(n,t){return t(n),n};var S=function(n,t,r,e){if(n===t)return 0!==n||1/n==1/t;if(null==n||null==t)return n===t;n instanceof w&&(n=n._wrapped),t instanceof w&&(t=t._wrapped);var u=l.call(n);if(u!=l.call(t))return!1;switch(u){case"[object String]":return n==t+"";case"[object Number]":return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case"[object Date]":case"[object Boolean]":return+n==+t;case"[object RegExp]":return n.source==t.source&&n.global==t.global&&n.multiline==t.multiline&&n.ignoreCase==t.ignoreCase}if("object"!=typeof n||"object"!=typeof t)return!1;for(var i=r.length;i--;)if(r[i]==n)return e[i]==t;r.push(n),e.push(t);var a=0,o=!0;if("[object Array]"==u){if(a=n.length,o=a==t.length)for(;a--&&(o=S(n[a],t[a],r,e)););}else{var c=n.constructor,f=t.constructor;if(c!==f&&!(w.isFunction(c)&&c instanceof c&&w.isFunction(f)&&f instanceof f))return!1;for(var s in n)if(w.has(n,s)&&(a++,!(o=w.has(t,s)&&S(n[s],t[s],r,e))))break;if(o){for(s in t)if(w.has(t,s)&&!a--)break;o=!a}}return r.pop(),e.pop(),o};w.isEqual=function(n,t){return S(n,t,[],[])},w.isEmpty=function(n){if(null==n)return!0;if(w.isArray(n)||w.isString(n))return 0===n.length;for(var t in n)if(w.has(n,t))return!1;return!0},w.isElement=function(n){return!(!n||1!==n.nodeType)},w.isArray=x||function(n){return"[object Array]"==l.call(n)},w.isObject=function(n){return n===Object(n)},A(["Arguments","Function","String","Number","Date","RegExp"],function(n){w["is"+n]=function(t){return l.call(t)=="[object "+n+"]"}}),w.isArguments(arguments)||(w.isArguments=function(n){return!(!n||!w.has(n,"callee"))}),w.isFunction=function(n){return"function"==typeof n},w.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},w.isNaN=function(n){return w.isNumber(n)&&n!=+n},w.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"==l.call(n)},w.isNull=function(n){return null===n},w.isUndefined=function(n){return void 0===n},w.has=function(n,t){return f.call(n,t)},w.noConflict=function(){return n._=t,this},w.identity=function(n){return n},w.times=function(n,t,r){for(var e=Array(n),u=0;n>u;u++)e[u]=t.call(r,u);return e},w.random=function(n,t){return null==t&&(t=n,n=0),n+(0|Math.random()*(t-n+1))};var T={escape:{"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;","/":"&#x2F;"}};T.unescape=w.invert(T.escape);var M={escape:RegExp("["+w.keys(T.escape).join("")+"]","g"),unescape:RegExp("("+w.keys(T.unescape).join("|")+")","g")};w.each(["escape","unescape"],function(n){w[n]=function(t){return null==t?"":(""+t).replace(M[n],function(t){return T[n][t]})}}),w.result=function(n,t){if(null==n)return null;var r=n[t];return w.isFunction(r)?r.call(n):r},w.mixin=function(n){A(w.functions(n),function(t){var r=w[t]=n[t];w.prototype[t]=function(){var n=[this._wrapped];return a.apply(n,arguments),z.call(this,r.apply(w,n))}})};var N=0;w.uniqueId=function(n){var t=""+ ++N;return n?n+t:t},w.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var q=/(.)^/,B={"'":"'","\\":"\\","\r":"r","\n":"n","	":"t","\u2028":"u2028","\u2029":"u2029"},D=/\\|'|\r|\n|\t|\u2028|\u2029/g;w.template=function(n,t,r){r=w.defaults({},r,w.templateSettings);var e=RegExp([(r.escape||q).source,(r.interpolate||q).source,(r.evaluate||q).source].join("|")+"|$","g"),u=0,i="__p+='";n.replace(e,function(t,r,e,a,o){return i+=n.slice(u,o).replace(D,function(n){return"\\"+B[n]}),r&&(i+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'"),e&&(i+="'+\n((__t=("+e+"))==null?'':__t)+\n'"),a&&(i+="';\n"+a+"\n__p+='"),u=o+t.length,t}),i+="';\n",r.variable||(i="with(obj||{}){\n"+i+"}\n"),i="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+i+"return __p;\n";try{var a=Function(r.variable||"obj","_",i)}catch(o){throw o.source=i,o}if(t)return a(t,w);var c=function(n){return a.call(this,n,w)};return c.source="function("+(r.variable||"obj")+"){\n"+i+"}",c},w.chain=function(n){return w(n).chain()};var z=function(n){return this._chain?w(n).chain():n};w.mixin(w),A(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=e[n];w.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!=n&&"splice"!=n||0!==r.length||delete r[0],z.call(this,r)}}),A(["concat","join","slice"],function(n){var t=e[n];w.prototype[n]=function(){return z.call(this,t.apply(this._wrapped,arguments))}}),w.extend(w.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this);
\ No newline at end of file
diff --git a/servers/admin/public/stylesheets/img/colResizable/range.png b/servers/admin/public/stylesheets/img/colResizable/range.png
deleted file mode 100755
index 33c184c..0000000
--- a/servers/admin/public/stylesheets/img/colResizable/range.png
+++ /dev/null
Binary files differ
diff --git a/servers/admin/public/stylesheets/img/colResizable/rangeBar.png b/servers/admin/public/stylesheets/img/colResizable/rangeBar.png
deleted file mode 100755
index f29f18e..0000000
--- a/servers/admin/public/stylesheets/img/colResizable/rangeBar.png
+++ /dev/null
Binary files differ
diff --git a/servers/admin/public/stylesheets/img/colResizable/slider.png b/servers/admin/public/stylesheets/img/colResizable/slider.png
deleted file mode 100755
index 43e91f4..0000000
--- a/servers/admin/public/stylesheets/img/colResizable/slider.png
+++ /dev/null
Binary files differ
diff --git a/servers/admin/public/stylesheets/img/glyphicons-halflings-white.png b/servers/admin/public/stylesheets/img/glyphicons-halflings-white.png
deleted file mode 100644
index 3bf6484..0000000
--- a/servers/admin/public/stylesheets/img/glyphicons-halflings-white.png
+++ /dev/null
Binary files differ
diff --git a/servers/admin/public/stylesheets/img/glyphicons-halflings.png b/servers/admin/public/stylesheets/img/glyphicons-halflings.png
deleted file mode 100644
index a996999..0000000
--- a/servers/admin/public/stylesheets/img/glyphicons-halflings.png
+++ /dev/null
Binary files differ
diff --git a/servers/admin/public/stylesheets/main.css b/servers/admin/public/stylesheets/main.css
deleted file mode 100755
index 5630b59..0000000
--- a/servers/admin/public/stylesheets/main.css
+++ /dev/null
@@ -1,506 +0,0 @@
-/* ==========================================================================
-   Author's custom styles
-   ========================================================================== */
-* {
-	margin: 0;
-}
-
-html,body {
-	height: 100%;
-}
-
-.wrapper {
-	min-height: 100%;
-	height: auto !important;
-	height: 100%;
-	margin: -1.4em auto -4em;
-}
-
-.footer,.push {
-	height: 8em;
-}
-
-[class^="icon-"], [class*=" icon-"] {
-    margin-top: 0;	
-}
-/* Darkness Fix */
-.well {
-	border: 1px solid rgba(0, 0, 0, 0.05) !important;
-	overflow: hidden;
-}
-h1, h2, h3, h4, h5, h6 {
-	text-shadow: 0 1px 1px #000000;
-}
-textarea, input[type="text"], input[type="password"], input[type="datetime"], input[type="datetime-local"], input[type="date"], input[type="month"], input[type="time"], input[type="week"], input[type="number"], input[type="email"], input[type="url"], input[type="search"], input[type="tel"], input[type="color"], .uneditable-input {
-    background: none repeat scroll 0 0 #212121 !important;
-    border: 1px solid #0F0F0F;
-    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.5) inset, 0 1px 0 rgba(255, 255, 255, 0.1);
-    color: #ffffff;
-    text-shadow: 0 1px 3px #000000;
-
-}
-input::-webkit-input-placeholder {
-    color:    #444444;
-    font-weight: 130;
-}
-input:-moz-placeholder {
-    color:    #444444;
-    font-weight: 130;
-}
-input:-ms-input-placeholder {
-    color:    #444444;
-    font-weight: 130;
-}
-input:focus::-webkit-input-placeholder {
-    color: #212121!important;
-    text-shadow: none!important;
-}
-input:focus:-moz-placeholder {
-    color: #212121!important;
-    text-shadow: none!important;
-}
-input:focus:-ms-input-placeholder {
-    color: #212121!important;
-    text-shadow: none!important;
-}
-
-.table-hover tbody tr:hover td,
-.table-hover tbody tr:hover th {
-  background-color: #444444;
-}
-
-.modal.modal-visible { /* convert modal to a box container */
-	width: auto;
-	position:relative;
-	top:auto;
-	left:auto;
-	margin:0 auto;
-	z-index:1;
-}
-.modal.modal-visible .modal-body {
-    max-height: none;
-}
-
-/* Silver box */
-.modal.modal-inverse {
-    background-color: #E7EBED;
-    border-radius: 4px 4px 4px 4px;
-    box-shadow: 1px 1px 5px #000000;
-    margin: 0 auto 60px;
-}
-.modal.modal-inverse a { 
-    color: #51555D;
-}
-.modal.modal-inverse input, .modal.modal-inverse input[type="file"], .modal.modal-inverse select, textarea {
-    border-color: #cccccc;
-    color: #51555D;
-}
-.modal.modal-inverse .well, .modal.modal-inverse .breadcrumb, .modal.modal-inverse input, input[type="file"], .modal.modal-inverse select, .modal.modal-inverse textarea, .modal.modal-inverse .progress, .modal.modal-inverse code, .modal.modal-inverse pre {
-    background: none repeat scroll 0 0 #E7EBED;
-    box-shadow: 0 1px 0 #FCFDFD, 0 1px 3px #96ACB9 inset;
-}
-
-.modal.modal-inverse input[type="text"], .modal.modal-inverse input[type="password"], .modal.modal-inverse input[type="email"] {
-    background: -moz-linear-gradient(-90deg, #D5DEE3, #E7EBED) repeat scroll 0 0 transparent !important;
-    background: -webkit-gradient(linear, left top, left bottom, from(#d5dee3), to(#e7ebed)) !important;
-    border: 0 none;
-    box-shadow: 0 1px 0 #FCFDFD, 0 1px 3px #96ACB9 inset;
-    color: #666666 !important;
-    font-size: 12px;
-    outline: 0 none;
-    text-shadow: 0 1px 1px #cccccc;
-}
-.app-info input[type="text"] {
-    padding: 10px 15px;
-    height: 50px!important;
-}
-
-.modal.modal-inverse .input-append input, .input-append select, .input-append .uneditable-input {
-    border-radius: 4px 0 0 4px;
-}
-
-.modal.modal-inverse input[disabled] {
-    color: #666666 !important;
-}
-.modal.modal-inverse input::-webkit-input-placeholder {
-    color:    #A4B4BD!important;
-    font-weight: 130;
-    text-shadow: none!important;
-}
-.modal.modal-inverse input:-moz-placeholder {
-    color:    #A4B4BD!important;
-    font-weight: 130;
-    text-shadow: none!important;
-}
-.modal.modal-inverse input:-ms-input-placeholder {
-    color:    #A4B4BD!important;
-    font-weight: 130;
-    text-shadow: none!important;
-}
-.modal.modal-inverse input:focus::-webkit-input-placeholder {
-  color: transparent!important;
-  text-shadow: none!important;
-}
-.modal.modal-inverse input:focus:-moz-placeholder {
-  color: transparent!important;
-  text-shadow: none!important;
-}
-.modal.modal-inverse input:focus:-ms-input-placeholder {
-  color: transparent!important;
-  text-shadow: none!important;
-}
-.modal.modal-inverse .table thead {
-    color: #86949D;
-}
-
-.modal.modal-inverse .modal-header {
-	-moz-box-sizing: border-box;
-	-webkit-box-sizing: border-box;
-	background: -webkit-gradient(linear, left top, left bottom, from(#fdfdfd), to(#d7dbde));
-    background: -moz-linear-gradient(-90deg, #FDFDFD, #D7DBDE) repeat scroll 0 0 transparent;
-    border-radius: 4px 4px 0 0;
-    -webkit-border-radius: 4px 4px 0 0;
-    -moz-border-radius: 4px 4px 0 0;
-    box-shadow: 0 1px 0 #E7ECEF inset, 1px 1px 3px #4A606A;
-    padding: 8px 15px;
-    border-bottom: none;
-}
-.modal.modal-inverse .modal-header h1,
-.modal.modal-inverse .modal-header h2,
-.modal.modal-inverse .modal-header h3,
-.modal.modal-inverse .modal-header h4,
-.modal.modal-inverse .modal-header h5,
-.modal.modal-inverse .modal-header h6 {
-    color: #575755;
-    text-shadow: 0 1px 2px #FFFFFF;
-}
-.modal.modal-inverse .modal-container {
-	-moz-box-sizing: border-box;
-}
-.modal.modal-inverse .modal-container h1,
-.modal.modal-inverse .modal-container h2,
-.modal.modal-inverse .modal-container h3,
-.modal.modal-inverse .modal-container h4,
-.modal.modal-inverse .modal-container h5,
-.modal.modal-inverse .modal-container h6 {
-    color: #51555D;
-    text-shadow: 0 1px 1px #FFFFFF;
-    font-weight: normal;
-}
-.modal.modal-inverse .modal-container .modal-content {
-    -moz-box-sizing: border-box;
-    overflow: hidden;
-    padding: 15px;
-    color: #86949D;
-}
-.modal.modal-inverse .modal-container .modal-item-box {
-    -moz-box-sizing: border-box;
-    -webkit-box-sizing: border-box;
-    background: -moz-linear-gradient(-90deg, #D5DEE3, #E7EBED) repeat scroll 0 0 transparent;
-    background: -webkit-gradient(linear, left top, left bottom, from(#d5dee3), to(#e7ebed));
-    border-radius: 6px 6px 6px 6px;
-    box-shadow: 0 1px 0 #FCFDFD, 1px 1px 3px #96ACB9 inset;
-
-    margin: 0 0 15px;
-    overflow: hidden;
-    padding: 5px;
-}
-.modal.modal-inverse .modal-container .modal-item-box .modal-item {
-    -moz-box-sizing: border-box;
-    -webkit-box-sizing: border-box;
-    background: -moz-linear-gradient(-90deg, #FDFDFD, #E9EBEC) repeat scroll 0 0 transparent;
-    background: -webkit-gradient(linear, left top, left bottom, from(#fdfdfd), to(#e9ebec));
-    border-radius: 4px 4px 4px 4px;
-    box-shadow: 0 1px 2px #A1B0BB, 0 1px 0 #FFFFFF inset;
-    margin: 0 0 5px;
-    padding: 1px 15px;
-}
-.modal.modal-inverse .modal-container .modal-item-box .modal-item .modal-item-panel {
-	margin-top: 10px;
-}
-.modal.modal-inverse .modal-container .modal-item-box a.actionbtn {
-    -moz-box-sizing: border-box;
-    -webkit-box-sizing: border-box;
-    background: none repeat scroll 0 0 rgba(0, 0, 0, 0.05);
-    border-radius: 7px 7px 7px 7px;
-    box-shadow: 0 1px 0 #FCFDFD, 0 1px 3px #96ACB9 inset;
-    color: #8794A0;
-    padding: 5px 8px 4px;
-    text-decoration: none;
-    text-shadow: 0 1px 1px white;
-    transition: all 0.3s ease-in-out 0s;
-    font-size: 13px;
-    margin-left: 8px;
-}
-.modal.modal-inverse .modal-container .modal-item-box a.actionbtn:hover {
-    background: none repeat scroll 0 0 transparent;
-    color: #5CB7E2;
-}
-/* End of Darkness Fix*/
-
-body {
-	font-family: "Droid Sans",Helvetica,Arial,serif;
-	font-size: 12px;
-	/* for footer and top */
-    padding-top: 60px; 
-    padding-bottom: 40px;
-}
-#headbar {
-	min-width: 940px;
-    -moz-box-sizing: border-box!important;
-    border-bottom: solid 2px #000000;
-}
-#mainarea {
-	min-width: 1150px;
-	padding-top: 20px;
-}
-
-.footer {
-    background-color: #2b2b2b;
-    text-align: center;
-}
-.footer footer {
-	padding-top: 20px;
-	font-size: 10px;
-	color: #999999;
-}
-.smallContent {
-	font-size: 12px;
-}
-.center { float: none; margin-left: auto; margin-right: auto; }
-.bottomMargin-large { margin-bottom: 50px!important; }
-.bottomMargin {margin-bottom: 20px!important; }
-.topMargin {margin-top: 20px!important; }
-.topMargin-large {margin-top: 50px!important; }
-.leftMargin {margin-left: 20px!important; }
-.leftMargin-small {margin-left: 8px!important; }
-.rightMargin {margin-right: 20px!important; }
-.rightMargin-small {margin-right: 8px!important; }
-.displayNone {display:none;}
-.textRight { text-align: right;}
-/* Sign In */
-#signinContainer { margin-top: 70px; width: 500px;}
-
-/* App DashBoard */
-.app-info, .install-info {
-	margin: 5px 0 8px 0;
-	padding: 15px;
-}
-.app-info p, .app-info input {
-	margin-bottom: 20px;
-}
-#addAppInput {
-	padding:5px 10px;
-}
-.app-info strong {
-	font-size: 14px;
-}
-
-/* Create Engine */
-#createEngine .row-fluid .span6 {
-	width: 48.8%;
-}
-/*
-#createEngine .row-fluid [class*="span"]:first-child {
-    margin-left: 0;
-}
-*/
-#createEngine .row-fluid [class*="span"] {
-	margin-left: 0.8%;
-}
-#createEngine .boxBlock .boxContent {
-    height: 240px;
-    overflow: hidden;
-}
-
-/* Engine Pages */
-#engineTab a {
-	font-weight: bold;
-	font-size: 14px;
-}
-
-#engineGoal .form-horizontal .controls {
-    margin-left: 227px;
-}
-#engineGoal .form-horizontal .control-label {
-    width: 220px;
-}
-
-.boxContainer {
-    -moz-box-sizing: border-box;
-    -webkit-box-sizing: border-box;
-    background: none repeat scroll 0 0 #272727;
-    border-radius: 6px 6px 6px 6px;
-    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.5) inset, 0 1px 0 rgba(255, 255, 255, 0.1);
-    padding: 5px;
-}
-.boxBlock {
-    border-radius: 4px 4px 4px 4px;
-    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.5), 0 1px 0 rgba(255, 255, 255, 0.1) inset;
-    margin: 0 0 5px;
-}
-.boxBlock:last-child {
-	margin: 0;
-} 
-.boxBlock .boxtitle {
-    -moz-box-sizing: border-box;
-    -webkit-box-sizing: border-box;
-    background: -moz-linear-gradient(-90deg, #3A3A3A, #393939) repeat scroll 0 0 transparent;
-    background: -webkit-gradient(linear, left top, left bottom, from(#3A3A3A), to(#393939));    
-    border-bottom: 1px solid #262626;
-    border-radius: 4px 4px 0 0;
-    box-shadow: 0 1px 0 rgba(255, 255, 255, 0.1) inset;
-    font-size: 16px;
-    padding: 8px 10px;
-    text-shadow: 0 1px 2px #000000;
-    color: #5CB5E2;
-}
-.boxBlock .boxContent {
-    -moz-box-sizing: border-box;
-    -webkit-box-sizing: border-box;
-    background: -moz-linear-gradient(-90deg, #393939, #343434) repeat scroll 0 0 transparent;
-    background: -webkit-gradient(linear, left top, left bottom, from(#393939), to(#343434));
-    border-bottom: 1px solid #262626;
-    box-shadow: 0 1px 0 rgba(255, 255, 255, 0.1) inset;
-    padding: 15px;
-    color: #8F8F8F;
-}
-.boxBlock .boxPanel {
-	background: -moz-linear-gradient(-90deg, #393939, #343434) repeat scroll 0 0 transparent;
-	background: -webkit-gradient(linear, left top, left bottom, from(#393939), to(#343434));
-	padding: 10px 10px 5px 10px;
-}
-.hbar {
-    background: -moz-linear-gradient(-90deg, #3B3B3B, #333333) repeat scroll 0 0 transparent;
-    background: -webkit-gradient(linear, left top, left bottom, from(#3B3B3B), to(#333333));
-    border-bottom: 1px solid #0F0F0F;
-    border-top: 1px solid #585858;
-    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.4);
-    height: 4px;
-}
-.hbar.hbar-thick {
-    height: 15px;
-}
-/*
-.btn-input {
-	height: 28px!important;
-	line-height: 28px!important;
-}
-*/
-
-
-/*
-.box1 {
-    background-color: #444444;
-    border: 1px solid #222222;
-    border-radius: 4px 4px 4px 4px;
-    margin: 15px 0;
-    padding: 39px 19px 14px;
-    position: relative;
-}
-.box1-cornertext {
-    background-color: #000000;
-    border: 1px solid #000000;
-    border-radius: 4px 0 4px 0;
-    color: #ffffff;
-    font-size: 12px;
-    font-weight: bold;
-    left: -1px;
-    padding: 3px 17px;
-    position: absolute;
-    top: -1px;
-}
-.box2 {
-    background-color: #FFFFFF;
-    border: 1px solid #000000;
-    border-radius: 4px 4px 4px 4px;
-    margin: 15px 0;
-    padding: 55px 19px 14px;
-    position: relative;
-}
-.box2-cornertext {
-    background-color: #000000;
-    border: 1px solid #000000;
-    border-radius: 4px 0 4px 0;
-    color: #ffffff;
-    font-size: 16px;
-    font-weight: bold;
-    left: -1px;
-    padding: 10px 50px;
-    position: absolute;
-    top: -1px;
-}
-*/
-
-
-
-/* Data Split Slider in EngineSimEvalSettings*/
-#dataSplitBar{
-    border:none;
-    height:15px;
-    background-image: url('img/colResizable/range.png');  
-}
-#dataSplitBar .selection {
-    background-image: url('img/colResizable/range.png');
-    background-position: 0px -15px;
-    padding:0px;
-    margin:0px;
-    vertical-align:text-top;
-}
-#dataSplitBar .selection span{
-    width:100%;
-    height:15px;
-    top: -2px;
-    position:relative;
-    display:block;
-    content:"";
-    padding-left: 10px;
-    font-size: 10px;
-    color: #000000;
-    font-weight: bold;
-}
-/*
-#dataSplitBar .selection span:after{
-    background-image: url('img/colResizable/range.png');
-    background-position: 0px -30px;
-    position:absolute;
-    left:0px;
-    top:0px;
-    display:block;
-    content:"";
-    height:15px;
-    width:22px;
-    display:block;
-    content:"";
-}
-*/
-#dataSplitBar .selection span:before{
-    background-image: url('img/colResizable/range.png');
-    background-position: 0px -45px;
-    position:absolute;
-    right:10px;
-    top:2px;
-    display:block;
-    content:"";
-    height:15px;
-    width:22px;
-    display:block;
-    content:"";
-}
-#dataSplitBar td{
-    border:none;
-}
-.rangeGrip{
-    width:14px;
-    height:21px;
-    cursor:e-resize;
-    background-image: url('img/colResizable/range.png');
-    background-position: 0px -60px;
-    position:absolute;
-    left:-3px;
-    top:-3px;
-    z-index:8;
-}
-.rangeDrag .rangeGrip, .rangeGrip:hover{
-    background-position: -14px -60px;
-}
diff --git a/servers/admin/public/stylesheets/vendors/bootstrap.css b/servers/admin/public/stylesheets/vendors/bootstrap.css
deleted file mode 100644
index 8ab3cef..0000000
--- a/servers/admin/public/stylesheets/vendors/bootstrap.css
+++ /dev/null
@@ -1,6039 +0,0 @@
-/*!
- * Bootstrap v2.2.2
- *
- * Copyright 2012 Twitter, Inc
- * Licensed under the Apache License v2.0
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Designed and built with all the love in the world @twitter by @mdo and @fat.
- */
-
-article,
-aside,
-details,
-figcaption,
-figure,
-footer,
-header,
-hgroup,
-nav,
-section {
-  display: block;
-}
-
-audio,
-canvas,
-video {
-  display: inline-block;
-  *display: inline;
-  *zoom: 1;
-}
-
-audio:not([controls]) {
-  display: none;
-}
-
-html {
-  font-size: 100%;
-  -webkit-text-size-adjust: 100%;
-      -ms-text-size-adjust: 100%;
-}
-
-a:focus {
-  outline: thin dotted #333;
-  outline: 5px auto -webkit-focus-ring-color;
-  outline-offset: -2px;
-}
-
-a:hover,
-a:active {
-  outline: 0;
-}
-
-sub,
-sup {
-  position: relative;
-  font-size: 75%;
-  line-height: 0;
-  vertical-align: baseline;
-}
-
-sup {
-  top: -0.5em;
-}
-
-sub {
-  bottom: -0.25em;
-}
-
-img {
-  width: auto\9;
-  height: auto;
-  max-width: 100%;
-  vertical-align: middle;
-  border: 0;
-  -ms-interpolation-mode: bicubic;
-}
-
-#map_canvas img,
-.google-maps img {
-  max-width: none;
-}
-
-button,
-input,
-select,
-textarea {
-  margin: 0;
-  font-size: 100%;
-  vertical-align: middle;
-}
-
-button,
-input {
-  *overflow: visible;
-  line-height: normal;
-}
-
-button::-moz-focus-inner,
-input::-moz-focus-inner {
-  padding: 0;
-  border: 0;
-}
-
-button,
-html input[type="button"],
-input[type="reset"],
-input[type="submit"] {
-  cursor: pointer;
-  -webkit-appearance: button;
-}
-
-label,
-select,
-button,
-input[type="button"],
-input[type="reset"],
-input[type="submit"],
-input[type="radio"],
-input[type="checkbox"] {
-  cursor: pointer;
-}
-
-input[type="search"] {
-  -webkit-box-sizing: content-box;
-     -moz-box-sizing: content-box;
-          box-sizing: content-box;
-  -webkit-appearance: textfield;
-}
-
-input[type="search"]::-webkit-search-decoration,
-input[type="search"]::-webkit-search-cancel-button {
-  -webkit-appearance: none;
-}
-
-textarea {
-  overflow: auto;
-  vertical-align: top;
-}
-
-@media print {
-  * {
-    color: #000 !important;
-    text-shadow: none !important;
-    background: transparent !important;
-    box-shadow: none !important;
-  }
-  a,
-  a:visited {
-    text-decoration: underline;
-  }
-  a[href]:after {
-    content: " (" attr(href) ")";
-  }
-  abbr[title]:after {
-    content: " (" attr(title) ")";
-  }
-  .ir a:after,
-  a[href^="javascript:"]:after,
-  a[href^="#"]:after {
-    content: "";
-  }
-  pre,
-  blockquote {
-    border: 1px solid #999;
-    page-break-inside: avoid;
-  }
-  thead {
-    display: table-header-group;
-  }
-  tr,
-  img {
-    page-break-inside: avoid;
-  }
-  img {
-    max-width: 100% !important;
-  }
-  @page  {
-    margin: 0.5cm;
-  }
-  p,
-  h2,
-  h3 {
-    orphans: 3;
-    widows: 3;
-  }
-  h2,
-  h3 {
-    page-break-after: avoid;
-  }
-}
-
-.clearfix {
-  *zoom: 1;
-}
-
-.clearfix:before,
-.clearfix:after {
-  display: table;
-  line-height: 0;
-  content: "";
-}
-
-.clearfix:after {
-  clear: both;
-}
-
-.hide-text {
-  font: 0/0 a;
-  color: transparent;
-  text-shadow: none;
-  background-color: transparent;
-  border: 0;
-}
-
-.input-block-level {
-  display: block;
-  width: 100%;
-  min-height: 30px;
-  -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
-}
-
-body {
-  margin: 0;
-  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
-  font-size: 14px;
-  line-height: 20px;
-  color: #333333;
-  background-color: #ffffff;
-}
-
-a {
-  color: #0088cc;
-  text-decoration: none;
-}
-
-a:hover {
-  color: #005580;
-  text-decoration: underline;
-}
-
-.img-rounded {
-  -webkit-border-radius: 6px;
-     -moz-border-radius: 6px;
-          border-radius: 6px;
-}
-
-.img-polaroid {
-  padding: 4px;
-  background-color: #fff;
-  border: 1px solid #ccc;
-  border: 1px solid rgba(0, 0, 0, 0.2);
-  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
-     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
-          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
-}
-
-.img-circle {
-  -webkit-border-radius: 500px;
-     -moz-border-radius: 500px;
-          border-radius: 500px;
-}
-
-.row {
-  margin-left: -20px;
-  *zoom: 1;
-}
-
-.row:before,
-.row:after {
-  display: table;
-  line-height: 0;
-  content: "";
-}
-
-.row:after {
-  clear: both;
-}
-
-[class*="span"] {
-  float: left;
-  min-height: 1px;
-  margin-left: 20px;
-}
-
-.container,
-.navbar-static-top .container,
-.navbar-fixed-top .container,
-.navbar-fixed-bottom .container {
-  width: 940px;
-}
-
-.span12 {
-  width: 940px;
-}
-
-.span11 {
-  width: 860px;
-}
-
-.span10 {
-  width: 780px;
-}
-
-.span9 {
-  width: 700px;
-}
-
-.span8 {
-  width: 620px;
-}
-
-.span7 {
-  width: 540px;
-}
-
-.span6 {
-  width: 460px;
-}
-
-.span5 {
-  width: 380px;
-}
-
-.span4 {
-  width: 300px;
-}
-
-.span3 {
-  width: 220px;
-}
-
-.span2 {
-  width: 140px;
-}
-
-.span1 {
-  width: 60px;
-}
-
-.offset12 {
-  margin-left: 980px;
-}
-
-.offset11 {
-  margin-left: 900px;
-}
-
-.offset10 {
-  margin-left: 820px;
-}
-
-.offset9 {
-  margin-left: 740px;
-}
-
-.offset8 {
-  margin-left: 660px;
-}
-
-.offset7 {
-  margin-left: 580px;
-}
-
-.offset6 {
-  margin-left: 500px;
-}
-
-.offset5 {
-  margin-left: 420px;
-}
-
-.offset4 {
-  margin-left: 340px;
-}
-
-.offset3 {
-  margin-left: 260px;
-}
-
-.offset2 {
-  margin-left: 180px;
-}
-
-.offset1 {
-  margin-left: 100px;
-}
-
-.row-fluid {
-  width: 100%;
-  *zoom: 1;
-}
-
-.row-fluid:before,
-.row-fluid:after {
-  display: table;
-  line-height: 0;
-  content: "";
-}
-
-.row-fluid:after {
-  clear: both;
-}
-
-.row-fluid [class*="span"] {
-  display: block;
-  float: left;
-  width: 100%;
-  min-height: 30px;
-  margin-left: 2.127659574468085%;
-  *margin-left: 2.074468085106383%;
-  -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
-}
-
-.row-fluid [class*="span"]:first-child {
-  margin-left: 0;
-}
-
-.row-fluid .controls-row [class*="span"] + [class*="span"] {
-  margin-left: 2.127659574468085%;
-}
-
-.row-fluid .span12 {
-  width: 100%;
-  *width: 99.94680851063829%;
-}
-
-.row-fluid .span11 {
-  width: 91.48936170212765%;
-  *width: 91.43617021276594%;
-}
-
-.row-fluid .span10 {
-  width: 82.97872340425532%;
-  *width: 82.92553191489361%;
-}
-
-.row-fluid .span9 {
-  width: 74.46808510638297%;
-  *width: 74.41489361702126%;
-}
-
-.row-fluid .span8 {
-  width: 65.95744680851064%;
-  *width: 65.90425531914893%;
-}
-
-.row-fluid .span7 {
-  width: 57.44680851063829%;
-  *width: 57.39361702127659%;
-}
-
-.row-fluid .span6 {
-  width: 48.93617021276595%;
-  *width: 48.88297872340425%;
-}
-
-.row-fluid .span5 {
-  width: 40.42553191489362%;
-  *width: 40.37234042553192%;
-}
-
-.row-fluid .span4 {
-  width: 31.914893617021278%;
-  *width: 31.861702127659576%;
-}
-
-.row-fluid .span3 {
-  width: 23.404255319148934%;
-  *width: 23.351063829787233%;
-}
-
-.row-fluid .span2 {
-  width: 14.893617021276595%;
-  *width: 14.840425531914894%;
-}
-
-.row-fluid .span1 {
-  width: 6.382978723404255%;
-  *width: 6.329787234042553%;
-}
-
-.row-fluid .offset12 {
-  margin-left: 104.25531914893617%;
-  *margin-left: 104.14893617021275%;
-}
-
-.row-fluid .offset12:first-child {
-  margin-left: 102.12765957446808%;
-  *margin-left: 102.02127659574467%;
-}
-
-.row-fluid .offset11 {
-  margin-left: 95.74468085106382%;
-  *margin-left: 95.6382978723404%;
-}
-
-.row-fluid .offset11:first-child {
-  margin-left: 93.61702127659574%;
-  *margin-left: 93.51063829787232%;
-}
-
-.row-fluid .offset10 {
-  margin-left: 87.23404255319149%;
-  *margin-left: 87.12765957446807%;
-}
-
-.row-fluid .offset10:first-child {
-  margin-left: 85.1063829787234%;
-  *margin-left: 84.99999999999999%;
-}
-
-.row-fluid .offset9 {
-  margin-left: 78.72340425531914%;
-  *margin-left: 78.61702127659572%;
-}
-
-.row-fluid .offset9:first-child {
-  margin-left: 76.59574468085106%;
-  *margin-left: 76.48936170212764%;
-}
-
-.row-fluid .offset8 {
-  margin-left: 70.2127659574468%;
-  *margin-left: 70.10638297872339%;
-}
-
-.row-fluid .offset8:first-child {
-  margin-left: 68.08510638297872%;
-  *margin-left: 67.9787234042553%;
-}
-
-.row-fluid .offset7 {
-  margin-left: 61.70212765957446%;
-  *margin-left: 61.59574468085106%;
-}
-
-.row-fluid .offset7:first-child {
-  margin-left: 59.574468085106375%;
-  *margin-left: 59.46808510638297%;
-}
-
-.row-fluid .offset6 {
-  margin-left: 53.191489361702125%;
-  *margin-left: 53.085106382978715%;
-}
-
-.row-fluid .offset6:first-child {
-  margin-left: 51.063829787234035%;
-  *margin-left: 50.95744680851063%;
-}
-
-.row-fluid .offset5 {
-  margin-left: 44.68085106382979%;
-  *margin-left: 44.57446808510638%;
-}
-
-.row-fluid .offset5:first-child {
-  margin-left: 42.5531914893617%;
-  *margin-left: 42.4468085106383%;
-}
-
-.row-fluid .offset4 {
-  margin-left: 36.170212765957444%;
-  *margin-left: 36.06382978723405%;
-}
-
-.row-fluid .offset4:first-child {
-  margin-left: 34.04255319148936%;
-  *margin-left: 33.93617021276596%;
-}
-
-.row-fluid .offset3 {
-  margin-left: 27.659574468085104%;
-  *margin-left: 27.5531914893617%;
-}
-
-.row-fluid .offset3:first-child {
-  margin-left: 25.53191489361702%;
-  *margin-left: 25.425531914893618%;
-}
-
-.row-fluid .offset2 {
-  margin-left: 19.148936170212764%;
-  *margin-left: 19.04255319148936%;
-}
-
-.row-fluid .offset2:first-child {
-  margin-left: 17.02127659574468%;
-  *margin-left: 16.914893617021278%;
-}
-
-.row-fluid .offset1 {
-  margin-left: 10.638297872340425%;
-  *margin-left: 10.53191489361702%;
-}
-
-.row-fluid .offset1:first-child {
-  margin-left: 8.51063829787234%;
-  *margin-left: 8.404255319148938%;
-}
-
-[class*="span"].hide,
-.row-fluid [class*="span"].hide {
-  display: none;
-}
-
-[class*="span"].pull-right,
-.row-fluid [class*="span"].pull-right {
-  float: right;
-}
-
-.container {
-  margin-right: auto;
-  margin-left: auto;
-  *zoom: 1;
-}
-
-.container:before,
-.container:after {
-  display: table;
-  line-height: 0;
-  content: "";
-}
-
-.container:after {
-  clear: both;
-}
-
-.container-fluid {
-  padding-right: 20px;
-  padding-left: 20px;
-  *zoom: 1;
-}
-
-.container-fluid:before,
-.container-fluid:after {
-  display: table;
-  line-height: 0;
-  content: "";
-}
-
-.container-fluid:after {
-  clear: both;
-}
-
-p {
-  margin: 0 0 10px;
-}
-
-.lead {
-  margin-bottom: 20px;
-  font-size: 21px;
-  font-weight: 200;
-  line-height: 30px;
-}
-
-small {
-  font-size: 85%;
-}
-
-strong {
-  font-weight: bold;
-}
-
-em {
-  font-style: italic;
-}
-
-cite {
-  font-style: normal;
-}
-
-.muted {
-  color: #999999;
-}
-
-a.muted:hover {
-  color: #808080;
-}
-
-.text-warning {
-  color: #c09853;
-}
-
-a.text-warning:hover {
-  color: #a47e3c;
-}
-
-.text-error {
-  color: #b94a48;
-}
-
-a.text-error:hover {
-  color: #953b39;
-}
-
-.text-info {
-  color: #3a87ad;
-}
-
-a.text-info:hover {
-  color: #2d6987;
-}
-
-.text-success {
-  color: #468847;
-}
-
-a.text-success:hover {
-  color: #356635;
-}
-
-h1,
-h2,
-h3,
-h4,
-h5,
-h6 {
-  margin: 10px 0;
-  font-family: inherit;
-  font-weight: bold;
-  line-height: 20px;
-  color: inherit;
-  text-rendering: optimizelegibility;
-}
-
-h1 small,
-h2 small,
-h3 small,
-h4 small,
-h5 small,
-h6 small {
-  font-weight: normal;
-  line-height: 1;
-  color: #999999;
-}
-
-h1,
-h2,
-h3 {
-  line-height: 40px;
-}
-
-h1 {
-  font-size: 38.5px;
-}
-
-h2 {
-  font-size: 31.5px;
-}
-
-h3 {
-  font-size: 24.5px;
-}
-
-h4 {
-  font-size: 17.5px;
-}
-
-h5 {
-  font-size: 14px;
-}
-
-h6 {
-  font-size: 11.9px;
-}
-
-h1 small {
-  font-size: 24.5px;
-}
-
-h2 small {
-  font-size: 17.5px;
-}
-
-h3 small {
-  font-size: 14px;
-}
-
-h4 small {
-  font-size: 14px;
-}
-
-.page-header {
-  padding-bottom: 9px;
-  margin: 20px 0 30px;
-  border-bottom: 1px solid #eeeeee;
-}
-
-ul,
-ol {
-  padding: 0;
-  margin: 0 0 10px 25px;
-}
-
-ul ul,
-ul ol,
-ol ol,
-ol ul {
-  margin-bottom: 0;
-}
-
-li {
-  line-height: 20px;
-}
-
-ul.unstyled,
-ol.unstyled {
-  margin-left: 0;
-  list-style: none;
-}
-
-ul.inline,
-ol.inline {
-  margin-left: 0;
-  list-style: none;
-}
-
-ul.inline > li,
-ol.inline > li {
-  display: inline-block;
-  padding-right: 5px;
-  padding-left: 5px;
-}
-
-dl {
-  margin-bottom: 20px;
-}
-
-dt,
-dd {
-  line-height: 20px;
-}
-
-dt {
-  font-weight: bold;
-}
-
-dd {
-  margin-left: 10px;
-}
-
-.dl-horizontal {
-  *zoom: 1;
-}
-
-.dl-horizontal:before,
-.dl-horizontal:after {
-  display: table;
-  line-height: 0;
-  content: "";
-}
-
-.dl-horizontal:after {
-  clear: both;
-}
-
-.dl-horizontal dt {
-  float: left;
-  width: 160px;
-  overflow: hidden;
-  clear: left;
-  text-align: right;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-}
-
-.dl-horizontal dd {
-  margin-left: 180px;
-}
-
-hr {
-  margin: 20px 0;
-  border: 0;
-  border-top: 1px solid #eeeeee;
-  border-bottom: 1px solid #ffffff;
-}
-
-abbr[title],
-abbr[data-original-title] {
-  cursor: help;
-  border-bottom: 1px dotted #999999;
-}
-
-abbr.initialism {
-  font-size: 90%;
-  text-transform: uppercase;
-}
-
-blockquote {
-  padding: 0 0 0 15px;
-  margin: 0 0 20px;
-  border-left: 5px solid #eeeeee;
-}
-
-blockquote p {
-  margin-bottom: 0;
-  font-size: 16px;
-  font-weight: 300;
-  line-height: 25px;
-}
-
-blockquote small {
-  display: block;
-  line-height: 20px;
-  color: #999999;
-}
-
-blockquote small:before {
-  content: '\2014 \00A0';
-}
-
-blockquote.pull-right {
-  float: right;
-  padding-right: 15px;
-  padding-left: 0;
-  border-right: 5px solid #eeeeee;
-  border-left: 0;
-}
-
-blockquote.pull-right p,
-blockquote.pull-right small {
-  text-align: right;
-}
-
-blockquote.pull-right small:before {
-  content: '';
-}
-
-blockquote.pull-right small:after {
-  content: '\00A0 \2014';
-}
-
-q:before,
-q:after,
-blockquote:before,
-blockquote:after {
-  content: "";
-}
-
-address {
-  display: block;
-  margin-bottom: 20px;
-  font-style: normal;
-  line-height: 20px;
-}
-
-code,
-pre {
-  padding: 0 3px 2px;
-  font-family: Monaco, Menlo, Consolas, "Courier New", monospace;
-  font-size: 12px;
-  color: #333333;
-  -webkit-border-radius: 3px;
-     -moz-border-radius: 3px;
-          border-radius: 3px;
-}
-
-code {
-  padding: 2px 4px;
-  color: #d14;
-  white-space: nowrap;
-  background-color: #f7f7f9;
-  border: 1px solid #e1e1e8;
-}
-
-pre {
-  display: block;
-  padding: 9.5px;
-  margin: 0 0 10px;
-  font-size: 13px;
-  line-height: 20px;
-  word-break: break-all;
-  word-wrap: break-word;
-  white-space: pre;
-  white-space: pre-wrap;
-  background-color: #f5f5f5;
-  border: 1px solid #ccc;
-  border: 1px solid rgba(0, 0, 0, 0.15);
-  -webkit-border-radius: 4px;
-     -moz-border-radius: 4px;
-          border-radius: 4px;
-}
-
-pre.prettyprint {
-  margin-bottom: 20px;
-}
-
-pre code {
-  padding: 0;
-  color: inherit;
-  white-space: pre;
-  white-space: pre-wrap;
-  background-color: transparent;
-  border: 0;
-}
-
-.pre-scrollable {
-  max-height: 340px;
-  overflow-y: scroll;
-}
-
-form {
-  margin: 0 0 20px;
-}
-
-fieldset {
-  padding: 0;
-  margin: 0;
-  border: 0;
-}
-
-legend {
-  display: block;
-  width: 100%;
-  padding: 0;
-  margin-bottom: 20px;
-  font-size: 21px;
-  line-height: 40px;
-  color: #333333;
-  border: 0;
-  border-bottom: 1px solid #e5e5e5;
-}
-
-legend small {
-  font-size: 15px;
-  color: #999999;
-}
-
-label,
-input,
-button,
-select,
-textarea {
-  font-size: 14px;
-  font-weight: normal;
-  line-height: 20px;
-}
-
-input,
-button,
-select,
-textarea {
-  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
-}
-
-label {
-  display: block;
-  margin-bottom: 5px;
-}
-
-select,
-textarea,
-input[type="text"],
-input[type="password"],
-input[type="datetime"],
-input[type="datetime-local"],
-input[type="date"],
-input[type="month"],
-input[type="time"],
-input[type="week"],
-input[type="number"],
-input[type="email"],
-input[type="url"],
-input[type="search"],
-input[type="tel"],
-input[type="color"],
-.uneditable-input {
-  display: inline-block;
-  height: 20px;
-  padding: 4px 6px;
-  margin-bottom: 10px;
-  font-size: 14px;
-  line-height: 20px;
-  color: #555555;
-  vertical-align: middle;
-  -webkit-border-radius: 4px;
-     -moz-border-radius: 4px;
-          border-radius: 4px;
-}
-
-input,
-textarea,
-.uneditable-input {
-  width: 206px;
-}
-
-textarea {
-  height: auto;
-}
-
-textarea,
-input[type="text"],
-input[type="password"],
-input[type="datetime"],
-input[type="datetime-local"],
-input[type="date"],
-input[type="month"],
-input[type="time"],
-input[type="week"],
-input[type="number"],
-input[type="email"],
-input[type="url"],
-input[type="search"],
-input[type="tel"],
-input[type="color"],
-.uneditable-input {
-  background-color: #ffffff;
-  border: 1px solid #cccccc;
-  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;
-     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;
-       -o-transition: border linear 0.2s, box-shadow linear 0.2s;
-          transition: border linear 0.2s, box-shadow linear 0.2s;
-}
-
-textarea:focus,
-input[type="text"]:focus,
-input[type="password"]:focus,
-input[type="datetime"]:focus,
-input[type="datetime-local"]:focus,
-input[type="date"]:focus,
-input[type="month"]:focus,
-input[type="time"]:focus,
-input[type="week"]:focus,
-input[type="number"]:focus,
-input[type="email"]:focus,
-input[type="url"]:focus,
-input[type="search"]:focus,
-input[type="tel"]:focus,
-input[type="color"]:focus,
-.uneditable-input:focus {
-  border-color: rgba(82, 168, 236, 0.8);
-  outline: 0;
-  outline: thin dotted \9;
-  /* IE6-9 */
-
-  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
-     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
-          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
-}
-
-input[type="radio"],
-input[type="checkbox"] {
-  margin: 4px 0 0;
-  margin-top: 1px \9;
-  *margin-top: 0;
-  line-height: normal;
-}
-
-input[type="file"],
-input[type="image"],
-input[type="submit"],
-input[type="reset"],
-input[type="button"],
-input[type="radio"],
-input[type="checkbox"] {
-  width: auto;
-}
-
-select,
-input[type="file"] {
-  height: 30px;
-  /* In IE7, the height of the select element cannot be changed by height, only font-size */
-
-  *margin-top: 4px;
-  /* For IE7, add top margin to align select with labels */
-
-  line-height: 30px;
-}
-
-select {
-  width: 220px;
-  background-color: #ffffff;
-  border: 1px solid #cccccc;
-}
-
-select[multiple],
-select[size] {
-  height: auto;
-}
-
-select:focus,
-input[type="file"]:focus,
-input[type="radio"]:focus,
-input[type="checkbox"]:focus {
-  outline: thin dotted #333;
-  outline: 5px auto -webkit-focus-ring-color;
-  outline-offset: -2px;
-}
-
-.uneditable-input,
-.uneditable-textarea {
-  color: #999999;
-  cursor: not-allowed;
-  background-color: #fcfcfc;
-  border-color: #cccccc;
-  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
-     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
-          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
-}
-
-.uneditable-input {
-  overflow: hidden;
-  white-space: nowrap;
-}
-
-.uneditable-textarea {
-  width: auto;
-  height: auto;
-}
-
-input:-moz-placeholder,
-textarea:-moz-placeholder {
-  color: #999999;
-}
-
-input:-ms-input-placeholder,
-textarea:-ms-input-placeholder {
-  color: #999999;
-}
-
-input::-webkit-input-placeholder,
-textarea::-webkit-input-placeholder {
-  color: #999999;
-}
-
-.radio,
-.checkbox {
-  min-height: 20px;
-  padding-left: 20px;
-}
-
-.radio input[type="radio"],
-.checkbox input[type="checkbox"] {
-  float: left;
-  margin-left: -20px;
-}
-
-.controls > .radio:first-child,
-.controls > .checkbox:first-child {
-  padding-top: 5px;
-}
-
-.radio.inline,
-.checkbox.inline {
-  display: inline-block;
-  padding-top: 5px;
-  margin-bottom: 0;
-  vertical-align: middle;
-}
-
-.radio.inline + .radio.inline,
-.checkbox.inline + .checkbox.inline {
-  margin-left: 10px;
-}
-
-.input-mini {
-  width: 60px;
-}
-
-.input-small {
-  width: 90px;
-}
-
-.input-medium {
-  width: 150px;
-}
-
-.input-large {
-  width: 210px;
-}
-
-.input-xlarge {
-  width: 270px;
-}
-
-.input-xxlarge {
-  width: 530px;
-}
-
-input[class*="span"],
-select[class*="span"],
-textarea[class*="span"],
-.uneditable-input[class*="span"],
-.row-fluid input[class*="span"],
-.row-fluid select[class*="span"],
-.row-fluid textarea[class*="span"],
-.row-fluid .uneditable-input[class*="span"] {
-  float: none;
-  margin-left: 0;
-}
-
-.input-append input[class*="span"],
-.input-append .uneditable-input[class*="span"],
-.input-prepend input[class*="span"],
-.input-prepend .uneditable-input[class*="span"],
-.row-fluid input[class*="span"],
-.row-fluid select[class*="span"],
-.row-fluid textarea[class*="span"],
-.row-fluid .uneditable-input[class*="span"],
-.row-fluid .input-prepend [class*="span"],
-.row-fluid .input-append [class*="span"] {
-  display: inline-block;
-}
-
-input,
-textarea,
-.uneditable-input {
-  margin-left: 0;
-}
-
-.controls-row [class*="span"] + [class*="span"] {
-  margin-left: 20px;
-}
-
-input.span12,
-textarea.span12,
-.uneditable-input.span12 {
-  width: 926px;
-}
-
-input.span11,
-textarea.span11,
-.uneditable-input.span11 {
-  width: 846px;
-}
-
-input.span10,
-textarea.span10,
-.uneditable-input.span10 {
-  width: 766px;
-}
-
-input.span9,
-textarea.span9,
-.uneditable-input.span9 {
-  width: 686px;
-}
-
-input.span8,
-textarea.span8,
-.uneditable-input.span8 {
-  width: 606px;
-}
-
-input.span7,
-textarea.span7,
-.uneditable-input.span7 {
-  width: 526px;
-}
-
-input.span6,
-textarea.span6,
-.uneditable-input.span6 {
-  width: 446px;
-}
-
-input.span5,
-textarea.span5,
-.uneditable-input.span5 {
-  width: 366px;
-}
-
-input.span4,
-textarea.span4,
-.uneditable-input.span4 {
-  width: 286px;
-}
-
-input.span3,
-textarea.span3,
-.uneditable-input.span3 {
-  width: 206px;
-}
-
-input.span2,
-textarea.span2,
-.uneditable-input.span2 {
-  width: 126px;
-}
-
-input.span1,
-textarea.span1,
-.uneditable-input.span1 {
-  width: 46px;
-}
-
-.controls-row {
-  *zoom: 1;
-}
-
-.controls-row:before,
-.controls-row:after {
-  display: table;
-  line-height: 0;
-  content: "";
-}
-
-.controls-row:after {
-  clear: both;
-}
-
-.controls-row [class*="span"],
-.row-fluid .controls-row [class*="span"] {
-  float: left;
-}
-
-.controls-row .checkbox[class*="span"],
-.controls-row .radio[class*="span"] {
-  padding-top: 5px;
-}
-
-input[disabled],
-select[disabled],
-textarea[disabled],
-input[readonly],
-select[readonly],
-textarea[readonly] {
-  cursor: not-allowed;
-  background-color: #eeeeee;
-}
-
-input[type="radio"][disabled],
-input[type="checkbox"][disabled],
-input[type="radio"][readonly],
-input[type="checkbox"][readonly] {
-  background-color: transparent;
-}
-
-.control-group.warning .control-label,
-.control-group.warning .help-block,
-.control-group.warning .help-inline {
-  color: #c09853;
-}
-
-.control-group.warning .checkbox,
-.control-group.warning .radio,
-.control-group.warning input,
-.control-group.warning select,
-.control-group.warning textarea {
-  color: #c09853;
-}
-
-.control-group.warning input,
-.control-group.warning select,
-.control-group.warning textarea {
-  border-color: #c09853;
-  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-}
-
-.control-group.warning input:focus,
-.control-group.warning select:focus,
-.control-group.warning textarea:focus {
-  border-color: #a47e3c;
-  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;
-     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;
-          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;
-}
-
-.control-group.warning .input-prepend .add-on,
-.control-group.warning .input-append .add-on {
-  color: #c09853;
-  background-color: #fcf8e3;
-  border-color: #c09853;
-}
-
-.control-group.error .control-label,
-.control-group.error .help-block,
-.control-group.error .help-inline {
-  color: #b94a48;
-}
-
-.control-group.error .checkbox,
-.control-group.error .radio,
-.control-group.error input,
-.control-group.error select,
-.control-group.error textarea {
-  color: #b94a48;
-}
-
-.control-group.error input,
-.control-group.error select,
-.control-group.error textarea {
-  border-color: #b94a48;
-  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-}
-
-.control-group.error input:focus,
-.control-group.error select:focus,
-.control-group.error textarea:focus {
-  border-color: #953b39;
-  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;
-     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;
-          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;
-}
-
-.control-group.error .input-prepend .add-on,
-.control-group.error .input-append .add-on {
-  color: #b94a48;
-  background-color: #f2dede;
-  border-color: #b94a48;
-}
-
-.control-group.success .control-label,
-.control-group.success .help-block,
-.control-group.success .help-inline {
-  color: #468847;
-}
-
-.control-group.success .checkbox,
-.control-group.success .radio,
-.control-group.success input,
-.control-group.success select,
-.control-group.success textarea {
-  color: #468847;
-}
-
-.control-group.success input,
-.control-group.success select,
-.control-group.success textarea {
-  border-color: #468847;
-  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-}
-
-.control-group.success input:focus,
-.control-group.success select:focus,
-.control-group.success textarea:focus {
-  border-color: #356635;
-  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;
-     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;
-          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;
-}
-
-.control-group.success .input-prepend .add-on,
-.control-group.success .input-append .add-on {
-  color: #468847;
-  background-color: #dff0d8;
-  border-color: #468847;
-}
-
-.control-group.info .control-label,
-.control-group.info .help-block,
-.control-group.info .help-inline {
-  color: #3a87ad;
-}
-
-.control-group.info .checkbox,
-.control-group.info .radio,
-.control-group.info input,
-.control-group.info select,
-.control-group.info textarea {
-  color: #3a87ad;
-}
-
-.control-group.info input,
-.control-group.info select,
-.control-group.info textarea {
-  border-color: #3a87ad;
-  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-}
-
-.control-group.info input:focus,
-.control-group.info select:focus,
-.control-group.info textarea:focus {
-  border-color: #2d6987;
-  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;
-     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;
-          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;
-}
-
-.control-group.info .input-prepend .add-on,
-.control-group.info .input-append .add-on {
-  color: #3a87ad;
-  background-color: #d9edf7;
-  border-color: #3a87ad;
-}
-
-input:focus:invalid,
-textarea:focus:invalid,
-select:focus:invalid {
-  color: #b94a48;
-  border-color: #ee5f5b;
-}
-
-input:focus:invalid:focus,
-textarea:focus:invalid:focus,
-select:focus:invalid:focus {
-  border-color: #e9322d;
-  -webkit-box-shadow: 0 0 6px #f8b9b7;
-     -moz-box-shadow: 0 0 6px #f8b9b7;
-          box-shadow: 0 0 6px #f8b9b7;
-}
-
-.form-actions {
-  padding: 19px 20px 20px;
-  margin-top: 20px;
-  margin-bottom: 20px;
-  background-color: #f5f5f5;
-  border-top: 1px solid #e5e5e5;
-  *zoom: 1;
-}
-
-.form-actions:before,
-.form-actions:after {
-  display: table;
-  line-height: 0;
-  content: "";
-}
-
-.form-actions:after {
-  clear: both;
-}
-
-.help-block,
-.help-inline {
-  color: #595959;
-}
-
-.help-block {
-  display: block;
-  margin-bottom: 10px;
-}
-
-.help-inline {
-  display: inline-block;
-  *display: inline;
-  padding-left: 5px;
-  vertical-align: middle;
-  *zoom: 1;
-}
-
-.input-append,
-.input-prepend {
-  margin-bottom: 5px;
-  font-size: 0;
-  white-space: nowrap;
-}
-
-.input-append input,
-.input-prepend input,
-.input-append select,
-.input-prepend select,
-.input-append .uneditable-input,
-.input-prepend .uneditable-input,
-.input-append .dropdown-menu,
-.input-prepend .dropdown-menu {
-  font-size: 14px;
-}
-
-.input-append input,
-.input-prepend input,
-.input-append select,
-.input-prepend select,
-.input-append .uneditable-input,
-.input-prepend .uneditable-input {
-  position: relative;
-  margin-bottom: 0;
-  *margin-left: 0;
-  vertical-align: top;
-  -webkit-border-radius: 0 4px 4px 0;
-     -moz-border-radius: 0 4px 4px 0;
-          border-radius: 0 4px 4px 0;
-}
-
-.input-append input:focus,
-.input-prepend input:focus,
-.input-append select:focus,
-.input-prepend select:focus,
-.input-append .uneditable-input:focus,
-.input-prepend .uneditable-input:focus {
-  z-index: 2;
-}
-
-.input-append .add-on,
-.input-prepend .add-on {
-  display: inline-block;
-  width: auto;
-  height: 20px;
-  min-width: 16px;
-  padding: 4px 5px;
-  font-size: 14px;
-  font-weight: normal;
-  line-height: 20px;
-  text-align: center;
-  text-shadow: 0 1px 0 #ffffff;
-  background-color: #eeeeee;
-  border: 1px solid #ccc;
-}
-
-.input-append .add-on,
-.input-prepend .add-on,
-.input-append .btn,
-.input-prepend .btn,
-.input-append .btn-group > .dropdown-toggle,
-.input-prepend .btn-group > .dropdown-toggle {
-  vertical-align: top;
-  -webkit-border-radius: 0;
-     -moz-border-radius: 0;
-          border-radius: 0;
-}
-
-.input-append .active,
-.input-prepend .active {
-  background-color: #a9dba9;
-  border-color: #46a546;
-}
-
-.input-prepend .add-on,
-.input-prepend .btn {
-  margin-right: -1px;
-}
-
-.input-prepend .add-on:first-child,
-.input-prepend .btn:first-child {
-  -webkit-border-radius: 4px 0 0 4px;
-     -moz-border-radius: 4px 0 0 4px;
-          border-radius: 4px 0 0 4px;
-}
-
-.input-append input,
-.input-append select,
-.input-append .uneditable-input {
-  -webkit-border-radius: 4px 0 0 4px;
-     -moz-border-radius: 4px 0 0 4px;
-          border-radius: 4px 0 0 4px;
-}
-
-.input-append input + .btn-group .btn:last-child,
-.input-append select + .btn-group .btn:last-child,
-.input-append .uneditable-input + .btn-group .btn:last-child {
-  -webkit-border-radius: 0 4px 4px 0;
-     -moz-border-radius: 0 4px 4px 0;
-          border-radius: 0 4px 4px 0;
-}
-
-.input-append .add-on,
-.input-append .btn,
-.input-append .btn-group {
-  margin-left: -1px;
-}
-
-.input-append .add-on:last-child,
-.input-append .btn:last-child,
-.input-append .btn-group:last-child > .dropdown-toggle {
-  -webkit-border-radius: 0 4px 4px 0;
-     -moz-border-radius: 0 4px 4px 0;
-          border-radius: 0 4px 4px 0;
-}
-
-.input-prepend.input-append input,
-.input-prepend.input-append select,
-.input-prepend.input-append .uneditable-input {
-  -webkit-border-radius: 0;
-     -moz-border-radius: 0;
-          border-radius: 0;
-}
-
-.input-prepend.input-append input + .btn-group .btn,
-.input-prepend.input-append select + .btn-group .btn,
-.input-prepend.input-append .uneditable-input + .btn-group .btn {
-  -webkit-border-radius: 0 4px 4px 0;
-     -moz-border-radius: 0 4px 4px 0;
-          border-radius: 0 4px 4px 0;
-}
-
-.input-prepend.input-append .add-on:first-child,
-.input-prepend.input-append .btn:first-child {
-  margin-right: -1px;
-  -webkit-border-radius: 4px 0 0 4px;
-     -moz-border-radius: 4px 0 0 4px;
-          border-radius: 4px 0 0 4px;
-}
-
-.input-prepend.input-append .add-on:last-child,
-.input-prepend.input-append .btn:last-child {
-  margin-left: -1px;
-  -webkit-border-radius: 0 4px 4px 0;
-     -moz-border-radius: 0 4px 4px 0;
-          border-radius: 0 4px 4px 0;
-}
-
-.input-prepend.input-append .btn-group:first-child {
-  margin-left: 0;
-}
-
-input.search-query {
-  padding-right: 14px;
-  padding-right: 4px \9;
-  padding-left: 14px;
-  padding-left: 4px \9;
-  /* IE7-8 doesn't have border-radius, so don't indent the padding */
-
-  margin-bottom: 0;
-  -webkit-border-radius: 15px;
-     -moz-border-radius: 15px;
-          border-radius: 15px;
-}
-
-/* Allow for input prepend/append in search forms */
-
-.form-search .input-append .search-query,
-.form-search .input-prepend .search-query {
-  -webkit-border-radius: 0;
-     -moz-border-radius: 0;
-          border-radius: 0;
-}
-
-.form-search .input-append .search-query {
-  -webkit-border-radius: 14px 0 0 14px;
-     -moz-border-radius: 14px 0 0 14px;
-          border-radius: 14px 0 0 14px;
-}
-
-.form-search .input-append .btn {
-  -webkit-border-radius: 0 14px 14px 0;
-     -moz-border-radius: 0 14px 14px 0;
-          border-radius: 0 14px 14px 0;
-}
-
-.form-search .input-prepend .search-query {
-  -webkit-border-radius: 0 14px 14px 0;
-     -moz-border-radius: 0 14px 14px 0;
-          border-radius: 0 14px 14px 0;
-}
-
-.form-search .input-prepend .btn {
-  -webkit-border-radius: 14px 0 0 14px;
-     -moz-border-radius: 14px 0 0 14px;
-          border-radius: 14px 0 0 14px;
-}
-
-.form-search input,
-.form-inline input,
-.form-horizontal input,
-.form-search textarea,
-.form-inline textarea,
-.form-horizontal textarea,
-.form-search select,
-.form-inline select,
-.form-horizontal select,
-.form-search .help-inline,
-.form-inline .help-inline,
-.form-horizontal .help-inline,
-.form-search .uneditable-input,
-.form-inline .uneditable-input,
-.form-horizontal .uneditable-input,
-.form-search .input-prepend,
-.form-inline .input-prepend,
-.form-horizontal .input-prepend,
-.form-search .input-append,
-.form-inline .input-append,
-.form-horizontal .input-append {
-  display: inline-block;
-  *display: inline;
-  margin-bottom: 0;
-  vertical-align: middle;
-  *zoom: 1;
-}
-
-.form-search .hide,
-.form-inline .hide,
-.form-horizontal .hide {
-  display: none;
-}
-
-.form-search label,
-.form-inline label,
-.form-search .btn-group,
-.form-inline .btn-group {
-  display: inline-block;
-}
-
-.form-search .input-append,
-.form-inline .input-append,
-.form-search .input-prepend,
-.form-inline .input-prepend {
-  margin-bottom: 0;
-}
-
-.form-search .radio,
-.form-search .checkbox,
-.form-inline .radio,
-.form-inline .checkbox {
-  padding-left: 0;
-  margin-bottom: 0;
-  vertical-align: middle;
-}
-
-.form-search .radio input[type="radio"],
-.form-search .checkbox input[type="checkbox"],
-.form-inline .radio input[type="radio"],
-.form-inline .checkbox input[type="checkbox"] {
-  float: left;
-  margin-right: 3px;
-  margin-left: 0;
-}
-
-.control-group {
-  margin-bottom: 10px;
-}
-
-legend + .control-group {
-  margin-top: 20px;
-  -webkit-margin-top-collapse: separate;
-}
-
-.form-horizontal .control-group {
-  margin-bottom: 20px;
-  *zoom: 1;
-}
-
-.form-horizontal .control-group:before,
-.form-horizontal .control-group:after {
-  display: table;
-  line-height: 0;
-  content: "";
-}
-
-.form-horizontal .control-group:after {
-  clear: both;
-}
-
-.form-horizontal .control-label {
-  float: left;
-  width: 160px;
-  padding-top: 5px;
-  text-align: right;
-}
-
-.form-horizontal .controls {
-  *display: inline-block;
-  *padding-left: 20px;
-  margin-left: 180px;
-  *margin-left: 0;
-}
-
-.form-horizontal .controls:first-child {
-  *padding-left: 180px;
-}
-
-.form-horizontal .help-block {
-  margin-bottom: 0;
-}
-
-.form-horizontal input + .help-block,
-.form-horizontal select + .help-block,
-.form-horizontal textarea + .help-block,
-.form-horizontal .uneditable-input + .help-block,
-.form-horizontal .input-prepend + .help-block,
-.form-horizontal .input-append + .help-block {
-  margin-top: 10px;
-}
-
-.form-horizontal .form-actions {
-  padding-left: 180px;
-}
-
-table {
-  max-width: 100%;
-  background-color: transparent;
-  border-collapse: collapse;
-  border-spacing: 0;
-}
-
-.table {
-  width: 100%;
-  margin-bottom: 20px;
-}
-
-.table th,
-.table td {
-  padding: 8px;
-  line-height: 20px;
-  text-align: left;
-  vertical-align: top;
-  border-top: 1px solid #dddddd;
-}
-
-.table th {
-  font-weight: bold;
-}
-
-.table thead th {
-  vertical-align: bottom;
-}
-
-.table caption + thead tr:first-child th,
-.table caption + thead tr:first-child td,
-.table colgroup + thead tr:first-child th,
-.table colgroup + thead tr:first-child td,
-.table thead:first-child tr:first-child th,
-.table thead:first-child tr:first-child td {
-  border-top: 0;
-}
-
-.table tbody + tbody {
-  border-top: 2px solid #dddddd;
-}
-
-.table .table {
-  background-color: #ffffff;
-}
-
-.table-condensed th,
-.table-condensed td {
-  padding: 4px 5px;
-}
-
-.table-bordered {
-  border: 1px solid #dddddd;
-  border-collapse: separate;
-  *border-collapse: collapse;
-  border-left: 0;
-  -webkit-border-radius: 4px;
-     -moz-border-radius: 4px;
-          border-radius: 4px;
-}
-
-.table-bordered th,
-.table-bordered td {
-  border-left: 1px solid #dddddd;
-}
-
-.table-bordered caption + thead tr:first-child th,
-.table-bordered caption + tbody tr:first-child th,
-.table-bordered caption + tbody tr:first-child td,
-.table-bordered colgroup + thead tr:first-child th,
-.table-bordered colgroup + tbody tr:first-child th,
-.table-bordered colgroup + tbody tr:first-child td,
-.table-bordered thead:first-child tr:first-child th,
-.table-bordered tbody:first-child tr:first-child th,
-.table-bordered tbody:first-child tr:first-child td {
-  border-top: 0;
-}
-
-.table-bordered thead:first-child tr:first-child > th:first-child,
-.table-bordered tbody:first-child tr:first-child > td:first-child {
-  -webkit-border-top-left-radius: 4px;
-          border-top-left-radius: 4px;
-  -moz-border-radius-topleft: 4px;
-}
-
-.table-bordered thead:first-child tr:first-child > th:last-child,
-.table-bordered tbody:first-child tr:first-child > td:last-child {
-  -webkit-border-top-right-radius: 4px;
-          border-top-right-radius: 4px;
-  -moz-border-radius-topright: 4px;
-}
-
-.table-bordered thead:last-child tr:last-child > th:first-child,
-.table-bordered tbody:last-child tr:last-child > td:first-child,
-.table-bordered tfoot:last-child tr:last-child > td:first-child {
-  -webkit-border-bottom-left-radius: 4px;
-          border-bottom-left-radius: 4px;
-  -moz-border-radius-bottomleft: 4px;
-}
-
-.table-bordered thead:last-child tr:last-child > th:last-child,
-.table-bordered tbody:last-child tr:last-child > td:last-child,
-.table-bordered tfoot:last-child tr:last-child > td:last-child {
-  -webkit-border-bottom-right-radius: 4px;
-          border-bottom-right-radius: 4px;
-  -moz-border-radius-bottomright: 4px;
-}
-
-.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {
-  -webkit-border-bottom-left-radius: 0;
-          border-bottom-left-radius: 0;
-  -moz-border-radius-bottomleft: 0;
-}
-
-.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {
-  -webkit-border-bottom-right-radius: 0;
-          border-bottom-right-radius: 0;
-  -moz-border-radius-bottomright: 0;
-}
-
-.table-bordered caption + thead tr:first-child th:first-child,
-.table-bordered caption + tbody tr:first-child td:first-child,
-.table-bordered colgroup + thead tr:first-child th:first-child,
-.table-bordered colgroup + tbody tr:first-child td:first-child {
-  -webkit-border-top-left-radius: 4px;
-          border-top-left-radius: 4px;
-  -moz-border-radius-topleft: 4px;
-}
-
-.table-bordered caption + thead tr:first-child th:last-child,
-.table-bordered caption + tbody tr:first-child td:last-child,
-.table-bordered colgroup + thead tr:first-child th:last-child,
-.table-bordered colgroup + tbody tr:first-child td:last-child {
-  -webkit-border-top-right-radius: 4px;
-          border-top-right-radius: 4px;
-  -moz-border-radius-topright: 4px;
-}
-
-.table-striped tbody > tr:nth-child(odd) > td,
-.table-striped tbody > tr:nth-child(odd) > th {
-  background-color: #f9f9f9;
-}
-
-.table-hover tbody tr:hover td,
-.table-hover tbody tr:hover th {
-  background-color: #f5f5f5;
-}
-
-table td[class*="span"],
-table th[class*="span"],
-.row-fluid table td[class*="span"],
-.row-fluid table th[class*="span"] {
-  display: table-cell;
-  float: none;
-  margin-left: 0;
-}
-
-.table td.span1,
-.table th.span1 {
-  float: none;
-  width: 44px;
-  margin-left: 0;
-}
-
-.table td.span2,
-.table th.span2 {
-  float: none;
-  width: 124px;
-  margin-left: 0;
-}
-
-.table td.span3,
-.table th.span3 {
-  float: none;
-  width: 204px;
-  margin-left: 0;
-}
-
-.table td.span4,
-.table th.span4 {
-  float: none;
-  width: 284px;
-  margin-left: 0;
-}
-
-.table td.span5,
-.table th.span5 {
-  float: none;
-  width: 364px;
-  margin-left: 0;
-}
-
-.table td.span6,
-.table th.span6 {
-  float: none;
-  width: 444px;
-  margin-left: 0;
-}
-
-.table td.span7,
-.table th.span7 {
-  float: none;
-  width: 524px;
-  margin-left: 0;
-}
-
-.table td.span8,
-.table th.span8 {
-  float: none;
-  width: 604px;
-  margin-left: 0;
-}
-
-.table td.span9,
-.table th.span9 {
-  float: none;
-  width: 684px;
-  margin-left: 0;
-}
-
-.table td.span10,
-.table th.span10 {
-  float: none;
-  width: 764px;
-  margin-left: 0;
-}
-
-.table td.span11,
-.table th.span11 {
-  float: none;
-  width: 844px;
-  margin-left: 0;
-}
-
-.table td.span12,
-.table th.span12 {
-  float: none;
-  width: 924px;
-  margin-left: 0;
-}
-
-.table tbody tr.success td {
-  background-color: #dff0d8;
-}
-
-.table tbody tr.error td {
-  background-color: #f2dede;
-}
-
-.table tbody tr.warning td {
-  background-color: #fcf8e3;
-}
-
-.table tbody tr.info td {
-  background-color: #d9edf7;
-}
-
-.table-hover tbody tr.success:hover td {
-  background-color: #d0e9c6;
-}
-
-.table-hover tbody tr.error:hover td {
-  background-color: #ebcccc;
-}
-
-.table-hover tbody tr.warning:hover td {
-  background-color: #faf2cc;
-}
-
-.table-hover tbody tr.info:hover td {
-  background-color: #c4e3f3;
-}
-
-[class^="icon-"],
-[class*=" icon-"] {
-  display: inline-block;
-  width: 14px;
-  height: 14px;
-  margin-top: 1px;
-  *margin-right: .3em;
-  line-height: 14px;
-  vertical-align: text-top;
-  background-image: url("../img/glyphicons-halflings.png");
-  background-position: 14px 14px;
-  background-repeat: no-repeat;
-}
-
-/* White icons with optional class, or on hover/active states of certain elements */
-
-.icon-white,
-.nav-pills > .active > a > [class^="icon-"],
-.nav-pills > .active > a > [class*=" icon-"],
-.nav-list > .active > a > [class^="icon-"],
-.nav-list > .active > a > [class*=" icon-"],
-.navbar-inverse .nav > .active > a > [class^="icon-"],
-.navbar-inverse .nav > .active > a > [class*=" icon-"],
-.dropdown-menu > li > a:hover > [class^="icon-"],
-.dropdown-menu > li > a:hover > [class*=" icon-"],
-.dropdown-menu > .active > a > [class^="icon-"],
-.dropdown-menu > .active > a > [class*=" icon-"],
-.dropdown-submenu:hover > a > [class^="icon-"],
-.dropdown-submenu:hover > a > [class*=" icon-"] {
-  background-image: url("../img/glyphicons-halflings-white.png");
-}
-
-.icon-glass {
-  background-position: 0      0;
-}
-
-.icon-music {
-  background-position: -24px 0;
-}
-
-.icon-search {
-  background-position: -48px 0;
-}
-
-.icon-envelope {
-  background-position: -72px 0;
-}
-
-.icon-heart {
-  background-position: -96px 0;
-}
-
-.icon-star {
-  background-position: -120px 0;
-}
-
-.icon-star-empty {
-  background-position: -144px 0;
-}
-
-.icon-user {
-  background-position: -168px 0;
-}
-
-.icon-film {
-  background-position: -192px 0;
-}
-
-.icon-th-large {
-  background-position: -216px 0;
-}
-
-.icon-th {
-  background-position: -240px 0;
-}
-
-.icon-th-list {
-  background-position: -264px 0;
-}
-
-.icon-ok {
-  background-position: -288px 0;
-}
-
-.icon-remove {
-  background-position: -312px 0;
-}
-
-.icon-zoom-in {
-  background-position: -336px 0;
-}
-
-.icon-zoom-out {
-  background-position: -360px 0;
-}
-
-.icon-off {
-  background-position: -384px 0;
-}
-
-.icon-signal {
-  background-position: -408px 0;
-}
-
-.icon-cog {
-  background-position: -432px 0;
-}
-
-.icon-trash {
-  background-position: -456px 0;
-}
-
-.icon-home {
-  background-position: 0 -24px;
-}
-
-.icon-file {
-  background-position: -24px -24px;
-}
-
-.icon-time {
-  background-position: -48px -24px;
-}
-
-.icon-road {
-  background-position: -72px -24px;
-}
-
-.icon-download-alt {
-  background-position: -96px -24px;
-}
-
-.icon-download {
-  background-position: -120px -24px;
-}
-
-.icon-upload {
-  background-position: -144px -24px;
-}
-
-.icon-inbox {
-  background-position: -168px -24px;
-}
-
-.icon-play-circle {
-  background-position: -192px -24px;
-}
-
-.icon-repeat {
-  background-position: -216px -24px;
-}
-
-.icon-refresh {
-  background-position: -240px -24px;
-}
-
-.icon-list-alt {
-  background-position: -264px -24px;
-}
-
-.icon-lock {
-  background-position: -287px -24px;
-}
-
-.icon-flag {
-  background-position: -312px -24px;
-}
-
-.icon-headphones {
-  background-position: -336px -24px;
-}
-
-.icon-volume-off {
-  background-position: -360px -24px;
-}
-
-.icon-volume-down {
-  background-position: -384px -24px;
-}
-
-.icon-volume-up {
-  background-position: -408px -24px;
-}
-
-.icon-qrcode {
-  background-position: -432px -24px;
-}
-
-.icon-barcode {
-  background-position: -456px -24px;
-}
-
-.icon-tag {
-  background-position: 0 -48px;
-}
-
-.icon-tags {
-  background-position: -25px -48px;
-}
-
-.icon-book {
-  background-position: -48px -48px;
-}
-
-.icon-bookmark {
-  background-position: -72px -48px;
-}
-
-.icon-print {
-  background-position: -96px -48px;
-}
-
-.icon-camera {
-  background-position: -120px -48px;
-}
-
-.icon-font {
-  background-position: -144px -48px;
-}
-
-.icon-bold {
-  background-position: -167px -48px;
-}
-
-.icon-italic {
-  background-position: -192px -48px;
-}
-
-.icon-text-height {
-  background-position: -216px -48px;
-}
-
-.icon-text-width {
-  background-position: -240px -48px;
-}
-
-.icon-align-left {
-  background-position: -264px -48px;
-}
-
-.icon-align-center {
-  background-position: -288px -48px;
-}
-
-.icon-align-right {
-  background-position: -312px -48px;
-}
-
-.icon-align-justify {
-  background-position: -336px -48px;
-}
-
-.icon-list {
-  background-position: -360px -48px;
-}
-
-.icon-indent-left {
-  background-position: -384px -48px;
-}
-
-.icon-indent-right {
-  background-position: -408px -48px;
-}
-
-.icon-facetime-video {
-  background-position: -432px -48px;
-}
-
-.icon-picture {
-  background-position: -456px -48px;
-}
-
-.icon-pencil {
-  background-position: 0 -72px;
-}
-
-.icon-map-marker {
-  background-position: -24px -72px;
-}
-
-.icon-adjust {
-  background-position: -48px -72px;
-}
-
-.icon-tint {
-  background-position: -72px -72px;
-}
-
-.icon-edit {
-  background-position: -96px -72px;
-}
-
-.icon-share {
-  background-position: -120px -72px;
-}
-
-.icon-check {
-  background-position: -144px -72px;
-}
-
-.icon-move {
-  background-position: -168px -72px;
-}
-
-.icon-step-backward {
-  background-position: -192px -72px;
-}
-
-.icon-fast-backward {
-  background-position: -216px -72px;
-}
-
-.icon-backward {
-  background-position: -240px -72px;
-}
-
-.icon-play {
-  background-position: -264px -72px;
-}
-
-.icon-pause {
-  background-position: -288px -72px;
-}
-
-.icon-stop {
-  background-position: -312px -72px;
-}
-
-.icon-forward {
-  background-position: -336px -72px;
-}
-
-.icon-fast-forward {
-  background-position: -360px -72px;
-}
-
-.icon-step-forward {
-  background-position: -384px -72px;
-}
-
-.icon-eject {
-  background-position: -408px -72px;
-}
-
-.icon-chevron-left {
-  background-position: -432px -72px;
-}
-
-.icon-chevron-right {
-  background-position: -456px -72px;
-}
-
-.icon-plus-sign {
-  background-position: 0 -96px;
-}
-
-.icon-minus-sign {
-  background-position: -24px -96px;
-}
-
-.icon-remove-sign {
-  background-position: -48px -96px;
-}
-
-.icon-ok-sign {
-  background-position: -72px -96px;
-}
-
-.icon-question-sign {
-  background-position: -96px -96px;
-}
-
-.icon-info-sign {
-  background-position: -120px -96px;
-}
-
-.icon-screenshot {
-  background-position: -144px -96px;
-}
-
-.icon-remove-circle {
-  background-position: -168px -96px;
-}
-
-.icon-ok-circle {
-  background-position: -192px -96px;
-}
-
-.icon-ban-circle {
-  background-position: -216px -96px;
-}
-
-.icon-arrow-left {
-  background-position: -240px -96px;
-}
-
-.icon-arrow-right {
-  background-position: -264px -96px;
-}
-
-.icon-arrow-up {
-  background-position: -289px -96px;
-}
-
-.icon-arrow-down {
-  background-position: -312px -96px;
-}
-
-.icon-share-alt {
-  background-position: -336px -96px;
-}
-
-.icon-resize-full {
-  background-position: -360px -96px;
-}
-
-.icon-resize-small {
-  background-position: -384px -96px;
-}
-
-.icon-plus {
-  background-position: -408px -96px;
-}
-
-.icon-minus {
-  background-position: -433px -96px;
-}
-
-.icon-asterisk {
-  background-position: -456px -96px;
-}
-
-.icon-exclamation-sign {
-  background-position: 0 -120px;
-}
-
-.icon-gift {
-  background-position: -24px -120px;
-}
-
-.icon-leaf {
-  background-position: -48px -120px;
-}
-
-.icon-fire {
-  background-position: -72px -120px;
-}
-
-.icon-eye-open {
-  background-position: -96px -120px;
-}
-
-.icon-eye-close {
-  background-position: -120px -120px;
-}
-
-.icon-warning-sign {
-  background-position: -144px -120px;
-}
-
-.icon-plane {
-  background-position: -168px -120px;
-}
-
-.icon-calendar {
-  background-position: -192px -120px;
-}
-
-.icon-random {
-  width: 16px;
-  background-position: -216px -120px;
-}
-
-.icon-comment {
-  background-position: -240px -120px;
-}
-
-.icon-magnet {
-  background-position: -264px -120px;
-}
-
-.icon-chevron-up {
-  background-position: -288px -120px;
-}
-
-.icon-chevron-down {
-  background-position: -313px -119px;
-}
-
-.icon-retweet {
-  background-position: -336px -120px;
-}
-
-.icon-shopping-cart {
-  background-position: -360px -120px;
-}
-
-.icon-folder-close {
-  background-position: -384px -120px;
-}
-
-.icon-folder-open {
-  width: 16px;
-  background-position: -408px -120px;
-}
-
-.icon-resize-vertical {
-  background-position: -432px -119px;
-}
-
-.icon-resize-horizontal {
-  background-position: -456px -118px;
-}
-
-.icon-hdd {
-  background-position: 0 -144px;
-}
-
-.icon-bullhorn {
-  background-position: -24px -144px;
-}
-
-.icon-bell {
-  background-position: -48px -144px;
-}
-
-.icon-certificate {
-  background-position: -72px -144px;
-}
-
-.icon-thumbs-up {
-  background-position: -96px -144px;
-}
-
-.icon-thumbs-down {
-  background-position: -120px -144px;
-}
-
-.icon-hand-right {
-  background-position: -144px -144px;
-}
-
-.icon-hand-left {
-  background-position: -168px -144px;
-}
-
-.icon-hand-up {
-  background-position: -192px -144px;
-}
-
-.icon-hand-down {
-  background-position: -216px -144px;
-}
-
-.icon-circle-arrow-right {
-  background-position: -240px -144px;
-}
-
-.icon-circle-arrow-left {
-  background-position: -264px -144px;
-}
-
-.icon-circle-arrow-up {
-  background-position: -288px -144px;
-}
-
-.icon-circle-arrow-down {
-  background-position: -312px -144px;
-}
-
-.icon-globe {
-  background-position: -336px -144px;
-}
-
-.icon-wrench {
-  background-position: -360px -144px;
-}
-
-.icon-tasks {
-  background-position: -384px -144px;
-}
-
-.icon-filter {
-  background-position: -408px -144px;
-}
-
-.icon-briefcase {
-  background-position: -432px -144px;
-}
-
-.icon-fullscreen {
-  background-position: -456px -144px;
-}
-
-.dropup,
-.dropdown {
-  position: relative;
-}
-
-.dropdown-toggle {
-  *margin-bottom: -3px;
-}
-
-.dropdown-toggle:active,
-.open .dropdown-toggle {
-  outline: 0;
-}
-
-.caret {
-  display: inline-block;
-  width: 0;
-  height: 0;
-  vertical-align: top;
-  border-top: 4px solid #000000;
-  border-right: 4px solid transparent;
-  border-left: 4px solid transparent;
-  content: "";
-}
-
-.dropdown .caret {
-  margin-top: 8px;
-  margin-left: 2px;
-}
-
-.dropdown-menu {
-  position: absolute;
-  top: 100%;
-  left: 0;
-  z-index: 1000;
-  display: none;
-  float: left;
-  min-width: 160px;
-  padding: 5px 0;
-  margin: 2px 0 0;
-  list-style: none;
-  background-color: #ffffff;
-  border: 1px solid #ccc;
-  border: 1px solid rgba(0, 0, 0, 0.2);
-  *border-right-width: 2px;
-  *border-bottom-width: 2px;
-  -webkit-border-radius: 6px;
-     -moz-border-radius: 6px;
-          border-radius: 6px;
-  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
-     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
-          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
-  -webkit-background-clip: padding-box;
-     -moz-background-clip: padding;
-          background-clip: padding-box;
-}
-
-.dropdown-menu.pull-right {
-  right: 0;
-  left: auto;
-}
-
-.dropdown-menu .divider {
-  *width: 100%;
-  height: 1px;
-  margin: 9px 1px;
-  *margin: -5px 0 5px;
-  overflow: hidden;
-  background-color: #e5e5e5;
-  border-bottom: 1px solid #ffffff;
-}
-
-.dropdown-menu li > a {
-  display: block;
-  padding: 3px 20px;
-  clear: both;
-  font-weight: normal;
-  line-height: 20px;
-  color: #333333;
-  white-space: nowrap;
-}
-
-.dropdown-menu li > a:hover,
-.dropdown-menu li > a:focus,
-.dropdown-submenu:hover > a {
-  color: #ffffff;
-  text-decoration: none;
-  background-color: #0081c2;
-  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);
-  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));
-  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);
-  background-image: -o-linear-gradient(top, #0088cc, #0077b3);
-  background-image: linear-gradient(to bottom, #0088cc, #0077b3);
-  background-repeat: repeat-x;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);
-}
-
-.dropdown-menu .active > a,
-.dropdown-menu .active > a:hover {
-  color: #ffffff;
-  text-decoration: none;
-  background-color: #0081c2;
-  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);
-  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));
-  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);
-  background-image: -o-linear-gradient(top, #0088cc, #0077b3);
-  background-image: linear-gradient(to bottom, #0088cc, #0077b3);
-  background-repeat: repeat-x;
-  outline: 0;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);
-}
-
-.dropdown-menu .disabled > a,
-.dropdown-menu .disabled > a:hover {
-  color: #999999;
-}
-
-.dropdown-menu .disabled > a:hover {
-  text-decoration: none;
-  cursor: default;
-  background-color: transparent;
-  background-image: none;
-  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
-}
-
-.open {
-  *z-index: 1000;
-}
-
-.open > .dropdown-menu {
-  display: block;
-}
-
-.pull-right > .dropdown-menu {
-  right: 0;
-  left: auto;
-}
-
-.dropup .caret,
-.navbar-fixed-bottom .dropdown .caret {
-  border-top: 0;
-  border-bottom: 4px solid #000000;
-  content: "";
-}
-
-.dropup .dropdown-menu,
-.navbar-fixed-bottom .dropdown .dropdown-menu {
-  top: auto;
-  bottom: 100%;
-  margin-bottom: 1px;
-}
-
-.dropdown-submenu {
-  position: relative;
-}
-
-.dropdown-submenu > .dropdown-menu {
-  top: 0;
-  left: 100%;
-  margin-top: -6px;
-  margin-left: -1px;
-  -webkit-border-radius: 0 6px 6px 6px;
-     -moz-border-radius: 0 6px 6px 6px;
-          border-radius: 0 6px 6px 6px;
-}
-
-.dropdown-submenu:hover > .dropdown-menu {
-  display: block;
-}
-
-.dropup .dropdown-submenu > .dropdown-menu {
-  top: auto;
-  bottom: 0;
-  margin-top: 0;
-  margin-bottom: -2px;
-  -webkit-border-radius: 5px 5px 5px 0;
-     -moz-border-radius: 5px 5px 5px 0;
-          border-radius: 5px 5px 5px 0;
-}
-
-.dropdown-submenu > a:after {
-  display: block;
-  float: right;
-  width: 0;
-  height: 0;
-  margin-top: 5px;
-  margin-right: -10px;
-  border-color: transparent;
-  border-left-color: #cccccc;
-  border-style: solid;
-  border-width: 5px 0 5px 5px;
-  content: " ";
-}
-
-.dropdown-submenu:hover > a:after {
-  border-left-color: #ffffff;
-}
-
-.dropdown-submenu.pull-left {
-  float: none;
-}
-
-.dropdown-submenu.pull-left > .dropdown-menu {
-  left: -100%;
-  margin-left: 10px;
-  -webkit-border-radius: 6px 0 6px 6px;
-     -moz-border-radius: 6px 0 6px 6px;
-          border-radius: 6px 0 6px 6px;
-}
-
-.dropdown .dropdown-menu .nav-header {
-  padding-right: 20px;
-  padding-left: 20px;
-}
-
-.typeahead {
-  z-index: 1051;
-  margin-top: 2px;
-  -webkit-border-radius: 4px;
-     -moz-border-radius: 4px;
-          border-radius: 4px;
-}
-
-.well {
-  min-height: 20px;
-  padding: 19px;
-  margin-bottom: 20px;
-  background-color: #f5f5f5;
-  border: 1px solid #e3e3e3;
-  -webkit-border-radius: 4px;
-     -moz-border-radius: 4px;
-          border-radius: 4px;
-  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
-     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
-          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
-}
-
-.well blockquote {
-  border-color: #ddd;
-  border-color: rgba(0, 0, 0, 0.15);
-}
-
-.well-large {
-  padding: 24px;
-  -webkit-border-radius: 6px;
-     -moz-border-radius: 6px;
-          border-radius: 6px;
-}
-
-.well-small {
-  padding: 9px;
-  -webkit-border-radius: 3px;
-     -moz-border-radius: 3px;
-          border-radius: 3px;
-}
-
-.fade {
-  opacity: 0;
-  -webkit-transition: opacity 0.15s linear;
-     -moz-transition: opacity 0.15s linear;
-       -o-transition: opacity 0.15s linear;
-          transition: opacity 0.15s linear;
-}
-
-.fade.in {
-  opacity: 1;
-}
-
-.collapse {
-  position: relative;
-  height: 0;
-  overflow: hidden;
-  -webkit-transition: height 0.35s ease;
-     -moz-transition: height 0.35s ease;
-       -o-transition: height 0.35s ease;
-          transition: height 0.35s ease;
-}
-
-.collapse.in {
-  height: auto;
-}
-
-.close {
-  float: right;
-  font-size: 20px;
-  font-weight: bold;
-  line-height: 20px;
-  color: #000000;
-  text-shadow: 0 1px 0 #ffffff;
-  opacity: 0.2;
-  filter: alpha(opacity=20);
-}
-
-.close:hover {
-  color: #000000;
-  text-decoration: none;
-  cursor: pointer;
-  opacity: 0.4;
-  filter: alpha(opacity=40);
-}
-
-button.close {
-  padding: 0;
-  cursor: pointer;
-  background: transparent;
-  border: 0;
-  -webkit-appearance: none;
-}
-
-.btn {
-  display: inline-block;
-  *display: inline;
-  padding: 4px 12px;
-  margin-bottom: 0;
-  *margin-left: .3em;
-  font-size: 14px;
-  line-height: 20px;
-  color: #333333;
-  text-align: center;
-  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
-  vertical-align: middle;
-  cursor: pointer;
-  background-color: #f5f5f5;
-  *background-color: #e6e6e6;
-  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);
-  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));
-  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);
-  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);
-  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);
-  background-repeat: repeat-x;
-  border: 1px solid #bbbbbb;
-  *border: 0;
-  border-color: #e6e6e6 #e6e6e6 #bfbfbf;
-  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
-  border-bottom-color: #a2a2a2;
-  -webkit-border-radius: 4px;
-     -moz-border-radius: 4px;
-          border-radius: 4px;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);
-  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
-  *zoom: 1;
-  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
-     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
-          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
-}
-
-.btn:hover,
-.btn:active,
-.btn.active,
-.btn.disabled,
-.btn[disabled] {
-  color: #333333;
-  background-color: #e6e6e6;
-  *background-color: #d9d9d9;
-}
-
-.btn:active,
-.btn.active {
-  background-color: #cccccc \9;
-}
-
-.btn:first-child {
-  *margin-left: 0;
-}
-
-.btn:hover {
-  color: #333333;
-  text-decoration: none;
-  background-position: 0 -15px;
-  -webkit-transition: background-position 0.1s linear;
-     -moz-transition: background-position 0.1s linear;
-       -o-transition: background-position 0.1s linear;
-          transition: background-position 0.1s linear;
-}
-
-.btn:focus {
-  outline: thin dotted #333;
-  outline: 5px auto -webkit-focus-ring-color;
-  outline-offset: -2px;
-}
-
-.btn.active,
-.btn:active {
-  background-image: none;
-  outline: 0;
-  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
-     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
-          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
-}
-
-.btn.disabled,
-.btn[disabled] {
-  cursor: default;
-  background-image: none;
-  opacity: 0.65;
-  filter: alpha(opacity=65);
-  -webkit-box-shadow: none;
-     -moz-box-shadow: none;
-          box-shadow: none;
-}
-
-.btn-large {
-  padding: 11px 19px;
-  font-size: 17.5px;
-  -webkit-border-radius: 6px;
-     -moz-border-radius: 6px;
-          border-radius: 6px;
-}
-
-.btn-large [class^="icon-"],
-.btn-large [class*=" icon-"] {
-  margin-top: 4px;
-}
-
-.btn-small {
-  padding: 2px 10px;
-  font-size: 11.9px;
-  -webkit-border-radius: 3px;
-     -moz-border-radius: 3px;
-          border-radius: 3px;
-}
-
-.btn-small [class^="icon-"],
-.btn-small [class*=" icon-"] {
-  margin-top: 0;
-}
-
-.btn-mini [class^="icon-"],
-.btn-mini [class*=" icon-"] {
-  margin-top: -1px;
-}
-
-.btn-mini {
-  padding: 0 6px;
-  font-size: 10.5px;
-  -webkit-border-radius: 3px;
-     -moz-border-radius: 3px;
-          border-radius: 3px;
-}
-
-.btn-block {
-  display: block;
-  width: 100%;
-  padding-right: 0;
-  padding-left: 0;
-  -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
-}
-
-.btn-block + .btn-block {
-  margin-top: 5px;
-}
-
-input[type="submit"].btn-block,
-input[type="reset"].btn-block,
-input[type="button"].btn-block {
-  width: 100%;
-}
-
-.btn-primary.active,
-.btn-warning.active,
-.btn-danger.active,
-.btn-success.active,
-.btn-info.active,
-.btn-inverse.active {
-  color: rgba(255, 255, 255, 0.75);
-}
-
-.btn {
-  border-color: #c5c5c5;
-  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);
-}
-
-.btn-primary {
-  color: #ffffff;
-  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
-  background-color: #006dcc;
-  *background-color: #0044cc;
-  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
-  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
-  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
-  background-image: -o-linear-gradient(top, #0088cc, #0044cc);
-  background-image: linear-gradient(to bottom, #0088cc, #0044cc);
-  background-repeat: repeat-x;
-  border-color: #0044cc #0044cc #002a80;
-  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);
-  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
-}
-
-.btn-primary:hover,
-.btn-primary:active,
-.btn-primary.active,
-.btn-primary.disabled,
-.btn-primary[disabled] {
-  color: #ffffff;
-  background-color: #0044cc;
-  *background-color: #003bb3;
-}
-
-.btn-primary:active,
-.btn-primary.active {
-  background-color: #003399 \9;
-}
-
-.btn-warning {
-  color: #ffffff;
-  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
-  background-color: #faa732;
-  *background-color: #f89406;
-  background-image: -moz-linear-gradient(top, #fbb450, #f89406);
-  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));
-  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);
-  background-image: -o-linear-gradient(top, #fbb450, #f89406);
-  background-image: linear-gradient(to bottom, #fbb450, #f89406);
-  background-repeat: repeat-x;
-  border-color: #f89406 #f89406 #ad6704;
-  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);
-  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
-}
-
-.btn-warning:hover,
-.btn-warning:active,
-.btn-warning.active,
-.btn-warning.disabled,
-.btn-warning[disabled] {
-  color: #ffffff;
-  background-color: #f89406;
-  *background-color: #df8505;
-}
-
-.btn-warning:active,
-.btn-warning.active {
-  background-color: #c67605 \9;
-}
-
-.btn-danger {
-  color: #ffffff;
-  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
-  background-color: #da4f49;
-  *background-color: #bd362f;
-  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);
-  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));
-  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);
-  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);
-  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);
-  background-repeat: repeat-x;
-  border-color: #bd362f #bd362f #802420;
-  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);
-  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
-}
-
-.btn-danger:hover,
-.btn-danger:active,
-.btn-danger.active,
-.btn-danger.disabled,
-.btn-danger[disabled] {
-  color: #ffffff;
-  background-color: #bd362f;
-  *background-color: #a9302a;
-}
-
-.btn-danger:active,
-.btn-danger.active {
-  background-color: #942a25 \9;
-}
-
-.btn-success {
-  color: #ffffff;
-  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
-  background-color: #5bb75b;
-  *background-color: #51a351;
-  background-image: -moz-linear-gradient(top, #62c462, #51a351);
-  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));
-  background-image: -webkit-linear-gradient(top, #62c462, #51a351);
-  background-image: -o-linear-gradient(top, #62c462, #51a351);
-  background-image: linear-gradient(to bottom, #62c462, #51a351);
-  background-repeat: repeat-x;
-  border-color: #51a351 #51a351 #387038;
-  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);
-  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
-}
-
-.btn-success:hover,
-.btn-success:active,
-.btn-success.active,
-.btn-success.disabled,
-.btn-success[disabled] {
-  color: #ffffff;
-  background-color: #51a351;
-  *background-color: #499249;
-}
-
-.btn-success:active,
-.btn-success.active {
-  background-color: #408140 \9;
-}
-
-.btn-info {
-  color: #ffffff;
-  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
-  background-color: #49afcd;
-  *background-color: #2f96b4;
-  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);
-  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));
-  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);
-  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);
-  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);
-  background-repeat: repeat-x;
-  border-color: #2f96b4 #2f96b4 #1f6377;
-  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);
-  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
-}
-
-.btn-info:hover,
-.btn-info:active,
-.btn-info.active,
-.btn-info.disabled,
-.btn-info[disabled] {
-  color: #ffffff;
-  background-color: #2f96b4;
-  *background-color: #2a85a0;
-}
-
-.btn-info:active,
-.btn-info.active {
-  background-color: #24748c \9;
-}
-
-.btn-inverse {
-  color: #ffffff;
-  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
-  background-color: #363636;
-  *background-color: #222222;
-  background-image: -moz-linear-gradient(top, #444444, #222222);
-  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));
-  background-image: -webkit-linear-gradient(top, #444444, #222222);
-  background-image: -o-linear-gradient(top, #444444, #222222);
-  background-image: linear-gradient(to bottom, #444444, #222222);
-  background-repeat: repeat-x;
-  border-color: #222222 #222222 #000000;
-  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);
-  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
-}
-
-.btn-inverse:hover,
-.btn-inverse:active,
-.btn-inverse.active,
-.btn-inverse.disabled,
-.btn-inverse[disabled] {
-  color: #ffffff;
-  background-color: #222222;
-  *background-color: #151515;
-}
-
-.btn-inverse:active,
-.btn-inverse.active {
-  background-color: #080808 \9;
-}
-
-button.btn,
-input[type="submit"].btn {
-  *padding-top: 3px;
-  *padding-bottom: 3px;
-}
-
-button.btn::-moz-focus-inner,
-input[type="submit"].btn::-moz-focus-inner {
-  padding: 0;
-  border: 0;
-}
-
-button.btn.btn-large,
-input[type="submit"].btn.btn-large {
-  *padding-top: 7px;
-  *padding-bottom: 7px;
-}
-
-button.btn.btn-small,
-input[type="submit"].btn.btn-small {
-  *padding-top: 3px;
-  *padding-bottom: 3px;
-}
-
-button.btn.btn-mini,
-input[type="submit"].btn.btn-mini {
-  *padding-top: 1px;
-  *padding-bottom: 1px;
-}
-
-.btn-link,
-.btn-link:active,
-.btn-link[disabled] {
-  background-color: transparent;
-  background-image: none;
-  -webkit-box-shadow: none;
-     -moz-box-shadow: none;
-          box-shadow: none;
-}
-
-.btn-link {
-  color: #0088cc;
-  cursor: pointer;
-  border-color: transparent;
-  -webkit-border-radius: 0;
-     -moz-border-radius: 0;
-          border-radius: 0;
-}
-
-.btn-link:hover {
-  color: #005580;
-  text-decoration: underline;
-  background-color: transparent;
-}
-
-.btn-link[disabled]:hover {
-  color: #333333;
-  text-decoration: none;
-}
-
-.btn-group {
-  position: relative;
-  display: inline-block;
-  *display: inline;
-  *margin-left: .3em;
-  font-size: 0;
-  white-space: nowrap;
-  vertical-align: middle;
-  *zoom: 1;
-}
-
-.btn-group:first-child {
-  *margin-left: 0;
-}
-
-.btn-group + .btn-group {
-  margin-left: 5px;
-}
-
-.btn-toolbar {
-  margin-top: 10px;
-  margin-bottom: 10px;
-  font-size: 0;
-}
-
-.btn-toolbar > .btn + .btn,
-.btn-toolbar > .btn-group + .btn,
-.btn-toolbar > .btn + .btn-group {
-  margin-left: 5px;
-}
-
-.btn-group > .btn {
-  position: relative;
-  -webkit-border-radius: 0;
-     -moz-border-radius: 0;
-          border-radius: 0;
-}
-
-.btn-group > .btn + .btn {
-  margin-left: -1px;
-}
-
-.btn-group > .btn,
-.btn-group > .dropdown-menu,
-.btn-group > .popover {
-  font-size: 14px;
-}
-
-.btn-group > .btn-mini {
-  font-size: 10.5px;
-}
-
-.btn-group > .btn-small {
-  font-size: 11.9px;
-}
-
-.btn-group > .btn-large {
-  font-size: 17.5px;
-}
-
-.btn-group > .btn:first-child {
-  margin-left: 0;
-  -webkit-border-bottom-left-radius: 4px;
-          border-bottom-left-radius: 4px;
-  -webkit-border-top-left-radius: 4px;
-          border-top-left-radius: 4px;
-  -moz-border-radius-bottomleft: 4px;
-  -moz-border-radius-topleft: 4px;
-}
-
-.btn-group > .btn:last-child,
-.btn-group > .dropdown-toggle {
-  -webkit-border-top-right-radius: 4px;
-          border-top-right-radius: 4px;
-  -webkit-border-bottom-right-radius: 4px;
-          border-bottom-right-radius: 4px;
-  -moz-border-radius-topright: 4px;
-  -moz-border-radius-bottomright: 4px;
-}
-
-.btn-group > .btn.large:first-child {
-  margin-left: 0;
-  -webkit-border-bottom-left-radius: 6px;
-          border-bottom-left-radius: 6px;
-  -webkit-border-top-left-radius: 6px;
-          border-top-left-radius: 6px;
-  -moz-border-radius-bottomleft: 6px;
-  -moz-border-radius-topleft: 6px;
-}
-
-.btn-group > .btn.large:last-child,
-.btn-group > .large.dropdown-toggle {
-  -webkit-border-top-right-radius: 6px;
-          border-top-right-radius: 6px;
-  -webkit-border-bottom-right-radius: 6px;
-          border-bottom-right-radius: 6px;
-  -moz-border-radius-topright: 6px;
-  -moz-border-radius-bottomright: 6px;
-}
-
-.btn-group > .btn:hover,
-.btn-group > .btn:focus,
-.btn-group > .btn:active,
-.btn-group > .btn.active {
-  z-index: 2;
-}
-
-.btn-group .dropdown-toggle:active,
-.btn-group.open .dropdown-toggle {
-  outline: 0;
-}
-
-.btn-group > .btn + .dropdown-toggle {
-  *padding-top: 5px;
-  padding-right: 8px;
-  *padding-bottom: 5px;
-  padding-left: 8px;
-  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
-     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
-          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
-}
-
-.btn-group > .btn-mini + .dropdown-toggle {
-  *padding-top: 2px;
-  padding-right: 5px;
-  *padding-bottom: 2px;
-  padding-left: 5px;
-}
-
-.btn-group > .btn-small + .dropdown-toggle {
-  *padding-top: 5px;
-  *padding-bottom: 4px;
-}
-
-.btn-group > .btn-large + .dropdown-toggle {
-  *padding-top: 7px;
-  padding-right: 12px;
-  *padding-bottom: 7px;
-  padding-left: 12px;
-}
-
-.btn-group.open .dropdown-toggle {
-  background-image: none;
-  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
-     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
-          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
-}
-
-.btn-group.open .btn.dropdown-toggle {
-  background-color: #e6e6e6;
-}
-
-.btn-group.open .btn-primary.dropdown-toggle {
-  background-color: #0044cc;
-}
-
-.btn-group.open .btn-warning.dropdown-toggle {
-  background-color: #f89406;
-}
-
-.btn-group.open .btn-danger.dropdown-toggle {
-  background-color: #bd362f;
-}
-
-.btn-group.open .btn-success.dropdown-toggle {
-  background-color: #51a351;
-}
-
-.btn-group.open .btn-info.dropdown-toggle {
-  background-color: #2f96b4;
-}
-
-.btn-group.open .btn-inverse.dropdown-toggle {
-  background-color: #222222;
-}
-
-.btn .caret {
-  margin-top: 8px;
-  margin-left: 0;
-}
-
-.btn-mini .caret,
-.btn-small .caret,
-.btn-large .caret {
-  margin-top: 6px;
-}
-
-.btn-large .caret {
-  border-top-width: 5px;
-  border-right-width: 5px;
-  border-left-width: 5px;
-}
-
-.dropup .btn-large .caret {
-  border-bottom-width: 5px;
-}
-
-.btn-primary .caret,
-.btn-warning .caret,
-.btn-danger .caret,
-.btn-info .caret,
-.btn-success .caret,
-.btn-inverse .caret {
-  border-top-color: #ffffff;
-  border-bottom-color: #ffffff;
-}
-
-.btn-group-vertical {
-  display: inline-block;
-  *display: inline;
-  /* IE7 inline-block hack */
-
-  *zoom: 1;
-}
-
-.btn-group-vertical > .btn {
-  display: block;
-  float: none;
-  max-width: 100%;
-  -webkit-border-radius: 0;
-     -moz-border-radius: 0;
-          border-radius: 0;
-}
-
-.btn-group-vertical > .btn + .btn {
-  margin-top: -1px;
-  margin-left: 0;
-}
-
-.btn-group-vertical > .btn:first-child {
-  -webkit-border-radius: 4px 4px 0 0;
-     -moz-border-radius: 4px 4px 0 0;
-          border-radius: 4px 4px 0 0;
-}
-
-.btn-group-vertical > .btn:last-child {
-  -webkit-border-radius: 0 0 4px 4px;
-     -moz-border-radius: 0 0 4px 4px;
-          border-radius: 0 0 4px 4px;
-}
-
-.btn-group-vertical > .btn-large:first-child {
-  -webkit-border-radius: 6px 6px 0 0;
-     -moz-border-radius: 6px 6px 0 0;
-          border-radius: 6px 6px 0 0;
-}
-
-.btn-group-vertical > .btn-large:last-child {
-  -webkit-border-radius: 0 0 6px 6px;
-     -moz-border-radius: 0 0 6px 6px;
-          border-radius: 0 0 6px 6px;
-}
-
-.alert {
-  padding: 8px 35px 8px 14px;
-  margin-bottom: 20px;
-  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
-  background-color: #fcf8e3;
-  border: 1px solid #fbeed5;
-  -webkit-border-radius: 4px;
-     -moz-border-radius: 4px;
-          border-radius: 4px;
-}
-
-.alert,
-.alert h4 {
-  color: #c09853;
-}
-
-.alert h4 {
-  margin: 0;
-}
-
-.alert .close {
-  position: relative;
-  top: -2px;
-  right: -21px;
-  line-height: 20px;
-}
-
-.alert-success {
-  color: #468847;
-  background-color: #dff0d8;
-  border-color: #d6e9c6;
-}
-
-.alert-success h4 {
-  color: #468847;
-}
-
-.alert-danger,
-.alert-error {
-  color: #b94a48;
-  background-color: #f2dede;
-  border-color: #eed3d7;
-}
-
-.alert-danger h4,
-.alert-error h4 {
-  color: #b94a48;
-}
-
-.alert-info {
-  color: #3a87ad;
-  background-color: #d9edf7;
-  border-color: #bce8f1;
-}
-
-.alert-info h4 {
-  color: #3a87ad;
-}
-
-.alert-block {
-  padding-top: 14px;
-  padding-bottom: 14px;
-}
-
-.alert-block > p,
-.alert-block > ul {
-  margin-bottom: 0;
-}
-
-.alert-block p + p {
-  margin-top: 5px;
-}
-
-.nav {
-  margin-bottom: 20px;
-  margin-left: 0;
-  list-style: none;
-}
-
-.nav > li > a {
-  display: block;
-}
-
-.nav > li > a:hover {
-  text-decoration: none;
-  background-color: #eeeeee;
-}
-
-.nav > li > a > img {
-  max-width: none;
-}
-
-.nav > .pull-right {
-  float: right;
-}
-
-.nav-header {
-  display: block;
-  padding: 3px 15px;
-  font-size: 11px;
-  font-weight: bold;
-  line-height: 20px;
-  color: #999999;
-  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
-  text-transform: uppercase;
-}
-
-.nav li + .nav-header {
-  margin-top: 9px;
-}
-
-.nav-list {
-  padding-right: 15px;
-  padding-left: 15px;
-  margin-bottom: 0;
-}
-
-.nav-list > li > a,
-.nav-list .nav-header {
-  margin-right: -15px;
-  margin-left: -15px;
-  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
-}
-
-.nav-list > li > a {
-  padding: 3px 15px;
-}
-
-.nav-list > .active > a,
-.nav-list > .active > a:hover {
-  color: #ffffff;
-  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);
-  background-color: #0088cc;
-}
-
-.nav-list [class^="icon-"],
-.nav-list [class*=" icon-"] {
-  margin-right: 2px;
-}
-
-.nav-list .divider {
-  *width: 100%;
-  height: 1px;
-  margin: 9px 1px;
-  *margin: -5px 0 5px;
-  overflow: hidden;
-  background-color: #e5e5e5;
-  border-bottom: 1px solid #ffffff;
-}
-
-.nav-tabs,
-.nav-pills {
-  *zoom: 1;
-}
-
-.nav-tabs:before,
-.nav-pills:before,
-.nav-tabs:after,
-.nav-pills:after {
-  display: table;
-  line-height: 0;
-  content: "";
-}
-
-.nav-tabs:after,
-.nav-pills:after {
-  clear: both;
-}
-
-.nav-tabs > li,
-.nav-pills > li {
-  float: left;
-}
-
-.nav-tabs > li > a,
-.nav-pills > li > a {
-  padding-right: 12px;
-  padding-left: 12px;
-  margin-right: 2px;
-  line-height: 14px;
-}
-
-.nav-tabs {
-  border-bottom: 1px solid #ddd;
-}
-
-.nav-tabs > li {
-  margin-bottom: -1px;
-}
-
-.nav-tabs > li > a {
-  padding-top: 8px;
-  padding-bottom: 8px;
-  line-height: 20px;
-  border: 1px solid transparent;
-  -webkit-border-radius: 4px 4px 0 0;
-     -moz-border-radius: 4px 4px 0 0;
-          border-radius: 4px 4px 0 0;
-}
-
-.nav-tabs > li > a:hover {
-  border-color: #eeeeee #eeeeee #dddddd;
-}
-
-.nav-tabs > .active > a,
-.nav-tabs > .active > a:hover {
-  color: #555555;
-  cursor: default;
-  background-color: #ffffff;
-  border: 1px solid #ddd;
-  border-bottom-color: transparent;
-}
-
-.nav-pills > li > a {
-  padding-top: 8px;
-  padding-bottom: 8px;
-  margin-top: 2px;
-  margin-bottom: 2px;
-  -webkit-border-radius: 5px;
-     -moz-border-radius: 5px;
-          border-radius: 5px;
-}
-
-.nav-pills > .active > a,
-.nav-pills > .active > a:hover {
-  color: #ffffff;
-  background-color: #0088cc;
-}
-
-.nav-stacked > li {
-  float: none;
-}
-
-.nav-stacked > li > a {
-  margin-right: 0;
-}
-
-.nav-tabs.nav-stacked {
-  border-bottom: 0;
-}
-
-.nav-tabs.nav-stacked > li > a {
-  border: 1px solid #ddd;
-  -webkit-border-radius: 0;
-     -moz-border-radius: 0;
-          border-radius: 0;
-}
-
-.nav-tabs.nav-stacked > li:first-child > a {
-  -webkit-border-top-right-radius: 4px;
-          border-top-right-radius: 4px;
-  -webkit-border-top-left-radius: 4px;
-          border-top-left-radius: 4px;
-  -moz-border-radius-topright: 4px;
-  -moz-border-radius-topleft: 4px;
-}
-
-.nav-tabs.nav-stacked > li:last-child > a {
-  -webkit-border-bottom-right-radius: 4px;
-          border-bottom-right-radius: 4px;
-  -webkit-border-bottom-left-radius: 4px;
-          border-bottom-left-radius: 4px;
-  -moz-border-radius-bottomright: 4px;
-  -moz-border-radius-bottomleft: 4px;
-}
-
-.nav-tabs.nav-stacked > li > a:hover {
-  z-index: 2;
-  border-color: #ddd;
-}
-
-.nav-pills.nav-stacked > li > a {
-  margin-bottom: 3px;
-}
-
-.nav-pills.nav-stacked > li:last-child > a {
-  margin-bottom: 1px;
-}
-
-.nav-tabs .dropdown-menu {
-  -webkit-border-radius: 0 0 6px 6px;
-     -moz-border-radius: 0 0 6px 6px;
-          border-radius: 0 0 6px 6px;
-}
-
-.nav-pills .dropdown-menu {
-  -webkit-border-radius: 6px;
-     -moz-border-radius: 6px;
-          border-radius: 6px;
-}
-
-.nav .dropdown-toggle .caret {
-  margin-top: 6px;
-  border-top-color: #0088cc;
-  border-bottom-color: #0088cc;
-}
-
-.nav .dropdown-toggle:hover .caret {
-  border-top-color: #005580;
-  border-bottom-color: #005580;
-}
-
-/* move down carets for tabs */
-
-.nav-tabs .dropdown-toggle .caret {
-  margin-top: 8px;
-}
-
-.nav .active .dropdown-toggle .caret {
-  border-top-color: #fff;
-  border-bottom-color: #fff;
-}
-
-.nav-tabs .active .dropdown-toggle .caret {
-  border-top-color: #555555;
-  border-bottom-color: #555555;
-}
-
-.nav > .dropdown.active > a:hover {
-  cursor: pointer;
-}
-
-.nav-tabs .open .dropdown-toggle,
-.nav-pills .open .dropdown-toggle,
-.nav > li.dropdown.open.active > a:hover {
-  color: #ffffff;
-  background-color: #999999;
-  border-color: #999999;
-}
-
-.nav li.dropdown.open .caret,
-.nav li.dropdown.open.active .caret,
-.nav li.dropdown.open a:hover .caret {
-  border-top-color: #ffffff;
-  border-bottom-color: #ffffff;
-  opacity: 1;
-  filter: alpha(opacity=100);
-}
-
-.tabs-stacked .open > a:hover {
-  border-color: #999999;
-}
-
-.tabbable {
-  *zoom: 1;
-}
-
-.tabbable:before,
-.tabbable:after {
-  display: table;
-  line-height: 0;
-  content: "";
-}
-
-.tabbable:after {
-  clear: both;
-}
-
-.tab-content {
-  overflow: auto;
-}
-
-.tabs-below > .nav-tabs,
-.tabs-right > .nav-tabs,
-.tabs-left > .nav-tabs {
-  border-bottom: 0;
-}
-
-.tab-content > .tab-pane,
-.pill-content > .pill-pane {
-  display: none;
-}
-
-.tab-content > .active,
-.pill-content > .active {
-  display: block;
-}
-
-.tabs-below > .nav-tabs {
-  border-top: 1px solid #ddd;
-}
-
-.tabs-below > .nav-tabs > li {
-  margin-top: -1px;
-  margin-bottom: 0;
-}
-
-.tabs-below > .nav-tabs > li > a {
-  -webkit-border-radius: 0 0 4px 4px;
-     -moz-border-radius: 0 0 4px 4px;
-          border-radius: 0 0 4px 4px;
-}
-
-.tabs-below > .nav-tabs > li > a:hover {
-  border-top-color: #ddd;
-  border-bottom-color: transparent;
-}
-
-.tabs-below > .nav-tabs > .active > a,
-.tabs-below > .nav-tabs > .active > a:hover {
-  border-color: transparent #ddd #ddd #ddd;
-}
-
-.tabs-left > .nav-tabs > li,
-.tabs-right > .nav-tabs > li {
-  float: none;
-}
-
-.tabs-left > .nav-tabs > li > a,
-.tabs-right > .nav-tabs > li > a {
-  min-width: 74px;
-  margin-right: 0;
-  margin-bottom: 3px;
-}
-
-.tabs-left > .nav-tabs {
-  float: left;
-  margin-right: 19px;
-  border-right: 1px solid #ddd;
-}
-
-.tabs-left > .nav-tabs > li > a {
-  margin-right: -1px;
-  -webkit-border-radius: 4px 0 0 4px;
-     -moz-border-radius: 4px 0 0 4px;
-          border-radius: 4px 0 0 4px;
-}
-
-.tabs-left > .nav-tabs > li > a:hover {
-  border-color: #eeeeee #dddddd #eeeeee #eeeeee;
-}
-
-.tabs-left > .nav-tabs .active > a,
-.tabs-left > .nav-tabs .active > a:hover {
-  border-color: #ddd transparent #ddd #ddd;
-  *border-right-color: #ffffff;
-}
-
-.tabs-right > .nav-tabs {
-  float: right;
-  margin-left: 19px;
-  border-left: 1px solid #ddd;
-}
-
-.tabs-right > .nav-tabs > li > a {
-  margin-left: -1px;
-  -webkit-border-radius: 0 4px 4px 0;
-     -moz-border-radius: 0 4px 4px 0;
-          border-radius: 0 4px 4px 0;
-}
-
-.tabs-right > .nav-tabs > li > a:hover {
-  border-color: #eeeeee #eeeeee #eeeeee #dddddd;
-}
-
-.tabs-right > .nav-tabs .active > a,
-.tabs-right > .nav-tabs .active > a:hover {
-  border-color: #ddd #ddd #ddd transparent;
-  *border-left-color: #ffffff;
-}
-
-.nav > .disabled > a {
-  color: #999999;
-}
-
-.nav > .disabled > a:hover {
-  text-decoration: none;
-  cursor: default;
-  background-color: transparent;
-}
-
-.navbar {
-  *position: relative;
-  *z-index: 2;
-  margin-bottom: 20px;
-  overflow: visible;
-}
-
-.navbar-inner {
-  min-height: 40px;
-  padding-right: 20px;
-  padding-left: 20px;
-  background-color: #fafafa;
-  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);
-  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));
-  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);
-  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);
-  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);
-  background-repeat: repeat-x;
-  border: 1px solid #d4d4d4;
-  -webkit-border-radius: 4px;
-     -moz-border-radius: 4px;
-          border-radius: 4px;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);
-  *zoom: 1;
-  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
-     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
-          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
-}
-
-.navbar-inner:before,
-.navbar-inner:after {
-  display: table;
-  line-height: 0;
-  content: "";
-}
-
-.navbar-inner:after {
-  clear: both;
-}
-
-.navbar .container {
-  width: auto;
-}
-
-.nav-collapse.collapse {
-  height: auto;
-  overflow: visible;
-}
-
-.navbar .brand {
-  display: block;
-  float: left;
-  padding: 10px 20px 10px;
-  margin-left: -20px;
-  font-size: 20px;
-  font-weight: 200;
-  color: #777777;
-  text-shadow: 0 1px 0 #ffffff;
-}
-
-.navbar .brand:hover {
-  text-decoration: none;
-}
-
-.navbar-text {
-  margin-bottom: 0;
-  line-height: 40px;
-  color: #777777;
-}
-
-.navbar-link {
-  color: #777777;
-}
-
-.navbar-link:hover {
-  color: #333333;
-}
-
-.navbar .divider-vertical {
-  height: 40px;
-  margin: 0 9px;
-  border-right: 1px solid #ffffff;
-  border-left: 1px solid #f2f2f2;
-}
-
-.navbar .btn,
-.navbar .btn-group {
-  margin-top: 5px;
-}
-
-.navbar .btn-group .btn,
-.navbar .input-prepend .btn,
-.navbar .input-append .btn {
-  margin-top: 0;
-}
-
-.navbar-form {
-  margin-bottom: 0;
-  *zoom: 1;
-}
-
-.navbar-form:before,
-.navbar-form:after {
-  display: table;
-  line-height: 0;
-  content: "";
-}
-
-.navbar-form:after {
-  clear: both;
-}
-
-.navbar-form input,
-.navbar-form select,
-.navbar-form .radio,
-.navbar-form .checkbox {
-  margin-top: 5px;
-}
-
-.navbar-form input,
-.navbar-form select,
-.navbar-form .btn {
-  display: inline-block;
-  margin-bottom: 0;
-}
-
-.navbar-form input[type="image"],
-.navbar-form input[type="checkbox"],
-.navbar-form input[type="radio"] {
-  margin-top: 3px;
-}
-
-.navbar-form .input-append,
-.navbar-form .input-prepend {
-  margin-top: 5px;
-  white-space: nowrap;
-}
-
-.navbar-form .input-append input,
-.navbar-form .input-prepend input {
-  margin-top: 0;
-}
-
-.navbar-search {
-  position: relative;
-  float: left;
-  margin-top: 5px;
-  margin-bottom: 0;
-}
-
-.navbar-search .search-query {
-  padding: 4px 14px;
-  margin-bottom: 0;
-  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
-  font-size: 13px;
-  font-weight: normal;
-  line-height: 1;
-  -webkit-border-radius: 15px;
-     -moz-border-radius: 15px;
-          border-radius: 15px;
-}
-
-.navbar-static-top {
-  position: static;
-  margin-bottom: 0;
-}
-
-.navbar-static-top .navbar-inner {
-  -webkit-border-radius: 0;
-     -moz-border-radius: 0;
-          border-radius: 0;
-}
-
-.navbar-fixed-top,
-.navbar-fixed-bottom {
-  position: fixed;
-  right: 0;
-  left: 0;
-  z-index: 1030;
-  margin-bottom: 0;
-}
-
-.navbar-fixed-top .navbar-inner,
-.navbar-static-top .navbar-inner {
-  border-width: 0 0 1px;
-}
-
-.navbar-fixed-bottom .navbar-inner {
-  border-width: 1px 0 0;
-}
-
-.navbar-fixed-top .navbar-inner,
-.navbar-fixed-bottom .navbar-inner {
-  padding-right: 0;
-  padding-left: 0;
-  -webkit-border-radius: 0;
-     -moz-border-radius: 0;
-          border-radius: 0;
-}
-
-.navbar-static-top .container,
-.navbar-fixed-top .container,
-.navbar-fixed-bottom .container {
-  width: 940px;
-}
-
-.navbar-fixed-top {
-  top: 0;
-}
-
-.navbar-fixed-top .navbar-inner,
-.navbar-static-top .navbar-inner {
-  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);
-     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);
-          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);
-}
-
-.navbar-fixed-bottom {
-  bottom: 0;
-}
-
-.navbar-fixed-bottom .navbar-inner {
-  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);
-     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);
-          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);
-}
-
-.navbar .nav {
-  position: relative;
-  left: 0;
-  display: block;
-  float: left;
-  margin: 0 10px 0 0;
-}
-
-.navbar .nav.pull-right {
-  float: right;
-  margin-right: 0;
-}
-
-.navbar .nav > li {
-  float: left;
-}
-
-.navbar .nav > li > a {
-  float: none;
-  padding: 10px 15px 10px;
-  color: #777777;
-  text-decoration: none;
-  text-shadow: 0 1px 0 #ffffff;
-}
-
-.navbar .nav .dropdown-toggle .caret {
-  margin-top: 8px;
-}
-
-.navbar .nav > li > a:focus,
-.navbar .nav > li > a:hover {
-  color: #333333;
-  text-decoration: none;
-  background-color: transparent;
-}
-
-.navbar .nav > .active > a,
-.navbar .nav > .active > a:hover,
-.navbar .nav > .active > a:focus {
-  color: #555555;
-  text-decoration: none;
-  background-color: #e5e5e5;
-  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);
-     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);
-          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);
-}
-
-.navbar .btn-navbar {
-  display: none;
-  float: right;
-  padding: 7px 10px;
-  margin-right: 5px;
-  margin-left: 5px;
-  color: #ffffff;
-  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
-  background-color: #ededed;
-  *background-color: #e5e5e5;
-  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);
-  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));
-  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);
-  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);
-  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);
-  background-repeat: repeat-x;
-  border-color: #e5e5e5 #e5e5e5 #bfbfbf;
-  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);
-  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
-  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);
-     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);
-          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);
-}
-
-.navbar .btn-navbar:hover,
-.navbar .btn-navbar:active,
-.navbar .btn-navbar.active,
-.navbar .btn-navbar.disabled,
-.navbar .btn-navbar[disabled] {
-  color: #ffffff;
-  background-color: #e5e5e5;
-  *background-color: #d9d9d9;
-}
-
-.navbar .btn-navbar:active,
-.navbar .btn-navbar.active {
-  background-color: #cccccc \9;
-}
-
-.navbar .btn-navbar .icon-bar {
-  display: block;
-  width: 18px;
-  height: 2px;
-  background-color: #f5f5f5;
-  -webkit-border-radius: 1px;
-     -moz-border-radius: 1px;
-          border-radius: 1px;
-  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
-     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
-          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
-}
-
-.btn-navbar .icon-bar + .icon-bar {
-  margin-top: 3px;
-}
-
-.navbar .nav > li > .dropdown-menu:before {
-  position: absolute;
-  top: -7px;
-  left: 9px;
-  display: inline-block;
-  border-right: 7px solid transparent;
-  border-bottom: 7px solid #ccc;
-  border-left: 7px solid transparent;
-  border-bottom-color: rgba(0, 0, 0, 0.2);
-  content: '';
-}
-
-.navbar .nav > li > .dropdown-menu:after {
-  position: absolute;
-  top: -6px;
-  left: 10px;
-  display: inline-block;
-  border-right: 6px solid transparent;
-  border-bottom: 6px solid #ffffff;
-  border-left: 6px solid transparent;
-  content: '';
-}
-
-.navbar-fixed-bottom .nav > li > .dropdown-menu:before {
-  top: auto;
-  bottom: -7px;
-  border-top: 7px solid #ccc;
-  border-bottom: 0;
-  border-top-color: rgba(0, 0, 0, 0.2);
-}
-
-.navbar-fixed-bottom .nav > li > .dropdown-menu:after {
-  top: auto;
-  bottom: -6px;
-  border-top: 6px solid #ffffff;
-  border-bottom: 0;
-}
-
-.navbar .nav li.dropdown > a:hover .caret {
-  border-top-color: #555555;
-  border-bottom-color: #555555;
-}
-
-.navbar .nav li.dropdown.open > .dropdown-toggle,
-.navbar .nav li.dropdown.active > .dropdown-toggle,
-.navbar .nav li.dropdown.open.active > .dropdown-toggle {
-  color: #555555;
-  background-color: #e5e5e5;
-}
-
-.navbar .nav li.dropdown > .dropdown-toggle .caret {
-  border-top-color: #777777;
-  border-bottom-color: #777777;
-}
-
-.navbar .nav li.dropdown.open > .dropdown-toggle .caret,
-.navbar .nav li.dropdown.active > .dropdown-toggle .caret,
-.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {
-  border-top-color: #555555;
-  border-bottom-color: #555555;
-}
-
-.navbar .pull-right > li > .dropdown-menu,
-.navbar .nav > li > .dropdown-menu.pull-right {
-  right: 0;
-  left: auto;
-}
-
-.navbar .pull-right > li > .dropdown-menu:before,
-.navbar .nav > li > .dropdown-menu.pull-right:before {
-  right: 12px;
-  left: auto;
-}
-
-.navbar .pull-right > li > .dropdown-menu:after,
-.navbar .nav > li > .dropdown-menu.pull-right:after {
-  right: 13px;
-  left: auto;
-}
-
-.navbar .pull-right > li > .dropdown-menu .dropdown-menu,
-.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {
-  right: 100%;
-  left: auto;
-  margin-right: -1px;
-  margin-left: 0;
-  -webkit-border-radius: 6px 0 6px 6px;
-     -moz-border-radius: 6px 0 6px 6px;
-          border-radius: 6px 0 6px 6px;
-}
-
-.navbar-inverse .navbar-inner {
-  background-color: #1b1b1b;
-  background-image: -moz-linear-gradient(top, #222222, #111111);
-  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));
-  background-image: -webkit-linear-gradient(top, #222222, #111111);
-  background-image: -o-linear-gradient(top, #222222, #111111);
-  background-image: linear-gradient(to bottom, #222222, #111111);
-  background-repeat: repeat-x;
-  border-color: #252525;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);
-}
-
-.navbar-inverse .brand,
-.navbar-inverse .nav > li > a {
-  color: #999999;
-  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
-}
-
-.navbar-inverse .brand:hover,
-.navbar-inverse .nav > li > a:hover {
-  color: #ffffff;
-}
-
-.navbar-inverse .brand {
-  color: #999999;
-}
-
-.navbar-inverse .navbar-text {
-  color: #999999;
-}
-
-.navbar-inverse .nav > li > a:focus,
-.navbar-inverse .nav > li > a:hover {
-  color: #ffffff;
-  background-color: transparent;
-}
-
-.navbar-inverse .nav .active > a,
-.navbar-inverse .nav .active > a:hover,
-.navbar-inverse .nav .active > a:focus {
-  color: #ffffff;
-  background-color: #111111;
-}
-
-.navbar-inverse .navbar-link {
-  color: #999999;
-}
-
-.navbar-inverse .navbar-link:hover {
-  color: #ffffff;
-}
-
-.navbar-inverse .divider-vertical {
-  border-right-color: #222222;
-  border-left-color: #111111;
-}
-
-.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,
-.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,
-.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {
-  color: #ffffff;
-  background-color: #111111;
-}
-
-.navbar-inverse .nav li.dropdown > a:hover .caret {
-  border-top-color: #ffffff;
-  border-bottom-color: #ffffff;
-}
-
-.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {
-  border-top-color: #999999;
-  border-bottom-color: #999999;
-}
-
-.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,
-.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,
-.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {
-  border-top-color: #ffffff;
-  border-bottom-color: #ffffff;
-}
-
-.navbar-inverse .navbar-search .search-query {
-  color: #ffffff;
-  background-color: #515151;
-  border-color: #111111;
-  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);
-     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);
-          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);
-  -webkit-transition: none;
-     -moz-transition: none;
-       -o-transition: none;
-          transition: none;
-}
-
-.navbar-inverse .navbar-search .search-query:-moz-placeholder {
-  color: #cccccc;
-}
-
-.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {
-  color: #cccccc;
-}
-
-.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {
-  color: #cccccc;
-}
-
-.navbar-inverse .navbar-search .search-query:focus,
-.navbar-inverse .navbar-search .search-query.focused {
-  padding: 5px 15px;
-  color: #333333;
-  text-shadow: 0 1px 0 #ffffff;
-  background-color: #ffffff;
-  border: 0;
-  outline: 0;
-  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
-     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
-          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
-}
-
-.navbar-inverse .btn-navbar {
-  color: #ffffff;
-  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
-  background-color: #0e0e0e;
-  *background-color: #040404;
-  background-image: -moz-linear-gradient(top, #151515, #040404);
-  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));
-  background-image: -webkit-linear-gradient(top, #151515, #040404);
-  background-image: -o-linear-gradient(top, #151515, #040404);
-  background-image: linear-gradient(to bottom, #151515, #040404);
-  background-repeat: repeat-x;
-  border-color: #040404 #040404 #000000;
-  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);
-  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
-}
-
-.navbar-inverse .btn-navbar:hover,
-.navbar-inverse .btn-navbar:active,
-.navbar-inverse .btn-navbar.active,
-.navbar-inverse .btn-navbar.disabled,
-.navbar-inverse .btn-navbar[disabled] {
-  color: #ffffff;
-  background-color: #040404;
-  *background-color: #000000;
-}
-
-.navbar-inverse .btn-navbar:active,
-.navbar-inverse .btn-navbar.active {
-  background-color: #000000 \9;
-}
-
-.breadcrumb {
-  padding: 8px 15px;
-  margin: 0 0 20px;
-  list-style: none;
-  background-color: #f5f5f5;
-  -webkit-border-radius: 4px;
-     -moz-border-radius: 4px;
-          border-radius: 4px;
-}
-
-.breadcrumb > li {
-  display: inline-block;
-  *display: inline;
-  text-shadow: 0 1px 0 #ffffff;
-  *zoom: 1;
-}
-
-.breadcrumb > li > .divider {
-  padding: 0 5px;
-  color: #ccc;
-}
-
-.breadcrumb > .active {
-  color: #999999;
-}
-
-.pagination {
-  margin: 20px 0;
-}
-
-.pagination ul {
-  display: inline-block;
-  *display: inline;
-  margin-bottom: 0;
-  margin-left: 0;
-  -webkit-border-radius: 4px;
-     -moz-border-radius: 4px;
-          border-radius: 4px;
-  *zoom: 1;
-  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
-     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
-          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
-}
-
-.pagination ul > li {
-  display: inline;
-}
-
-.pagination ul > li > a,
-.pagination ul > li > span {
-  float: left;
-  padding: 4px 12px;
-  line-height: 20px;
-  text-decoration: none;
-  background-color: #ffffff;
-  border: 1px solid #dddddd;
-  border-left-width: 0;
-}
-
-.pagination ul > li > a:hover,
-.pagination ul > .active > a,
-.pagination ul > .active > span {
-  background-color: #f5f5f5;
-}
-
-.pagination ul > .active > a,
-.pagination ul > .active > span {
-  color: #999999;
-  cursor: default;
-}
-
-.pagination ul > .disabled > span,
-.pagination ul > .disabled > a,
-.pagination ul > .disabled > a:hover {
-  color: #999999;
-  cursor: default;
-  background-color: transparent;
-}
-
-.pagination ul > li:first-child > a,
-.pagination ul > li:first-child > span {
-  border-left-width: 1px;
-  -webkit-border-bottom-left-radius: 4px;
-          border-bottom-left-radius: 4px;
-  -webkit-border-top-left-radius: 4px;
-          border-top-left-radius: 4px;
-  -moz-border-radius-bottomleft: 4px;
-  -moz-border-radius-topleft: 4px;
-}
-
-.pagination ul > li:last-child > a,
-.pagination ul > li:last-child > span {
-  -webkit-border-top-right-radius: 4px;
-          border-top-right-radius: 4px;
-  -webkit-border-bottom-right-radius: 4px;
-          border-bottom-right-radius: 4px;
-  -moz-border-radius-topright: 4px;
-  -moz-border-radius-bottomright: 4px;
-}
-
-.pagination-centered {
-  text-align: center;
-}
-
-.pagination-right {
-  text-align: right;
-}
-
-.pagination-large ul > li > a,
-.pagination-large ul > li > span {
-  padding: 11px 19px;
-  font-size: 17.5px;
-}
-
-.pagination-large ul > li:first-child > a,
-.pagination-large ul > li:first-child > span {
-  -webkit-border-bottom-left-radius: 6px;
-          border-bottom-left-radius: 6px;
-  -webkit-border-top-left-radius: 6px;
-          border-top-left-radius: 6px;
-  -moz-border-radius-bottomleft: 6px;
-  -moz-border-radius-topleft: 6px;
-}
-
-.pagination-large ul > li:last-child > a,
-.pagination-large ul > li:last-child > span {
-  -webkit-border-top-right-radius: 6px;
-          border-top-right-radius: 6px;
-  -webkit-border-bottom-right-radius: 6px;
-          border-bottom-right-radius: 6px;
-  -moz-border-radius-topright: 6px;
-  -moz-border-radius-bottomright: 6px;
-}
-
-.pagination-mini ul > li:first-child > a,
-.pagination-small ul > li:first-child > a,
-.pagination-mini ul > li:first-child > span,
-.pagination-small ul > li:first-child > span {
-  -webkit-border-bottom-left-radius: 3px;
-          border-bottom-left-radius: 3px;
-  -webkit-border-top-left-radius: 3px;
-          border-top-left-radius: 3px;
-  -moz-border-radius-bottomleft: 3px;
-  -moz-border-radius-topleft: 3px;
-}
-
-.pagination-mini ul > li:last-child > a,
-.pagination-small ul > li:last-child > a,
-.pagination-mini ul > li:last-child > span,
-.pagination-small ul > li:last-child > span {
-  -webkit-border-top-right-radius: 3px;
-          border-top-right-radius: 3px;
-  -webkit-border-bottom-right-radius: 3px;
-          border-bottom-right-radius: 3px;
-  -moz-border-radius-topright: 3px;
-  -moz-border-radius-bottomright: 3px;
-}
-
-.pagination-small ul > li > a,
-.pagination-small ul > li > span {
-  padding: 2px 10px;
-  font-size: 11.9px;
-}
-
-.pagination-mini ul > li > a,
-.pagination-mini ul > li > span {
-  padding: 0 6px;
-  font-size: 10.5px;
-}
-
-.pager {
-  margin: 20px 0;
-  text-align: center;
-  list-style: none;
-  *zoom: 1;
-}
-
-.pager:before,
-.pager:after {
-  display: table;
-  line-height: 0;
-  content: "";
-}
-
-.pager:after {
-  clear: both;
-}
-
-.pager li {
-  display: inline;
-}
-
-.pager li > a,
-.pager li > span {
-  display: inline-block;
-  padding: 5px 14px;
-  background-color: #fff;
-  border: 1px solid #ddd;
-  -webkit-border-radius: 15px;
-     -moz-border-radius: 15px;
-          border-radius: 15px;
-}
-
-.pager li > a:hover {
-  text-decoration: none;
-  background-color: #f5f5f5;
-}
-
-.pager .next > a,
-.pager .next > span {
-  float: right;
-}
-
-.pager .previous > a,
-.pager .previous > span {
-  float: left;
-}
-
-.pager .disabled > a,
-.pager .disabled > a:hover,
-.pager .disabled > span {
-  color: #999999;
-  cursor: default;
-  background-color: #fff;
-}
-
-.modal-backdrop {
-  position: fixed;
-  top: 0;
-  right: 0;
-  bottom: 0;
-  left: 0;
-  z-index: 1040;
-  background-color: #000000;
-}
-
-.modal-backdrop.fade {
-  opacity: 0;
-}
-
-.modal-backdrop,
-.modal-backdrop.fade.in {
-  opacity: 0.8;
-  filter: alpha(opacity=80);
-}
-
-.modal {
-  position: fixed;
-  top: 10%;
-  left: 50%;
-  z-index: 1050;
-  width: 560px;
-  margin-left: -280px;
-  background-color: #ffffff;
-  border: 1px solid #999;
-  border: 1px solid rgba(0, 0, 0, 0.3);
-  *border: 1px solid #999;
-  -webkit-border-radius: 6px;
-     -moz-border-radius: 6px;
-          border-radius: 6px;
-  outline: none;
-  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
-     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
-          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
-  -webkit-background-clip: padding-box;
-     -moz-background-clip: padding-box;
-          background-clip: padding-box;
-}
-
-.modal.fade {
-  top: -25%;
-  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;
-     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;
-       -o-transition: opacity 0.3s linear, top 0.3s ease-out;
-          transition: opacity 0.3s linear, top 0.3s ease-out;
-}
-
-.modal.fade.in {
-  top: 10%;
-}
-
-.modal-header {
-  padding: 9px 15px;
-  border-bottom: 1px solid #eee;
-}
-
-.modal-header .close {
-  margin-top: 2px;
-}
-
-.modal-header h3 {
-  margin: 0;
-  line-height: 30px;
-}
-
-.modal-body {
-  position: relative;
-  max-height: 400px;
-  padding: 15px;
-  overflow-y: auto;
-}
-
-.modal-form {
-  margin-bottom: 0;
-}
-
-.modal-footer {
-  padding: 14px 15px 15px;
-  margin-bottom: 0;
-  text-align: right;
-  background-color: #f5f5f5;
-  border-top: 1px solid #ddd;
-  -webkit-border-radius: 0 0 6px 6px;
-     -moz-border-radius: 0 0 6px 6px;
-          border-radius: 0 0 6px 6px;
-  *zoom: 1;
-  -webkit-box-shadow: inset 0 1px 0 #ffffff;
-     -moz-box-shadow: inset 0 1px 0 #ffffff;
-          box-shadow: inset 0 1px 0 #ffffff;
-}
-
-.modal-footer:before,
-.modal-footer:after {
-  display: table;
-  line-height: 0;
-  content: "";
-}
-
-.modal-footer:after {
-  clear: both;
-}
-
-.modal-footer .btn + .btn {
-  margin-bottom: 0;
-  margin-left: 5px;
-}
-
-.modal-footer .btn-group .btn + .btn {
-  margin-left: -1px;
-}
-
-.modal-footer .btn-block + .btn-block {
-  margin-left: 0;
-}
-
-.tooltip {
-  position: absolute;
-  z-index: 1030;
-  display: block;
-  padding: 5px;
-  font-size: 11px;
-  opacity: 0;
-  filter: alpha(opacity=0);
-  visibility: visible;
-}
-
-.tooltip.in {
-  opacity: 0.8;
-  filter: alpha(opacity=80);
-}
-
-.tooltip.top {
-  margin-top: -3px;
-}
-
-.tooltip.right {
-  margin-left: 3px;
-}
-
-.tooltip.bottom {
-  margin-top: 3px;
-}
-
-.tooltip.left {
-  margin-left: -3px;
-}
-
-.tooltip-inner {
-  max-width: 200px;
-  padding: 3px 8px;
-  color: #ffffff;
-  text-align: center;
-  text-decoration: none;
-  background-color: #000000;
-  -webkit-border-radius: 4px;
-     -moz-border-radius: 4px;
-          border-radius: 4px;
-}
-
-.tooltip-arrow {
-  position: absolute;
-  width: 0;
-  height: 0;
-  border-color: transparent;
-  border-style: solid;
-}
-
-.tooltip.top .tooltip-arrow {
-  bottom: 0;
-  left: 50%;
-  margin-left: -5px;
-  border-top-color: #000000;
-  border-width: 5px 5px 0;
-}
-
-.tooltip.right .tooltip-arrow {
-  top: 50%;
-  left: 0;
-  margin-top: -5px;
-  border-right-color: #000000;
-  border-width: 5px 5px 5px 0;
-}
-
-.tooltip.left .tooltip-arrow {
-  top: 50%;
-  right: 0;
-  margin-top: -5px;
-  border-left-color: #000000;
-  border-width: 5px 0 5px 5px;
-}
-
-.tooltip.bottom .tooltip-arrow {
-  top: 0;
-  left: 50%;
-  margin-left: -5px;
-  border-bottom-color: #000000;
-  border-width: 0 5px 5px;
-}
-
-.popover {
-  position: absolute;
-  top: 0;
-  left: 0;
-  z-index: 1010;
-  display: none;
-  width: 236px;
-  padding: 1px;
-  text-align: left;
-  white-space: normal;
-  background-color: #ffffff;
-  border: 1px solid #ccc;
-  border: 1px solid rgba(0, 0, 0, 0.2);
-  -webkit-border-radius: 6px;
-     -moz-border-radius: 6px;
-          border-radius: 6px;
-  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
-     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
-          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
-  -webkit-background-clip: padding-box;
-     -moz-background-clip: padding;
-          background-clip: padding-box;
-}
-
-.popover.top {
-  margin-top: -10px;
-}
-
-.popover.right {
-  margin-left: 10px;
-}
-
-.popover.bottom {
-  margin-top: 10px;
-}
-
-.popover.left {
-  margin-left: -10px;
-}
-
-.popover-title {
-  padding: 8px 14px;
-  margin: 0;
-  font-size: 14px;
-  font-weight: normal;
-  line-height: 18px;
-  background-color: #f7f7f7;
-  border-bottom: 1px solid #ebebeb;
-  -webkit-border-radius: 5px 5px 0 0;
-     -moz-border-radius: 5px 5px 0 0;
-          border-radius: 5px 5px 0 0;
-}
-
-.popover-content {
-  padding: 9px 14px;
-}
-
-.popover .arrow,
-.popover .arrow:after {
-  position: absolute;
-  display: block;
-  width: 0;
-  height: 0;
-  border-color: transparent;
-  border-style: solid;
-}
-
-.popover .arrow {
-  border-width: 11px;
-}
-
-.popover .arrow:after {
-  border-width: 10px;
-  content: "";
-}
-
-.popover.top .arrow {
-  bottom: -11px;
-  left: 50%;
-  margin-left: -11px;
-  border-top-color: #999;
-  border-top-color: rgba(0, 0, 0, 0.25);
-  border-bottom-width: 0;
-}
-
-.popover.top .arrow:after {
-  bottom: 1px;
-  margin-left: -10px;
-  border-top-color: #ffffff;
-  border-bottom-width: 0;
-}
-
-.popover.right .arrow {
-  top: 50%;
-  left: -11px;
-  margin-top: -11px;
-  border-right-color: #999;
-  border-right-color: rgba(0, 0, 0, 0.25);
-  border-left-width: 0;
-}
-
-.popover.right .arrow:after {
-  bottom: -10px;
-  left: 1px;
-  border-right-color: #ffffff;
-  border-left-width: 0;
-}
-
-.popover.bottom .arrow {
-  top: -11px;
-  left: 50%;
-  margin-left: -11px;
-  border-bottom-color: #999;
-  border-bottom-color: rgba(0, 0, 0, 0.25);
-  border-top-width: 0;
-}
-
-.popover.bottom .arrow:after {
-  top: 1px;
-  margin-left: -10px;
-  border-bottom-color: #ffffff;
-  border-top-width: 0;
-}
-
-.popover.left .arrow {
-  top: 50%;
-  right: -11px;
-  margin-top: -11px;
-  border-left-color: #999;
-  border-left-color: rgba(0, 0, 0, 0.25);
-  border-right-width: 0;
-}
-
-.popover.left .arrow:after {
-  right: 1px;
-  bottom: -10px;
-  border-left-color: #ffffff;
-  border-right-width: 0;
-}
-
-.thumbnails {
-  margin-left: -20px;
-  list-style: none;
-  *zoom: 1;
-}
-
-.thumbnails:before,
-.thumbnails:after {
-  display: table;
-  line-height: 0;
-  content: "";
-}
-
-.thumbnails:after {
-  clear: both;
-}
-
-.row-fluid .thumbnails {
-  margin-left: 0;
-}
-
-.thumbnails > li {
-  float: left;
-  margin-bottom: 20px;
-  margin-left: 20px;
-}
-
-.thumbnail {
-  display: block;
-  padding: 4px;
-  line-height: 20px;
-  border: 1px solid #ddd;
-  -webkit-border-radius: 4px;
-     -moz-border-radius: 4px;
-          border-radius: 4px;
-  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);
-     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);
-          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);
-  -webkit-transition: all 0.2s ease-in-out;
-     -moz-transition: all 0.2s ease-in-out;
-       -o-transition: all 0.2s ease-in-out;
-          transition: all 0.2s ease-in-out;
-}
-
-a.thumbnail:hover {
-  border-color: #0088cc;
-  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);
-     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);
-          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);
-}
-
-.thumbnail > img {
-  display: block;
-  max-width: 100%;
-  margin-right: auto;
-  margin-left: auto;
-}
-
-.thumbnail .caption {
-  padding: 9px;
-  color: #555555;
-}
-
-.media,
-.media-body {
-  overflow: hidden;
-  *overflow: visible;
-  zoom: 1;
-}
-
-.media,
-.media .media {
-  margin-top: 15px;
-}
-
-.media:first-child {
-  margin-top: 0;
-}
-
-.media-object {
-  display: block;
-}
-
-.media-heading {
-  margin: 0 0 5px;
-}
-
-.media .pull-left {
-  margin-right: 10px;
-}
-
-.media .pull-right {
-  margin-left: 10px;
-}
-
-.media-list {
-  margin-left: 0;
-  list-style: none;
-}
-
-.label,
-.badge {
-  display: inline-block;
-  padding: 2px 4px;
-  font-size: 11.844px;
-  font-weight: bold;
-  line-height: 14px;
-  color: #ffffff;
-  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
-  white-space: nowrap;
-  vertical-align: baseline;
-  background-color: #999999;
-}
-
-.label {
-  -webkit-border-radius: 3px;
-     -moz-border-radius: 3px;
-          border-radius: 3px;
-}
-
-.badge {
-  padding-right: 9px;
-  padding-left: 9px;
-  -webkit-border-radius: 9px;
-     -moz-border-radius: 9px;
-          border-radius: 9px;
-}
-
-.label:empty,
-.badge:empty {
-  display: none;
-}
-
-a.label:hover,
-a.badge:hover {
-  color: #ffffff;
-  text-decoration: none;
-  cursor: pointer;
-}
-
-.label-important,
-.badge-important {
-  background-color: #b94a48;
-}
-
-.label-important[href],
-.badge-important[href] {
-  background-color: #953b39;
-}
-
-.label-warning,
-.badge-warning {
-  background-color: #f89406;
-}
-
-.label-warning[href],
-.badge-warning[href] {
-  background-color: #c67605;
-}
-
-.label-success,
-.badge-success {
-  background-color: #468847;
-}
-
-.label-success[href],
-.badge-success[href] {
-  background-color: #356635;
-}
-
-.label-info,
-.badge-info {
-  background-color: #3a87ad;
-}
-
-.label-info[href],
-.badge-info[href] {
-  background-color: #2d6987;
-}
-
-.label-inverse,
-.badge-inverse {
-  background-color: #333333;
-}
-
-.label-inverse[href],
-.badge-inverse[href] {
-  background-color: #1a1a1a;
-}
-
-.btn .label,
-.btn .badge {
-  position: relative;
-  top: -1px;
-}
-
-.btn-mini .label,
-.btn-mini .badge {
-  top: 0;
-}
-
-@-webkit-keyframes progress-bar-stripes {
-  from {
-    background-position: 40px 0;
-  }
-  to {
-    background-position: 0 0;
-  }
-}
-
-@-moz-keyframes progress-bar-stripes {
-  from {
-    background-position: 40px 0;
-  }
-  to {
-    background-position: 0 0;
-  }
-}
-
-@-ms-keyframes progress-bar-stripes {
-  from {
-    background-position: 40px 0;
-  }
-  to {
-    background-position: 0 0;
-  }
-}
-
-@-o-keyframes progress-bar-stripes {
-  from {
-    background-position: 0 0;
-  }
-  to {
-    background-position: 40px 0;
-  }
-}
-
-@keyframes progress-bar-stripes {
-  from {
-    background-position: 40px 0;
-  }
-  to {
-    background-position: 0 0;
-  }
-}
-
-.progress {
-  height: 20px;
-  margin-bottom: 20px;
-  overflow: hidden;
-  background-color: #f7f7f7;
-  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);
-  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));
-  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);
-  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);
-  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);
-  background-repeat: repeat-x;
-  -webkit-border-radius: 4px;
-     -moz-border-radius: 4px;
-          border-radius: 4px;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);
-  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
-     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
-          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
-}
-
-.progress .bar {
-  float: left;
-  width: 0;
-  height: 100%;
-  font-size: 12px;
-  color: #ffffff;
-  text-align: center;
-  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
-  background-color: #0e90d2;
-  background-image: -moz-linear-gradient(top, #149bdf, #0480be);
-  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));
-  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);
-  background-image: -o-linear-gradient(top, #149bdf, #0480be);
-  background-image: linear-gradient(to bottom, #149bdf, #0480be);
-  background-repeat: repeat-x;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);
-  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
-     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
-          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
-  -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
-  -webkit-transition: width 0.6s ease;
-     -moz-transition: width 0.6s ease;
-       -o-transition: width 0.6s ease;
-          transition: width 0.6s ease;
-}
-
-.progress .bar + .bar {
-  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);
-     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);
-          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);
-}
-
-.progress-striped .bar {
-  background-color: #149bdf;
-  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
-  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-  -webkit-background-size: 40px 40px;
-     -moz-background-size: 40px 40px;
-       -o-background-size: 40px 40px;
-          background-size: 40px 40px;
-}
-
-.progress.active .bar {
-  -webkit-animation: progress-bar-stripes 2s linear infinite;
-     -moz-animation: progress-bar-stripes 2s linear infinite;
-      -ms-animation: progress-bar-stripes 2s linear infinite;
-       -o-animation: progress-bar-stripes 2s linear infinite;
-          animation: progress-bar-stripes 2s linear infinite;
-}
-
-.progress-danger .bar,
-.progress .bar-danger {
-  background-color: #dd514c;
-  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);
-  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));
-  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);
-  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);
-  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);
-  background-repeat: repeat-x;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);
-}
-
-.progress-danger.progress-striped .bar,
-.progress-striped .bar-danger {
-  background-color: #ee5f5b;
-  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
-  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-}
-
-.progress-success .bar,
-.progress .bar-success {
-  background-color: #5eb95e;
-  background-image: -moz-linear-gradient(top, #62c462, #57a957);
-  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));
-  background-image: -webkit-linear-gradient(top, #62c462, #57a957);
-  background-image: -o-linear-gradient(top, #62c462, #57a957);
-  background-image: linear-gradient(to bottom, #62c462, #57a957);
-  background-repeat: repeat-x;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);
-}
-
-.progress-success.progress-striped .bar,
-.progress-striped .bar-success {
-  background-color: #62c462;
-  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
-  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-}
-
-.progress-info .bar,
-.progress .bar-info {
-  background-color: #4bb1cf;
-  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);
-  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));
-  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);
-  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);
-  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);
-  background-repeat: repeat-x;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);
-}
-
-.progress-info.progress-striped .bar,
-.progress-striped .bar-info {
-  background-color: #5bc0de;
-  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
-  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-}
-
-.progress-warning .bar,
-.progress .bar-warning {
-  background-color: #faa732;
-  background-image: -moz-linear-gradient(top, #fbb450, #f89406);
-  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));
-  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);
-  background-image: -o-linear-gradient(top, #fbb450, #f89406);
-  background-image: linear-gradient(to bottom, #fbb450, #f89406);
-  background-repeat: repeat-x;
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);
-}
-
-.progress-warning.progress-striped .bar,
-.progress-striped .bar-warning {
-  background-color: #fbb450;
-  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
-  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-}
-
-.accordion {
-  margin-bottom: 20px;
-}
-
-.accordion-group {
-  margin-bottom: 2px;
-  border: 1px solid #e5e5e5;
-  -webkit-border-radius: 4px;
-     -moz-border-radius: 4px;
-          border-radius: 4px;
-}
-
-.accordion-heading {
-  border-bottom: 0;
-}
-
-.accordion-heading .accordion-toggle {
-  display: block;
-  padding: 8px 15px;
-}
-
-.accordion-toggle {
-  cursor: pointer;
-}
-
-.accordion-inner {
-  padding: 9px 15px;
-  border-top: 1px solid #e5e5e5;
-}
-
-.carousel {
-  position: relative;
-  margin-bottom: 20px;
-  line-height: 1;
-}
-
-.carousel-inner {
-  position: relative;
-  width: 100%;
-  overflow: hidden;
-}
-
-.carousel-inner > .item {
-  position: relative;
-  display: none;
-  -webkit-transition: 0.6s ease-in-out left;
-     -moz-transition: 0.6s ease-in-out left;
-       -o-transition: 0.6s ease-in-out left;
-          transition: 0.6s ease-in-out left;
-}
-
-.carousel-inner > .item > img {
-  display: block;
-  line-height: 1;
-}
-
-.carousel-inner > .active,
-.carousel-inner > .next,
-.carousel-inner > .prev {
-  display: block;
-}
-
-.carousel-inner > .active {
-  left: 0;
-}
-
-.carousel-inner > .next,
-.carousel-inner > .prev {
-  position: absolute;
-  top: 0;
-  width: 100%;
-}
-
-.carousel-inner > .next {
-  left: 100%;
-}
-
-.carousel-inner > .prev {
-  left: -100%;
-}
-
-.carousel-inner > .next.left,
-.carousel-inner > .prev.right {
-  left: 0;
-}
-
-.carousel-inner > .active.left {
-  left: -100%;
-}
-
-.carousel-inner > .active.right {
-  left: 100%;
-}
-
-.carousel-control {
-  position: absolute;
-  top: 40%;
-  left: 15px;
-  width: 40px;
-  height: 40px;
-  margin-top: -20px;
-  font-size: 60px;
-  font-weight: 100;
-  line-height: 30px;
-  color: #ffffff;
-  text-align: center;
-  background: #222222;
-  border: 3px solid #ffffff;
-  -webkit-border-radius: 23px;
-     -moz-border-radius: 23px;
-          border-radius: 23px;
-  opacity: 0.5;
-  filter: alpha(opacity=50);
-}
-
-.carousel-control.right {
-  right: 15px;
-  left: auto;
-}
-
-.carousel-control:hover {
-  color: #ffffff;
-  text-decoration: none;
-  opacity: 0.9;
-  filter: alpha(opacity=90);
-}
-
-.carousel-caption {
-  position: absolute;
-  right: 0;
-  bottom: 0;
-  left: 0;
-  padding: 15px;
-  background: #333333;
-  background: rgba(0, 0, 0, 0.75);
-}
-
-.carousel-caption h4,
-.carousel-caption p {
-  line-height: 20px;
-  color: #ffffff;
-}
-
-.carousel-caption h4 {
-  margin: 0 0 5px;
-}
-
-.carousel-caption p {
-  margin-bottom: 0;
-}
-
-.hero-unit {
-  padding: 60px;
-  margin-bottom: 30px;
-  font-size: 18px;
-  font-weight: 200;
-  line-height: 30px;
-  color: inherit;
-  background-color: #eeeeee;
-  -webkit-border-radius: 6px;
-     -moz-border-radius: 6px;
-          border-radius: 6px;
-}
-
-.hero-unit h1 {
-  margin-bottom: 0;
-  font-size: 60px;
-  line-height: 1;
-  letter-spacing: -1px;
-  color: inherit;
-}
-
-.hero-unit li {
-  line-height: 30px;
-}
-
-.pull-right {
-  float: right;
-}
-
-.pull-left {
-  float: left;
-}
-
-.hide {
-  display: none;
-}
-
-.show {
-  display: block;
-}
-
-.invisible {
-  visibility: hidden;
-}
-
-.affix {
-  position: fixed;
-}
diff --git a/servers/admin/public/stylesheets/vendors/bootstrap.min.css b/servers/admin/public/stylesheets/vendors/bootstrap.min.css
deleted file mode 100644
index 140f731..0000000
--- a/servers/admin/public/stylesheets/vendors/bootstrap.min.css
+++ /dev/null
@@ -1,9 +0,0 @@
-/*!
- * Bootstrap v2.2.2
- *
- * Copyright 2012 Twitter, Inc
- * Licensed under the Apache License v2.0
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Designed and built with all the love in the world @twitter by @mdo and @fat.
- */article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}a:hover,a:active{outline:0}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{width:auto\9;height:auto;max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic}#map_canvas img,.google-maps img{max-width:none}button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle}button,input{*overflow:visible;line-height:normal}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}button,html input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}label,select,button,input[type="button"],input[type="reset"],input[type="submit"],input[type="radio"],input[type="checkbox"]{cursor:pointer}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}textarea{overflow:auto;vertical-align:top}@media print{*{color:#000!important;text-shadow:none!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:20px;color:#333;background-color:#fff}a{color:#08c;text-decoration:none}a:hover{color:#005580;text-decoration:underline}.img-rounded{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.img-polaroid{padding:4px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.1)}.img-circle{-webkit-border-radius:500px;-moz-border-radius:500px;border-radius:500px}.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.span12{width:940px}.span11{width:860px}.span10{width:780px}.span9{width:700px}.span8{width:620px}.span7{width:540px}.span6{width:460px}.span5{width:380px}.span4{width:300px}.span3{width:220px}.span2{width:140px}.span1{width:60px}.offset12{margin-left:980px}.offset11{margin-left:900px}.offset10{margin-left:820px}.offset9{margin-left:740px}.offset8{margin-left:660px}.offset7{margin-left:580px}.offset6{margin-left:500px}.offset5{margin-left:420px}.offset4{margin-left:340px}.offset3{margin-left:260px}.offset2{margin-left:180px}.offset1{margin-left:100px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.127659574468085%;*margin-left:2.074468085106383%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.127659574468085%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.48936170212765%;*width:91.43617021276594%}.row-fluid .span10{width:82.97872340425532%;*width:82.92553191489361%}.row-fluid .span9{width:74.46808510638297%;*width:74.41489361702126%}.row-fluid .span8{width:65.95744680851064%;*width:65.90425531914893%}.row-fluid .span7{width:57.44680851063829%;*width:57.39361702127659%}.row-fluid .span6{width:48.93617021276595%;*width:48.88297872340425%}.row-fluid .span5{width:40.42553191489362%;*width:40.37234042553192%}.row-fluid .span4{width:31.914893617021278%;*width:31.861702127659576%}.row-fluid .span3{width:23.404255319148934%;*width:23.351063829787233%}.row-fluid .span2{width:14.893617021276595%;*width:14.840425531914894%}.row-fluid .span1{width:6.382978723404255%;*width:6.329787234042553%}.row-fluid .offset12{margin-left:104.25531914893617%;*margin-left:104.14893617021275%}.row-fluid .offset12:first-child{margin-left:102.12765957446808%;*margin-left:102.02127659574467%}.row-fluid .offset11{margin-left:95.74468085106382%;*margin-left:95.6382978723404%}.row-fluid .offset11:first-child{margin-left:93.61702127659574%;*margin-left:93.51063829787232%}.row-fluid .offset10{margin-left:87.23404255319149%;*margin-left:87.12765957446807%}.row-fluid .offset10:first-child{margin-left:85.1063829787234%;*margin-left:84.99999999999999%}.row-fluid .offset9{margin-left:78.72340425531914%;*margin-left:78.61702127659572%}.row-fluid .offset9:first-child{margin-left:76.59574468085106%;*margin-left:76.48936170212764%}.row-fluid .offset8{margin-left:70.2127659574468%;*margin-left:70.10638297872339%}.row-fluid .offset8:first-child{margin-left:68.08510638297872%;*margin-left:67.9787234042553%}.row-fluid .offset7{margin-left:61.70212765957446%;*margin-left:61.59574468085106%}.row-fluid .offset7:first-child{margin-left:59.574468085106375%;*margin-left:59.46808510638297%}.row-fluid .offset6{margin-left:53.191489361702125%;*margin-left:53.085106382978715%}.row-fluid .offset6:first-child{margin-left:51.063829787234035%;*margin-left:50.95744680851063%}.row-fluid .offset5{margin-left:44.68085106382979%;*margin-left:44.57446808510638%}.row-fluid .offset5:first-child{margin-left:42.5531914893617%;*margin-left:42.4468085106383%}.row-fluid .offset4{margin-left:36.170212765957444%;*margin-left:36.06382978723405%}.row-fluid .offset4:first-child{margin-left:34.04255319148936%;*margin-left:33.93617021276596%}.row-fluid .offset3{margin-left:27.659574468085104%;*margin-left:27.5531914893617%}.row-fluid .offset3:first-child{margin-left:25.53191489361702%;*margin-left:25.425531914893618%}.row-fluid .offset2{margin-left:19.148936170212764%;*margin-left:19.04255319148936%}.row-fluid .offset2:first-child{margin-left:17.02127659574468%;*margin-left:16.914893617021278%}.row-fluid .offset1{margin-left:10.638297872340425%;*margin-left:10.53191489361702%}.row-fluid .offset1:first-child{margin-left:8.51063829787234%;*margin-left:8.404255319148938%}[class*="span"].hide,.row-fluid [class*="span"].hide{display:none}[class*="span"].pull-right,.row-fluid [class*="span"].pull-right{float:right}.container{margin-right:auto;margin-left:auto;*zoom:1}.container:before,.container:after{display:table;line-height:0;content:""}.container:after{clear:both}.container-fluid{padding-right:20px;padding-left:20px;*zoom:1}.container-fluid:before,.container-fluid:after{display:table;line-height:0;content:""}.container-fluid:after{clear:both}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:21px;font-weight:200;line-height:30px}small{font-size:85%}strong{font-weight:bold}em{font-style:italic}cite{font-style:normal}.muted{color:#999}a.muted:hover{color:#808080}.text-warning{color:#c09853}a.text-warning:hover{color:#a47e3c}.text-error{color:#b94a48}a.text-error:hover{color:#953b39}.text-info{color:#3a87ad}a.text-info:hover{color:#2d6987}.text-success{color:#468847}a.text-success:hover{color:#356635}h1,h2,h3,h4,h5,h6{margin:10px 0;font-family:inherit;font-weight:bold;line-height:20px;color:inherit;text-rendering:optimizelegibility}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;line-height:1;color:#999}h1,h2,h3{line-height:40px}h1{font-size:38.5px}h2{font-size:31.5px}h3{font-size:24.5px}h4{font-size:17.5px}h5{font-size:14px}h6{font-size:11.9px}h1 small{font-size:24.5px}h2 small{font-size:17.5px}h3 small{font-size:14px}h4 small{font-size:14px}.page-header{padding-bottom:9px;margin:20px 0 30px;border-bottom:1px solid #eee}ul,ol{padding:0;margin:0 0 10px 25px}ul ul,ul ol,ol ol,ol ul{margin-bottom:0}li{line-height:20px}ul.unstyled,ol.unstyled{margin-left:0;list-style:none}ul.inline,ol.inline{margin-left:0;list-style:none}ul.inline>li,ol.inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-bottom:20px}dt,dd{line-height:20px}dt{font-weight:bold}dd{margin-left:10px}.dl-horizontal{*zoom:1}.dl-horizontal:before,.dl-horizontal:after{display:table;line-height:0;content:""}.dl-horizontal:after{clear:both}.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}hr{margin:20px 0;border:0;border-top:1px solid #eee;border-bottom:1px solid #fff}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{margin-bottom:0;font-size:16px;font-weight:300;line-height:25px}blockquote small{display:block;line-height:20px;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small{text-align:right}blockquote.pull-right small:before{content:''}blockquote.pull-right small:after{content:'\00A0 \2014'}q:before,q:after,blockquote:before,blockquote:after{content:""}address{display:block;margin-bottom:20px;font-style:normal;line-height:20px}code,pre{padding:0 3px 2px;font-family:Monaco,Menlo,Consolas,"Courier New",monospace;font-size:12px;color:#333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}code{padding:2px 4px;color:#d14;white-space:nowrap;background-color:#f7f7f9;border:1px solid #e1e1e8}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}pre.prettyprint{margin-bottom:20px}pre code{padding:0;color:inherit;white-space:pre;white-space:pre-wrap;background-color:transparent;border:0}.pre-scrollable{max-height:340px;overflow-y:scroll}form{margin:0 0 20px}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:40px;color:#333;border:0;border-bottom:1px solid #e5e5e5}legend small{font-size:15px;color:#999}label,input,button,select,textarea{font-size:14px;font-weight:normal;line-height:20px}input,button,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}label{display:block;margin-bottom:5px}select,textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{display:inline-block;height:20px;padding:4px 6px;margin-bottom:10px;font-size:14px;line-height:20px;color:#555;vertical-align:middle;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}input,textarea,.uneditable-input{width:206px}textarea{height:auto}textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{background-color:#fff;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border linear .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-o-transition:border linear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .2s}textarea:focus,input[type="text"]:focus,input[type="password"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus,.uneditable-input:focus{border-color:rgba(82,168,236,0.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6)}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;*margin-top:0;line-height:normal}input[type="file"],input[type="image"],input[type="submit"],input[type="reset"],input[type="button"],input[type="radio"],input[type="checkbox"]{width:auto}select,input[type="file"]{height:30px;*margin-top:4px;line-height:30px}select{width:220px;background-color:#fff;border:1px solid #ccc}select[multiple],select[size]{height:auto}select:focus,input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.uneditable-input,.uneditable-textarea{color:#999;cursor:not-allowed;background-color:#fcfcfc;border-color:#ccc;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);box-shadow:inset 0 1px 2px rgba(0,0,0,0.025)}.uneditable-input{overflow:hidden;white-space:nowrap}.uneditable-textarea{width:auto;height:auto}input:-moz-placeholder,textarea:-moz-placeholder{color:#999}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#999}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#999}.radio,.checkbox{min-height:20px;padding-left:20px}.radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-20px}.controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px}.radio.inline,.checkbox.inline{display:inline-block;padding-top:5px;margin-bottom:0;vertical-align:middle}.radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px}.input-mini{width:60px}.input-small{width:90px}.input-medium{width:150px}.input-large{width:210px}.input-xlarge{width:270px}.input-xxlarge{width:530px}input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"]{float:none;margin-left:0}.input-append input[class*="span"],.input-append .uneditable-input[class*="span"],.input-prepend input[class*="span"],.input-prepend .uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"],.row-fluid .input-prepend [class*="span"],.row-fluid .input-append [class*="span"]{display:inline-block}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:926px}input.span11,textarea.span11,.uneditable-input.span11{width:846px}input.span10,textarea.span10,.uneditable-input.span10{width:766px}input.span9,textarea.span9,.uneditable-input.span9{width:686px}input.span8,textarea.span8,.uneditable-input.span8{width:606px}input.span7,textarea.span7,.uneditable-input.span7{width:526px}input.span6,textarea.span6,.uneditable-input.span6{width:446px}input.span5,textarea.span5,.uneditable-input.span5{width:366px}input.span4,textarea.span4,.uneditable-input.span4{width:286px}input.span3,textarea.span3,.uneditable-input.span3{width:206px}input.span2,textarea.span2,.uneditable-input.span2{width:126px}input.span1,textarea.span1,.uneditable-input.span1{width:46px}.controls-row{*zoom:1}.controls-row:before,.controls-row:after{display:table;line-height:0;content:""}.controls-row:after{clear:both}.controls-row [class*="span"],.row-fluid .controls-row [class*="span"]{float:left}.controls-row .checkbox[class*="span"],.controls-row .radio[class*="span"]{padding-top:5px}input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#eee}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"][readonly],input[type="checkbox"][readonly]{background-color:transparent}.control-group.warning .control-label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853}.control-group.warning .checkbox,.control-group.warning .radio,.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09853}.control-group.warning input,.control-group.warning select,.control-group.warning textarea{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e}.control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853}.control-group.error .control-label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48}.control-group.error .checkbox,.control-group.error .radio,.control-group.error input,.control-group.error select,.control-group.error textarea{color:#b94a48}.control-group.error input,.control-group.error select,.control-group.error textarea{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392}.control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48}.control-group.success .control-label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847}.control-group.success .checkbox,.control-group.success .radio,.control-group.success input,.control-group.success select,.control-group.success textarea{color:#468847}.control-group.success input,.control-group.success select,.control-group.success textarea{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b}.control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847}.control-group.info .control-label,.control-group.info .help-block,.control-group.info .help-inline{color:#3a87ad}.control-group.info .checkbox,.control-group.info .radio,.control-group.info input,.control-group.info select,.control-group.info textarea{color:#3a87ad}.control-group.info input,.control-group.info select,.control-group.info textarea{border-color:#3a87ad;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.info input:focus,.control-group.info select:focus,.control-group.info textarea:focus{border-color:#2d6987;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3}.control-group.info .input-prepend .add-on,.control-group.info .input-append .add-on{color:#3a87ad;background-color:#d9edf7;border-color:#3a87ad}input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#b94a48;border-color:#ee5f5b}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7}.form-actions{padding:19px 20px 20px;margin-top:20px;margin-bottom:20px;background-color:#f5f5f5;border-top:1px solid #e5e5e5;*zoom:1}.form-actions:before,.form-actions:after{display:table;line-height:0;content:""}.form-actions:after{clear:both}.help-block,.help-inline{color:#595959}.help-block{display:block;margin-bottom:10px}.help-inline{display:inline-block;*display:inline;padding-left:5px;vertical-align:middle;*zoom:1}.input-append,.input-prepend{margin-bottom:5px;font-size:0;white-space:nowrap}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input,.input-append .dropdown-menu,.input-prepend .dropdown-menu{font-size:14px}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input{position:relative;margin-bottom:0;*margin-left:0;vertical-align:top;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append input:focus,.input-prepend input:focus,.input-append select:focus,.input-prepend select:focus,.input-append .uneditable-input:focus,.input-prepend .uneditable-input:focus{z-index:2}.input-append .add-on,.input-prepend .add-on{display:inline-block;width:auto;height:20px;min-width:16px;padding:4px 5px;font-size:14px;font-weight:normal;line-height:20px;text-align:center;text-shadow:0 1px 0 #fff;background-color:#eee;border:1px solid #ccc}.input-append .add-on,.input-prepend .add-on,.input-append .btn,.input-prepend .btn,.input-append .btn-group>.dropdown-toggle,.input-prepend .btn-group>.dropdown-toggle{vertical-align:top;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-append .active,.input-prepend .active{background-color:#a9dba9;border-color:#46a546}.input-prepend .add-on,.input-prepend .btn{margin-right:-1px}.input-prepend .add-on:first-child,.input-prepend .btn:first-child{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input,.input-append select,.input-append .uneditable-input{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input+.btn-group .btn:last-child,.input-append select+.btn-group .btn:last-child,.input-append .uneditable-input+.btn-group .btn:last-child{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append .add-on,.input-append .btn,.input-append .btn-group{margin-left:-1px}.input-append .add-on:last-child,.input-append .btn:last-child,.input-append .btn-group:last-child>.dropdown-toggle{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append input,.input-prepend.input-append select,.input-prepend.input-append .uneditable-input{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-prepend.input-append input+.btn-group .btn,.input-prepend.input-append select+.btn-group .btn,.input-prepend.input-append .uneditable-input+.btn-group .btn{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append .add-on:first-child,.input-prepend.input-append .btn:first-child{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-prepend.input-append .add-on:last-child,.input-prepend.input-append .btn:last-child{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append .btn-group:first-child{margin-left:0}input.search-query{padding-right:14px;padding-right:4px \9;padding-left:14px;padding-left:4px \9;margin-bottom:0;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.form-search .input-append .search-query,.form-search .input-prepend .search-query{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.form-search .input-append .search-query{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search .input-append .btn{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .search-query{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .btn{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input,.form-search .input-prepend,.form-inline .input-prepend,.form-horizontal .input-prepend,.form-search .input-append,.form-inline .input-append,.form-horizontal .input-append{display:inline-block;*display:inline;margin-bottom:0;vertical-align:middle;*zoom:1}.form-search .hide,.form-inline .hide,.form-horizontal .hide{display:none}.form-search label,.form-inline label,.form-search .btn-group,.form-inline .btn-group{display:inline-block}.form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{margin-bottom:0}.form-search .radio,.form-search .checkbox,.form-inline .radio,.form-inline .checkbox{padding-left:0;margin-bottom:0;vertical-align:middle}.form-search .radio input[type="radio"],.form-search .checkbox input[type="checkbox"],.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:left;margin-right:3px;margin-left:0}.control-group{margin-bottom:10px}legend+.control-group{margin-top:20px;-webkit-margin-top-collapse:separate}.form-horizontal .control-group{margin-bottom:20px;*zoom:1}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;line-height:0;content:""}.form-horizontal .control-group:after{clear:both}.form-horizontal .control-label{float:left;width:160px;padding-top:5px;text-align:right}.form-horizontal .controls{*display:inline-block;*padding-left:20px;margin-left:180px;*margin-left:0}.form-horizontal .controls:first-child{*padding-left:180px}.form-horizontal .help-block{margin-bottom:0}.form-horizontal input+.help-block,.form-horizontal select+.help-block,.form-horizontal textarea+.help-block,.form-horizontal .uneditable-input+.help-block,.form-horizontal .input-prepend+.help-block,.form-horizontal .input-append+.help-block{margin-top:10px}.form-horizontal .form-actions{padding-left:180px}table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0}.table{width:100%;margin-bottom:20px}.table th,.table td{padding:8px;line-height:20px;text-align:left;vertical-align:top;border-top:1px solid #ddd}.table th{font-weight:bold}.table thead th{vertical-align:bottom}.table caption+thead tr:first-child th,.table caption+thead tr:first-child td,.table colgroup+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table thead:first-child tr:first-child th,.table thead:first-child tr:first-child td{border-top:0}.table tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed th,.table-condensed td{padding:4px 5px}.table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapse;border-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.table-bordered th,.table-bordered td{border-left:1px solid #ddd}.table-bordered caption+thead tr:first-child th,.table-bordered caption+tbody tr:first-child th,.table-bordered caption+tbody tr:first-child td,.table-bordered colgroup+thead tr:first-child th,.table-bordered colgroup+tbody tr:first-child th,.table-bordered colgroup+tbody tr:first-child td,.table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0}.table-bordered thead:first-child tr:first-child>th:first-child,.table-bordered tbody:first-child tr:first-child>td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered thead:first-child tr:first-child>th:last-child,.table-bordered tbody:first-child tr:first-child>td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-bordered thead:last-child tr:last-child>th:first-child,.table-bordered tbody:last-child tr:last-child>td:first-child,.table-bordered tfoot:last-child tr:last-child>td:first-child{-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px}.table-bordered thead:last-child tr:last-child>th:last-child,.table-bordered tbody:last-child tr:last-child>td:last-child,.table-bordered tfoot:last-child tr:last-child>td:last-child{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px}.table-bordered tfoot+tbody:last-child tr:last-child td:first-child{-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-moz-border-radius-bottomleft:0}.table-bordered tfoot+tbody:last-child tr:last-child td:last-child{-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-moz-border-radius-bottomright:0}.table-bordered caption+thead tr:first-child th:first-child,.table-bordered caption+tbody tr:first-child td:first-child,.table-bordered colgroup+thead tr:first-child th:first-child,.table-bordered colgroup+tbody tr:first-child td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered caption+thead tr:first-child th:last-child,.table-bordered caption+tbody tr:first-child td:last-child,.table-bordered colgroup+thead tr:first-child th:last-child,.table-bordered colgroup+tbody tr:first-child td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-striped tbody>tr:nth-child(odd)>td,.table-striped tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover tbody tr:hover td,.table-hover tbody tr:hover th{background-color:#f5f5f5}table td[class*="span"],table th[class*="span"],.row-fluid table td[class*="span"],.row-fluid table th[class*="span"]{display:table-cell;float:none;margin-left:0}.table td.span1,.table th.span1{float:none;width:44px;margin-left:0}.table td.span2,.table th.span2{float:none;width:124px;margin-left:0}.table td.span3,.table th.span3{float:none;width:204px;margin-left:0}.table td.span4,.table th.span4{float:none;width:284px;margin-left:0}.table td.span5,.table th.span5{float:none;width:364px;margin-left:0}.table td.span6,.table th.span6{float:none;width:444px;margin-left:0}.table td.span7,.table th.span7{float:none;width:524px;margin-left:0}.table td.span8,.table th.span8{float:none;width:604px;margin-left:0}.table td.span9,.table th.span9{float:none;width:684px;margin-left:0}.table td.span10,.table th.span10{float:none;width:764px;margin-left:0}.table td.span11,.table th.span11{float:none;width:844px;margin-left:0}.table td.span12,.table th.span12{float:none;width:924px;margin-left:0}.table tbody tr.success td{background-color:#dff0d8}.table tbody tr.error td{background-color:#f2dede}.table tbody tr.warning td{background-color:#fcf8e3}.table tbody tr.info td{background-color:#d9edf7}.table-hover tbody tr.success:hover td{background-color:#d0e9c6}.table-hover tbody tr.error:hover td{background-color:#ebcccc}.table-hover tbody tr.warning:hover td{background-color:#faf2cc}.table-hover tbody tr.info:hover td{background-color:#c4e3f3}[class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;margin-top:1px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../img/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat}.icon-white,.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"]{background-image:url("../img/glyphicons-halflings-white.png")}.icon-glass{background-position:0 0}.icon-music{background-position:-24px 0}.icon-search{background-position:-48px 0}.icon-envelope{background-position:-72px 0}.icon-heart{background-position:-96px 0}.icon-star{background-position:-120px 0}.icon-star-empty{background-position:-144px 0}.icon-user{background-position:-168px 0}.icon-film{background-position:-192px 0}.icon-th-large{background-position:-216px 0}.icon-th{background-position:-240px 0}.icon-th-list{background-position:-264px 0}.icon-ok{background-position:-288px 0}.icon-remove{background-position:-312px 0}.icon-zoom-in{background-position:-336px 0}.icon-zoom-out{background-position:-360px 0}.icon-off{background-position:-384px 0}.icon-signal{background-position:-408px 0}.icon-cog{background-position:-432px 0}.icon-trash{background-position:-456px 0}.icon-home{background-position:0 -24px}.icon-file{background-position:-24px -24px}.icon-time{background-position:-48px -24px}.icon-road{background-position:-72px -24px}.icon-download-alt{background-position:-96px -24px}.icon-download{background-position:-120px -24px}.icon-upload{background-position:-144px -24px}.icon-inbox{background-position:-168px -24px}.icon-play-circle{background-position:-192px -24px}.icon-repeat{background-position:-216px -24px}.icon-refresh{background-position:-240px -24px}.icon-list-alt{background-position:-264px -24px}.icon-lock{background-position:-287px -24px}.icon-flag{background-position:-312px -24px}.icon-headphones{background-position:-336px -24px}.icon-volume-off{background-position:-360px -24px}.icon-volume-down{background-position:-384px -24px}.icon-volume-up{background-position:-408px -24px}.icon-qrcode{background-position:-432px -24px}.icon-barcode{background-position:-456px -24px}.icon-tag{background-position:0 -48px}.icon-tags{background-position:-25px -48px}.icon-book{background-position:-48px -48px}.icon-bookmark{background-position:-72px -48px}.icon-print{background-position:-96px -48px}.icon-camera{background-position:-120px -48px}.icon-font{background-position:-144px -48px}.icon-bold{background-position:-167px -48px}.icon-italic{background-position:-192px -48px}.icon-text-height{background-position:-216px -48px}.icon-text-width{background-position:-240px -48px}.icon-align-left{background-position:-264px -48px}.icon-align-center{background-position:-288px -48px}.icon-align-right{background-position:-312px -48px}.icon-align-justify{background-position:-336px -48px}.icon-list{background-position:-360px -48px}.icon-indent-left{background-position:-384px -48px}.icon-indent-right{background-position:-408px -48px}.icon-facetime-video{background-position:-432px -48px}.icon-picture{background-position:-456px -48px}.icon-pencil{background-position:0 -72px}.icon-map-marker{background-position:-24px -72px}.icon-adjust{background-position:-48px -72px}.icon-tint{background-position:-72px -72px}.icon-edit{background-position:-96px -72px}.icon-share{background-position:-120px -72px}.icon-check{background-position:-144px -72px}.icon-move{background-position:-168px -72px}.icon-step-backward{background-position:-192px -72px}.icon-fast-backward{background-position:-216px -72px}.icon-backward{background-position:-240px -72px}.icon-play{background-position:-264px -72px}.icon-pause{background-position:-288px -72px}.icon-stop{background-position:-312px -72px}.icon-forward{background-position:-336px -72px}.icon-fast-forward{background-position:-360px -72px}.icon-step-forward{background-position:-384px -72px}.icon-eject{background-position:-408px -72px}.icon-chevron-left{background-position:-432px -72px}.icon-chevron-right{background-position:-456px -72px}.icon-plus-sign{background-position:0 -96px}.icon-minus-sign{background-position:-24px -96px}.icon-remove-sign{background-position:-48px -96px}.icon-ok-sign{background-position:-72px -96px}.icon-question-sign{background-position:-96px -96px}.icon-info-sign{background-position:-120px -96px}.icon-screenshot{background-position:-144px -96px}.icon-remove-circle{background-position:-168px -96px}.icon-ok-circle{background-position:-192px -96px}.icon-ban-circle{background-position:-216px -96px}.icon-arrow-left{background-position:-240px -96px}.icon-arrow-right{background-position:-264px -96px}.icon-arrow-up{background-position:-289px -96px}.icon-arrow-down{background-position:-312px -96px}.icon-share-alt{background-position:-336px -96px}.icon-resize-full{background-position:-360px -96px}.icon-resize-small{background-position:-384px -96px}.icon-plus{background-position:-408px -96px}.icon-minus{background-position:-433px -96px}.icon-asterisk{background-position:-456px -96px}.icon-exclamation-sign{background-position:0 -120px}.icon-gift{background-position:-24px -120px}.icon-leaf{background-position:-48px -120px}.icon-fire{background-position:-72px -120px}.icon-eye-open{background-position:-96px -120px}.icon-eye-close{background-position:-120px -120px}.icon-warning-sign{background-position:-144px -120px}.icon-plane{background-position:-168px -120px}.icon-calendar{background-position:-192px -120px}.icon-random{width:16px;background-position:-216px -120px}.icon-comment{background-position:-240px -120px}.icon-magnet{background-position:-264px -120px}.icon-chevron-up{background-position:-288px -120px}.icon-chevron-down{background-position:-313px -119px}.icon-retweet{background-position:-336px -120px}.icon-shopping-cart{background-position:-360px -120px}.icon-folder-close{background-position:-384px -120px}.icon-folder-open{width:16px;background-position:-408px -120px}.icon-resize-vertical{background-position:-432px -119px}.icon-resize-horizontal{background-position:-456px -118px}.icon-hdd{background-position:0 -144px}.icon-bullhorn{background-position:-24px -144px}.icon-bell{background-position:-48px -144px}.icon-certificate{background-position:-72px -144px}.icon-thumbs-up{background-position:-96px -144px}.icon-thumbs-down{background-position:-120px -144px}.icon-hand-right{background-position:-144px -144px}.icon-hand-left{background-position:-168px -144px}.icon-hand-up{background-position:-192px -144px}.icon-hand-down{background-position:-216px -144px}.icon-circle-arrow-right{background-position:-240px -144px}.icon-circle-arrow-left{background-position:-264px -144px}.icon-circle-arrow-up{background-position:-288px -144px}.icon-circle-arrow-down{background-position:-312px -144px}.icon-globe{background-position:-336px -144px}.icon-wrench{background-position:-360px -144px}.icon-tasks{background-position:-384px -144px}.icon-filter{background-position:-408px -144px}.icon-briefcase{background-position:-432px -144px}.icon-fullscreen{background-position:-456px -144px}.dropup,.dropdown{position:relative}.dropdown-toggle{*margin-bottom:-3px}.dropdown-toggle:active,.open .dropdown-toggle{outline:0}.caret{display:inline-block;width:0;height:0;vertical-align:top;border-top:4px solid #000;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.dropdown .caret{margin-top:8px;margin-left:2px}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);*border-right-width:2px;*border-bottom-width:2px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.dropdown-menu li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap}.dropdown-menu li>a:hover,.dropdown-menu li>a:focus,.dropdown-submenu:hover>a{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu .active>a,.dropdown-menu .active>a:hover{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;outline:0;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu .disabled>a,.dropdown-menu .disabled>a:hover{color:#999}.dropdown-menu .disabled>a:hover{text-decoration:none;cursor:default;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open{*z-index:1000}.open>.dropdown-menu{display:block}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid #000;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}.dropdown-submenu{position:relative}.dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px;-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px 6px;border-radius:0 6px 6px 6px}.dropdown-submenu:hover>.dropdown-menu{display:block}.dropup .dropdown-submenu>.dropdown-menu{top:auto;bottom:0;margin-top:0;margin-bottom:-2px;-webkit-border-radius:5px 5px 5px 0;-moz-border-radius:5px 5px 5px 0;border-radius:5px 5px 5px 0}.dropdown-submenu>a:after{display:block;float:right;width:0;height:0;margin-top:5px;margin-right:-10px;border-color:transparent;border-left-color:#ccc;border-style:solid;border-width:5px 0 5px 5px;content:" "}.dropdown-submenu:hover>a:after{border-left-color:#fff}.dropdown-submenu.pull-left{float:none}.dropdown-submenu.pull-left>.dropdown-menu{left:-100%;margin-left:10px;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.dropdown .dropdown-menu .nav-header{padding-right:20px;padding-left:20px}.typeahead{z-index:1051;margin-top:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-large{padding:24px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.well-small{padding:9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.fade{opacity:0;-webkit-transition:opacity .15s linear;-moz-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-moz-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.collapse.in{height:auto}.close{float:right;font-size:20px;font-weight:bold;line-height:20px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.btn{display:inline-block;*display:inline;padding:4px 12px;margin-bottom:0;*margin-left:.3em;font-size:14px;line-height:20px;color:#333;text-align:center;text-shadow:0 1px 1px rgba(255,255,255,0.75);vertical-align:middle;cursor:pointer;background-color:#f5f5f5;*background-color:#e6e6e6;background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(to bottom,#fff,#e6e6e6);background-repeat:repeat-x;border:1px solid #bbb;*border:0;border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);border-bottom-color:#a2a2a2;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe6e6e6',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);*zoom:1;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn:hover,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{color:#333;background-color:#e6e6e6;*background-color:#d9d9d9}.btn:active,.btn.active{background-color:#ccc \9}.btn:first-child{*margin-left:0}.btn:hover{color:#333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn.disabled,.btn[disabled]{cursor:default;background-image:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-large{padding:11px 19px;font-size:17.5px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.btn-large [class^="icon-"],.btn-large [class*=" icon-"]{margin-top:4px}.btn-small{padding:2px 10px;font-size:11.9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.btn-small [class^="icon-"],.btn-small [class*=" icon-"]{margin-top:0}.btn-mini [class^="icon-"],.btn-mini [class*=" icon-"]{margin-top:-1px}.btn-mini{padding:0 6px;font-size:10.5px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.btn-block{display:block;width:100%;padding-right:0;padding-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-inverse.active{color:rgba(255,255,255,0.75)}.btn{border-color:#c5c5c5;border-color:rgba(0,0,0,0.15) rgba(0,0,0,0.15) rgba(0,0,0,0.25)}.btn-primary{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#006dcc;*background-color:#04c;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0044cc',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-primary:hover,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{color:#fff;background-color:#04c;*background-color:#003bb3}.btn-primary:active,.btn-primary.active{background-color:#039 \9}.btn-warning{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#faa732;*background-color:#f89406;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;border-color:#f89406 #f89406 #ad6704;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-warning:hover,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{color:#fff;background-color:#f89406;*background-color:#df8505}.btn-warning:active,.btn-warning.active{background-color:#c67605 \9}.btn-danger{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#da4f49;*background-color:#bd362f;background-image:-moz-linear-gradient(top,#ee5f5b,#bd362f);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#bd362f));background-image:-webkit-linear-gradient(top,#ee5f5b,#bd362f);background-image:-o-linear-gradient(top,#ee5f5b,#bd362f);background-image:linear-gradient(to bottom,#ee5f5b,#bd362f);background-repeat:repeat-x;border-color:#bd362f #bd362f #802420;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffbd362f',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-danger:hover,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{color:#fff;background-color:#bd362f;*background-color:#a9302a}.btn-danger:active,.btn-danger.active{background-color:#942a25 \9}.btn-success{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#5bb75b;*background-color:#51a351;background-image:-moz-linear-gradient(top,#62c462,#51a351);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#51a351));background-image:-webkit-linear-gradient(top,#62c462,#51a351);background-image:-o-linear-gradient(top,#62c462,#51a351);background-image:linear-gradient(to bottom,#62c462,#51a351);background-repeat:repeat-x;border-color:#51a351 #51a351 #387038;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff51a351',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-success:hover,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{color:#fff;background-color:#51a351;*background-color:#499249}.btn-success:active,.btn-success.active{background-color:#408140 \9}.btn-info{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#49afcd;*background-color:#2f96b4;background-image:-moz-linear-gradient(top,#5bc0de,#2f96b4);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#2f96b4));background-image:-webkit-linear-gradient(top,#5bc0de,#2f96b4);background-image:-o-linear-gradient(top,#5bc0de,#2f96b4);background-image:linear-gradient(to bottom,#5bc0de,#2f96b4);background-repeat:repeat-x;border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff2f96b4',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-info:hover,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{color:#fff;background-color:#2f96b4;*background-color:#2a85a0}.btn-info:active,.btn-info.active{background-color:#24748c \9}.btn-inverse{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#363636;*background-color:#222;background-image:-moz-linear-gradient(top,#444,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#444),to(#222));background-image:-webkit-linear-gradient(top,#444,#222);background-image:-o-linear-gradient(top,#444,#222);background-image:linear-gradient(to bottom,#444,#222);background-repeat:repeat-x;border-color:#222 #222 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444',endColorstr='#ff222222',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-inverse:hover,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{color:#fff;background-color:#222;*background-color:#151515}.btn-inverse:active,.btn-inverse.active{background-color:#080808 \9}button.btn,input[type="submit"].btn{*padding-top:3px;*padding-bottom:3px}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0}button.btn.btn-large,input[type="submit"].btn.btn-large{*padding-top:7px;*padding-bottom:7px}button.btn.btn-small,input[type="submit"].btn.btn-small{*padding-top:3px;*padding-bottom:3px}button.btn.btn-mini,input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-bottom:1px}.btn-link,.btn-link:active,.btn-link[disabled]{background-color:transparent;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-link{color:#08c;cursor:pointer;border-color:transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-link:hover{color:#005580;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover{color:#333;text-decoration:none}.btn-group{position:relative;display:inline-block;*display:inline;*margin-left:.3em;font-size:0;white-space:nowrap;vertical-align:middle;*zoom:1}.btn-group:first-child{*margin-left:0}.btn-group+.btn-group{margin-left:5px}.btn-toolbar{margin-top:10px;margin-bottom:10px;font-size:0}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group{margin-left:5px}.btn-group>.btn{position:relative;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group>.btn+.btn{margin-left:-1px}.btn-group>.btn,.btn-group>.dropdown-menu,.btn-group>.popover{font-size:14px}.btn-group>.btn-mini{font-size:10.5px}.btn-group>.btn-small{font-size:11.9px}.btn-group>.btn-large{font-size:17.5px}.btn-group>.btn:first-child{margin-left:0;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.btn-group>.btn:last-child,.btn-group>.dropdown-toggle{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.btn-group>.btn.large:first-child{margin-left:0;-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.btn-group>.btn.large:last-child,.btn-group>.large.dropdown-toggle{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active{z-index:2}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{*padding-top:5px;padding-right:8px;*padding-bottom:5px;padding-left:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn-group>.btn-mini+.dropdown-toggle{*padding-top:2px;padding-right:5px;*padding-bottom:2px;padding-left:5px}.btn-group>.btn-small+.dropdown-toggle{*padding-top:5px;*padding-bottom:4px}.btn-group>.btn-large+.dropdown-toggle{*padding-top:7px;padding-right:12px;*padding-bottom:7px;padding-left:12px}.btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn-group.open .btn.dropdown-toggle{background-color:#e6e6e6}.btn-group.open .btn-primary.dropdown-toggle{background-color:#04c}.btn-group.open .btn-warning.dropdown-toggle{background-color:#f89406}.btn-group.open .btn-danger.dropdown-toggle{background-color:#bd362f}.btn-group.open .btn-success.dropdown-toggle{background-color:#51a351}.btn-group.open .btn-info.dropdown-toggle{background-color:#2f96b4}.btn-group.open .btn-inverse.dropdown-toggle{background-color:#222}.btn .caret{margin-top:8px;margin-left:0}.btn-mini .caret,.btn-small .caret,.btn-large .caret{margin-top:6px}.btn-large .caret{border-top-width:5px;border-right-width:5px;border-left-width:5px}.dropup .btn-large .caret{border-bottom-width:5px}.btn-primary .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret,.btn-inverse .caret{border-top-color:#fff;border-bottom-color:#fff}.btn-group-vertical{display:inline-block;*display:inline;*zoom:1}.btn-group-vertical>.btn{display:block;float:none;max-width:100%;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group-vertical>.btn+.btn{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:first-child{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.btn-group-vertical>.btn:last-child{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.btn-group-vertical>.btn-large:first-child{-webkit-border-radius:6px 6px 0 0;-moz-border-radius:6px 6px 0 0;border-radius:6px 6px 0 0}.btn-group-vertical>.btn-large:last-child{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.alert{padding:8px 35px 8px 14px;margin-bottom:20px;text-shadow:0 1px 0 rgba(255,255,255,0.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.alert,.alert h4{color:#c09853}.alert h4{margin:0}.alert .close{position:relative;top:-2px;right:-21px;line-height:20px}.alert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.alert-success h4{color:#468847}.alert-danger,.alert-error{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.alert-danger h4,.alert-error h4{color:#b94a48}.alert-info{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.alert-info h4{color:#3a87ad}.alert-block{padding-top:14px;padding-bottom:14px}.alert-block>p,.alert-block>ul{margin-bottom:0}.alert-block p+p{margin-top:5px}.nav{margin-bottom:20px;margin-left:0;list-style:none}.nav>li>a{display:block}.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li>a>img{max-width:none}.nav>.pull-right{float:right}.nav-header{display:block;padding:3px 15px;font-size:11px;font-weight:bold;line-height:20px;color:#999;text-shadow:0 1px 0 rgba(255,255,255,0.5);text-transform:uppercase}.nav li+.nav-header{margin-top:9px}.nav-list{padding-right:15px;padding-left:15px;margin-bottom:0}.nav-list>li>a,.nav-list .nav-header{margin-right:-15px;margin-left:-15px;text-shadow:0 1px 0 rgba(255,255,255,0.5)}.nav-list>li>a{padding:3px 15px}.nav-list>.active>a,.nav-list>.active>a:hover{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.2);background-color:#08c}.nav-list [class^="icon-"],.nav-list [class*=" icon-"]{margin-right:2px}.nav-list .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.nav-tabs,.nav-pills{*zoom:1}.nav-tabs:before,.nav-pills:before,.nav-tabs:after,.nav-pills:after{display:table;line-height:0;content:""}.nav-tabs:after,.nav-pills:after{clear:both}.nav-tabs>li,.nav-pills>li{float:left}.nav-tabs>li>a,.nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{margin-bottom:-1px}.nav-tabs>li>a{padding-top:8px;padding-bottom:8px;line-height:20px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>.active>a,.nav-tabs>.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.nav-pills>.active>a,.nav-pills>.active>a:hover{color:#fff;background-color:#08c}.nav-stacked>li{float:none}.nav-stacked>li>a{margin-right:0}.nav-tabs.nav-stacked{border-bottom:0}.nav-tabs.nav-stacked>li>a{border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.nav-tabs.nav-stacked>li:first-child>a{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-topleft:4px}.nav-tabs.nav-stacked>li:last-child>a{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomright:4px;-moz-border-radius-bottomleft:4px}.nav-tabs.nav-stacked>li>a:hover{z-index:2;border-color:#ddd}.nav-pills.nav-stacked>li>a{margin-bottom:3px}.nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px}.nav-tabs .dropdown-menu{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.nav-pills .dropdown-menu{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.nav .dropdown-toggle .caret{margin-top:6px;border-top-color:#08c;border-bottom-color:#08c}.nav .dropdown-toggle:hover .caret{border-top-color:#005580;border-bottom-color:#005580}.nav-tabs .dropdown-toggle .caret{margin-top:8px}.nav .active .dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.nav-tabs .active .dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.nav>.dropdown.active>a:hover{cursor:pointer}.nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>li.dropdown.open.active>a:hover{color:#fff;background-color:#999;border-color:#999}.nav li.dropdown.open .caret,.nav li.dropdown.open.active .caret,.nav li.dropdown.open a:hover .caret{border-top-color:#fff;border-bottom-color:#fff;opacity:1;filter:alpha(opacity=100)}.tabs-stacked .open>a:hover{border-color:#999}.tabbable{*zoom:1}.tabbable:before,.tabbable:after{display:table;line-height:0;content:""}.tabbable:after{clear:both}.tab-content{overflow:auto}.tabs-below>.nav-tabs,.tabs-right>.nav-tabs,.tabs-left>.nav-tabs{border-bottom:0}.tab-content>.tab-pane,.pill-content>.pill-pane{display:none}.tab-content>.active,.pill-content>.active{display:block}.tabs-below>.nav-tabs{border-top:1px solid #ddd}.tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0}.tabs-below>.nav-tabs>li>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.tabs-below>.nav-tabs>li>a:hover{border-top-color:#ddd;border-bottom-color:transparent}.tabs-below>.nav-tabs>.active>a,.tabs-below>.nav-tabs>.active>a:hover{border-color:transparent #ddd #ddd #ddd}.tabs-left>.nav-tabs>li,.tabs-right>.nav-tabs>li{float:none}.tabs-left>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px}.tabs-left>.nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd}.tabs-left>.nav-tabs>li>a{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.tabs-left>.nav-tabs>li>a:hover{border-color:#eee #ddd #eee #eee}.tabs-left>.nav-tabs .active>a,.tabs-left>.nav-tabs .active>a:hover{border-color:#ddd transparent #ddd #ddd;*border-right-color:#fff}.tabs-right>.nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd}.tabs-right>.nav-tabs>li>a{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.tabs-right>.nav-tabs>li>a:hover{border-color:#eee #eee #eee #ddd}.tabs-right>.nav-tabs .active>a,.tabs-right>.nav-tabs .active>a:hover{border-color:#ddd #ddd #ddd transparent;*border-left-color:#fff}.nav>.disabled>a{color:#999}.nav>.disabled>a:hover{text-decoration:none;cursor:default;background-color:transparent}.navbar{*position:relative;*z-index:2;margin-bottom:20px;overflow:visible}.navbar-inner{min-height:40px;padding-right:20px;padding-left:20px;background-color:#fafafa;background-image:-moz-linear-gradient(top,#fff,#f2f2f2);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#f2f2f2));background-image:-webkit-linear-gradient(top,#fff,#f2f2f2);background-image:-o-linear-gradient(top,#fff,#f2f2f2);background-image:linear-gradient(to bottom,#fff,#f2f2f2);background-repeat:repeat-x;border:1px solid #d4d4d4;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff2f2f2',GradientType=0);*zoom:1;-webkit-box-shadow:0 1px 4px rgba(0,0,0,0.065);-moz-box-shadow:0 1px 4px rgba(0,0,0,0.065);box-shadow:0 1px 4px rgba(0,0,0,0.065)}.navbar-inner:before,.navbar-inner:after{display:table;line-height:0;content:""}.navbar-inner:after{clear:both}.navbar .container{width:auto}.nav-collapse.collapse{height:auto;overflow:visible}.navbar .brand{display:block;float:left;padding:10px 20px 10px;margin-left:-20px;font-size:20px;font-weight:200;color:#777;text-shadow:0 1px 0 #fff}.navbar .brand:hover{text-decoration:none}.navbar-text{margin-bottom:0;line-height:40px;color:#777}.navbar-link{color:#777}.navbar-link:hover{color:#333}.navbar .divider-vertical{height:40px;margin:0 9px;border-right:1px solid #fff;border-left:1px solid #f2f2f2}.navbar .btn,.navbar .btn-group{margin-top:5px}.navbar .btn-group .btn,.navbar .input-prepend .btn,.navbar .input-append .btn{margin-top:0}.navbar-form{margin-bottom:0;*zoom:1}.navbar-form:before,.navbar-form:after{display:table;line-height:0;content:""}.navbar-form:after{clear:both}.navbar-form input,.navbar-form select,.navbar-form .radio,.navbar-form .checkbox{margin-top:5px}.navbar-form input,.navbar-form select,.navbar-form .btn{display:inline-block;margin-bottom:0}.navbar-form input[type="image"],.navbar-form input[type="checkbox"],.navbar-form input[type="radio"]{margin-top:3px}.navbar-form .input-append,.navbar-form .input-prepend{margin-top:5px;white-space:nowrap}.navbar-form .input-append input,.navbar-form .input-prepend input{margin-top:0}.navbar-search{position:relative;float:left;margin-top:5px;margin-bottom:0}.navbar-search .search-query{padding:4px 14px;margin-bottom:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.navbar-static-top{position:static;margin-bottom:0}.navbar-static-top .navbar-inner{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;margin-bottom:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{border-width:0 0 1px}.navbar-fixed-bottom .navbar-inner{border-width:1px 0 0}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding-right:0;padding-left:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.navbar-fixed-top{top:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{-webkit-box-shadow:0 1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 10px rgba(0,0,0,0.1);box-shadow:0 1px 10px rgba(0,0,0,0.1)}.navbar-fixed-bottom{bottom:0}.navbar-fixed-bottom .navbar-inner{-webkit-box-shadow:0 -1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 -1px 10px rgba(0,0,0,0.1);box-shadow:0 -1px 10px rgba(0,0,0,0.1)}.navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0}.navbar .nav.pull-right{float:right;margin-right:0}.navbar .nav>li{float:left}.navbar .nav>li>a{float:none;padding:10px 15px 10px;color:#777;text-decoration:none;text-shadow:0 1px 0 #fff}.navbar .nav .dropdown-toggle .caret{margin-top:8px}.navbar .nav>li>a:focus,.navbar .nav>li>a:hover{color:#333;text-decoration:none;background-color:transparent}.navbar .nav>.active>a,.navbar .nav>.active>a:hover,.navbar .nav>.active>a:focus{color:#555;text-decoration:none;background-color:#e5e5e5;-webkit-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);-moz-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);box-shadow:inset 0 3px 8px rgba(0,0,0,0.125)}.navbar .btn-navbar{display:none;float:right;padding:7px 10px;margin-right:5px;margin-left:5px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#ededed;*background-color:#e5e5e5;background-image:-moz-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f2f2f2),to(#e5e5e5));background-image:-webkit-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-o-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:linear-gradient(to bottom,#f2f2f2,#e5e5e5);background-repeat:repeat-x;border-color:#e5e5e5 #e5e5e5 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2',endColorstr='#ffe5e5e5',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075)}.navbar .btn-navbar:hover,.navbar .btn-navbar:active,.navbar .btn-navbar.active,.navbar .btn-navbar.disabled,.navbar .btn-navbar[disabled]{color:#fff;background-color:#e5e5e5;*background-color:#d9d9d9}.navbar .btn-navbar:active,.navbar .btn-navbar.active{background-color:#ccc \9}.navbar .btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,0.25);-moz-box-shadow:0 1px 0 rgba(0,0,0,0.25);box-shadow:0 1px 0 rgba(0,0,0,0.25)}.btn-navbar .icon-bar+.icon-bar{margin-top:3px}.navbar .nav>li>.dropdown-menu:before{position:absolute;top:-7px;left:9px;display:inline-block;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-left:7px solid transparent;border-bottom-color:rgba(0,0,0,0.2);content:''}.navbar .nav>li>.dropdown-menu:after{position:absolute;top:-6px;left:10px;display:inline-block;border-right:6px solid transparent;border-bottom:6px solid #fff;border-left:6px solid transparent;content:''}.navbar-fixed-bottom .nav>li>.dropdown-menu:before{top:auto;bottom:-7px;border-top:7px solid #ccc;border-bottom:0;border-top-color:rgba(0,0,0,0.2)}.navbar-fixed-bottom .nav>li>.dropdown-menu:after{top:auto;bottom:-6px;border-top:6px solid #fff;border-bottom:0}.navbar .nav li.dropdown>a:hover .caret{border-top-color:#555;border-bottom-color:#555}.navbar .nav li.dropdown.open>.dropdown-toggle,.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle{color:#555;background-color:#e5e5e5}.navbar .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#777;border-bottom-color:#777}.navbar .nav li.dropdown.open>.dropdown-toggle .caret,.navbar .nav li.dropdown.active>.dropdown-toggle .caret,.navbar .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.navbar .pull-right>li>.dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right{right:0;left:auto}.navbar .pull-right>li>.dropdown-menu:before,.navbar .nav>li>.dropdown-menu.pull-right:before{right:12px;left:auto}.navbar .pull-right>li>.dropdown-menu:after,.navbar .nav>li>.dropdown-menu.pull-right:after{right:13px;left:auto}.navbar .pull-right>li>.dropdown-menu .dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right .dropdown-menu{right:100%;left:auto;margin-right:-1px;margin-left:0;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.navbar-inverse .navbar-inner{background-color:#1b1b1b;background-image:-moz-linear-gradient(top,#222,#111);background-image:-webkit-gradient(linear,0 0,0 100%,from(#222),to(#111));background-image:-webkit-linear-gradient(top,#222,#111);background-image:-o-linear-gradient(top,#222,#111);background-image:linear-gradient(to bottom,#222,#111);background-repeat:repeat-x;border-color:#252525;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222',endColorstr='#ff111111',GradientType=0)}.navbar-inverse .brand,.navbar-inverse .nav>li>a{color:#999;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-inverse .brand:hover,.navbar-inverse .nav>li>a:hover{color:#fff}.navbar-inverse .brand{color:#999}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .nav>li>a:focus,.navbar-inverse .nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .nav .active>a,.navbar-inverse .nav .active>a:hover,.navbar-inverse .nav .active>a:focus{color:#fff;background-color:#111}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .divider-vertical{border-right-color:#222;border-left-color:#111}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle{color:#fff;background-color:#111}.navbar-inverse .nav li.dropdown>a:hover .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#999;border-bottom-color:#999}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .navbar-search .search-query{color:#fff;background-color:#515151;border-color:#111;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none}.navbar-inverse .navbar-search .search-query:-moz-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:-ms-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:focus,.navbar-inverse .navbar-search .search-query.focused{padding:5px 15px;color:#333;text-shadow:0 1px 0 #fff;background-color:#fff;border:0;outline:0;-webkit-box-shadow:0 0 3px rgba(0,0,0,0.15);-moz-box-shadow:0 0 3px rgba(0,0,0,0.15);box-shadow:0 0 3px rgba(0,0,0,0.15)}.navbar-inverse .btn-navbar{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e0e0e;*background-color:#040404;background-image:-moz-linear-gradient(top,#151515,#040404);background-image:-webkit-gradient(linear,0 0,0 100%,from(#151515),to(#040404));background-image:-webkit-linear-gradient(top,#151515,#040404);background-image:-o-linear-gradient(top,#151515,#040404);background-image:linear-gradient(to bottom,#151515,#040404);background-repeat:repeat-x;border-color:#040404 #040404 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515',endColorstr='#ff040404',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.navbar-inverse .btn-navbar:hover,.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active,.navbar-inverse .btn-navbar.disabled,.navbar-inverse .btn-navbar[disabled]{color:#fff;background-color:#040404;*background-color:#000}.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active{background-color:#000 \9}.breadcrumb{padding:8px 15px;margin:0 0 20px;list-style:none;background-color:#f5f5f5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.breadcrumb>li{display:inline-block;*display:inline;text-shadow:0 1px 0 #fff;*zoom:1}.breadcrumb>li>.divider{padding:0 5px;color:#ccc}.breadcrumb>.active{color:#999}.pagination{margin:20px 0}.pagination ul{display:inline-block;*display:inline;margin-bottom:0;margin-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;*zoom:1;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.pagination ul>li{display:inline}.pagination ul>li>a,.pagination ul>li>span{float:left;padding:4px 12px;line-height:20px;text-decoration:none;background-color:#fff;border:1px solid #ddd;border-left-width:0}.pagination ul>li>a:hover,.pagination ul>.active>a,.pagination ul>.active>span{background-color:#f5f5f5}.pagination ul>.active>a,.pagination ul>.active>span{color:#999;cursor:default}.pagination ul>.disabled>span,.pagination ul>.disabled>a,.pagination ul>.disabled>a:hover{color:#999;cursor:default;background-color:transparent}.pagination ul>li:first-child>a,.pagination ul>li:first-child>span{border-left-width:1px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.pagination ul>li:last-child>a,.pagination ul>li:last-child>span{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.pagination-centered{text-align:center}.pagination-right{text-align:right}.pagination-large ul>li>a,.pagination-large ul>li>span{padding:11px 19px;font-size:17.5px}.pagination-large ul>li:first-child>a,.pagination-large ul>li:first-child>span{-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.pagination-large ul>li:last-child>a,.pagination-large ul>li:last-child>span{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.pagination-mini ul>li:first-child>a,.pagination-small ul>li:first-child>a,.pagination-mini ul>li:first-child>span,.pagination-small ul>li:first-child>span{-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px;-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-moz-border-radius-bottomleft:3px;-moz-border-radius-topleft:3px}.pagination-mini ul>li:last-child>a,.pagination-small ul>li:last-child>a,.pagination-mini ul>li:last-child>span,.pagination-small ul>li:last-child>span{-webkit-border-top-right-radius:3px;border-top-right-radius:3px;-webkit-border-bottom-right-radius:3px;border-bottom-right-radius:3px;-moz-border-radius-topright:3px;-moz-border-radius-bottomright:3px}.pagination-small ul>li>a,.pagination-small ul>li>span{padding:2px 10px;font-size:11.9px}.pagination-mini ul>li>a,.pagination-mini ul>li>span{padding:0 6px;font-size:10.5px}.pager{margin:20px 0;text-align:center;list-style:none;*zoom:1}.pager:before,.pager:after{display:table;line-height:0;content:""}.pager:after{clear:both}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.pager li>a:hover{text-decoration:none;background-color:#f5f5f5}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>span{color:#999;cursor:default;background-color:#fff}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop,.modal-backdrop.fade.in{opacity:.8;filter:alpha(opacity=80)}.modal{position:fixed;top:10%;left:50%;z-index:1050;width:560px;margin-left:-280px;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;outline:0;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.3);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.3);box-shadow:0 3px 7px rgba(0,0,0,0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box}.modal.fade{top:-25%;-webkit-transition:opacity .3s linear,top .3s ease-out;-moz-transition:opacity .3s linear,top .3s ease-out;-o-transition:opacity .3s linear,top .3s ease-out;transition:opacity .3s linear,top .3s ease-out}.modal.fade.in{top:10%}.modal-header{padding:9px 15px;border-bottom:1px solid #eee}.modal-header .close{margin-top:2px}.modal-header h3{margin:0;line-height:30px}.modal-body{position:relative;max-height:400px;padding:15px;overflow-y:auto}.modal-form{margin-bottom:0}.modal-footer{padding:14px 15px 15px;margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;*zoom:1;-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.modal-footer:before,.modal-footer:after{display:table;line-height:0;content:""}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.tooltip{position:absolute;z-index:1030;display:block;padding:5px;font-size:11px;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.8;filter:alpha(opacity=80)}.tooltip.top{margin-top:-3px}.tooltip.right{margin-left:3px}.tooltip.bottom{margin-top:3px}.tooltip.left{margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;border-width:0 5px 5px}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;width:236px;padding:1px;text-align:left;white-space:normal;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover .arrow{border-width:11px}.popover .arrow:after{border-width:10px;content:""}.popover.top .arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);border-bottom-width:0}.popover.top .arrow:after{bottom:1px;margin-left:-10px;border-top-color:#fff;border-bottom-width:0}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,0.25);border-left-width:0}.popover.right .arrow:after{bottom:-10px;left:1px;border-right-color:#fff;border-left-width:0}.popover.bottom .arrow{top:-11px;left:50%;margin-left:-11px;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);border-top-width:0}.popover.bottom .arrow:after{top:1px;margin-left:-10px;border-bottom-color:#fff;border-top-width:0}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-left-color:#999;border-left-color:rgba(0,0,0,0.25);border-right-width:0}.popover.left .arrow:after{right:1px;bottom:-10px;border-left-color:#fff;border-right-width:0}.thumbnails{margin-left:-20px;list-style:none;*zoom:1}.thumbnails:before,.thumbnails:after{display:table;line-height:0;content:""}.thumbnails:after{clear:both}.row-fluid .thumbnails{margin-left:0}.thumbnails>li{float:left;margin-bottom:20px;margin-left:20px}.thumbnail{display:block;padding:4px;line-height:20px;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.055);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.055);box-shadow:0 1px 3px rgba(0,0,0,0.055);-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}a.thumbnail:hover{border-color:#08c;-webkit-box-shadow:0 1px 4px rgba(0,105,214,0.25);-moz-box-shadow:0 1px 4px rgba(0,105,214,0.25);box-shadow:0 1px 4px rgba(0,105,214,0.25)}.thumbnail>img{display:block;max-width:100%;margin-right:auto;margin-left:auto}.thumbnail .caption{padding:9px;color:#555}.media,.media-body{overflow:hidden;*overflow:visible;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media .pull-left{margin-right:10px}.media .pull-right{margin-left:10px}.media-list{margin-left:0;list-style:none}.label,.badge{display:inline-block;padding:2px 4px;font-size:11.844px;font-weight:bold;line-height:14px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);white-space:nowrap;vertical-align:baseline;background-color:#999}.label{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.badge{padding-right:9px;padding-left:9px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px}.label:empty,.badge:empty{display:none}a.label:hover,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.label-important,.badge-important{background-color:#b94a48}.label-important[href],.badge-important[href]{background-color:#953b39}.label-warning,.badge-warning{background-color:#f89406}.label-warning[href],.badge-warning[href]{background-color:#c67605}.label-success,.badge-success{background-color:#468847}.label-success[href],.badge-success[href]{background-color:#356635}.label-info,.badge-info{background-color:#3a87ad}.label-info[href],.badge-info[href]{background-color:#2d6987}.label-inverse,.badge-inverse{background-color:#333}.label-inverse[href],.badge-inverse[href]{background-color:#1a1a1a}.btn .label,.btn .badge{position:relative;top:-1px}.btn-mini .label,.btn-mini .badge{top:0}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-ms-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0}to{background-position:40px 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f7f7f7;background-image:-moz-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f5f5f5),to(#f9f9f9));background-image:-webkit-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-o-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:linear-gradient(to bottom,#f5f5f5,#f9f9f9);background-repeat:repeat-x;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#fff9f9f9',GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress .bar{float:left;width:0;height:100%;font-size:12px;color:#fff;text-align:center;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e90d2;background-image:-moz-linear-gradient(top,#149bdf,#0480be);background-image:-webkit-gradient(linear,0 0,0 100%,from(#149bdf),to(#0480be));background-image:-webkit-linear-gradient(top,#149bdf,#0480be);background-image:-o-linear-gradient(top,#149bdf,#0480be);background-image:linear-gradient(to bottom,#149bdf,#0480be);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf',endColorstr='#ff0480be',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width .6s ease;-moz-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress .bar+.bar{-webkit-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15)}.progress-striped .bar{background-color:#149bdf;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px}.progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-danger .bar,.progress .bar-danger{background-color:#dd514c;background-image:-moz-linear-gradient(top,#ee5f5b,#c43c35);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#c43c35));background-image:-webkit-linear-gradient(top,#ee5f5b,#c43c35);background-image:-o-linear-gradient(top,#ee5f5b,#c43c35);background-image:linear-gradient(to bottom,#ee5f5b,#c43c35);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffc43c35',GradientType=0)}.progress-danger.progress-striped .bar,.progress-striped .bar-danger{background-color:#ee5f5b;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-success .bar,.progress .bar-success{background-color:#5eb95e;background-image:-moz-linear-gradient(top,#62c462,#57a957);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#57a957));background-image:-webkit-linear-gradient(top,#62c462,#57a957);background-image:-o-linear-gradient(top,#62c462,#57a957);background-image:linear-gradient(to bottom,#62c462,#57a957);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff57a957',GradientType=0)}.progress-success.progress-striped .bar,.progress-striped .bar-success{background-color:#62c462;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-info .bar,.progress .bar-info{background-color:#4bb1cf;background-image:-moz-linear-gradient(top,#5bc0de,#339bb9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#339bb9));background-image:-webkit-linear-gradient(top,#5bc0de,#339bb9);background-image:-o-linear-gradient(top,#5bc0de,#339bb9);background-image:linear-gradient(to bottom,#5bc0de,#339bb9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff339bb9',GradientType=0)}.progress-info.progress-striped .bar,.progress-striped .bar-info{background-color:#5bc0de;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-warning .bar,.progress .bar-warning{background-color:#faa732;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0)}.progress-warning.progress-striped .bar,.progress-striped .bar-warning{background-color:#fbb450;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.accordion{margin-bottom:20px}.accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.accordion-heading{border-bottom:0}.accordion-heading .accordion-toggle{display:block;padding:8px 15px}.accordion-toggle{cursor:pointer}.accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5}.carousel{position:relative;margin-bottom:20px;line-height:1}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-moz-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img{display:block;line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#fff;text-align:center;background:#222;border:3px solid #fff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:.5;filter:alpha(opacity=50)}.carousel-control.right{right:15px;left:auto}.carousel-control:hover{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-caption{position:absolute;right:0;bottom:0;left:0;padding:15px;background:#333;background:rgba(0,0,0,0.75)}.carousel-caption h4,.carousel-caption p{line-height:20px;color:#fff}.carousel-caption h4{margin:0 0 5px}.carousel-caption p{margin-bottom:0}.hero-unit{padding:60px;margin-bottom:30px;font-size:18px;font-weight:200;line-height:30px;color:inherit;background-color:#eee;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;letter-spacing:-1px;color:inherit}.hero-unit li{line-height:30px}.pull-right{float:right}.pull-left{float:left}.hide{display:none}.show{display:block}.invisible{visibility:hidden}.affix{position:fixed}
diff --git a/servers/admin/public/stylesheets/vendors/darkstrap.css b/servers/admin/public/stylesheets/vendors/darkstrap.css
deleted file mode 100644
index 41b87a4..0000000
--- a/servers/admin/public/stylesheets/vendors/darkstrap.css
+++ /dev/null
@@ -1,430 +0,0 @@
-/* line 31, ../sass/darkstrap.scss */
-.well, .breadcrumb, input,
-input[type="file"],
-select,
-textarea, .progress, code, pre {
-  -moz-box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0, rgba(0, 0, 0, 0.8) 0 1px 7px 0px inset;
-  -webkit-box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0, rgba(0, 0, 0, 0.8) 0 1px 7px 0px inset;
-  -o-box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0, rgba(0, 0, 0, 0.8) 0 1px 7px 0px inset;
-  box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0, rgba(0, 0, 0, 0.8) 0 1px 7px 0px inset;
-  background: #202020;
-  background-color: rgba(0, 0, 0, 0.3);
-}
-
-/* line 33, ../sass/darkstrap.scss */
-body {
-  background: #2f2f2f;
-  color: #c6c6c6;
-}
-
-/* line 39, ../sass/darkstrap.scss */
-.breadcrumb {
-  border: 0;
-}
-/* line 42, ../sass/darkstrap.scss */
-.breadcrumb li {
-  text-shadow: 0 1px 0 #000;
-}
-
-/* line 48, ../sass/darkstrap.scss */
-.page-header {
-  -moz-box-shadow: rgba(255, 255, 255, 0.07) 0 1px 0;
-  -webkit-box-shadow: rgba(255, 255, 255, 0.07) 0 1px 0;
-  -o-box-shadow: rgba(255, 255, 255, 0.07) 0 1px 0;
-  box-shadow: rgba(255, 255, 255, 0.07) 0 1px 0;
-  border-bottom: 1px solid #121212;
-}
-
-/* line 49, ../sass/darkstrap.scss */
-h1, h2, h3, h4, h5, h6 {
-  color: white;
-}
-
-/* line 50, ../sass/darkstrap.scss */
-h6 {
-  color: #999;
-}
-
-/* line 57, ../sass/darkstrap.scss */
-.nav-tabs .open .dropdown-toggle,
-.nav-pills .open .dropdown-toggle,
-.nav > .open.active > a:hover {
-  background-color: #222222;
-  border-color: #2f2f2f #2f2f2f transparent #2f2f2f;
-}
-
-/* line 61, ../sass/darkstrap.scss */
-.nav > .dropdown.active > a:hover {
-  color: #fff;
-}
-
-/* line 65, ../sass/darkstrap.scss */
-.nav-tabs .active .dropdown-toggle .caret,
-.nav-pills .active .dropdown-toggle .caret {
-  border-top-color: #fff;
-}
-
-/* line 68, ../sass/darkstrap.scss */
-.nav-tabs {
-  border-bottom: 1px solid #666;
-}
-/* line 71, ../sass/darkstrap.scss */
-.nav-tabs > .active > a, .nav-tabs > .active > a:hover {
-  background-color: #2f2f2f;
-  color: #fff;
-  border-color: #666 #666 transparent #666;
-}
-/* line 76, ../sass/darkstrap.scss */
-.nav-tabs > li > a:hover {
-  border-color: #2f2f2f #2f2f2f #666666 #2f2f2f;
-  background-color: #222222;
-  color: #00aaff;
-}
-/* line 83, ../sass/darkstrap.scss */
-.nav-tabs.nav-stacked > li > a, .nav-tabs.nav-stacked > li > a:hover {
-  border-color: #666;
-}
-
-/* line 89, ../sass/darkstrap.scss */
-.nav-pills > li > a:hover {
-  background-color: #222222;
-  color: #00aaff;
-}
-
-/* line 95, ../sass/darkstrap.scss */
-.nav-list > li > a,
-.nav-list .nav-header {
-  text-shadow: 0 1px 0 #000;
-}
-
-/* line 98, ../sass/darkstrap.scss */
-.nav-list > li > a:hover {
-  background-color: #161616;
-  color: #00aaff;
-}
-
-/* line 103, ../sass/darkstrap.scss */
-.nav-list .active > a:hover {
-  background-color: #0088cc;
-  color: white;
-}
-
-/* line 109, ../sass/darkstrap.scss */
-.tabs-below .nav-tabs {
-  border-top: 1px solid #666;
-}
-
-/* line 110, ../sass/darkstrap.scss */
-.tabs-left .nav-tabs {
-  border-right: 1px solid #666;
-}
-
-/* line 111, ../sass/darkstrap.scss */
-.tabs-right .nav-tabs {
-  border-left: 1px solid #666;
-}
-
-/* line 113, ../sass/darkstrap.scss */
-.tabs-below .nav-tabs > li > a:hover {
-  border-top: 1px solid #666;
-}
-
-/* line 116, ../sass/darkstrap.scss */
-.tabs-left .nav-tabs > li > a:hover {
-  border-color: transparent #666 transparent transparent;
-}
-
-/* line 119, ../sass/darkstrap.scss */
-.tabs-right .nav-tabs > li > a:hover {
-  border-color: transparent transparent transparent #666;
-}
-
-/* line 124, ../sass/darkstrap.scss */
-.tabs-below .nav-tabs .active > a,
-.tabs-below .nav-tabs .active > a:hover {
-  border-color: transparent #666 #666 #666;
-}
-
-/* line 128, ../sass/darkstrap.scss */
-.tabs-left .nav-tabs .active > a,
-.tabs-left .nav-tabs .active > a:hover {
-  border-color: #666 transparent #666 #666;
-}
-
-/* line 132, ../sass/darkstrap.scss */
-.tabs-right .nav-tabs .active > a,
-.tabs-right .nav-tabs .active > a:hover {
-  border-color: #666 #666 #666 transparent;
-}
-
-/* line 2, ../sass/mixins.scss */
-:-moz-placeholder {
-  color: #666666;
-}
-
-/* line 5, ../sass/mixins.scss */
-::-webkit-input-placeholder {
-  color: #666666;
-}
-
-/* line 140, ../sass/darkstrap.scss */
-.input-prepend .add-on,
-.input-append .add-on {
-  background: #444;
-  color: #c6c6c6;
-  border-color: #111;
-  text-shadow: 0 1px 0  black;
-}
-
-/* line 147, ../sass/darkstrap.scss */
-label {
-  color: #c6c6c6;
-}
-
-/* line 154, ../sass/darkstrap.scss */
-input,
-input[type="file"],
-select,
-textarea {
-  color: white;
-  border-color: #111111;
-}
-
-/* line 160, ../sass/darkstrap.scss */
-.search-query {
-  -webkit-box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0, rgba(0, 0, 0, 0) 0 1px 7px 0px inset;
-}
-
-/* line 163, ../sass/darkstrap.scss */
-legend {
-  color: white;
-  -moz-box-shadow: rgba(255, 255, 255, 0.07) 0 1px 0;
-  -webkit-box-shadow: rgba(255, 255, 255, 0.07) 0 1px 0;
-  -o-box-shadow: rgba(255, 255, 255, 0.07) 0 1px 0;
-  box-shadow: rgba(255, 255, 255, 0.07) 0 1px 0;
-  border-bottom: 1px solid #121212;
-}
-
-/* line 167, ../sass/darkstrap.scss */
-.form-actions {
-  border-top-color: #222;
-  background-color: #444;
-}
-
-/* line 172, ../sass/darkstrap.scss */
-.help-inline {
-  color: #999;
-}
-
-/* line 12, ../sass/mixins.scss */
-.control-group.warning > label,
-.control-group.warning .help-block,
-.control-group.warning .help-inline {
-  color: #faa732;
-}
-/* line 13, ../sass/mixins.scss */
-.control-group.warning input, .control-group.warning select, .control-group.warning textarea {
-  color: #faa732;
-  border-color: #faa732;
-}
-/* line 20, ../sass/mixins.scss */
-.control-group.warning input:focus,
-.control-group.warning select:focus,
-.control-group.warning textarea:focus {
-  border-color: #faa732;
-  -moz-box-shadow: 0 0 6px #faa732;
-  -webkit-box-shadow: 0 0 6px #faa732;
-  -o-box-shadow: 0 0 6px #faa732;
-  box-shadow: 0 0 6px #faa732;
-}
-/* line 12, ../sass/mixins.scss */
-.control-group.success > label, .control-group.success .help-block, .control-group.success .help-inline {
-  color: #5bb75b;
-}
-/* line 13, ../sass/mixins.scss */
-.control-group.success input, .control-group.success select, .control-group.success textarea {
-  color: #5bb75b;
-  border-color: #5bb75b;
-}
-/* line 20, ../sass/mixins.scss */
-.control-group.success input:focus, .control-group.success select:focus, .control-group.success textarea:focus {
-  border-color: #5bb75b;
-  -moz-box-shadow: 0 0 6px #5bb75b;
-  -webkit-box-shadow: 0 0 6px #5bb75b;
-  -o-box-shadow: 0 0 6px #5bb75b;
-  box-shadow: 0 0 6px #5bb75b;
-}
-/* line 12, ../sass/mixins.scss */
-.control-group.error > label, .control-group.error .help-block, .control-group.error .help-inline {
-  color: #fc5b5e;
-}
-/* line 13, ../sass/mixins.scss */
-.control-group.error input, .control-group.error select, .control-group.error textarea {
-  color: #fc5b5e;
-  border-color: #fc5b5e;
-}
-/* line 20, ../sass/mixins.scss */
-.control-group.error input:focus, .control-group.error select:focus, .control-group.error textarea:focus {
-  border-color: #fc5b5e;
-  -moz-box-shadow: 0 0 6px #fc5b5e;
-  -webkit-box-shadow: 0 0 6px #fc5b5e;
-  -o-box-shadow: 0 0 6px #fc5b5e;
-  box-shadow: 0 0 6px #fc5b5e;
-}
-
-/* line 182, ../sass/darkstrap.scss */
-.table thead {
-  color: white;
-}
-/* line 185, ../sass/darkstrap.scss */
-.table td {
-  border-top-color: #666;
-}
-
-/* line 191, ../sass/darkstrap.scss */
-.table-striped tbody tr:nth-child(2n+1) td, .table-striped tbody tr:nth-child(2n+1) th {
-  background-color: #444;
-}
-
-/* line 197, ../sass/darkstrap.scss */
-.table-bordered {
-  border: 1px solid #666;
-}
-/* line 202, ../sass/darkstrap.scss */
-.table-bordered th + th,
-.table-bordered td + td,
-.table-bordered th + td,
-.table-bordered td + th {
-  border-left: 1px solid #666;
-}
-
-/* line 208, ../sass/darkstrap.scss */
-.pagination a:hover {
-  color: #00aaff;
-  background-color: #222222;
-}
-
-/* line 212, ../sass/darkstrap.scss */
-.pagination .active a {
-  color: #fff;
-  background-color: #222222;
-}
-
-/* line 216, ../sass/darkstrap.scss */
-.pagination a {
-  border-color: #666;
-}
-
-/* line 219, ../sass/darkstrap.scss */
-.pager a {
-  background-color: #2f2f2f;
-  border-color: #666;
-}
-/* line 222, ../sass/darkstrap.scss */
-.pager a:hover {
-  background-color: #222222;
-  color: #00aaff;
-}
-
-/* line 238, ../sass/darkstrap.scss */
-.alert {
-  color: #fff;
-  background-color: #faa732;
-  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
-  border-color: #a86404;
-}
-/* line 234, ../sass/darkstrap.scss */
-.alert h4 {
-  color: #c17305;
-}
-
-/* line 239, ../sass/darkstrap.scss */
-.alert-success {
-  color: #fff;
-  background-color: #5bb75b;
-  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
-  border-color: #2d662d;
-}
-/* line 234, ../sass/darkstrap.scss */
-.alert-success h4 {
-  color: #347834;
-}
-
-/* line 240, ../sass/darkstrap.scss */
-.alert-error {
-  color: #fff;
-  background-color: #fc5b5e;
-  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
-  border-color: #d40408;
-}
-/* line 234, ../sass/darkstrap.scss */
-.alert-error h4 {
-  color: #ed0409;
-}
-
-/* line 241, ../sass/darkstrap.scss */
-.alert-info {
-  color: #fff;
-  background-color: #3a87ad;
-  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
-  border-color: #1a3c4e;
-}
-/* line 234, ../sass/darkstrap.scss */
-.alert-info h4 {
-  color: #204b61;
-}
-
-/* line 245, ../sass/darkstrap.scss */
-.modal {
-  background-color: #444;
-}
-
-/* line 248, ../sass/darkstrap.scss */
-.modal-header {
-  border-bottom: 1px solid #222;
-}
-
-/* line 251, ../sass/darkstrap.scss */
-.modal-body p {
-  color: #c6c6c6;
-}
-
-/* line 254, ../sass/darkstrap.scss */
-.modal-footer {
-  background-color: #373737;
-  border-top: 1px solid #222;
-  -moz-box-shadow: 0 1px 0 #333333 inset;
-  -webkit-box-shadow: 0 1px 0 #333333 inset;
-  -o-box-shadow: 0 1px 0 #333333 inset;
-  box-shadow: 0 1px 0 #333333 inset;
-}
-
-/* line 266, ../sass/darkstrap.scss */
-blockquote {
-  border-left-color: #111;
-}
-/* line 268, ../sass/darkstrap.scss */
-blockquote.pull-right {
-  border-right-color: #111;
-}
-
-/* line 271, ../sass/darkstrap.scss */
-hr {
-  -moz-box-shadow: rgba(255, 255, 255, 0.07) 0 1px 0;
-  -webkit-box-shadow: rgba(255, 255, 255, 0.07) 0 1px 0;
-  -o-box-shadow: rgba(255, 255, 255, 0.07) 0 1px 0;
-  box-shadow: rgba(255, 255, 255, 0.07) 0 1px 0;
-  border-bottom: 1px solid #121212;
-  border-top: none;
-}
-
-/* line 277, ../sass/darkstrap.scss */
-code {
-  border: none;
-}
-
-/* line 281, ../sass/darkstrap.scss */
-pre {
-  border: none;
-  color: #c6c6c6;
-}
diff --git a/servers/admin/public/stylesheets/vendors/images/ui-bg_flat_30_cccccc_40x100.png b/servers/admin/public/stylesheets/vendors/images/ui-bg_flat_30_cccccc_40x100.png
deleted file mode 100755
index 5473aff..0000000
--- a/servers/admin/public/stylesheets/vendors/images/ui-bg_flat_30_cccccc_40x100.png
+++ /dev/null
Binary files differ
diff --git a/servers/admin/public/stylesheets/vendors/images/ui-bg_flat_50_5c5c5c_40x100.png b/servers/admin/public/stylesheets/vendors/images/ui-bg_flat_50_5c5c5c_40x100.png
deleted file mode 100755
index 5950a8d..0000000
--- a/servers/admin/public/stylesheets/vendors/images/ui-bg_flat_50_5c5c5c_40x100.png
+++ /dev/null
Binary files differ
diff --git a/servers/admin/public/stylesheets/vendors/images/ui-bg_glass_20_555555_1x400.png b/servers/admin/public/stylesheets/vendors/images/ui-bg_glass_20_555555_1x400.png
deleted file mode 100755
index 1ad224a..0000000
--- a/servers/admin/public/stylesheets/vendors/images/ui-bg_glass_20_555555_1x400.png
+++ /dev/null
Binary files differ
diff --git a/servers/admin/public/stylesheets/vendors/images/ui-bg_glass_40_0078a3_1x400.png b/servers/admin/public/stylesheets/vendors/images/ui-bg_glass_40_0078a3_1x400.png
deleted file mode 100755
index 1cf1cac..0000000
--- a/servers/admin/public/stylesheets/vendors/images/ui-bg_glass_40_0078a3_1x400.png
+++ /dev/null
Binary files differ
diff --git a/servers/admin/public/stylesheets/vendors/images/ui-bg_glass_40_ffc73d_1x400.png b/servers/admin/public/stylesheets/vendors/images/ui-bg_glass_40_ffc73d_1x400.png
deleted file mode 100755
index 35ec0d9..0000000
--- a/servers/admin/public/stylesheets/vendors/images/ui-bg_glass_40_ffc73d_1x400.png
+++ /dev/null
Binary files differ
diff --git a/servers/admin/public/stylesheets/vendors/images/ui-bg_gloss-wave_25_333333_500x100.png b/servers/admin/public/stylesheets/vendors/images/ui-bg_gloss-wave_25_333333_500x100.png
deleted file mode 100755
index b1b03b6..0000000
--- a/servers/admin/public/stylesheets/vendors/images/ui-bg_gloss-wave_25_333333_500x100.png
+++ /dev/null
Binary files differ
diff --git a/servers/admin/public/stylesheets/vendors/images/ui-bg_highlight-soft_80_eeeeee_1x100.png b/servers/admin/public/stylesheets/vendors/images/ui-bg_highlight-soft_80_eeeeee_1x100.png
deleted file mode 100755
index e56eefd..0000000
--- a/servers/admin/public/stylesheets/vendors/images/ui-bg_highlight-soft_80_eeeeee_1x100.png
+++ /dev/null
Binary files differ
diff --git a/servers/admin/public/stylesheets/vendors/images/ui-bg_inset-soft_25_000000_1x100.png b/servers/admin/public/stylesheets/vendors/images/ui-bg_inset-soft_25_000000_1x100.png
deleted file mode 100755
index 3525eb9..0000000
--- a/servers/admin/public/stylesheets/vendors/images/ui-bg_inset-soft_25_000000_1x100.png
+++ /dev/null
Binary files differ
diff --git a/servers/admin/public/stylesheets/vendors/images/ui-bg_inset-soft_30_2d7be6_1x100.png b/servers/admin/public/stylesheets/vendors/images/ui-bg_inset-soft_30_2d7be6_1x100.png
deleted file mode 100755
index d12f70e..0000000
--- a/servers/admin/public/stylesheets/vendors/images/ui-bg_inset-soft_30_2d7be6_1x100.png
+++ /dev/null
Binary files differ
diff --git a/servers/admin/public/stylesheets/vendors/images/ui-icons_222222_256x240.png b/servers/admin/public/stylesheets/vendors/images/ui-icons_222222_256x240.png
deleted file mode 100755
index b273ff1..0000000
--- a/servers/admin/public/stylesheets/vendors/images/ui-icons_222222_256x240.png
+++ /dev/null
Binary files differ
diff --git a/servers/admin/public/stylesheets/vendors/images/ui-icons_4b8e0b_256x240.png b/servers/admin/public/stylesheets/vendors/images/ui-icons_4b8e0b_256x240.png
deleted file mode 100755
index 3bdb67b..0000000
--- a/servers/admin/public/stylesheets/vendors/images/ui-icons_4b8e0b_256x240.png
+++ /dev/null
Binary files differ
diff --git a/servers/admin/public/stylesheets/vendors/images/ui-icons_a83300_256x240.png b/servers/admin/public/stylesheets/vendors/images/ui-icons_a83300_256x240.png
deleted file mode 100755
index 95993ea..0000000
--- a/servers/admin/public/stylesheets/vendors/images/ui-icons_a83300_256x240.png
+++ /dev/null
Binary files differ
diff --git a/servers/admin/public/stylesheets/vendors/images/ui-icons_cccccc_256x240.png b/servers/admin/public/stylesheets/vendors/images/ui-icons_cccccc_256x240.png
deleted file mode 100755
index 9254e05..0000000
--- a/servers/admin/public/stylesheets/vendors/images/ui-icons_cccccc_256x240.png
+++ /dev/null
Binary files differ
diff --git a/servers/admin/public/stylesheets/vendors/images/ui-icons_ffffff_256x240.png b/servers/admin/public/stylesheets/vendors/images/ui-icons_ffffff_256x240.png
deleted file mode 100755
index 42f8f99..0000000
--- a/servers/admin/public/stylesheets/vendors/images/ui-icons_ffffff_256x240.png
+++ /dev/null
Binary files differ
diff --git a/servers/admin/public/stylesheets/vendors/jquery-ui-1.9.2.custom.css b/servers/admin/public/stylesheets/vendors/jquery-ui-1.9.2.custom.css
deleted file mode 100755
index 243b394..0000000
--- a/servers/admin/public/stylesheets/vendors/jquery-ui-1.9.2.custom.css
+++ /dev/null
@@ -1,462 +0,0 @@
-/*! jQuery UI - v1.9.2 - 2013-01-03
-* http://jqueryui.com
-* Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css
-* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Segoe%20UI%2CArial%2Csans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=6px&bgColorHeader=333333&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=25&borderColorHeader=333333&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=000000&bgTextureContent=05_inset_soft.png&bgImgOpacityContent=25&borderColorContent=666666&fcContent=ffffff&iconColorContent=cccccc&bgColorDefault=555555&bgTextureDefault=02_glass.png&bgImgOpacityDefault=20&borderColorDefault=666666&fcDefault=eeeeee&iconColorDefault=cccccc&bgColorHover=0078a3&bgTextureHover=02_glass.png&bgImgOpacityHover=40&borderColorHover=59b4d4&fcHover=ffffff&iconColorHover=ffffff&bgColorActive=2d7be6&bgTextureActive=05_inset_soft.png&bgImgOpacityActive=30&borderColorActive=0f58ff&fcActive=ffffff&iconColorActive=222222&bgColorHighlight=eeeeee&bgTextureHighlight=03_highlight_soft.png&bgImgOpacityHighlight=80&borderColorHighlight=cccccc&fcHighlight=2e7db2&iconColorHighlight=4b8e0b&bgColorError=ffc73d&bgTextureError=02_glass.png&bgImgOpacityError=40&borderColorError=ffb73d&fcError=111111&iconColorError=a83300&bgColorOverlay=5c5c5c&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=50&opacityOverlay=80&bgColorShadow=cccccc&bgTextureShadow=01_flat.png&bgImgOpacityShadow=30&opacityShadow=60&thicknessShadow=7px&offsetTopShadow=-7px&offsetLeftShadow=-7px&cornerRadiusShadow=8px
-* Copyright (c) 2013 jQuery Foundation and other contributors Licensed MIT */
-
-/* Layout helpers
-----------------------------------*/
-.ui-helper-hidden { display: none; }
-.ui-helper-hidden-accessible { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; }
-.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
-.ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; }
-.ui-helper-clearfix:after { clear: both; }
-.ui-helper-clearfix { zoom: 1; }
-.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
-
-
-/* Interaction Cues
-----------------------------------*/
-.ui-state-disabled { cursor: default !important; }
-
-
-/* Icons
-----------------------------------*/
-
-/* states and images */
-.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
-
-
-/* Misc visuals
-----------------------------------*/
-
-/* Overlays */
-.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
-.ui-resizable { position: relative;}
-.ui-resizable-handle { position: absolute;font-size: 0.1px; display: block; }
-.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
-.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
-.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
-.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
-.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
-.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
-.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
-.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
-.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
-.ui-accordion .ui-accordion-header { display: block; cursor: pointer; position: relative; margin-top: 2px; padding: .5em .5em .5em .7em; zoom: 1; }
-.ui-accordion .ui-accordion-icons { padding-left: 2.2em; }
-.ui-accordion .ui-accordion-noicons { padding-left: .7em; }
-.ui-accordion .ui-accordion-icons .ui-accordion-icons { padding-left: 2.2em; }
-.ui-accordion .ui-accordion-header .ui-accordion-header-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
-.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; overflow: auto; zoom: 1; }
-.ui-autocomplete {
-	position: absolute;
-	top: 0;
-	left: 0;
-	cursor: default;
-}
-
-/* workarounds */
-* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
-.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
-.ui-button, .ui-button:link, .ui-button:visited, .ui-button:hover, .ui-button:active { text-decoration: none; }
-.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
-button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
-.ui-button-icons-only { width: 3.4em; } 
-button.ui-button-icons-only { width: 3.7em; } 
-
-/*button text element */
-.ui-button .ui-button-text { display: block; line-height: 1.4;  }
-.ui-button-text-only .ui-button-text { padding: .4em 1em; }
-.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
-.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
-.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
-.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
-/* no icon support for input elements, provide padding by default */
-input.ui-button { padding: .4em 1em; }
-
-/*button icon element(s) */
-.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
-.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
-.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
-.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
-.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
-
-/*button sets*/
-.ui-buttonset { margin-right: 7px; }
-.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
-
-/* workarounds */
-button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
-.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
-.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
-.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
-.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
-.ui-datepicker .ui-datepicker-prev { left:2px; }
-.ui-datepicker .ui-datepicker-next { right:2px; }
-.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
-.ui-datepicker .ui-datepicker-next-hover { right:1px; }
-.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px;  }
-.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
-.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
-.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
-.ui-datepicker select.ui-datepicker-month, 
-.ui-datepicker select.ui-datepicker-year { width: 49%;}
-.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
-.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0;  }
-.ui-datepicker td { border: 0; padding: 1px; }
-.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
-.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
-.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
-.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
-
-/* with multiple calendars */
-.ui-datepicker.ui-datepicker-multi { width:auto; }
-.ui-datepicker-multi .ui-datepicker-group { float:left; }
-.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
-.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
-.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
-.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
-.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
-.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
-.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
-.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
-
-/* RTL support */
-.ui-datepicker-rtl { direction: rtl; }
-.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
-.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
-.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
-.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
-.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
-.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
-.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
-.ui-datepicker-rtl .ui-datepicker-group { float:right; }
-.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
-.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
-
-/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
-.ui-datepicker-cover {
-    position: absolute; /*must have*/
-    z-index: -1; /*must have*/
-    filter: mask(); /*must have*/
-    top: -4px; /*must have*/
-    left: -4px; /*must have*/
-    width: 200px; /*must have*/
-    height: 200px; /*must have*/
-}.ui-dialog { position: absolute; top: 0; left: 0; padding: .2em; width: 300px; overflow: hidden; }
-.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative;  }
-.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
-.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
-.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
-.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
-.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
-.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
-.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
-.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
-.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
-.ui-draggable .ui-dialog-titlebar { cursor: move; }
-.ui-menu { list-style:none; padding: 2px; margin: 0; display:block; outline: none; }
-.ui-menu .ui-menu { margin-top: -3px; position: absolute; }
-.ui-menu .ui-menu-item { margin: 0; padding: 0; zoom: 1; width: 100%; }
-.ui-menu .ui-menu-divider { margin: 5px -2px 5px -2px; height: 0; font-size: 0; line-height: 0; border-width: 1px 0 0 0; }
-.ui-menu .ui-menu-item a { text-decoration: none; display: block; padding: 2px .4em; line-height: 1.5; zoom: 1; font-weight: normal; }
-.ui-menu .ui-menu-item a.ui-state-focus,
-.ui-menu .ui-menu-item a.ui-state-active { font-weight: normal; margin: -1px; }
-
-.ui-menu .ui-state-disabled { font-weight: normal; margin: .4em 0 .2em; line-height: 1.5; }
-.ui-menu .ui-state-disabled a { cursor: default; }
-
-/* icon support */
-.ui-menu-icons { position: relative; }
-.ui-menu-icons .ui-menu-item a { position: relative; padding-left: 2em; }
-
-/* left-aligned */
-.ui-menu .ui-icon { position: absolute; top: .2em; left: .2em; }
-
-/* right-aligned */
-.ui-menu .ui-menu-icon { position: static; float: right; }
-.ui-progressbar { height:2em; text-align: left; overflow: hidden; }
-.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }.ui-slider { position: relative; text-align: left; }
-.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
-.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
-
-.ui-slider-horizontal { height: .8em; }
-.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
-.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
-.ui-slider-horizontal .ui-slider-range-min { left: 0; }
-.ui-slider-horizontal .ui-slider-range-max { right: 0; }
-
-.ui-slider-vertical { width: .8em; height: 100px; }
-.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
-.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
-.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
-.ui-slider-vertical .ui-slider-range-max { top: 0; }.ui-spinner { position:relative; display: inline-block; overflow: hidden; padding: 0; vertical-align: middle; }
-.ui-spinner-input { border: none; background: none; padding: 0; margin: .2em 0; vertical-align: middle; margin-left: .4em; margin-right: 22px; }
-.ui-spinner-button { width: 16px; height: 50%; font-size: .5em; padding: 0; margin: 0; text-align: center; position: absolute; cursor: default; display: block; overflow: hidden; right: 0; }
-.ui-spinner a.ui-spinner-button { border-top: none; border-bottom: none; border-right: none; } /* more specificity required here to overide default borders */
-.ui-spinner .ui-icon { position: absolute; margin-top: -8px; top: 50%; left: 0; } /* vertical centre icon */
-.ui-spinner-up { top: 0; }
-.ui-spinner-down { bottom: 0; }
-
-/* TR overrides */
-.ui-spinner .ui-icon-triangle-1-s {
-	/* need to fix icons sprite */
-	background-position:-65px -16px;
-}
-.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
-.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
-.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 0; margin: 1px .2em 0 0; border-bottom: 0; padding: 0; white-space: nowrap; }
-.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
-.ui-tabs .ui-tabs-nav li.ui-tabs-active { margin-bottom: -1px; padding-bottom: 1px; }
-.ui-tabs .ui-tabs-nav li.ui-tabs-active a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-tabs-loading a { cursor: text; }
-.ui-tabs .ui-tabs-nav li a, .ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
-.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
-.ui-tooltip {
-	padding: 8px;
-	position: absolute;
-	z-index: 9999;
-	max-width: 300px;
-	-webkit-box-shadow: 0 0 5px #aaa;
-	box-shadow: 0 0 5px #aaa;
-}
-/* Fades and background-images don't work well together in IE6, drop the image */
-* html .ui-tooltip {
-	background-image: none;
-}
-body .ui-tooltip { border-width: 2px; }
-
-/* Component containers
-----------------------------------*/
-.ui-widget { font-family: Segoe UI,Arial,sans-serif; font-size: 1.1em; }
-.ui-widget .ui-widget { font-size: 1em; }
-.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Segoe UI,Arial,sans-serif; font-size: 1em; }
-.ui-widget-content { border: 1px solid #666666; background: #000000 url(images/ui-bg_inset-soft_25_000000_1x100.png) 50% bottom repeat-x; color: #ffffff; }
-.ui-widget-content a { color: #ffffff; }
-.ui-widget-header { border: 1px solid #333333; background: #333333 url(images/ui-bg_gloss-wave_25_333333_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; }
-.ui-widget-header a { color: #ffffff; }
-
-/* Interaction states
-----------------------------------*/
-.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #666666; background: #555555 url(images/ui-bg_glass_20_555555_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #eeeeee; }
-.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #eeeeee; text-decoration: none; }
-.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #59b4d4; background: #0078a3 url(images/ui-bg_glass_40_0078a3_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #ffffff; }
-.ui-state-hover a, .ui-state-hover a:hover, .ui-state-hover a:link, .ui-state-hover a:visited { color: #ffffff; text-decoration: none; }
-.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #0f58ff; background: #2d7be6 url(images/ui-bg_inset-soft_30_2d7be6_1x100.png) 50% 50% repeat-x; font-weight: bold; color: #ffffff; }
-.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #ffffff; text-decoration: none; }
-
-/* Interaction Cues
-----------------------------------*/
-.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight  {border: 1px solid #cccccc; background: #eeeeee url(images/ui-bg_highlight-soft_80_eeeeee_1x100.png) 50% top repeat-x; color: #2e7db2; }
-.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #2e7db2; }
-.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #ffb73d; background: #ffc73d url(images/ui-bg_glass_40_ffc73d_1x400.png) 50% 50% repeat-x; color: #111111; }
-.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #111111; }
-.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #111111; }
-.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
-.ui-priority-secondary, .ui-widget-content .ui-priority-secondary,  .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
-.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
-.ui-state-disabled .ui-icon { filter:Alpha(Opacity=35); } /* For IE8 - See #6059 */
-
-/* Icons
-----------------------------------*/
-
-/* states and images */
-.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_cccccc_256x240.png); }
-.ui-widget-content .ui-icon {background-image: url(images/ui-icons_cccccc_256x240.png); }
-.ui-widget-header .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); }
-.ui-state-default .ui-icon { background-image: url(images/ui-icons_cccccc_256x240.png); }
-.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); }
-.ui-state-active .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
-.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_4b8e0b_256x240.png); }
-.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_a83300_256x240.png); }
-
-/* positioning */
-.ui-icon-carat-1-n { background-position: 0 0; }
-.ui-icon-carat-1-ne { background-position: -16px 0; }
-.ui-icon-carat-1-e { background-position: -32px 0; }
-.ui-icon-carat-1-se { background-position: -48px 0; }
-.ui-icon-carat-1-s { background-position: -64px 0; }
-.ui-icon-carat-1-sw { background-position: -80px 0; }
-.ui-icon-carat-1-w { background-position: -96px 0; }
-.ui-icon-carat-1-nw { background-position: -112px 0; }
-.ui-icon-carat-2-n-s { background-position: -128px 0; }
-.ui-icon-carat-2-e-w { background-position: -144px 0; }
-.ui-icon-triangle-1-n { background-position: 0 -16px; }
-.ui-icon-triangle-1-ne { background-position: -16px -16px; }
-.ui-icon-triangle-1-e { background-position: -32px -16px; }
-.ui-icon-triangle-1-se { background-position: -48px -16px; }
-.ui-icon-triangle-1-s { background-position: -64px -16px; }
-.ui-icon-triangle-1-sw { background-position: -80px -16px; }
-.ui-icon-triangle-1-w { background-position: -96px -16px; }
-.ui-icon-triangle-1-nw { background-position: -112px -16px; }
-.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
-.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
-.ui-icon-arrow-1-n { background-position: 0 -32px; }
-.ui-icon-arrow-1-ne { background-position: -16px -32px; }
-.ui-icon-arrow-1-e { background-position: -32px -32px; }
-.ui-icon-arrow-1-se { background-position: -48px -32px; }
-.ui-icon-arrow-1-s { background-position: -64px -32px; }
-.ui-icon-arrow-1-sw { background-position: -80px -32px; }
-.ui-icon-arrow-1-w { background-position: -96px -32px; }
-.ui-icon-arrow-1-nw { background-position: -112px -32px; }
-.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
-.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
-.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
-.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
-.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
-.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
-.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
-.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
-.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
-.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
-.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
-.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
-.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
-.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
-.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
-.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
-.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
-.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
-.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
-.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
-.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
-.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
-.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
-.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
-.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
-.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
-.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
-.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
-.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
-.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
-.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
-.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
-.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
-.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
-.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
-.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
-.ui-icon-arrow-4 { background-position: 0 -80px; }
-.ui-icon-arrow-4-diag { background-position: -16px -80px; }
-.ui-icon-extlink { background-position: -32px -80px; }
-.ui-icon-newwin { background-position: -48px -80px; }
-.ui-icon-refresh { background-position: -64px -80px; }
-.ui-icon-shuffle { background-position: -80px -80px; }
-.ui-icon-transfer-e-w { background-position: -96px -80px; }
-.ui-icon-transferthick-e-w { background-position: -112px -80px; }
-.ui-icon-folder-collapsed { background-position: 0 -96px; }
-.ui-icon-folder-open { background-position: -16px -96px; }
-.ui-icon-document { background-position: -32px -96px; }
-.ui-icon-document-b { background-position: -48px -96px; }
-.ui-icon-note { background-position: -64px -96px; }
-.ui-icon-mail-closed { background-position: -80px -96px; }
-.ui-icon-mail-open { background-position: -96px -96px; }
-.ui-icon-suitcase { background-position: -112px -96px; }
-.ui-icon-comment { background-position: -128px -96px; }
-.ui-icon-person { background-position: -144px -96px; }
-.ui-icon-print { background-position: -160px -96px; }
-.ui-icon-trash { background-position: -176px -96px; }
-.ui-icon-locked { background-position: -192px -96px; }
-.ui-icon-unlocked { background-position: -208px -96px; }
-.ui-icon-bookmark { background-position: -224px -96px; }
-.ui-icon-tag { background-position: -240px -96px; }
-.ui-icon-home { background-position: 0 -112px; }
-.ui-icon-flag { background-position: -16px -112px; }
-.ui-icon-calendar { background-position: -32px -112px; }
-.ui-icon-cart { background-position: -48px -112px; }
-.ui-icon-pencil { background-position: -64px -112px; }
-.ui-icon-clock { background-position: -80px -112px; }
-.ui-icon-disk { background-position: -96px -112px; }
-.ui-icon-calculator { background-position: -112px -112px; }
-.ui-icon-zoomin { background-position: -128px -112px; }
-.ui-icon-zoomout { background-position: -144px -112px; }
-.ui-icon-search { background-position: -160px -112px; }
-.ui-icon-wrench { background-position: -176px -112px; }
-.ui-icon-gear { background-position: -192px -112px; }
-.ui-icon-heart { background-position: -208px -112px; }
-.ui-icon-star { background-position: -224px -112px; }
-.ui-icon-link { background-position: -240px -112px; }
-.ui-icon-cancel { background-position: 0 -128px; }
-.ui-icon-plus { background-position: -16px -128px; }
-.ui-icon-plusthick { background-position: -32px -128px; }
-.ui-icon-minus { background-position: -48px -128px; }
-.ui-icon-minusthick { background-position: -64px -128px; }
-.ui-icon-close { background-position: -80px -128px; }
-.ui-icon-closethick { background-position: -96px -128px; }
-.ui-icon-key { background-position: -112px -128px; }
-.ui-icon-lightbulb { background-position: -128px -128px; }
-.ui-icon-scissors { background-position: -144px -128px; }
-.ui-icon-clipboard { background-position: -160px -128px; }
-.ui-icon-copy { background-position: -176px -128px; }
-.ui-icon-contact { background-position: -192px -128px; }
-.ui-icon-image { background-position: -208px -128px; }
-.ui-icon-video { background-position: -224px -128px; }
-.ui-icon-script { background-position: -240px -128px; }
-.ui-icon-alert { background-position: 0 -144px; }
-.ui-icon-info { background-position: -16px -144px; }
-.ui-icon-notice { background-position: -32px -144px; }
-.ui-icon-help { background-position: -48px -144px; }
-.ui-icon-check { background-position: -64px -144px; }
-.ui-icon-bullet { background-position: -80px -144px; }
-.ui-icon-radio-on { background-position: -96px -144px; }
-.ui-icon-radio-off { background-position: -112px -144px; }
-.ui-icon-pin-w { background-position: -128px -144px; }
-.ui-icon-pin-s { background-position: -144px -144px; }
-.ui-icon-play { background-position: 0 -160px; }
-.ui-icon-pause { background-position: -16px -160px; }
-.ui-icon-seek-next { background-position: -32px -160px; }
-.ui-icon-seek-prev { background-position: -48px -160px; }
-.ui-icon-seek-end { background-position: -64px -160px; }
-.ui-icon-seek-start { background-position: -80px -160px; }
-/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
-.ui-icon-seek-first { background-position: -80px -160px; }
-.ui-icon-stop { background-position: -96px -160px; }
-.ui-icon-eject { background-position: -112px -160px; }
-.ui-icon-volume-off { background-position: -128px -160px; }
-.ui-icon-volume-on { background-position: -144px -160px; }
-.ui-icon-power { background-position: 0 -176px; }
-.ui-icon-signal-diag { background-position: -16px -176px; }
-.ui-icon-signal { background-position: -32px -176px; }
-.ui-icon-battery-0 { background-position: -48px -176px; }
-.ui-icon-battery-1 { background-position: -64px -176px; }
-.ui-icon-battery-2 { background-position: -80px -176px; }
-.ui-icon-battery-3 { background-position: -96px -176px; }
-.ui-icon-circle-plus { background-position: 0 -192px; }
-.ui-icon-circle-minus { background-position: -16px -192px; }
-.ui-icon-circle-close { background-position: -32px -192px; }
-.ui-icon-circle-triangle-e { background-position: -48px -192px; }
-.ui-icon-circle-triangle-s { background-position: -64px -192px; }
-.ui-icon-circle-triangle-w { background-position: -80px -192px; }
-.ui-icon-circle-triangle-n { background-position: -96px -192px; }
-.ui-icon-circle-arrow-e { background-position: -112px -192px; }
-.ui-icon-circle-arrow-s { background-position: -128px -192px; }
-.ui-icon-circle-arrow-w { background-position: -144px -192px; }
-.ui-icon-circle-arrow-n { background-position: -160px -192px; }
-.ui-icon-circle-zoomin { background-position: -176px -192px; }
-.ui-icon-circle-zoomout { background-position: -192px -192px; }
-.ui-icon-circle-check { background-position: -208px -192px; }
-.ui-icon-circlesmall-plus { background-position: 0 -208px; }
-.ui-icon-circlesmall-minus { background-position: -16px -208px; }
-.ui-icon-circlesmall-close { background-position: -32px -208px; }
-.ui-icon-squaresmall-plus { background-position: -48px -208px; }
-.ui-icon-squaresmall-minus { background-position: -64px -208px; }
-.ui-icon-squaresmall-close { background-position: -80px -208px; }
-.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
-.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
-.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
-.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
-.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
-.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
-
-
-/* Misc visuals
-----------------------------------*/
-
-/* Corner radius */
-.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; -khtml-border-top-left-radius: 6px; border-top-left-radius: 6px; }
-.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 6px; -webkit-border-top-right-radius: 6px; -khtml-border-top-right-radius: 6px; border-top-right-radius: 6px; }
-.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; -khtml-border-bottom-left-radius: 6px; border-bottom-left-radius: 6px; }
-.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 6px; -webkit-border-bottom-right-radius: 6px; -khtml-border-bottom-right-radius: 6px; border-bottom-right-radius: 6px; }
-
-/* Overlays */
-.ui-widget-overlay { background: #5c5c5c url(images/ui-bg_flat_50_5c5c5c_40x100.png) 50% 50% repeat-x; opacity: .8;filter:Alpha(Opacity=80); }
-.ui-widget-shadow { margin: -7px 0 0 -7px; padding: 7px; background: #cccccc url(images/ui-bg_flat_30_cccccc_40x100.png) 50% 50% repeat-x; opacity: .6;filter:Alpha(Opacity=60); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }
\ No newline at end of file
diff --git a/servers/admin/public/stylesheets/vendors/jquery-ui-1.9.2.custom.min.css b/servers/admin/public/stylesheets/vendors/jquery-ui-1.9.2.custom.min.css
deleted file mode 100755
index 3a9e233..0000000
--- a/servers/admin/public/stylesheets/vendors/jquery-ui-1.9.2.custom.min.css
+++ /dev/null
@@ -1,5 +0,0 @@
-/*! jQuery UI - v1.9.2 - 2013-01-03
-* http://jqueryui.com
-* Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css
-* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Segoe%20UI%2CArial%2Csans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=6px&bgColorHeader=333333&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=25&borderColorHeader=333333&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=000000&bgTextureContent=05_inset_soft.png&bgImgOpacityContent=25&borderColorContent=666666&fcContent=ffffff&iconColorContent=cccccc&bgColorDefault=555555&bgTextureDefault=02_glass.png&bgImgOpacityDefault=20&borderColorDefault=666666&fcDefault=eeeeee&iconColorDefault=cccccc&bgColorHover=0078a3&bgTextureHover=02_glass.png&bgImgOpacityHover=40&borderColorHover=59b4d4&fcHover=ffffff&iconColorHover=ffffff&bgColorActive=2d7be6&bgTextureActive=05_inset_soft.png&bgImgOpacityActive=30&borderColorActive=0f58ff&fcActive=ffffff&iconColorActive=222222&bgColorHighlight=eeeeee&bgTextureHighlight=03_highlight_soft.png&bgImgOpacityHighlight=80&borderColorHighlight=cccccc&fcHighlight=2e7db2&iconColorHighlight=4b8e0b&bgColorError=ffc73d&bgTextureError=02_glass.png&bgImgOpacityError=40&borderColorError=ffb73d&fcError=111111&iconColorError=a83300&bgColorOverlay=5c5c5c&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=50&opacityOverlay=80&bgColorShadow=cccccc&bgTextureShadow=01_flat.png&bgImgOpacityShadow=30&opacityShadow=60&thicknessShadow=7px&offsetTopShadow=-7px&offsetLeftShadow=-7px&cornerRadiusShadow=8px
-* Copyright (c) 2013 jQuery Foundation and other contributors Licensed MIT */.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{zoom:1}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:absolute;top:0;left:0;width:100%;height:100%}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin-top:2px;padding:.5em .5em .5em .7em;zoom:1}.ui-accordion .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-noicons{padding-left:.7em}.ui-accordion .ui-accordion-icons .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-header .ui-accordion-header-icon{position:absolute;left:.5em;top:50%;margin-top:-8px}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto;zoom:1}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}* html .ui-autocomplete{width:1px}.ui-button{display:inline-block;position:relative;padding:0;margin-right:.1em;cursor:pointer;text-align:center;zoom:1;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:1.4}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-8px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:.5em}.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month-year{width:100%}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:49%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0em}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current{float:right}.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-datepicker-cover{position:absolute;z-index:-1;filter:mask();top:-4px;left:-4px;width:200px;height:200px}.ui-dialog{position:absolute;top:0;left:0;padding:.2em;width:300px;overflow:hidden}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 16px .1em 0}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:19px;margin:-10px 0 0 0;padding:1px;height:18px}.ui-dialog .ui-dialog-titlebar-close span{display:block;margin:1px}.ui-dialog .ui-dialog-titlebar-close:hover,.ui-dialog .ui-dialog-titlebar-close:focus{padding:0}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto;zoom:1}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin:.5em 0 0 0;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-se{width:14px;height:14px;right:3px;bottom:3px}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-menu{list-style:none;padding:2px;margin:0;display:block;outline:none}.ui-menu .ui-menu{margin-top:-3px;position:absolute}.ui-menu .ui-menu-item{margin:0;padding:0;zoom:1;width:100%}.ui-menu .ui-menu-divider{margin:5px -2px 5px -2px;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-menu-item a{text-decoration:none;display:block;padding:2px .4em;line-height:1.5;zoom:1;font-weight:normal}.ui-menu .ui-menu-item a.ui-state-focus,.ui-menu .ui-menu-item a.ui-state-active{font-weight:normal;margin:-1px}.ui-menu .ui-state-disabled{font-weight:normal;margin:.4em 0 .2em;line-height:1.5}.ui-menu .ui-state-disabled a{cursor:default}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item a{position:relative;padding-left:2em}.ui-menu .ui-icon{position:absolute;top:.2em;left:.2em}.ui-menu .ui-menu-icon{position:static;float:right}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:none;background:none;padding:0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:22px}.ui-spinner-button{width:16px;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top:none;border-bottom:none;border-right:none}.ui-spinner .ui-icon{position:absolute;margin-top:-8px;top:50%;left:0}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-spinner .ui-icon-triangle-1-s{background-position:-65px -16px}.ui-tabs{position:relative;padding:.2em;zoom:1}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav li a{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active a,.ui-tabs .ui-tabs-nav li.ui-state-disabled a,.ui-tabs .ui-tabs-nav li.ui-tabs-loading a{cursor:text}.ui-tabs .ui-tabs-nav li a,.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px;-webkit-box-shadow:0 0 5px #aaa;box-shadow:0 0 5px #aaa}* html .ui-tooltip{background-image:none}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Segoe UI,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Segoe UI,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #666;background:#000 url(images/ui-bg_inset-soft_25_000000_1x100.png) 50% bottom repeat-x;color:#fff}.ui-widget-content a{color:#fff}.ui-widget-header{border:1px solid #333;background:#333 url(images/ui-bg_gloss-wave_25_333333_500x100.png) 50% 50% repeat-x;color:#fff;font-weight:bold}.ui-widget-header a{color:#fff}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #666;background:#555 url(images/ui-bg_glass_20_555555_1x400.png) 50% 50% repeat-x;font-weight:bold;color:#eee}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#eee;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #59b4d4;background:#0078a3 url(images/ui-bg_glass_40_0078a3_1x400.png) 50% 50% repeat-x;font-weight:bold;color:#fff}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited{color:#fff;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #0f58ff;background:#2d7be6 url(images/ui-bg_inset-soft_30_2d7be6_1x100.png) 50% 50% repeat-x;font-weight:bold;color:#fff}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#fff;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #ccc;background:#eee url(images/ui-bg_highlight-soft_80_eeeeee_1x100.png) 50% top repeat-x;color:#2e7db2}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#2e7db2}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #ffb73d;background:#ffc73d url(images/ui-bg_glass_40_ffc73d_1x400.png) 50% 50% repeat-x;color:#111}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#111}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#111}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px;background-image:url(images/ui-icons_cccccc_256x240.png)}.ui-widget-content .ui-icon{background-image:url(images/ui-icons_cccccc_256x240.png)}.ui-widget-header .ui-icon{background-image:url(images/ui-icons_ffffff_256x240.png)}.ui-state-default .ui-icon{background-image:url(images/ui-icons_cccccc_256x240.png)}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url(images/ui-icons_ffffff_256x240.png)}.ui-state-active .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.ui-state-highlight .ui-icon{background-image:url(images/ui-icons_4b8e0b_256x240.png)}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url(images/ui-icons_a83300_256x240.png)}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{-moz-border-radius-topleft:6px;-webkit-border-top-left-radius:6px;-khtml-border-top-left-radius:6px;border-top-left-radius:6px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{-moz-border-radius-topright:6px;-webkit-border-top-right-radius:6px;-khtml-border-top-right-radius:6px;border-top-right-radius:6px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{-moz-border-radius-bottomleft:6px;-webkit-border-bottom-left-radius:6px;-khtml-border-bottom-left-radius:6px;border-bottom-left-radius:6px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{-moz-border-radius-bottomright:6px;-webkit-border-bottom-right-radius:6px;-khtml-border-bottom-right-radius:6px;border-bottom-right-radius:6px}.ui-widget-overlay{background:#5c5c5c url(images/ui-bg_flat_50_5c5c5c_40x100.png) 50% 50% repeat-x;opacity:.8;filter:Alpha(Opacity=80)}.ui-widget-shadow{margin:-7px 0 0 -7px;padding:7px;background:#ccc url(images/ui-bg_flat_30_cccccc_40x100.png) 50% 50% repeat-x;opacity:.6;filter:Alpha(Opacity=60);-moz-border-radius:8px;-khtml-border-radius:8px;-webkit-border-radius:8px;border-radius:8px}
\ No newline at end of file
diff --git a/servers/admin/public/stylesheets/vendors/toastr-1.2.2.css b/servers/admin/public/stylesheets/vendors/toastr-1.2.2.css
deleted file mode 100644
index 20a65d8..0000000
--- a/servers/admin/public/stylesheets/vendors/toastr-1.2.2.css
+++ /dev/null
@@ -1,157 +0,0 @@
-.toast-title {
-    font-weight: bold;
-}
-
-.toast-message {
-    -ms-word-wrap: break-word;
-    word-wrap: break-word;
-}
-
-    .toast-message a,
-    .toast-message label {
-        color: #FFF;
-    }
-
-        .toast-message a:hover {
-            color: #CCC;
-            text-decoration: none;
-        }
-
-
-.toast-top-full-width {
-    top: 0;
-    right: 0;
-    width: 100%;
-}
-
-.toast-bottom-full-width {
-    bottom: 0;
-    right: 0;
-    width: 100%;
-}
-
-.toast-top-left {
-    top: 12px;
-    left: 12px;
-}
-
-.toast-top-right {
-    top: 12px;
-    right: 12px;
-}
-
-.toast-bottom-right {
-    right: 12px;
-    bottom: 12px;
-}
-
-.toast-bottom-left {
-    bottom: 12px;
-    left: 12px;
-}
-
-#toast-container {
-    position: fixed;
-    z-index: 999999;
-}
-
-    #toast-container > div {
-        margin: 0 0 6px;
-        padding: 15px 15px 15px 50px;
-        width: 300px;
-        -moz-border-radius: 3px 3px 3px 3px;
-        -webkit-border-radius: 3px 3px 3px 3px;
-        border-radius: 3px 3px 3px 3px;
-        background-position: 15px center;
-        background-repeat: no-repeat;
-        -moz-box-shadow: 0 0 12px #999999;
-        -webkit-box-shadow: 0 0 12px #999999;
-        box-shadow: 0 0 12px #999999;
-        color: #FFFFFF;
-        opacity: 0.8;
-        -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=80)";
-        filter: alpha(opacity=80);
-    }
-
-.toast {
-    background-color: #030303;
-}
-
-.toast-success {
-    background-color: #51A351;
-}
-
-.toast-error {
-    background-color: #BD362F;
-}
-
-.toast-info {
-    background-color: #2F96B4;
-}
-
-.toast-warning {
-    background-color: #F89406;
-}
-
-#toast-container > :hover {
-    -moz-box-shadow: 0 0 12px #000000;
-    -webkit-box-shadow: 0 0 12px #000000;
-    box-shadow: 0 0 12px #000000;
-    opacity: 1;
-    -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
-    filter: alpha(opacity=100);
-    cursor: pointer;
-}
-
-#toast-container > .toast-info {
-    background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=") !important;
-}
-
-#toast-container > .toast-error {
-    background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=") !important;
-}
-
-#toast-container > .toast-success {
-    background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==") !important;
-}
-
-#toast-container > .toast-warning {
-    background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=") !important;
-}
-
-/*Responsive Design*/
-
-@media all and (max-width: 240px) {
-    #toast-container > div {
-        padding: 8px 8px 8px 50px;
-        width: 108px;
-    }
-}
-
-@media all and (min-width: 241px) and (max-width: 320px) {
-    #toast-container > div {
-        padding: 8px 8px 8px 50px;
-        width: 128px;
-    }
-}
-
-@media all and (min-width: 321px) and (max-width: 480px) {
-    #toast-container > div {
-        padding: 8px 8px 8px 50px;
-        width: 192px;
-    }
-}
-
-@media all and (min-width: 481px) and (max-width: 768px) {
-    #toast-container > div {
-        padding: 15px 15px 15px 50px;
-        width: 300px;
-    }
-}
-
-/* overrides */
-#toast-container.toast-top-full-width > div,
-#toast-container.toast-bottom-full-width > div {
-    width: 100%;
-    margin: 1px 0 1px 0;
-}
diff --git a/servers/admin/public/stylesheets/vendors/toastr-1.2.2.min.css b/servers/admin/public/stylesheets/vendors/toastr-1.2.2.min.css
deleted file mode 100644
index 1e0a527..0000000
--- a/servers/admin/public/stylesheets/vendors/toastr-1.2.2.min.css
+++ /dev/null
@@ -1 +0,0 @@
-.toast-title{font-weight:bold}.toast-message{-ms-word-wrap:break-word;word-wrap:break-word}.toast-message a,.toast-message label{color:#fff}.toast-message a:hover{color:#ccc;text-decoration:none}.toast-top-full-width{top:0;right:0;width:100%}.toast-bottom-full-width{bottom:0;right:0;width:100%}.toast-top-left{top:12px;left:12px}.toast-top-right{top:12px;right:12px}.toast-bottom-right{right:12px;bottom:12px}.toast-bottom-left{bottom:12px;left:12px}#toast-container{position:fixed;z-index:9999}#toast-container>div{margin:0 0 6px;padding:15px 15px 15px 50px;width:300px;-moz-border-radius:3px 3px 3px 3px;-webkit-border-radius:3px 3px 3px 3px;border-radius:3px 3px 3px 3px;background-position:15px center;background-repeat:no-repeat;-moz-box-shadow:0 0 12px #999;-webkit-box-shadow:0 0 12px #999;box-shadow:0 0 12px #999;color:#fff;opacity:.8;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=80)";filter:alpha(opacity=80)}.toast{background-color:#030303}.toast-success{background-color:#51a351}.toast-error{background-color:#bd362f}.toast-info{background-color:#2f96b4}.toast-warning{background-color:#f89406}#toast-container>:hover{-moz-box-shadow:0 0 12px #000;-webkit-box-shadow:0 0 12px #000;box-shadow:0 0 12px #000;opacity:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";filter:alpha(opacity=100);cursor:pointer}#toast-container>.toast-info{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=")!important}#toast-container>.toast-error{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=")!important}#toast-container>.toast-success{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==")!important}#toast-container>.toast-warning{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=")!important}@media all and (max-width:240px){#toast-container>div{padding:8px 8px 8px 50px;width:108px}}@media all and (min-width:241px)and (max-width:320px){#toast-container>div{padding:8px 8px 8px 50px;width:128px}}@media all and (min-width:321px)and (max-width:480px){#toast-container>div{padding:8px 8px 8px 50px;width:192px}}@media all and (min-width:481px)and (max-width:768px){#toast-container>div{padding:15px 15px 15px 50px;width:300px}}#toast-container.toast-top-full-width>div,#toast-container.toast-bottom-full-width>div{width:100%;margin:1px 0 1px 0}
\ No newline at end of file
diff --git a/servers/admin/public/stylesheets/vendors/toggle-switch.css b/servers/admin/public/stylesheets/vendors/toggle-switch.css
deleted file mode 100755
index e435a69..0000000
--- a/servers/admin/public/stylesheets/vendors/toggle-switch.css
+++ /dev/null
@@ -1,421 +0,0 @@
-/* ------------------------------------------

-CSS TOGGLE SWITCHES (IonuÈ› Colceriu)

-Licensed under Unlicense 

-https://github.com/ghinda/css-toggle-switch

------------------------------------------- */

-

-/* Hide by default */

-

-.switch .slide-button,

-.toggle p span {

-	display: none;

-}

-

-/* Toggle Switches */

-

-/* We can't test for a specific feature,

- * so we only target browsers with support for media queries.

- */

-@media only screen {

-

-	/* Checkbox

-	 */

-	.toggle {

-		position: relative;

-		padding: 0;

-		margin-left: 100px;

-	}

-

-	/* Position the label over all the elements, except the slide-button

-	 * Clicking anywhere on the label will change the switch-state

-	 */

-	.toggle label {

-		position: relative;

-		z-index: 3;

-		

-		display: block;

-		width: 100%;

-	}

-

-	/* Don't hide the input from screen-readers and keyboard access

-	 */

-	.toggle input {

-		position: absolute;

-		opacity: 0;

-		z-index: 5;

-	}

-	

-	.toggle p {

-		position: absolute;

-		left: -100px;

-		

-		width: 100%;

-		margin: 0;

-		padding-right: 100px;

-		

-		text-align: left;

-	}

-	

-	.toggle p span {

-		position: absolute;

-		top: 0;

-		left: 0;

-		z-index: 5;

-		

-		display: block;

-		width: 50%;

-		margin-left: 100px;

-		

-		text-align: center;

-	}

-	

-	.toggle p span:last-child {

-		left: 50%;

-	}

-

-	.toggle .slide-button {

-		position: absolute;

-		right: 0;

-		top: 0;

-		z-index: 4;

-		

-		display: block;

-		width: 50%;

-		height: 100%;

-		padding: 0;

-	}

-

-	/* Radio Switch

-	 */

-	.switch {

-		position: relative;

-		padding: 0;

-	}

-	

-	.switch input {

-		position: absolute;

-		opacity: 0;

-	}

-	

-	.switch label {

-		position: relative;

-		z-index: 2;

-		

-		float: left;

-		width: 50%;

-		height: 100%;

-		

-		margin: 0;

-		text-align: center;

-	}

-

-	.switch .slide-button {

-		position: absolute;

-		top: 0;

-		left: 0;

-		padding: 0;

-		z-index: 1;

-		

-		width: 50%;

-		height: 100%;

-	}

-

-	.switch input:last-of-type:checked ~ .slide-button {

-		left: 50%;

-	}

-

-	/* Switch with 3 items */

-	.switch.switch-three label,

-	.switch.switch-three .slide-button {

-		width: 33.3%;

-	}

-

-	.switch.switch-three input:checked:nth-of-type(2) ~ .slide-button {	

-		left: 33.3%;

-	}

-

-	.switch.switch-three input:checked:last-of-type ~ .slide-button {

-		left: 66.6%;

-	}

-	

-	/* Switch with 4 items */

-	.switch.switch-four label,

-	.switch.switch-four .slide-button {

-		width: 25%;

-	}

-

-	.switch.switch-four input:checked:nth-of-type(2) ~ .slide-button {	

-		left: 25%;

-	}

-	

-	.switch.switch-four input:checked:nth-of-type(3) ~ .slide-button {	

-		left: 50%;

-	}

-

-	.switch.switch-four input:checked:last-of-type ~ .slide-button {

-		left: 75%;

-	}

-	

-	/* Switch with 5 items */

-	.switch.switch-five label,

-	.switch.switch-five .slide-button {

-		width: 20%;

-	}

-

-	.switch.switch-five input:checked:nth-of-type(2) ~ .slide-button {	

-		left: 20%;

-	}

-	

-	.switch.switch-five input:checked:nth-of-type(3) ~ .slide-button {	

-		left: 40%;

-	}

-	

-	.switch.switch-five input:checked:nth-of-type(4) ~ .slide-button {	

-		left: 60%;

-	}

-

-	.switch.switch-five input:checked:last-of-type ~ .slide-button {

-		left: 80%;

-	}

-

-	/* Shared */

-	.toggle,

-	.switch {

-		display: block;

-		height: 30px;

-	}

-	

-	.switch *,

-	.toggle * {

-		-webkit-box-sizing: border-box;

-		-moz-box-sizing: border-box;

-		-ms-box-sizing: border-box;

-		-o-box-sizing: border-box;

-		box-sizing: border-box;

-	}

-	

-	.switch .slide-button,

-	.toggle .slide-button {

-		display: block;

-		

-		-webkit-transition: all 0.3s ease-out;

-		-moz-transition: all 0.3s ease-out;

-		-ms-transition: all 0.3s ease-out;

-		-o-transition: all 0.3s ease-out;

-		transition: all 0.3s ease-out;

-	}

-	

-	.toggle label,

-	.toggle p,

-	.switch label {

-		line-height: 30px;

-		vertical-align: middle;

-	}

-	

-	.toggle input:checked ~ .slide-button {

-		right: 50%;

-	}

-	

-	/* Outline the toggles when the inputs are focused */

-	.toggle input:focus ~ .slide-button,

-	.switch input:focus + label {

-		outline: 1px dotted #888;

-	}

-	

-	/* Bugfix for older Webkit, including mobile Webkit. Adapted from:

-	 * http://css-tricks.com/webkit-sibling-bug/

-	 */

-	.switch, .toggle {

-		-webkit-animation: bugfix infinite 1s;

-	}

-	

-	@-webkit-keyframes bugfix { from { position: relative; } to { position: relative; } }

-

-

-	/* Standalone Themes */

-

-

-	/* Candy Theme

-	 * Based on the "Sort Switches / Toggles (PSD)" by Ormal Clarck

-	 * http://www.premiumpixels.com/freebies/sort-switches-toggles-psd/

-	 */

-	 

-	.candy {

-		background-color: #2d3035;

-		

-		color: #fff;

-		font-weight: bold;

-		text-align: center;

-		text-shadow: 1px 1px 1px #191b1e;

-			

-		border-radius: 3px;	

-		

-		box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.3), 0 1px 0px rgba(255, 255, 255, 0.2);

-	}

-

-	.candy input:checked + label {

-		color: #333;

-		text-shadow: 0 1px 0 rgba(255,255,255,0.5);

-	}

-		

-	.candy .slide-button {

-		border: 1px solid #333;

-

-		background-color: #70c66b;

-		

-		background-image: -webkit-linear-gradient(top, rgba(255, 255, 255, 0.2), rgba(0, 0, 0, 0));

-		background-image:    -moz-linear-gradient(top, rgba(255, 255, 255, 0.2), rgba(0, 0, 0, 0));

-		background-image:     -ms-linear-gradient(top, rgba(255, 255, 255, 0.2), rgba(0, 0, 0, 0));

-		background-image:      -o-linear-gradient(top, rgba(255, 255, 255, 0.2), rgba(0, 0, 0, 0));

-		background-image:         linear-gradient(top, rgba(255, 255, 255, 0.2), rgba(0, 0, 0, 0));

-		

-		box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), inset 0 1px 1px rgba(255, 255, 255, 0.45);

-		

-		border-radius: 3px;

-	}

-

-	.candy p {

-		color: #333;

-		

-		text-shadow: none;

-	}

-

-	.candy span {

-		color: #fff;

-	}

-

-	.candy.blue .slide-button {

-		background-color: #38a3d4;

-	}

-

-	.candy.yellow .slide-button {

-		background-color: #f5e560;

-	}

-

-	/* Android Theme

-	 * Based on Holo

-	 */

-	 

-	.android {

-		background-color: #b6b6b6;

-		

-		color: #fff;

-	}

-

-	.android.toggle {

-		border: 2px solid #b6b6b6;

-	}

-

-	.android.switch {

-		overflow: hidden;

-	}

-		

-	.android.switch .slide-button {

-		background-color: #279fca;

-		

-		-webkit-transform: skew(20deg) translateX(10px);

-		-moz-transform: skew(20deg) translateX(10px);

-		-ms-transform: skew(20deg) translateX(10px);

-		-o-transform: skew(20deg) translateX(10px);

-		transform: skew(20deg);

-	}

-

-	.android.toggle .slide-button {

-		border-radius: 2px;

-		

-		background-color: #848484;

-	}

-

-	/* Selected ON toggle */

-	.android.toggle input:first-of-type:checked ~ .slide-button {

-		background-color: #279fca;

-	}

-

-	.android.switch input:first-of-type:checked ~ .slide-button {

-		-webkit-transform: skew(20deg) translateX(-10px);

-		-moz-transform: skew(20deg) translateX(-10px);

-		-ms-transform: skew(20deg) translateX(-10px);

-		-o-transform: skew(20deg) translateX(-10px);

-		transform: skew(20deg) translateX(-10px);

-	}

-

-	.android p {

-		color: #333;

-	}

-

-	.android span {

-		color: #fff;

-	}

-

-	.android.switch,

-	.android span {

-		text-transform: uppercase;

-	}

-

-	/* iOS Theme

-	 * Similar to iOS but more accessible

-	 */ 

-

-	.ios {

-		background: -webkit-linear-gradient(top, #cfcfcf, #efefef 50%, #f9f9f9 50%, #fefefe);

-		background: -moz-linear-gradient(top, #cfcfcf, #efefef 50%, #f9f9f9 50%, #fefefe);

-		background: -o-linear-gradient(top, #cfcfcf, #efefef 50%, #f9f9f9 50%, #fefefe);

-		background: -ms-linear-gradient(top, #cfcfcf, #efefef 50%, #f9f9f9 50%, #fefefe);

-		background: linear-gradient(top, #cfcfcf, #efefef 50%, #f9f9f9 50%, #fefefe);

-		

-		-webkit-box-shadow: inset 0 2px 2px #b6b6b6, inset 3px 0 3px #b6b6b6;

-		box-shadow: inset 0 2px 2px #b6b6b6, inset 3px 0 3px #b6b6b6;

-

-		border: 1px solid #efefef;

-		border-radius: 3px;

-		

-		color: #7f7f7f;

-		font: bold 14px sans-serif; 

-		text-align: center;

-		text-shadow: none;

-	}

-

-	.ios.toggle .slide-button {

-		border: 1px solid #919191;

-		background: -webkit-linear-gradient(top, #cdcdcd, #fbfbfb);

-		background: -moz-linear-gradient(top, #cdcdcd, #fbfbfb);

-		background: -o-linear-gradient(top, #cdcdcd, #fbfbfb);

-		background: -ms-linear-gradient(top, #cdcdcd, #fbfbfb);

-		background: linear-gradient(top, #cdcdcd, #fbfbfb);

-		

-		border-radius: 3px;

-		

-		-webkit-box-shadow: inset 0 1px 0 #f0f0f0;

-		box-shadow: inset 0 1px 0 #f0f0f0;

-	}

-

-	/* Selected ON toggle */

-	.ios.toggle input:first-of-type:checked ~ p span:first-child,

-	.ios.switch input:checked + label {

-		color: #fff;

-		text-shadow: 0 -1px 0 #1b3b6f;

-	}

-

-	.ios.toggle input:first-of-type:checked ~ .slide-button,

-	.ios.switch .slide-button {

-		background: -webkit-linear-gradient(top, #3672dc, #4085ec 50%, #4d8fef 50%, #76adfc);

-		background: -moz-linear-gradient(top, #3672dc, #4085ec 50%, #4d8fef 50%, #76adfc);

-		background: -o-linear-gradient(top, #3672dc, #4085ec 50%, #4d8fef 50%, #76adfc);

-		background: -ms-linear-gradient(top, #3672dc, #4085ec 50%, #4d8fef 50%, #76adfc);

-		background: linear-gradient(top, #3672dc, #4085ec 50%, #4d8fef 50%, #76adfc);

-		

-		border-radius: 3px;

-		border: 1px solid #1654b5;

-		

-		text-align: center;

-		color: #fff;

-		

-		font: bold 14px sans-serif; 

-		text-shadow: 0 -1px 0 #1b3b6f;

-	}

-	

-	.ios.toggle p span {

-		color: #7f7f7f;

-	}

-	

-}

diff --git a/servers/admin/test/AdminServerSpec.scala b/servers/admin/test/AdminServerSpec.scala
deleted file mode 100644
index 3783123..0000000
--- a/servers/admin/test/AdminServerSpec.scala
+++ /dev/null
@@ -1,2226 +0,0 @@
-package controllers
-
-import org.specs2.mutable.Specification
-import org.specs2.matcher.JsonMatchers
-import org.specs2.execute.Pending
-import play.api.test.{ WithServer, Port }
-import play.api.test.Helpers.{ OK, FORBIDDEN, BAD_REQUEST, NOT_FOUND, NO_CONTENT }
-import play.api.test.Helpers.{ await => HelperAwait, wsUrl, defaultAwaitTimeout }
-import play.api.libs.json.{ JsNull, JsArray, Json, JsValue }
-import play.api.libs.ws.WS.{ WSRequestHolder }
-import org.apache.commons.codec.digest.DigestUtils
-
-import com.github.nscala_time.time.Imports._
-
-import com.mongodb.casbah.Imports._
-
-import java.net.URLEncoder
-
-import io.prediction.commons.Config
-import io.prediction.commons.settings.{ App, Engine, Algo }
-import io.prediction.commons.settings.{ Param, ParamDoubleConstraint, ParamIntegerConstraint, ParamBooleanConstraint, ParamUI }
-import io.prediction.commons.settings.{ OfflineEval, OfflineEvalMetric, OfflineEvalSplitter, OfflineEvalResult }
-import io.prediction.commons.settings.{ EngineInfo, AlgoInfo, OfflineEvalMetricInfo, OfflineEvalSplitterInfo }
-
-import Helper.{ algoParamToString, offlineEvalMetricParamToString }
-
-class AdminServerSpec extends Specification with JsonMatchers {
-  private def md5password(password: String) = DigestUtils.md5Hex(password)
-
-  val config = new Config
-  val users = config.getSettingsUsers()
-  val apps = config.getSettingsApps()
-  val engineInfos = config.getSettingsEngineInfos()
-  val algoInfos = config.getSettingsAlgoInfos()
-  val offlineEvalMetricInfos = config.getSettingsOfflineEvalMetricInfos()
-  val offlineEvalSplitterInfos = config.getSettingsOfflineEvalSplitterInfos()
-  val engines = config.getSettingsEngines()
-  val algos = config.getSettingsAlgos()
-  val offlineEvals = config.getSettingsOfflineEvals()
-  val offlineEvalMetrics = config.getSettingsOfflineEvalMetrics()
-  val offlineEvalSplitters = config.getSettingsOfflineEvalSplitters()
-  val offlineEvalResults = config.getSettingsOfflineEvalResults()
-
-  val timeFormat = DateTimeFormat.forPattern("yyyy-MM-dd hh:mm:ss a z")
-
-  /* create test user account */
-  def createTestUser(firstname: String, lastname: String, email: String, password: String): (Int, JsValue) = {
-    val testUserid = users.insert(
-      email = email,
-      password = md5password(password),
-      firstname = firstname,
-      lastname = Some(lastname),
-      confirm = email
-    )
-    users.confirm(email)
-
-    val testUser = Json.obj("id" -> testUserid, "username" -> s"${firstname} ${lastname}", "email" -> email)
-
-    (testUserid, testUser)
-  }
-
-  /* signin first, and then add cookie to header of the request */
-  def signedinRequest(req: WSRequestHolder, email: String, password: String)(implicit port: Port): WSRequestHolder = {
-    val response = HelperAwait(wsUrl("/signin").post(Json.obj("email" -> email, "password" -> password)))
-    val signinCookie = response.header("Set-Cookie").get
-
-    req.withHeaders("Cookie" -> signinCookie)
-  }
-
-  /* setup system info (engineinfo, algoinfo, etc) */
-  val appleEngineInfo = EngineInfo(
-    id = "apple-engine",
-    name = "Apple Engine Info Name",
-    description = Some("Apple engine info description"),
-    params = Map[String, Param](
-      "abc" -> Param(
-        id = "abc",
-        name = "",
-        description = None,
-        defaultvalue = 123.4,
-        constraint = ParamDoubleConstraint(),
-        ui = ParamUI())),
-    paramsections = Seq(),
-    defaultalgoinfoid = "pizza-algo",
-    defaultofflineevalmetricinfoid = "vanilla-metric",
-    defaultofflineevalsplitterinfoid = "brownie-splitter"
-  )
-
-  engineInfos.insert(appleEngineInfo)
-
-  val pizzaAlgoInfo = AlgoInfo(
-    id = "pizza-algo",
-    name = "Pizza Algo Info Name",
-    description = Some("Pizza algo info description."),
-    batchcommands = Some(Seq(
-      "algo cmd1",
-      "algo cmd2",
-      "algo cmd3")),
-    offlineevalcommands = Some(Seq(
-      "algo cmd1",
-      "algo cmd2",
-      "algo cmd3")),
-    params = Map(
-      "aParam" -> Param(
-        id = "aParam",
-        name = "A Parameter",
-        description = Some("A parameter description"),
-        defaultvalue = 4,
-        constraint = ParamIntegerConstraint(),
-        ui = ParamUI()),
-      "bParam" -> Param(
-        id = "bParam",
-        name = "B Parameter",
-        description = Some("B parameter description"),
-        defaultvalue = 55,
-        constraint = ParamIntegerConstraint(),
-        ui = ParamUI())
-    ),
-    paramorder = Seq(
-      "aParam",
-      "bParam"),
-    paramsections = Seq(),
-    engineinfoid = "apple-engine",
-    techreq = Seq("Hadoop"),
-    datareq = Seq("Users, Items, and U2I Actions such as Like, Buy and Rate."))
-
-  algoInfos.insert(pizzaAlgoInfo)
-
-  val vanillaMetricInfo = OfflineEvalMetricInfo(
-    id = "vanilla-metric",
-    name = "Vanilla Metric Name",
-    description = Some("Vanilla metric description"),
-    engineinfoids = Seq("apple-engine"),
-    commands = Some(Seq(
-      "cmd1",
-      "cmd2",
-      "cmd3")),
-    params = Map(
-      "jParam" -> Param(
-        id = "jParam",
-        name = "J parameter",
-        description = Some("J parameter description"),
-        defaultvalue = 21,
-        constraint = ParamIntegerConstraint(),
-        ui = ParamUI())
-    ),
-    paramsections = Seq(),
-    paramorder = Seq("jParam")
-  )
-
-  offlineEvalMetricInfos.insert(vanillaMetricInfo)
-
-  val brownieSplitterInfo = OfflineEvalSplitterInfo(
-    id = "brownie-splitter",
-    name = "Brownie Splitter Name",
-    description = Some("Brownie Splitter description"),
-    engineinfoids = Seq("apple-engine"),
-    commands = Some(Seq(
-      "cmd1",
-      "cmd2",
-      "cmd3")),
-    params = Map(
-      "sParam" -> Param(
-        id = "sParam",
-        name = "S parameter",
-        description = Some("S parameter description"),
-        defaultvalue = 21,
-        constraint = ParamIntegerConstraint(),
-        ui = ParamUI()),
-      "tParam" -> Param(
-        id = "tParam",
-        name = "T parameter",
-        description = Some("T parameter description"),
-        defaultvalue = false,
-        constraint = ParamBooleanConstraint(),
-        ui = ParamUI())
-    ),
-    paramsections = Seq(),
-    paramorder = Seq("sParam", "tParam")
-  )
-
-  offlineEvalSplitterInfos.insert(brownieSplitterInfo)
-
-  /* convert algo to Json */
-  def algoToJson(algo: Algo, appid: Int) = {
-    Json.obj(
-      "id" -> algo.id,
-      "algoname" -> algo.name,
-      "appid" -> appid,
-      "engineid" -> algo.engineid,
-      "algoinfoid" -> algo.infoid,
-      "algoinfoname" -> algoInfos.get(algo.infoid).get.name,
-      "status" -> algo.status,
-      "createdtime" -> timeFormat.print(algo.createtime.withZone(DateTimeZone.forID("UTC"))),
-      "updatedtime" -> timeFormat.print(algo.updatetime.withZone(DateTimeZone.forID("UTC")))
-    )
-  }
-
-  def algoToJsonWithParam(algo: Algo, appid: Int) = {
-    Json.obj(
-      "id" -> algo.id,
-      "algoname" -> algo.name,
-      "appid" -> appid,
-      "engineid" -> algo.engineid,
-      "algoinfoid" -> algo.infoid,
-      "algoinfoname" -> algoInfos.get(algo.infoid).get.name,
-      "settingsstring" -> algoParamToString(algo, algoInfos.get(algo.infoid))
-    )
-  }
-
-  def offlineEvalMetricToJson(metric: OfflineEvalMetric, engineid: Int) = {
-    Json.obj(
-      "id" -> metric.id,
-      "engineid" -> engineid,
-      "engineinfoid" -> engines.get(engineid).get.id,
-      "metricsinfoid" -> metric.infoid,
-      "metricsname" -> offlineEvalMetricInfos.get(metric.infoid).get.name
-    )
-  }
-
-  def offlineEvalMetricToJsonWithParam(metric: OfflineEvalMetric, engineid: Int) = {
-    Json.obj(
-      "id" -> metric.id,
-      "metricsinfoid" -> metric.infoid,
-      "metricsname" -> offlineEvalMetricInfos.get(metric.infoid).get.name,
-      "settingsstring" -> offlineEvalMetricParamToString(metric, offlineEvalMetricInfos.get(metric.infoid))
-    )
-  }
-
-  def appTemplate(testUserid: Int) = App(
-    id = 0,
-    userid = testUserid,
-    appkey = "appkeystring",
-    display = "App Name",
-    url = None,
-    cat = None,
-    desc = None,
-    timezone = "UTC"
-  )
-
-  def engineTemplate(appid: Int) = Engine(
-    id = 0,
-    appid = appid,
-    name = "test-engine",
-    infoid = "apple-engine",
-    itypes = None, // NOTE: default None (means all itypes)
-    params = engineInfos.get("apple-engine").get.params.mapValues(_.defaultvalue)
-  )
-
-  def algoTemplate(engineid: Int) = {
-    val algoInfo = algoInfos.get("pizza-algo").get
-    Algo(
-      id = 0,
-      engineid = 0,
-      name = "test-algo",
-      infoid = "pizza-algo",
-      command = "",
-      params = algoInfo.params.mapValues(_.defaultvalue),
-      settings = Map(), // no use for now
-      modelset = false, // init value
-      createtime = DateTime.now.hour(4).minute(56).second(35),
-      updatetime = DateTime.now.hour(5).minute(6).second(7),
-      status = "ready", // default status
-      offlineevalid = None,
-      loop = None
-    )
-  }
-
-  def offlineEvalTemplate(engineid: Int) = {
-    OfflineEval(
-      id = -1,
-      engineid = engineid,
-      name = "",
-      iterations = 3,
-      tuneid = None,
-      createtime = Some(DateTime.now.hour(9).minute(12).second(5)),
-      starttime = None,
-      endtime = None
-    )
-  }
-
-  def offlineEvalSplitterTemplate(evalid: Int) = {
-    val splitterInfo = offlineEvalSplitterInfos.get("brownie-splitter").get
-    OfflineEvalSplitter(
-      id = -1,
-      evalid = evalid,
-      name = ("sim-eval-" + evalid + "-splitter"),
-      infoid = "brownie-splitter",
-      settings = Map(
-        "trainingPercent" -> 0.5,
-        "validationPercent" -> 0.2,
-        "testPercent" -> 0.2
-      ) ++ splitterInfo.params.mapValues(_.defaultvalue)
-    )
-  }
-
-  def offlineEvalMetricTemplate(evalid: Int) = {
-    val metricInfo = offlineEvalMetricInfos.get("vanilla-metric").get
-    OfflineEvalMetric(
-      id = -1,
-      infoid = "vanilla-metric",
-      evalid = evalid,
-      params = metricInfo.params.mapValues(_.defaultvalue)
-    )
-  }
-
-  /* tests */
-  "POST /signin" should {
-
-    val (testUserid, testUser) = createTestUser("Test", "Account", "abc@test.com", "testpassword")
-
-    "accept correct password and return user data" in new WithServer {
-      val response = HelperAwait(wsUrl("/signin").post(Json.obj("email" -> "abc@test.com", "password" -> "testpassword")))
-
-      response.status must equalTo(OK) and
-        (response.json must equalTo(testUser))
-    }
-
-    "return FORBIDDEN if incorrect email or password" in new WithServer {
-      val response1 = HelperAwait(wsUrl("/signin").post(Json.obj("email" -> "abc@test.com", "password" -> "incorrect password")))
-      val response2 = HelperAwait(wsUrl("/signin").post(Json.obj("email" -> "other@test.com", "password" -> "testpassword")))
-
-      response1.status must equalTo(FORBIDDEN) and
-        (response2.status must equalTo(FORBIDDEN))
-    }
-
-  }
-
-  "POST /signout" should {
-    "return OK" in new WithServer {
-      val response = HelperAwait(wsUrl("/signout").post(Json.obj()))
-      // TODO: check session is cleared
-      response.status must equalTo(OK)
-    }
-  }
-
-  "GET /auth" should {
-
-    val email = "auth@test.com"
-    val password = "authtestpassword"
-    val (testUserid, testUser) = createTestUser("Test", "Account", email, password)
-
-    "return OK and user data if the user has signed in" in new WithServer {
-      val response = HelperAwait(signedinRequest(wsUrl("/auth"), email, password).get)
-
-      response.status must equalTo(OK) and
-        (response.json must equalTo(testUser))
-    }
-
-    "return FORBIDDEN if user has not signed in" in new WithServer {
-      val response = HelperAwait(wsUrl("/auth").get)
-
-      response.status must equalTo(FORBIDDEN)
-    }
-  }
-
-  "POST /apps" should {
-
-    val email = "postapps@test.com"
-    val password = "postappspassword"
-    val (testUserid, testUser) = createTestUser("Test", "Account", email, password)
-
-    "return BAD_REQUEST if empty appname" in new WithServer {
-      val r = HelperAwait(signedinRequest(wsUrl("/apps"), email, password).
-        post(Json.obj("appname" -> "")))
-
-      r.status must equalTo(BAD_REQUEST)
-    }
-
-    "create an app and write to database" in new WithServer {
-      val appname = "My Test App"
-      val r = HelperAwait(signedinRequest(wsUrl("/apps"), email, password).
-        post(Json.obj("appname" -> appname)))
-
-      val appid = (r.json \ "id").asOpt[Int].getOrElse(0)
-
-      val validAppid = (appid != 0)
-      val dbWritten = apps.get(appid).map { app =>
-        (appname == app.display) && (appid == app.id)
-      }.getOrElse(false)
-
-      r.status must equalTo(OK) and
-        (r.json must equalTo(Json.obj("id" -> appid, "appname" -> appname))) and
-        (dbWritten must beTrue) and
-        (validAppid must beTrue)
-
-    }
-  }
-
-  "GET /apps" should {
-
-    val email = "getapps@test.com"
-    val password = "getappspassword"
-    val (testUserid, testUser) = createTestUser("Test", "Account", email, password)
-
-    val email2 = "getapps2@test.com"
-    val password2 = "getapps2password"
-    val (testUserid2, testUser2) = createTestUser("Test", "Account", email2, password2)
-
-    val email3 = "getapps3@test.com"
-    val password3 = "getapps3password"
-    val (testUserid3, testUser3) = createTestUser("Test", "Account", email3, password3)
-
-    val testApp = App(
-      id = 0,
-      userid = testUserid,
-      appkey = "appkeystring",
-      display = "Get App Name",
-      url = None,
-      cat = None,
-      desc = None,
-      timezone = "UTC"
-    )
-
-    val testApp2 = testApp.copy(
-      userid = testUserid2, // other userid
-      display = "Get App Name 2"
-    )
-
-    val testApp3 = testApp.copy(display = "Get App Name 3")
-    val testApp4 = testApp.copy(display = "Get App Name 4")
-
-    val appid = apps.insert(testApp)
-    val appid2 = apps.insert(testApp2)
-    val appid3 = apps.insert(testApp3)
-    val appid4 = apps.insert(testApp4)
-
-    "return the app of the specified /:appid" in new WithServer {
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}"), email, password).get())
-
-      r.status must equalTo(OK) and
-        (r.json must equalTo(Json.obj("id" -> appid, "appname" -> "Get App Name")))
-    }
-
-    "return NOT_FOUND if invalid appid" in new WithServer {
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid2}"), email, password).get())
-
-      r.status must equalTo(NOT_FOUND)
-    }
-
-    "return NO_CONTENT if 0 app" in new WithServer {
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps"), email3, password3).get())
-
-      r.status must equalTo(NO_CONTENT)
-    }
-
-    "return list of 1 app" in new WithServer {
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps"), email2, password2).get())
-
-      r.status must equalTo(OK) and
-        (r.json must equalTo(Json.arr(Json.obj("id" -> appid2, "appname" -> "Get App Name 2"))))
-    }
-
-    "return list of more than 1 app" in new WithServer {
-      val r = HelperAwait(signedinRequest(wsUrl("/apps"), email, password).get())
-
-      val appJson1 = Json.obj("id" -> appid, "appname" -> "Get App Name")
-      val appJson3 = Json.obj("id" -> appid3, "appname" -> "Get App Name 3")
-      val appJson4 = Json.obj("id" -> appid4, "appname" -> "Get App Name 4")
-
-      r.status must equalTo(OK) and
-        (r.json must equalTo(Json.arr(appJson1, appJson3, appJson4)))
-    }
-
-    "return app details of the specified /:appid" in new WithServer {
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/details"), email, password).get())
-
-      r.status must equalTo(OK) and
-        (r.body must /("id" -> appid)) and
-        (r.body must /("updatedtime" -> """.*""".r)) and
-        (r.body must /("userscount" -> 0)) and
-        (r.body must /("itemscount" -> 0)) and
-        (r.body must /("u2icount" -> 0)) and
-        (r.body must /("apiurl" -> """.*""".r)) and
-        (r.body must /("appkey" -> "appkeystring"))
-    }
-
-  }
-
-  "DELETE /apps/:appid" should {
-    "delete an app" in new WithServer {
-      new Pending("TODO")
-    }
-
-    "return NOT_FOUND if invalid appid" in new WithServer {
-      new Pending("TODO")
-    }
-  }
-
-  "POST /apps/:id/erase_data" should {
-    "erase all app data" in new WithServer {
-      new Pending("TODO")
-    }
-
-    "return NOT_FOUND if invalid appid" in new WithServer {
-      new Pending("TODO")
-    }
-  }
-
-  "GET /engineinfos" should {
-
-    "return all engine infos" in new WithServer {
-      val r = HelperAwait(wsUrl(s"/engineinfos").get())
-
-      r.status must equalTo(OK) and
-        (r.json must equalTo(Json.arr(Json.obj(
-          "id" -> appleEngineInfo.id,
-          "engineinfoname" -> appleEngineInfo.name,
-          "description" -> appleEngineInfo.description))))
-    }
-
-    "return all algo infos of a engineinfoid" in new WithServer {
-      val r = HelperAwait(wsUrl(s"/engineinfos/${appleEngineInfo.id}/algoinfos").get())
-
-      r.status must equalTo(OK) and
-        (r.json must equalTo(Json.obj(
-          "engineinfoname" -> appleEngineInfo.name,
-          "algotypelist" -> Json.arr(Json.obj(
-            "id" -> pizzaAlgoInfo.id,
-            "algoinfoname" -> pizzaAlgoInfo.name,
-            "description" -> pizzaAlgoInfo.description,
-            "req" -> Json.toJson(pizzaAlgoInfo.techreq),
-            "datareq" -> Json.toJson(pizzaAlgoInfo.datareq)
-          ))
-        )))
-    }
-
-    "return all metric infos of a engineinfoid" in new WithServer {
-      val r = HelperAwait(wsUrl(s"/engineinfos/${appleEngineInfo.id}/metricinfos").get())
-
-      r.status must equalTo(OK) and
-        (r.json must equalTo(Json.obj(
-          "engineinfoname" -> appleEngineInfo.name,
-          "defaultmetric" -> appleEngineInfo.defaultofflineevalmetricinfoid,
-          "metricslist" -> Json.arr(Json.obj(
-            "id" -> vanillaMetricInfo.id,
-            "name" -> vanillaMetricInfo.name,
-            "description" -> vanillaMetricInfo.description
-          ))
-        )))
-    }
-
-    "return all spitter infos of a engineinfoid" in new WithServer {
-      val r = HelperAwait(wsUrl(s"/engineinfos/${appleEngineInfo.id}/splitterinfos").get())
-
-      r.status must equalTo(OK) and
-        (r.json must equalTo(Json.obj(
-          "engineinfoname" -> appleEngineInfo.name,
-          "defaultsplitter" -> appleEngineInfo.defaultofflineevalsplitterinfoid,
-          "splitterlist" -> Json.arr(Json.obj(
-            "id" -> brownieSplitterInfo.id,
-            "name" -> brownieSplitterInfo.name,
-            "description" -> brownieSplitterInfo.description
-          ))
-        )))
-    }
-
-  }
-
-  "POST /apps/:appid/engines" should {
-
-    val email = "postengines@test.com"
-    val password = "postenginespassword"
-    val (testUserid, testUser) = createTestUser("Test", "Account", email, password)
-
-    val testApp = App(
-      id = 0,
-      userid = testUserid,
-      appkey = "appkeystring",
-      display = "POST Engines App Name",
-      url = None,
-      cat = None,
-      desc = None,
-      timezone = "UTC"
-    )
-    val appid = apps.insert(testApp)
-
-    "create an engine and write to database" in new WithServer {
-      val engineinfoid = "apple-engine"
-      val enginename = "My-Engine-A"
-
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines"), email, password).
-        post(Json.obj("engineinfoid" -> engineinfoid, "enginename" -> enginename)))
-
-      val engineid = (r.json \ "id").asOpt[Int].getOrElse(0)
-
-      val validEngineid = (engineid != 0)
-      // check database
-      val dbWritten = engines.get(engineid).map { eng =>
-        (eng.name == enginename) &&
-          (eng.infoid == engineinfoid) &&
-          (eng.appid == appid)
-      }.getOrElse(false)
-
-      r.status must equalTo(OK) and
-        (r.json must equalTo(Json.obj(
-          "id" -> engineid,
-          "engineinfoid" -> engineinfoid,
-          "appid" -> appid,
-          "enginename" -> enginename))) and
-        (dbWritten must beTrue) and
-        (validEngineid must beTrue)
-    }
-
-    "return BAD_REQUEST if engine name has space" in new WithServer {
-      val engineinfoid = "apple-engine"
-      val enginename = "Space is not allowed"
-
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines"), email, password).
-        post(Json.obj("engineinfoid" -> engineinfoid, "enginename" -> enginename)))
-
-      r.status must equalTo(BAD_REQUEST)
-    }
-
-    "return BAD_REQUEST if empty engine name" in new WithServer {
-      new Pending("TODO")
-    }
-
-    "return BAD_REQUEST if duplicated engine name" in new WithServer {
-      val engineinfoid = "apple-engine"
-      val enginename = "myengine"
-      val enginename2 = "myengine2"
-
-      val r1 = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines"), email, password).
-        post(Json.obj("engineinfoid" -> engineinfoid, "enginename" -> enginename)))
-
-      val r1dup = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines"), email, password).
-        post(Json.obj("engineinfoid" -> engineinfoid, "enginename" -> enginename)))
-
-      val r2 = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines"), email, password).
-        post(Json.obj("engineinfoid" -> engineinfoid, "enginename" -> enginename2)))
-
-      r1.status must equalTo(OK) and
-        (r1dup.status must equalTo(BAD_REQUEST)) and
-        (r2.status must equalTo(OK))
-    }
-
-    "return BAD_REQUEST if invalid engineinfoid" in new WithServer {
-      val engineinfoid = "unknown"
-      val enginename = "unknown-engine"
-
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines"), email, password).
-        post(Json.obj("engineinfoid" -> engineinfoid, "enginename" -> enginename)))
-
-      r.status must equalTo(BAD_REQUEST)
-    }
-
-    "return NOT_FOUND if invalid appid" in new WithServer {
-      new Pending("TODO")
-    }
-
-  }
-
-  "GET /apps/:appid/engines" should {
-
-    val email = "getengines@test.com"
-    val password = "getenginespassword"
-    val (testUserid, testUser) = createTestUser("Test", "Account", email, password)
-
-    val testApp = App(
-      id = 0,
-      userid = testUserid,
-      appkey = "appkeystring",
-      display = "Get Engines App Name",
-      url = None,
-      cat = None,
-      desc = None,
-      timezone = "UTC"
-    )
-    val testApp2 = testApp.copy(
-      appkey = "appkeystring2",
-      display = "Get Engines App Name2"
-    )
-    val testApp3 = testApp.copy(
-      appkey = "appkeystring3",
-      display = "Get Engines App Name3"
-    )
-
-    val appid = apps.insert(testApp)
-    val appid2 = apps.insert(testApp2)
-    val appid3 = apps.insert(testApp3)
-
-    val engineinfoid = "apple-engine"
-    val testEngine = Engine(
-      id = 0,
-      appid = appid,
-      name = "get-engine",
-      infoid = engineinfoid,
-      itypes = None, // NOTE: default None (means all itypes)
-      params = Map("a" -> "b")
-    )
-    val testEngine2 = testEngine.copy(appid = appid2, name = "get-engine2") // diff app
-    val testEngine3 = testEngine.copy(name = "get-engine3") // diff name
-    val testEngine4 = testEngine.copy(name = "get-engine4") // diff name
-
-    val engineid = engines.insert(testEngine)
-    val engineid2 = engines.insert(testEngine2)
-    val engineid3 = engines.insert(testEngine3)
-    val engineid4 = engines.insert(testEngine4)
-
-    "return the engine of the specificied /:engineid" in new WithServer {
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}"), email, password).get)
-
-      r.status must equalTo(OK) and
-        (r.json must equalTo(Json.obj(
-          "id" -> engineid,
-          "engineinfoid" -> engineinfoid,
-          "appid" -> appid,
-          "enginename" -> "get-engine",
-          "enginestatus" -> "noappdata"
-        )))
-    }
-
-    "return NOT_FOUND if invalid engineid" in new WithServer {
-      // get engine of diff app
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid2}"), email, password).get)
-
-      r.status must equalTo(NOT_FOUND)
-    }
-
-    "return NOT_FOUND if invalid appid" in new WithServer {
-      // appid not belong to this user
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/99999/engines"), email, password).get)
-
-      r.status must equalTo(NOT_FOUND)
-    }
-
-    "return NO_CONTENT if 0 engine" in new WithServer {
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid3}/engines"), email, password).get)
-
-      r.status must equalTo(NO_CONTENT)
-    }
-
-    "return list of 1 engine" in new WithServer {
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid2}/engines"), email, password).get)
-
-      r.status must equalTo(OK) and
-        (r.json must equalTo(Json.obj(
-          "id" -> appid2,
-          "enginelist" -> Json.arr(
-            Json.obj(
-              "id" -> engineid2,
-              "enginename" -> "get-engine2",
-              "engineinfoid" -> engineinfoid
-            )
-          )
-        )))
-    }
-
-    "retutn list of engines" in new WithServer {
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines"), email, password).get)
-
-      r.status must equalTo(OK) and
-        (r.json must equalTo(Json.obj(
-          "id" -> appid,
-          "enginelist" -> Json.arr(
-            Json.obj(
-              "id" -> engineid,
-              "enginename" -> "get-engine",
-              "engineinfoid" -> engineinfoid
-            ),
-            Json.obj(
-              "id" -> engineid3,
-              "enginename" -> "get-engine3",
-              "engineinfoid" -> engineinfoid
-            ),
-            Json.obj(
-              "id" -> engineid4,
-              "enginename" -> "get-engine4",
-              "engineinfoid" -> engineinfoid
-            )
-          )
-        )))
-    }
-  }
-
-  "DELETE /apps/:appid/engines/:id" should {
-    "delete the engine" in new WithServer {
-      new Pending("TODO")
-    }
-
-    "return NOT_FOUND if invalid appid" in new WithServer {
-      new Pending("TODO")
-    }
-
-    "return NOT_FOUND if invalid engineid" in new WithServer {
-      new Pending("TODO")
-    }
-  }
-
-  "POST /apps/:appid/engines/:engineid/algos_available" should {
-
-    val email = "postalgosavailable@test.com"
-    val password = "postalgosavailablepassword"
-    val (testUserid, testUser) = createTestUser("Test", "Account", email, password)
-
-    val testApp = App(
-      id = 0,
-      userid = testUserid,
-      appkey = "postalgosavailableappkeystring",
-      display = "postalgosavailable App Name",
-      url = None,
-      cat = None,
-      desc = None,
-      timezone = "UTC"
-    )
-    val appid = apps.insert(testApp)
-
-    val engineinfoid = "apple-engine"
-    val testEngine = Engine(
-      id = 0,
-      appid = appid,
-      name = "test-engine",
-      infoid = engineinfoid,
-      itypes = None, // NOTE: default None (means all itypes)
-      params = Map("a" -> "b")
-    )
-    val engineid = engines.insert(testEngine)
-
-    "create algo and write to database" in new WithServer {
-      val algoinfoid = "pizza-algo"
-      val algoname = "my-algo"
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}/algos_available"), email, password).
-        post(Json.obj("algoinfoid" -> algoinfoid, "algoname" -> algoname)))
-
-      val algoid = (r.json \ "id").asOpt[Int].getOrElse(0)
-
-      val validAlgoid = (algoid != 0)
-      // check database
-      val algoInDB = algos.get(algoid)
-      val dbWritten = algoInDB.map { algo =>
-        (algo.engineid == engineid) &&
-          (algo.name == algoname) &&
-          (algo.infoid == algoinfoid)
-      }.getOrElse(false)
-
-      val expectedAlgoJson = Json.obj(
-        "id" -> algoid,
-        "algoname" -> algoname,
-        "appid" -> appid,
-        "engineid" -> engineid,
-        "algoinfoid" -> algoinfoid,
-        "algoinfoname" -> algoInfos.get("pizza-algo").get.name,
-        "status" -> "ready",
-        "createdtime" -> algoInDB.map(x => timeFormat.print(x.createtime.withZone(DateTimeZone.forID("UTC")))).getOrElse[String]("error"),
-        "updatedtime" -> algoInDB.map(x => timeFormat.print(x.updatetime.withZone(DateTimeZone.forID("UTC")))).getOrElse[String]("error")
-      )
-
-      r.status must equalTo(OK) and
-        (r.json must equalTo(expectedAlgoJson))
-    }
-
-    "return BAD_REQUEST if invalid algoinfoid" in new WithServer {
-      val algoinfoid = "unkownalgoinfoid"
-      val algoname = "my-new-algo"
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}/algos_available"), email, password).
-        post(Json.obj("algoinfoid" -> algoinfoid, "algoname" -> algoname)))
-
-      r.status must equalTo(BAD_REQUEST)
-    }
-
-    "return BAD_REQUEST if algo name has space" in new WithServer {
-      val algoinfoid = "pizza-algo"
-      val algoname = "name with-space"
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}/algos_available"), email, password).
-        post(Json.obj("algoinfoid" -> algoinfoid, "algoname" -> algoname)))
-
-      r.status must equalTo(BAD_REQUEST)
-    }
-
-    "return BAD_REQUEST if empty algo name" in new WithServer {
-      val algoinfoid = "pizza-algo"
-      val algoname = ""
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}/algos_available"), email, password).
-        post(Json.obj("algoinfoid" -> algoinfoid, "algoname" -> algoname)))
-
-      r.status must equalTo(BAD_REQUEST)
-    }
-
-    "return BAD_REQUEST if duplicated algo name" in new WithServer {
-      val algoinfoid = "pizza-algo"
-      val algoname = "my-dup-algo"
-      val algoname2 = "my-dup-algo2"
-
-      val r1 = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}/algos_available"), email, password).
-        post(Json.obj("algoinfoid" -> algoinfoid, "algoname" -> algoname)))
-
-      val r1dup = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}/algos_available"), email, password).
-        post(Json.obj("algoinfoid" -> algoinfoid, "algoname" -> algoname)))
-
-      val r2 = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}/algos_available"), email, password).
-        post(Json.obj("algoinfoid" -> algoinfoid, "algoname" -> algoname2)))
-
-      r1.status must equalTo(OK) and
-        (r1dup.status must equalTo(BAD_REQUEST)) and
-        (r2.status must equalTo(OK))
-    }
-
-    "return NOT_FOUND if appid is invalid" in new WithServer {
-      val algoinfoid = "pizza-algo"
-      val algoname = "my-algoname"
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/99999/engines/${engineid}/algos_available"), email, password).
-        post(Json.obj("algoinfoid" -> algoinfoid, "algoname" -> algoname)))
-
-      r.status must equalTo(NOT_FOUND)
-    }
-
-    "return NOT_FOUND if engineid is invalid" in new WithServer {
-      val algoinfoid = "pizza-algo"
-      val algoname = "my-algoname"
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/999999/algos_available"), email, password).
-        post(Json.obj("algoinfoid" -> algoinfoid, "algoname" -> algoname)))
-
-      r.status must equalTo(NOT_FOUND)
-    }
-  }
-
-  "GET /apps/:appid/engines/:engineid/algos_available" should {
-
-    val email = "getalgosavailable@test.com"
-    val password = "getalgosavailablepassword"
-    val (testUserid, testUser) = createTestUser("Test", "Account", email, password)
-
-    val testApp = App(
-      id = 0,
-      userid = testUserid,
-      appkey = "getalgosavailableappkeystring",
-      display = "getalgosavailable App Name",
-      url = None,
-      cat = None,
-      desc = None,
-      timezone = "UTC"
-    )
-
-    val testApp2 = testApp.copy(
-      appkey = "getalgosavailableappkeystring 2",
-      display = "getalgosavailable App Name 2"
-    )
-
-    val appid = apps.insert(testApp)
-    val appid2 = apps.insert(testApp2)
-
-    val engineinfoid = "apple-engine"
-    val testEngine = Engine(
-      id = 0,
-      appid = appid,
-      name = "test-engine",
-      infoid = engineinfoid,
-      itypes = None, // NOTE: default None (means all itypes)
-      params = Map("a" -> "b")
-    )
-
-    val testEngine2 = testEngine.copy(
-      name = "test-engine2"
-    )
-
-    val testEngine3 = testEngine.copy(
-      name = "test-engin3"
-    )
-
-    val engineid = engines.insert(testEngine)
-    val engineid2 = engines.insert(testEngine2)
-    val engineid3 = engines.insert(testEngine3)
-
-    val algoInfo = algoInfos.get("pizza-algo").get
-
-    val newAlgo = Algo(
-      id = -1,
-      engineid = engineid,
-      name = "get-algo",
-      infoid = "pizza-algo",
-      command = "",
-      params = algoInfo.params.mapValues(_.defaultvalue),
-      settings = Map(), // no use for now
-      modelset = false, // init value
-      createtime = DateTime.now.hour(4).minute(56).second(35),
-      updatetime = DateTime.now.hour(5).minute(6).second(7),
-      status = "ready", // default status
-      offlineevalid = None,
-      loop = None
-    )
-
-    val newAlgo2 = newAlgo.copy(engineid = engineid2, name = "get-algo2") // diff engine\
-    val newAlgo3 = newAlgo.copy(name = "get-algo3") // diff name
-    val newAlgo4 = newAlgo.copy(name = "get-algo4") // diff name
-
-    val algoid = algos.insert(newAlgo)
-    val algoid2 = algos.insert(newAlgo2)
-    val algoid3 = algos.insert(newAlgo3)
-    val algoid4 = algos.insert(newAlgo4)
-
-    val testAlgo = newAlgo.copy(id = algoid)
-    val testAlgo2 = newAlgo2.copy(id = algoid2)
-    val testAlgo3 = newAlgo3.copy(id = algoid3)
-    val testAlgo4 = newAlgo4.copy(id = algoid4)
-
-    "return the algo of the specified /:algoid" in new WithServer {
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}/algos_available/${algoid}"), email, password).
-        get)
-
-      r.status must equalTo(OK) and
-        (r.json must equalTo(Json.obj(
-          "id" -> algoid,
-          "algoname" -> "get-algo",
-          "appid" -> appid,
-          "engineid" -> engineid,
-          "algoinfoid" -> "pizza-algo",
-          "algoinfoname" -> algoInfos.get("pizza-algo").get.name,
-          "status" -> "ready",
-          "createdtime" -> timeFormat.print(DateTime.now.hour(4).minute(56).second(35).withZone(DateTimeZone.forID("UTC"))),
-          "updatedtime" -> timeFormat.print(DateTime.now.hour(5).minute(6).second(7).withZone(DateTimeZone.forID("UTC")))
-        )))
-    }
-
-    "return NOT_FOUND if invalid algoid" in new WithServer {
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}/algos_available/${algoid2}"), email, password).
-        get)
-
-      r.status must equalTo(NOT_FOUND)
-    }
-
-    "return NOT_FOUND if invalid appid" in new WithServer {
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/999999/engines/${engineid}/algos_available"), email, password).
-        get)
-
-      r.status must equalTo(NOT_FOUND)
-    }
-
-    "return NOT_FOUND if invalid engineid" in new WithServer {
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/9999/algos_available"), email, password).
-        get)
-
-      r.status must equalTo(NOT_FOUND)
-    }
-
-    "return NO_CONTENT if 0 algo" in new WithServer {
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid3}/algos_available"), email, password).
-        get)
-
-      r.status must equalTo(NO_CONTENT)
-    }
-
-    "return list of 1 algo" in new WithServer {
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid2}/algos_available"), email, password).
-        get)
-
-      r.status must equalTo(OK) and
-        (r.json must equalTo(Json.arr(Json.obj(
-          "id" -> algoid2,
-          "algoname" -> "get-algo2",
-          "appid" -> appid,
-          "engineid" -> engineid2,
-          "algoinfoid" -> "pizza-algo",
-          "algoinfoname" -> algoInfos.get("pizza-algo").get.name,
-          "status" -> "ready",
-          "createdtime" -> timeFormat.print(DateTime.now.hour(4).minute(56).second(35).withZone(DateTimeZone.forID("UTC"))),
-          "updatedtime" -> timeFormat.print(DateTime.now.hour(5).minute(6).second(7).withZone(DateTimeZone.forID("UTC")))
-        ))))
-    }
-
-    "return list of algos" in new WithServer {
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}/algos_available"), email, password).
-        get)
-
-      val algo = Json.obj(
-        "id" -> algoid,
-        "algoname" -> "get-algo",
-        "appid" -> appid,
-        "engineid" -> engineid,
-        "algoinfoid" -> "pizza-algo",
-        "algoinfoname" -> algoInfos.get("pizza-algo").get.name,
-        "status" -> "ready",
-        "createdtime" -> timeFormat.print(DateTime.now.hour(4).minute(56).second(35).withZone(DateTimeZone.forID("UTC"))),
-        "updatedtime" -> timeFormat.print(DateTime.now.hour(5).minute(6).second(7).withZone(DateTimeZone.forID("UTC")))
-      )
-      val algo3 = Json.obj(
-        "id" -> algoid3,
-        "algoname" -> "get-algo3",
-        "appid" -> appid,
-        "engineid" -> engineid,
-        "algoinfoid" -> "pizza-algo",
-        "algoinfoname" -> algoInfos.get("pizza-algo").get.name,
-        "status" -> "ready",
-        "createdtime" -> timeFormat.print(DateTime.now.hour(4).minute(56).second(35).withZone(DateTimeZone.forID("UTC"))),
-        "updatedtime" -> timeFormat.print(DateTime.now.hour(5).minute(6).second(7).withZone(DateTimeZone.forID("UTC")))
-      )
-      val algo4 = Json.obj(
-        "id" -> algoid4,
-        "algoname" -> "get-algo4",
-        "appid" -> appid,
-        "engineid" -> engineid,
-        "algoinfoid" -> "pizza-algo",
-        "algoinfoname" -> algoInfos.get("pizza-algo").get.name,
-        "status" -> "ready",
-        "createdtime" -> timeFormat.print(DateTime.now.hour(4).minute(56).second(35).withZone(DateTimeZone.forID("UTC"))),
-        "updatedtime" -> timeFormat.print(DateTime.now.hour(5).minute(6).second(7).withZone(DateTimeZone.forID("UTC")))
-      )
-      r.status must equalTo(OK) and
-        (r.json must equalTo(Json.arr(algo, algo3, algo4)))
-    }
-
-    "include algos with ready/tuning/tuned status and exclude algos with simeval/deployed status" in new WithServer {
-      // create a new engine for this test
-      val testEngineNew = testEngine.copy(
-        name = "test-engine-new"
-      )
-
-      val engineid = engines.insert(testEngineNew)
-
-      val readyAlgo = newAlgo.copy(name = "get-algo-deployed-ready", status = "ready", engineid = engineid)
-      val tuningAlgo = newAlgo.copy(name = "get-algo-deployed-tuning", status = "tuning", engineid = engineid)
-      val tunedAlgo = newAlgo.copy(name = "get-algo-deployed-tuned", status = "tuned", engineid = engineid)
-      val simevalAlgo = newAlgo.copy(name = "get-algo-deployed-simeval", status = "simeval", engineid = engineid)
-
-      val readyAlgoid = algos.insert(readyAlgo)
-      val tuningAlgoid = algos.insert(tuningAlgo)
-      val tunedAlgoid = algos.insert(tunedAlgo)
-      val simevalAlgoid = algos.insert(simevalAlgo)
-
-      val r1 = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}/algos_available"), email, password).
-        get)
-
-      // change the status to deployed
-      val readyAlgoUpdated = readyAlgo.copy(id = readyAlgoid, status = "deployed")
-      val tunedAlgoUpdated = tunedAlgo.copy(id = tunedAlgoid, status = "simeval")
-      val simevalAlgoUpdated = simevalAlgo.copy(id = simevalAlgoid, status = "ready")
-
-      algos.update(readyAlgoUpdated)
-      algos.update(tunedAlgoUpdated)
-      algos.update(simevalAlgoUpdated)
-
-      val r2 = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}/algos_available"), email, password).
-        get)
-
-      r1.status must equalTo(OK) and
-        (r1.json must equalTo(Json.arr(
-          algoToJson(readyAlgo.copy(id = readyAlgoid), appid),
-          algoToJson(tunedAlgo.copy(id = tunedAlgoid), appid),
-          algoToJson(tuningAlgo.copy(id = tuningAlgoid), appid)))) and
-        (r2.status must equalTo(OK)) and
-        (r2.json must equalTo(Json.arr(
-          algoToJson(simevalAlgoUpdated, appid),
-          algoToJson(tuningAlgo.copy(id = tuningAlgoid), appid))))
-    }
-  }
-
-  "DELETE /apps/:appid/engines/:engineid/algos_available/:id" should {
-
-    val email = "deletealgosavailable@test.com"
-    val password = "deletealgosavailablepassword"
-    val (testUserid, testUser) = createTestUser("Test", "Account", email, password)
-
-    val testApp = App(
-      id = 0,
-      userid = testUserid,
-      appkey = "deletealgosavailableappkeystring",
-      display = "deletealgosavailable App Name",
-      url = None,
-      cat = None,
-      desc = None,
-      timezone = "UTC"
-    )
-
-    val appid = apps.insert(testApp)
-
-    val engineinfoid = "apple-engine"
-    val testEngine = Engine(
-      id = 0,
-      appid = appid,
-      name = "test-engine",
-      infoid = engineinfoid,
-      itypes = None, // NOTE: default None (means all itypes)
-      params = Map("a" -> "b")
-    )
-
-    val engineid = engines.insert(testEngine)
-
-    val algoInfo = algoInfos.get("pizza-algo").get
-
-    val testAlgo = Algo(
-      id = -1,
-      engineid = engineid,
-      name = "delete-algo",
-      infoid = "pizza-algo",
-      command = "",
-      params = algoInfo.params.mapValues(_.defaultvalue),
-      settings = Map(), // no use for now
-      modelset = false, // init value
-      createtime = DateTime.now.hour(4).minute(56).second(35),
-      updatetime = DateTime.now.hour(5).minute(6).second(7),
-      status = "ready", // default status
-      offlineevalid = None,
-      loop = None
-    )
-
-    val testAlgo2 = testAlgo.copy(name = "delete-algo2") // diff name
-
-    val algoid = algos.insert(testAlgo)
-    val algoid2 = algos.insert(testAlgo2)
-
-    "delete the algo" in new WithServer {
-      //val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}/algos_available/${algoid}"), email, password).
-      //  delete)
-
-      new Pending("TODO")
-    }
-
-    "return NOT_FOUND if invalid appid" in new WithServer {
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/9999/engines/${engineid}/algos_available/${algoid}"), email, password).
-        delete)
-
-      r.status must equalTo(NOT_FOUND)
-    }
-
-    "return NOT_FOUND if invalid engineid" in new WithServer {
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/999999/algos_available/${algoid}"), email, password).
-        delete)
-
-      r.status must equalTo(NOT_FOUND)
-    }
-
-    "return NOT_FOUND if invalid algoid" in new WithServer {
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}/algos_available/99999"), email, password).
-        delete)
-
-      r.status must equalTo(NOT_FOUND)
-    }
-  }
-
-  "GET /apps/:appid/engines/:engineid/algos_deployed" should {
-
-    val email = "getalgosdeployed@test.com"
-    val password = "getalgosdeployedpassword"
-    val (testUserid, testUser) = createTestUser("Test", "Account", email, password)
-
-    val testApp = App(
-      id = 0,
-      userid = testUserid,
-      appkey = "getalgosdeployedappkeystring",
-      display = "getalgosdeployed App Name",
-      url = None,
-      cat = None,
-      desc = None,
-      timezone = "UTC"
-    )
-
-    val testApp2 = testApp.copy(
-      appkey = "getalgosdeployedappkeystring 2",
-      display = "getalgosdeployed App Name 2"
-    )
-
-    val appid = apps.insert(testApp)
-    val appid2 = apps.insert(testApp2)
-
-    val engineinfoid = "apple-engine"
-    val testEngine = Engine(
-      id = 0,
-      appid = appid,
-      name = "test-engine",
-      infoid = engineinfoid,
-      itypes = None, // NOTE: default None (means all itypes)
-      params = Map("a" -> "b")
-    )
-
-    val testEngine2 = testEngine.copy(
-      name = "test-engine2"
-    )
-
-    val testEngine3 = testEngine.copy(
-      name = "test-engin3"
-    )
-
-    val engineid = engines.insert(testEngine)
-    val engineid2 = engines.insert(testEngine2)
-    val engineid3 = engines.insert(testEngine3)
-
-    val algoInfo = algoInfos.get("pizza-algo").get
-
-    val newAlgo = Algo(
-      id = -1,
-      engineid = engineid,
-      name = "get-algo-deployed",
-      infoid = "pizza-algo",
-      command = "",
-      params = algoInfo.params.mapValues(_.defaultvalue),
-      settings = Map(), // no use for now
-      modelset = false, // init value
-      createtime = DateTime.now.hour(4).minute(56).second(35),
-      updatetime = DateTime.now.hour(5).minute(6).second(7),
-      status = "deployed", // default status
-      offlineevalid = None,
-      loop = None
-    )
-
-    val newAlgo2 = newAlgo.copy(engineid = engineid2, name = "get-algo-deployed2") // diff engine\
-    val newAlgo3 = newAlgo.copy(name = "get-algo-deployed3") // diff name
-    val newAlgo4 = newAlgo.copy(name = "get-algo-deployed4") // diff name
-
-    val algoid = algos.insert(newAlgo)
-    val algoid2 = algos.insert(newAlgo2)
-    val algoid3 = algos.insert(newAlgo3)
-    val algoid4 = algos.insert(newAlgo4)
-
-    val testAlgo = newAlgo.copy(id = algoid)
-    val testAlgo2 = newAlgo2.copy(id = algoid2)
-    val testAlgo3 = newAlgo3.copy(id = algoid3)
-    val testAlgo4 = newAlgo4.copy(id = algoid4)
-
-    "return NOT_FOUND if invalid appid" in new WithServer {
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/9999/engines/${engineid}/algos_deployed"), email, password).
-        get)
-
-      r.status must equalTo(NOT_FOUND)
-    }
-
-    "return NOT_FOUND if invalid engineid" in new WithServer {
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/99999/algos_deployed"), email, password).
-        get)
-
-      r.status must equalTo(NOT_FOUND)
-    }
-
-    "return NO_CONTENT if 0 deployed algo" in new WithServer {
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid3}/algos_deployed"), email, password).
-        get)
-
-      r.status must equalTo(NO_CONTENT)
-    }
-
-    "return list of 1 deployed algo" in new WithServer {
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid2}/algos_deployed"), email, password).
-        get)
-
-      r.status must equalTo(OK) and
-        (r.json must equalTo(Json.obj(
-          "updatedtime" -> "12-03-2012 12:32:12",
-          "status" -> "Running",
-          "algolist" -> Json.arr(algoToJson(testAlgo2, appid))
-        )))
-    }
-
-    "return list of deployed algos" in new WithServer {
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}/algos_deployed"), email, password).
-        get)
-
-      r.status must equalTo(OK) and
-        (r.json must equalTo(Json.obj(
-          "updatedtime" -> "12-03-2012 12:32:12",
-          "status" -> "Running",
-          "algolist" -> Json.arr(algoToJson(testAlgo, appid), algoToJson(testAlgo3, appid), algoToJson(testAlgo4, appid))
-        )))
-    }
-
-    "include algos with deployed status and exclude algos with ready/tuning/tuned/simeval status" in new WithServer {
-      // create a new engine for this test
-      val testEngineNew = testEngine.copy(
-        name = "test-engine-new"
-      )
-
-      val engineid = engines.insert(testEngineNew)
-
-      val readyAlgo = newAlgo.copy(name = "get-algo-deployed-ready", status = "ready", engineid = engineid)
-      val tuningAlgo = newAlgo.copy(name = "get-algo-deployed-tuning", status = "tuning", engineid = engineid)
-      val tunedAlgo = newAlgo.copy(name = "get-algo-deployed-tuned", status = "tuned", engineid = engineid)
-      val simevalAlgo = newAlgo.copy(name = "get-algo-deployed-simeval", status = "simeval", engineid = engineid)
-
-      val readyAlgoid = algos.insert(readyAlgo)
-      val tuningAlgoid = algos.insert(tuningAlgo)
-      val tunedAlgoid = algos.insert(tunedAlgo)
-      val simevalAlgoid = algos.insert(simevalAlgo)
-
-      val r1 = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}/algos_deployed"), email, password).
-        get)
-
-      // change the status to deployed
-      val readyAlgoUpdated = readyAlgo.copy(id = readyAlgoid, status = "deployed")
-      val tunedAlgoUpdated = tunedAlgo.copy(id = tunedAlgoid, status = "deployed")
-
-      algos.update(readyAlgoUpdated)
-      algos.update(tunedAlgoUpdated)
-
-      val r2 = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}/algos_deployed"), email, password).
-        get)
-
-      r1.status must equalTo(NO_CONTENT) and
-        (r2.status must equalTo(OK)) and
-        (r2.json must equalTo(Json.obj(
-          "updatedtime" -> "12-03-2012 12:32:12",
-          "status" -> "Running",
-          "algolist" -> Json.arr(algoToJson(readyAlgoUpdated, appid), algoToJson(tunedAlgoUpdated, appid))
-        )))
-    }
-  }
-
-  "POST /apps/:appid/engines/:engineid/algos_deploy" should {
-
-    val email = "postalgosdeploy@test.com"
-    val password = "postalgosdeploypassword"
-    val (testUserid, testUser) = createTestUser("Test", "Account", email, password)
-
-    val testApp = App(
-      id = 0,
-      userid = testUserid,
-      appkey = "postalgosdeployappkeystring",
-      display = "postalgosdeploy App Name",
-      url = None,
-      cat = None,
-      desc = None,
-      timezone = "UTC"
-    )
-
-    val appid = apps.insert(testApp)
-
-    val engineinfoid = "apple-engine"
-    val testEngine = Engine(
-      id = 0,
-      appid = appid,
-      name = "test-engine",
-      infoid = engineinfoid,
-      itypes = None, // NOTE: default None (means all itypes)
-      params = Map("a" -> "b")
-    )
-
-    val algoInfo = algoInfos.get("pizza-algo").get
-
-    val testAlgo = Algo(
-      id = -1,
-      engineid = -1,
-      name = "post-algos-deploy",
-      infoid = "pizza-algo",
-      command = "",
-      params = algoInfo.params.mapValues(_.defaultvalue),
-      settings = Map(), // no use for now
-      modelset = false, // init value
-      createtime = DateTime.now.hour(4).minute(56).second(35),
-      updatetime = DateTime.now.hour(5).minute(6).second(7),
-      status = "ready", // default status
-      offlineevalid = None,
-      loop = None
-    )
-
-    "change the specified 1 algo status to deployed" in new WithServer {
-      val engineid = engines.insert(testEngine.copy(name = "test-engine-1"))
-      val myalgo = testAlgo.copy(name = "post-algs-deploy-1", status = "ready", engineid = engineid)
-      val myalgo2 = testAlgo.copy(name = "post-algs-deploy-2", status = "ready", engineid = engineid)
-      val myalgo3 = testAlgo.copy(name = "post-algs-deploy-3", status = "ready", engineid = engineid)
-      val myalgo4 = testAlgo.copy(name = "post-algs-deploy-4", status = "ready", engineid = engineid)
-
-      val algoid = algos.insert(myalgo)
-      val algoid2 = algos.insert(myalgo2)
-      val algoid3 = algos.insert(myalgo3)
-      val algoid4 = algos.insert(myalgo4)
-
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}/algos_deploy"), email, password).
-        post(Json.obj("algoidlist" -> Json.toJson(Seq(algoid))))) // only 1 algo
-
-      // read back and check
-      val updatedAlgo = algos.get(algoid)
-      val updatedAlgo2 = algos.get(algoid2)
-      val updatedAlgo3 = algos.get(algoid3)
-      val updatedAlgo4 = algos.get(algoid4)
-
-      r.status must equalTo(OK) and
-        (updatedAlgo must beSome(myalgo.copy(id = algoid, status = "deployed"))) and
-        (updatedAlgo2 must beSome(myalgo2.copy(id = algoid2, status = "ready"))) and
-        (updatedAlgo3 must beSome(myalgo3.copy(id = algoid3, status = "ready"))) and
-        (updatedAlgo4 must beSome(myalgo4.copy(id = algoid4, status = "ready")))
-    }
-
-    "change the specified multiple algos' status to deployed" in new WithServer {
-      val engineid = engines.insert(testEngine.copy(name = "test-engine-2"))
-      val myalgo = testAlgo.copy(name = "post-algs-deploy-1", status = "ready", engineid = engineid)
-      val myalgo2 = testAlgo.copy(name = "post-algs-deploy-2", status = "ready", engineid = engineid)
-      val myalgo3 = testAlgo.copy(name = "post-algs-deploy-3", status = "ready", engineid = engineid)
-      val myalgo4 = testAlgo.copy(name = "post-algs-deploy-4", status = "ready", engineid = engineid)
-
-      val algoid = algos.insert(myalgo)
-      val algoid2 = algos.insert(myalgo2)
-      val algoid3 = algos.insert(myalgo3)
-      val algoid4 = algos.insert(myalgo4)
-
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}/algos_deploy"), email, password).
-        post(Json.obj("algoidlist" -> Json.toJson(Seq(algoid, algoid2, algoid3))))) // multiple algos
-
-      // read back and check
-      val updatedAlgo = algos.get(algoid)
-      val updatedAlgo2 = algos.get(algoid2)
-      val updatedAlgo3 = algos.get(algoid3)
-      val updatedAlgo4 = algos.get(algoid4)
-
-      r.status must equalTo(OK) and
-        (updatedAlgo must beSome(myalgo.copy(id = algoid, status = "deployed"))) and
-        (updatedAlgo2 must beSome(myalgo2.copy(id = algoid2, status = "deployed"))) and
-        (updatedAlgo3 must beSome(myalgo3.copy(id = algoid3, status = "deployed"))) and
-        (updatedAlgo4 must beSome(myalgo4.copy(id = algoid4, status = "ready")))
-    }
-
-    "also change deployed algos of this engine to ready" in new WithServer {
-      val engineid = engines.insert(testEngine.copy(name = "test-engine-2"))
-      val myalgo = testAlgo.copy(name = "post-algs-deploy-1", status = "ready", engineid = engineid)
-      val myalgo2 = testAlgo.copy(name = "post-algs-deploy-2", status = "deployed", engineid = engineid)
-      val myalgo3 = testAlgo.copy(name = "post-algs-deploy-3", status = "deployed", engineid = engineid)
-      val myalgo4 = testAlgo.copy(name = "post-algs-deploy-4", status = "ready", engineid = engineid)
-
-      val algoid = algos.insert(myalgo)
-      val algoid2 = algos.insert(myalgo2)
-      val algoid3 = algos.insert(myalgo3)
-      val algoid4 = algos.insert(myalgo4)
-
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}/algos_deploy"), email, password).
-        post(Json.obj("algoidlist" -> Json.toJson(Seq(algoid)))))
-
-      // read back and check
-      val updatedAlgo = algos.get(algoid)
-      val updatedAlgo2 = algos.get(algoid2)
-      val updatedAlgo3 = algos.get(algoid3)
-      val updatedAlgo4 = algos.get(algoid4)
-
-      r.status must equalTo(OK) and
-        (updatedAlgo must beSome(myalgo.copy(id = algoid, status = "deployed"))) and
-        (updatedAlgo2 must beSome(myalgo2.copy(id = algoid2, status = "ready"))) and
-        (updatedAlgo3 must beSome(myalgo3.copy(id = algoid3, status = "ready"))) and
-        (updatedAlgo4 must beSome(myalgo4.copy(id = algoid4, status = "ready")))
-    }
-
-    "return NOT_FOUND if invalid appid" in new WithServer {
-      val engineid = engines.insert(testEngine.copy(name = "test-engine-invalidappid"))
-      val myalgo = testAlgo.copy(name = "post-algs-deploy-1", status = "ready", engineid = engineid)
-      val algoid = algos.insert(myalgo)
-
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/99999/engines/${engineid}/algos_deploy"), email, password).
-        post(Json.obj("algoidlist" -> Json.toJson(Seq(algoid)))))
-
-      // read back and check
-      val updatedAlgo = algos.get(algoid)
-
-      r.status must equalTo(NOT_FOUND) and
-        (updatedAlgo must beSome(myalgo.copy(id = algoid)))
-    }
-
-    "return NOT_FOUND if invalid engineid" in new WithServer {
-      val engineid = engines.insert(testEngine.copy(name = "test-engine-invalidengineid"))
-      val myalgo = testAlgo.copy(name = "post-algs-deploy-1", status = "ready", engineid = engineid)
-      val algoid = algos.insert(myalgo)
-
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/9999/algos_deploy"), email, password).
-        post(Json.obj("algoidlist" -> Json.toJson(Seq(algoid)))))
-
-      // read back and check
-      val updatedAlgo = algos.get(algoid)
-
-      r.status must equalTo(NOT_FOUND) and
-        (updatedAlgo must beSome(myalgo.copy(id = algoid)))
-    }
-
-    "return BAD_REQUEST if any of the algo ids is invalid (not belong to this engine)" in new WithServer {
-      val engineid = engines.insert(testEngine.copy(name = "test-engine-invalidengine1"))
-      val engineid2 = engines.insert(testEngine.copy(name = "test-engine-invalidengine2"))
-
-      val myalgo = testAlgo.copy(name = "post-algs-deploy-1", status = "ready", engineid = engineid)
-      val myalgo2 = testAlgo.copy(name = "post-algs-deploy-2", status = "ready", engineid = engineid2) // NOTE: other engineid
-      val myalgo3 = testAlgo.copy(name = "post-algs-deploy-3", status = "ready", engineid = engineid)
-      val myalgo4 = testAlgo.copy(name = "post-algs-deploy-4", status = "ready", engineid = engineid)
-
-      val algoid = algos.insert(myalgo)
-      val algoid2 = algos.insert(myalgo2)
-      val algoid3 = algos.insert(myalgo3)
-      val algoid4 = algos.insert(myalgo4)
-
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}/algos_deploy"), email, password).
-        post(Json.obj("algoidlist" -> Json.toJson(Seq(algoid, algoid2, algoid3)))))
-
-      // read back and check
-      val updatedAlgo = algos.get(algoid)
-      val updatedAlgo2 = algos.get(algoid2)
-      val updatedAlgo3 = algos.get(algoid3)
-      val updatedAlgo4 = algos.get(algoid4)
-
-      r.status must equalTo(BAD_REQUEST) and
-        (updatedAlgo must beSome(myalgo.copy(id = algoid, status = "ready"))) and
-        (updatedAlgo2 must beSome(myalgo2.copy(id = algoid2, status = "ready"))) and
-        (updatedAlgo3 must beSome(myalgo3.copy(id = algoid3, status = "ready"))) and
-        (updatedAlgo4 must beSome(myalgo4.copy(id = algoid4, status = "ready")))
-    }
-
-    "return BAD_REQUEST if any of the algo ids is invalid (not ready)" in new WithServer {
-      val engineid = engines.insert(testEngine.copy(name = "test-engine-notready1"))
-
-      val myalgo = testAlgo.copy(name = "post-algs-deploy-1", status = "ready", engineid = engineid)
-      val myalgo2 = testAlgo.copy(name = "post-algs-deploy-2", status = "tuning", engineid = engineid) // NOTE: not ready status
-      val myalgo3 = testAlgo.copy(name = "post-algs-deploy-3", status = "ready", engineid = engineid)
-      val myalgo4 = testAlgo.copy(name = "post-algs-deploy-4", status = "ready", engineid = engineid)
-
-      val algoid = algos.insert(myalgo)
-      val algoid2 = algos.insert(myalgo2)
-      val algoid3 = algos.insert(myalgo3)
-      val algoid4 = algos.insert(myalgo4)
-
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}/algos_deploy"), email, password).
-        post(Json.obj("algoidlist" -> Json.toJson(Seq(algoid, algoid2, algoid3)))))
-
-      // read back and check
-      val updatedAlgo = algos.get(algoid)
-      val updatedAlgo2 = algos.get(algoid2)
-      val updatedAlgo3 = algos.get(algoid3)
-      val updatedAlgo4 = algos.get(algoid4)
-
-      r.status must equalTo(BAD_REQUEST) and
-        (updatedAlgo must beSome(myalgo.copy(id = algoid, status = "ready"))) and
-        (updatedAlgo2 must beSome(myalgo2.copy(id = algoid2, status = "tuning"))) and
-        (updatedAlgo3 must beSome(myalgo3.copy(id = algoid3, status = "ready"))) and
-        (updatedAlgo4 must beSome(myalgo4.copy(id = algoid4, status = "ready")))
-    }
-  }
-
-  "POST /apps/:appid/engines/:engineid/algos_undeploy" should {
-
-    val email = "postalgosundeploy@test.com"
-    val password = "postalgosundeploypassword"
-    val (testUserid, testUser) = createTestUser("Test", "Account", email, password)
-
-    val testApp = App(
-      id = 0,
-      userid = testUserid,
-      appkey = "postalgosundeployappkeystring",
-      display = "postalgosundeploy App Name",
-      url = None,
-      cat = None,
-      desc = None,
-      timezone = "UTC"
-    )
-
-    val appid = apps.insert(testApp)
-
-    val engineinfoid = "apple-engine"
-    val testEngine = Engine(
-      id = 0,
-      appid = appid,
-      name = "test-engine",
-      infoid = engineinfoid,
-      itypes = None, // NOTE: default None (means all itypes)
-      params = Map("a" -> "b")
-    )
-
-    val algoInfo = algoInfos.get("pizza-algo").get
-
-    val testAlgo = Algo(
-      id = -1,
-      engineid = -1,
-      name = "post-algos-undeploy",
-      infoid = "pizza-algo",
-      command = "",
-      params = algoInfo.params.mapValues(_.defaultvalue),
-      settings = Map(), // no use for now
-      modelset = false, // init value
-      createtime = DateTime.now.hour(4).minute(56).second(35),
-      updatetime = DateTime.now.hour(5).minute(6).second(7),
-      status = "ready", // default status
-      offlineevalid = None,
-      loop = None
-    )
-
-    "change deployed algos of this engine to ready" in new WithServer {
-      val engineid = engines.insert(testEngine.copy(name = "test-engine-undeploy1"))
-      val engineid2 = engines.insert(testEngine.copy(name = "test-engine-undeploy2"))
-
-      val myalgo = testAlgo.copy(name = "post-algs-undeploy-1", status = "deployed", engineid = engineid)
-      val myalgo2 = testAlgo.copy(name = "post-algs-undeploy-2", status = "ready", engineid = engineid)
-      val myalgo3 = testAlgo.copy(name = "post-algs-undeploy-3", status = "simeval", engineid = engineid)
-      val myalgo4 = testAlgo.copy(name = "post-algs-undeploy-4", status = "deployed", engineid = engineid2) // diff engine
-      val myalgo5 = testAlgo.copy(name = "post-algs-undeploy-5", status = "deployed", engineid = engineid)
-
-      val algoid = algos.insert(myalgo)
-      val algoid2 = algos.insert(myalgo2)
-      val algoid3 = algos.insert(myalgo3)
-      val algoid4 = algos.insert(myalgo4)
-      val algoid5 = algos.insert(myalgo5)
-
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}/algos_undeploy"), email, password).
-        post(Json.obj()))
-
-      // read back and check
-      val updatedAlgo = algos.get(algoid)
-      val updatedAlgo2 = algos.get(algoid2)
-      val updatedAlgo3 = algos.get(algoid3)
-      val updatedAlgo4 = algos.get(algoid4)
-      val updatedAlgo5 = algos.get(algoid5)
-
-      r.status must equalTo(OK) and
-        (updatedAlgo must beSome(myalgo.copy(id = algoid, status = "ready"))) and
-        (updatedAlgo2 must beSome(myalgo2.copy(id = algoid2, status = "ready"))) and
-        (updatedAlgo3 must beSome(myalgo3.copy(id = algoid3, status = "simeval"))) and
-        (updatedAlgo4 must beSome(myalgo4.copy(id = algoid4, status = "deployed"))) and
-        (updatedAlgo5 must beSome(myalgo5.copy(id = algoid5, status = "ready")))
-    }
-
-    "return NOT_FOUND if invalid appid" in new WithServer {
-      val engineid = engines.insert(testEngine.copy(name = "test-engine-invalidappid"))
-
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/9999/engines/${engineid}/algos_undeploy"), email, password).
-        post(Json.obj()))
-
-      r.status must equalTo(NOT_FOUND)
-    }
-
-    "return NOT_FOUND if invalid engineid" in new WithServer {
-      val engineid = engines.insert(testEngine.copy(name = "test-engine-invalidengineid"))
-
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/9999/algos_undeploy"), email, password).
-        post(Json.obj()))
-
-      r.status must equalTo(NOT_FOUND)
-    }
-  }
-
-  "POST /apps/:appid/engines/:engineid/algos_trainnow" should {
-    "return OK" in new WithServer {
-      new Pending("TODO")
-    }
-  }
-
-  "POST /apps/:appid/engines/:engineid/simevals" should {
-
-    val testName = "postsimevals"
-    val email = s"${testName}@test.com"
-    val password = s"${testName}password"
-    val (testUserid, testUser) = createTestUser("Test", "Account", email, password)
-    val appid = apps.insert(appTemplate(testUserid).copy(appkey = s"{testName}appkeystring", display = s"{testName} App Name"))
-
-    "create simeval with 1 algo, 1 metric, 1 splitter and write to database" in new WithServer {
-      val engineid = engines.insert(engineTemplate(appid).copy(name = "test-engine-1algo1metric"))
-      val myAlgo = algoTemplate(engineid).copy(name = "test-algo-1")
-      val myAlgo2 = algoTemplate(engineid).copy(name = "test-algo-2")
-      val myAlgo3 = algoTemplate(engineid).copy(name = "test-algo-3")
-
-      val algoid = algos.insert(myAlgo)
-      val algoid2 = algos.insert(myAlgo2)
-      val algoid3 = algos.insert(myAlgo3)
-
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}/simevals"), email, password).
-        post(Json.obj(
-          "algoids" -> Json.toJson(Seq(algoid)),
-          "infoid" -> Json.toJson(Seq("vanilla-metric", "brownie-splitter")),
-          "infotype" -> Json.toJson(Seq("offlineevalmetric", "offlineevalsplitter")),
-          "splittrain" -> 66,
-          "splittest" -> 13,
-          "evaliteration" -> 4,
-          "jParam[0]" -> 27, // metric param
-          "sParam[1]" -> 38, // splitter param
-          "tParam[1]" -> true
-        )))
-
-      // check offlineEval, metric, splitter, shadow algo
-      // this engine should only have this offline eval
-      val evalList = offlineEvals.getByEngineid(engineid).toList
-
-      val eval: OfflineEval = evalList(0)
-      val metricsList: List[OfflineEvalMetric] = offlineEvalMetrics.getByEvalid(eval.id).toList
-      val splittersList: List[OfflineEvalSplitter] = offlineEvalSplitters.getByEvalid(eval.id).toList
-      val algosList: List[Algo] = algos.getByOfflineEvalid(eval.id).toList
-
-      val expectedEval = eval.copy(
-        engineid = engineid,
-        iterations = 4,
-        tuneid = None)
-
-      val expectedMetric = OfflineEvalMetric(
-        id = metricsList(0).id, // don't check id, just copy over
-        infoid = "vanilla-metric",
-        evalid = eval.id,
-        params = Map("jParam" -> 27))
-
-      val expectedSplitter = OfflineEvalSplitter(
-        id = splittersList(0).id, // don't check id, just copy over
-        evalid = eval.id,
-        name = splittersList(0).name, // don't check name
-        infoid = "pio-distributed-trainingtestsplit",
-        settings = Map(
-          "sParam" -> 38,
-          "tParam" -> true,
-          "trainingPercent" -> 0.66,
-          "validationPercent" -> 0.0,
-          "testPercent" -> 0.13))
-
-      val expectedAlgo = myAlgo.copy(
-        id = algosList(0).id, // don't check id
-        status = "simeval",
-        offlineevalid = Some(eval.id)
-      )
-
-      if (r.status != OK) {
-        println((r.json \ "message").asOpt[String].getOrElse(""))
-      }
-
-      r.status must equalTo(OK) and
-        (evalList must equalTo(List(expectedEval))) and
-        (metricsList must equalTo(List(expectedMetric))) and
-        (splittersList must equalTo(List(expectedSplitter))) and
-        (algosList must equalTo(List(expectedAlgo)))
-    }
-
-    "create simeval with multiple algos, multiple metrics, 1 splitter and write to database" in new WithServer {
-      val engineid = engines.insert(engineTemplate(appid).copy(name = "test-engine-malgommetric"))
-      val myAlgo = algoTemplate(engineid).copy(name = "test-algo-1")
-      val myAlgo2 = algoTemplate(engineid).copy(name = "test-algo-2")
-      val myAlgo3 = algoTemplate(engineid).copy(name = "test-algo-3")
-
-      val algoid = algos.insert(myAlgo)
-      val algoid2 = algos.insert(myAlgo2)
-      val algoid3 = algos.insert(myAlgo3)
-
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}/simevals"), email, password).
-        post(Json.obj(
-          "algoids" -> Json.toJson(Seq(algoid, algoid2, algoid3)),
-          "infoid" -> Json.toJson(Seq("vanilla-metric", "brownie-splitter", "vanilla-metric")),
-          "infotype" -> Json.toJson(Seq("offlineevalmetric", "offlineevalsplitter", "offlineevalmetric")),
-          "splittrain" -> 68,
-          "splittest" -> 12,
-          "evaliteration" -> 2,
-          "jParam[0]" -> 22, // metric param
-          "sParam[1]" -> 31, // splitter param
-          "tParaa[1]" -> false,
-          "jParam[2]" -> 44 // 2nd metric param
-        )))
-
-      // check offlineEval, metric, splitter, shadow algo
-      // this engine should only have this offline eval
-      val evalList = offlineEvals.getByEngineid(engineid).toList
-
-      val eval: OfflineEval = evalList(0)
-      val metricsList: List[OfflineEvalMetric] = offlineEvalMetrics.getByEvalid(eval.id).toList
-      val splittersList: List[OfflineEvalSplitter] = offlineEvalSplitters.getByEvalid(eval.id).toList
-      val algosList: List[Algo] = algos.getByOfflineEvalid(eval.id).toList
-
-      val expectedEval = eval.copy(
-        engineid = engineid,
-        iterations = 2,
-        tuneid = None)
-
-      val expectedMetric = OfflineEvalMetric(
-        id = metricsList(0).id, // don't check id, just copy over
-        infoid = "vanilla-metric",
-        evalid = eval.id,
-        params = Map("jParam" -> 22))
-
-      val expectedMetric2 = OfflineEvalMetric(
-        id = metricsList(1).id, // don't check id, just copy over
-        infoid = "vanilla-metric",
-        evalid = eval.id,
-        params = Map("jParam" -> 44))
-
-      val expectedSplitter = OfflineEvalSplitter(
-        id = splittersList(0).id, // don't check id, just copy over
-        evalid = eval.id,
-        name = splittersList(0).name, // don't check name
-        infoid = "pio-distributed-trainingtestsplit",
-        settings = Map(
-          "sParam" -> 31,
-          "tParam" -> false,
-          "trainingPercent" -> 0.68,
-          "validationPercent" -> 0.0,
-          "testPercent" -> 0.12))
-
-      val expectedAlgo = myAlgo.copy(
-        id = algosList(0).id, // don't check id
-        status = "simeval",
-        offlineevalid = Some(eval.id)
-      )
-
-      val expectedAlgo2 = myAlgo2.copy(
-        id = algosList(1).id, // don't check id
-        status = "simeval",
-        offlineevalid = Some(eval.id)
-      )
-      val expectedAlgo3 = myAlgo3.copy(
-        id = algosList(2).id, // don't check id
-        status = "simeval",
-        offlineevalid = Some(eval.id)
-      )
-
-      if (r.status != OK) {
-        println((r.json \ "message").asOpt[String].getOrElse(""))
-      }
-
-      r.status must equalTo(OK) and
-        (evalList must equalTo(List(expectedEval))) and
-        (metricsList must equalTo(List(expectedMetric, expectedMetric2))) and
-        (splittersList must equalTo(List(expectedSplitter))) and
-        (algosList must equalTo(List(expectedAlgo, expectedAlgo2, expectedAlgo3)))
-    }
-
-    "return BAD_REQUEST if no metric" in new WithServer {
-      new Pending("TODO")
-    }
-
-    "return BAD_REQUEST if no splitter" in new WithServer {
-      new Pending("TODO")
-    }
-
-    "return BAD_REQUEST if no algoid" in new WithServer {
-      new Pending("TODO")
-    }
-
-    "return BAD_REQUEST if invalid algoid in param" in new WithServer {
-      new Pending("TODO")
-    }
-
-    "return BAD_REQUEST if invalid metricinfoid in param" in new WithServer {
-      new Pending("TODO")
-    }
-
-    "return BAD_REQUEST if invalid metric param" in new WithServer {
-      new Pending("TODO")
-    }
-
-    "return BAD_REQUEST if invalid splitter param" in new WithServer {
-      new Pending("TODO")
-    }
-
-    "return BAD_REQUEST if splittrain is not within 1-100" in new WithServer {
-      new Pending("TODO")
-    }
-
-    "return BAD_REQUEST if splittest is not within 1-100" in new WithServer {
-      new Pending("TODO")
-    }
-
-    "return BAD_REQUEST if evaliteration is <= 0" in new WithServer {
-      new Pending("TODO")
-    }
-
-    "return NOT_FOUND if invalid appid" in new WithServer {
-      new Pending("TODO")
-    }
-
-    "return NOT_FOUND if invalid engineid" in new WithServer {
-      new Pending("TODO")
-    }
-
-  }
-
-  "GET /apps/:appid/engines/:engineid/simevals" should {
-
-    val testName = "getsimevals"
-    val email = s"${testName}@test.com"
-    val password = s"${testName}password"
-    val (testUserid, testUser) = createTestUser("Test", "Account", email, password)
-    val appid = apps.insert(appTemplate(testUserid).copy(appkey = s"{testName}appkeystring", display = s"{testName} App Name"))
-
-    "return NO_CONTENT if 0 simeval" in new WithServer {
-      val engineid = engines.insert(engineTemplate(appid).copy(name = "test-engine-0simeval"))
-
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}/simevals"), email, password).get)
-
-      r.status must equalTo(NO_CONTENT)
-    }
-
-    "return list of 1 simeval of 1 algo" in new WithServer {
-      val engineid = engines.insert(engineTemplate(appid).copy(name = "test-engine-1simeval-1"))
-      val engineid2 = engines.insert(engineTemplate(appid).copy(name = "test-engine-1simeval-2"))
-
-      val simEval = offlineEvalTemplate(engineid)
-      val simEval2 = offlineEvalTemplate(engineid2) // note: diff engine
-      val evalid = offlineEvals.insert(simEval)
-      val evalid2 = offlineEvals.insert(simEval2)
-
-      val myAlgo = algoTemplate(engineid).copy(name = "test-algo-1", status = "simeval", offlineevalid = Some(evalid))
-      val myAlgo2 = algoTemplate(engineid2).copy(name = "test-algo-2", status = "simeval", offlineevalid = Some(evalid2))
-      val algoid = algos.insert(myAlgo)
-      val algoid2 = algos.insert(myAlgo2)
-
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}/simevals"), email, password).get)
-
-      val algoJson = algoToJsonWithParam(myAlgo.copy(id = algoid), appid)
-
-      val simEvalJson = Json.obj(
-        "id" -> evalid,
-        "appid" -> appid,
-        "engineid" -> engineid,
-        "algolist" -> Json.arr(algoJson),
-        "status" -> "pending",
-        "createtime" -> simEval.createtime.map(x => timeFormat.print(x.withZone(DateTimeZone.forID("UTC")))).getOrElse[String]("error"),
-        "endtime" -> "-"
-      )
-
-      r.status must equalTo(OK) and
-        (r.json must equalTo(Json.arr(simEvalJson)))
-    }
-
-    "return list of 1 simeval of multiple algos" in new WithServer {
-      val engineid = engines.insert(engineTemplate(appid).copy(name = "test-engine-1simevalmalgos-1"))
-
-      val simEval = offlineEvalTemplate(engineid)
-      val evalid = offlineEvals.insert(simEval)
-
-      val myAlgo = algoTemplate(engineid).copy(name = "test-algo-1", status = "simeval", offlineevalid = Some(evalid))
-      val myAlgo2 = algoTemplate(engineid).copy(name = "test-algo-2", status = "simeval", offlineevalid = Some(evalid))
-      val myAlgo3 = algoTemplate(engineid).copy(name = "test-algo-2", status = "simeval", offlineevalid = Some(evalid))
-      val algoid = algos.insert(myAlgo)
-      val algoid2 = algos.insert(myAlgo2)
-      val algoid3 = algos.insert(myAlgo3)
-
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}/simevals"), email, password).get)
-
-      val algoJson = algoToJsonWithParam(myAlgo.copy(id = algoid), appid)
-      val algoJson2 = algoToJsonWithParam(myAlgo2.copy(id = algoid2), appid)
-      val algoJson3 = algoToJsonWithParam(myAlgo3.copy(id = algoid3), appid)
-
-      val simEvalJson = Json.obj(
-        "id" -> evalid,
-        "appid" -> appid,
-        "engineid" -> engineid,
-        "algolist" -> Json.arr(algoJson, algoJson2, algoJson3),
-        "status" -> "pending",
-        "createtime" -> simEval.createtime.map(x => timeFormat.print(x.withZone(DateTimeZone.forID("UTC")))).getOrElse[String]("error"),
-        "endtime" -> "-"
-      )
-
-      r.status must equalTo(OK) and
-        (r.json must equalTo(Json.arr(simEvalJson)))
-    }
-
-    "return list of simevals" in new WithServer {
-      val engineid = engines.insert(engineTemplate(appid).copy(name = "test-engine-simevals"))
-
-      // TODO: check eval status 
-      val simEval = offlineEvalTemplate(engineid)
-      val evalid = offlineEvals.insert(simEval)
-      val evalid2 = offlineEvals.insert(simEval)
-      val evalid3 = offlineEvals.insert(simEval)
-
-      val myAlgo = algoTemplate(engineid).copy(name = "test-algo-1", status = "simeval", offlineevalid = Some(evalid))
-      val myAlgo2 = algoTemplate(engineid).copy(name = "test-algo-2", status = "simeval", offlineevalid = Some(evalid))
-      val myAlgo3 = algoTemplate(engineid).copy(name = "test-algo-3", status = "simeval", offlineevalid = Some(evalid))
-      val myAlgo4 = algoTemplate(engineid).copy(name = "test-algo-4", status = "simeval", offlineevalid = Some(evalid2))
-      val myAlgo5 = algoTemplate(engineid).copy(name = "test-algo-5", status = "simeval", offlineevalid = Some(evalid2))
-      val myAlgo6 = algoTemplate(engineid).copy(name = "test-algo-6", status = "simeval", offlineevalid = Some(evalid3))
-
-      val algoid = algos.insert(myAlgo)
-      val algoid2 = algos.insert(myAlgo2)
-      val algoid3 = algos.insert(myAlgo3)
-      val algoid4 = algos.insert(myAlgo4)
-      val algoid5 = algos.insert(myAlgo5)
-      val algoid6 = algos.insert(myAlgo6)
-
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}/simevals"), email, password).get)
-
-      val algoJson = algoToJsonWithParam(myAlgo.copy(id = algoid), appid)
-      val algoJson2 = algoToJsonWithParam(myAlgo2.copy(id = algoid2), appid)
-      val algoJson3 = algoToJsonWithParam(myAlgo3.copy(id = algoid3), appid)
-      val algoJson4 = algoToJsonWithParam(myAlgo4.copy(id = algoid4), appid)
-      val algoJson5 = algoToJsonWithParam(myAlgo5.copy(id = algoid5), appid)
-      val algoJson6 = algoToJsonWithParam(myAlgo6.copy(id = algoid6), appid)
-
-      val simEvalJson = Json.obj(
-        "id" -> evalid,
-        "appid" -> appid,
-        "engineid" -> engineid,
-        "algolist" -> Json.arr(algoJson, algoJson2, algoJson3),
-        "status" -> "pending",
-        "createtime" -> simEval.createtime.map(x => timeFormat.print(x.withZone(DateTimeZone.forID("UTC")))).getOrElse[String]("error"),
-        "endtime" -> "-"
-      )
-      val simEvalJson2 = Json.obj(
-        "id" -> evalid2,
-        "appid" -> appid,
-        "engineid" -> engineid,
-        "algolist" -> Json.arr(algoJson4, algoJson5),
-        "status" -> "pending",
-        "createtime" -> simEval.createtime.map(x => timeFormat.print(x.withZone(DateTimeZone.forID("UTC")))).getOrElse[String]("error"),
-        "endtime" -> "-"
-      )
-      val simEvalJson3 = Json.obj(
-        "id" -> evalid3,
-        "appid" -> appid,
-        "engineid" -> engineid,
-        "algolist" -> Json.arr(algoJson6),
-        "status" -> "pending",
-        "createtime" -> simEval.createtime.map(x => timeFormat.print(x.withZone(DateTimeZone.forID("UTC")))).getOrElse[String]("error"),
-        "endtime" -> "-"
-      )
-
-      if (r.status != OK) {
-        println((r.json \ "message").asOpt[String].getOrElse(""))
-      }
-
-      r.status must equalTo(OK) and
-        (r.json must equalTo(Json.arr(simEvalJson, simEvalJson2, simEvalJson3)))
-    }
-
-    "return NOT_FOUND if invalid appid" in new WithServer {
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/9999/simevals"), email, password).get)
-
-      r.status must equalTo(NOT_FOUND)
-    }
-
-    "return NOT_FOUND if invalid engineid" in new WithServer {
-      val engineid = engines.insert(engineTemplate(appid).copy(name = "test-engine-invalidappid"))
-
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/9999/engines/${engineid}/simevals"), email, password).get)
-
-      r.status must equalTo(NOT_FOUND)
-    }
-  }
-
-  "DELETE /apps/:appid/engines/:engineid/simevals/:id " should {
-    "delete the simeval" in new WithServer {
-      new Pending("TODO")
-    }
-
-    "return NOT_FOUND if invalid appid" in new WithServer {
-      new Pending("TODO")
-    }
-
-    "return NOT_FOUND if invalid engineid" in new WithServer {
-      new Pending("TODO")
-    }
-
-    "return NOT_FOUND if invalid simevalid" in new WithServer {
-      new Pending("TODO")
-    }
-  }
-
-  "GET /apps/:appid/engines/:engineid/simevals/:id/report" should {
-
-    val testName = "getsimevalsreport"
-    val email = s"${testName}@test.com"
-    val password = s"${testName}password"
-    val (testUserid, testUser) = createTestUser("Test", "Account", email, password)
-    val appid = apps.insert(appTemplate(testUserid).copy(appkey = s"{testName}appkeystring", display = s"{testName} App Name"))
-
-    "return the report of the simeval of 1 algo, 1 metric and 1 iteration" in new WithServer {
-      val engineid = engines.insert(engineTemplate(appid).copy(name = "test-engine-1simevalmalgos-1"))
-
-      val simEval = offlineEvalTemplate(engineid).copy(
-        iterations = 1
-      )
-      val evalid = offlineEvals.insert(simEval)
-
-      val myAlgo = algoTemplate(engineid).copy(name = "test-algo-1", status = "simeval", offlineevalid = Some(evalid))
-      val algoid = algos.insert(myAlgo)
-
-      val metric = offlineEvalMetricTemplate(evalid)
-      val metricid = offlineEvalMetrics.insert(metric)
-
-      val mySplitter = offlineEvalSplitterTemplate(evalid).copy(
-        settings = Map(
-          "sParam" -> 31,
-          "tParam" -> false,
-          "trainingPercent" -> 0.68,
-          "validationPercent" -> 0.0,
-          "testPercent" -> 0.12))
-
-      val splitterid = offlineEvalSplitters.insert(mySplitter)
-
-      offlineEvalResults.save(OfflineEvalResult(
-        evalid = evalid,
-        metricid = metricid,
-        algoid = algoid,
-        score = 1.23,
-        iteration = 1,
-        splitset = "test"
-      ))
-
-      val r = HelperAwait(signedinRequest(wsUrl(s"/apps/${appid}/engines/${engineid}/simevals/${evalid}/report"), email, password).get)
-
-      val algoJson = algoToJsonWithParam(myAlgo.copy(id = algoid), appid)
-
-      val metricJson = offlineEvalMetricToJsonWithParam(metric.copy(id = metricid), engineid)
-
-      val scoreJson = Json.obj(
-        "algoid" -> algoid,
-        "metricsid" -> metricid,
-        "score" -> "1.23"
-      )
-
-      val iteration1algoJson = Json.obj(
-        "algoid" -> algoid,
-        "metricsid" -> metricid,
-        "score" -> "1.23"
-      )
-
-      val iteartion1Json = Json.arr(iteration1algoJson)
-
-      val reportJson = Json.obj(
-        "id" -> evalid,
-        "appid" -> appid,
-        "engineid" -> engineid,
-        "algolist" -> Json.arr(algoJson),
-        "metricslist" -> Json.arr(metricJson),
-        "metricscorelist" -> Json.arr(scoreJson),
-        "metricscoreiterationlist" -> Json.arr(iteartion1Json),
-        "splittrain" -> 68,
-        "splittest" -> 12,
-        "splittersettingsstring" -> "S parameter: 31, T parameter: false",
-        "evaliteration" -> 1,
-        "status" -> "pending",
-        "starttime" -> "-",
-        "endtime" -> "-"
-      )
-
-      if (r.status != OK) {
-        println(r.body)
-      }
-
-      r.status must equalTo(OK) and
-        (r.json must equalTo(reportJson))
-    }
-
-    "return NOT_FOUND if invalid appid" in new WithServer {
-      new Pending("TODO")
-    }
-
-    "return NOT_FOUND if invalid engineid" in new WithServer {
-      new Pending("TODO")
-    }
-
-    "return NOT_FOUND if invalid simevalid" in new WithServer {
-      new Pending("TODO")
-    }
-  }
-
-  step {
-    MongoConnection()(config.settingsDbName).dropDatabase()
-  }
-}
\ No newline at end of file
diff --git a/servers/admin/test/AdminSpec.scala b/servers/admin/test/AdminSpec.scala
deleted file mode 100644
index 24b77fb..0000000
--- a/servers/admin/test/AdminSpec.scala
+++ /dev/null
@@ -1,390 +0,0 @@
-package controllers
-
-import io.prediction.commons.Config
-import io.prediction.commons.settings._
-
-import play.api.data._
-import play.api.data.Forms._
-import play.api.test._
-import play.api.test.Helpers._
-
-import org.specs2.mutable._
-
-import com.mongodb.casbah.Imports._
-
-import Forms._
-
-class AdminSpec extends Specification {
-  "PredictionIO Admin Specification".txt
-
-  /** Setup test data. */
-  val config = new Config
-  val algoInfos = config.getSettingsAlgoInfos()
-  val engineInfos = config.getSettingsEngineInfos()
-  val offlineEvalMetricInfos = config.getSettingsOfflineEvalMetricInfos()
-  val offlineEvalSplitterInfos = config.getSettingsOfflineEvalSplitterInfos()
-
-  algoInfos.insert(AlgoInfo(
-    id = "dummy",
-    name = "dummy",
-    description = None,
-    batchcommands = None,
-    offlineevalcommands = None,
-    params = Map(
-      "ab" -> Param(
-        id = "ab",
-        name = "ab",
-        description = None,
-        defaultvalue = "ab",
-        ui = ParamUI(),
-        constraint = ParamIntegerConstraint()),
-      "cd" -> Param(
-        id = "cd",
-        name = "cd",
-        description = None,
-        defaultvalue = "cd",
-        constraint = ParamBooleanConstraint(),
-        ui = ParamUI(),
-        scopes = Some(Set("manual"))),
-      "ef" -> Param(
-        id = "ef",
-        name = "ef",
-        description = None,
-        defaultvalue = "ef",
-        ui = ParamUI(),
-        constraint = ParamStringConstraint()),
-      "gh" -> Param(
-        id = "gh",
-        name = "gh",
-        description = None,
-        defaultvalue = "gh",
-        constraint = ParamDoubleConstraint(),
-        ui = ParamUI(),
-        scopes = Some(Set("auto", "manual")))),
-    paramorder = Seq("ab", "cd", "ef", "gh", "ij"),
-    paramsections = Seq(),
-    engineinfoid = "dummy",
-    techreq = Seq(),
-    datareq = Seq()))
-
-  engineInfos.insert(EngineInfo(
-    id = "v12",
-    name = "v12",
-    description = None,
-    params = Map(
-      "similarityFunction" -> Param(
-        id = "similarityFunction",
-        name = "similarityFunction",
-        description = None,
-        defaultvalue = "coocurrence",
-        ui = ParamUI(),
-        constraint = ParamStringConstraint()),
-      "freshness" -> Param(
-        id = "freshness",
-        name = "freshness",
-        description = None,
-        defaultvalue = 0,
-        ui = ParamUI(),
-        constraint = ParamIntegerConstraint())),
-    paramsections = Seq(),
-    defaultalgoinfoid = "dummy",
-    defaultofflineevalmetricinfoid = "dummy-metric",
-    defaultofflineevalsplitterinfoid = "dummy-splitter"))
-
-  offlineEvalMetricInfos.insert(OfflineEvalMetricInfo(
-    id = "dummy-metric",
-    name = "dummy-metric",
-    description = None,
-    engineinfoids = Seq("itemrec"),
-    commands = None,
-    params = Map(
-      "foo" -> Param(
-        id = "foo",
-        name = "foo",
-        description = None,
-        defaultvalue = "bar",
-        ui = ParamUI(),
-        constraint = ParamStringConstraint()),
-      "bar" -> Param(
-        id = "bar",
-        name = "bar",
-        description = None,
-        defaultvalue = 3.14,
-        ui = ParamUI(),
-        constraint = ParamDoubleConstraint())),
-    paramsections = Seq(),
-    paramorder = Seq()))
-
-  offlineEvalSplitterInfos.insert(OfflineEvalSplitterInfo(
-    id = "dummy-splitter",
-    name = "dummy-splitter",
-    description = None,
-    engineinfoids = Seq("itemsim"),
-    commands = None,
-    params = Map(
-      "foo" -> Param(
-        id = "foo",
-        name = "foo",
-        description = None,
-        defaultvalue = true,
-        ui = ParamUI(),
-        constraint = ParamBooleanConstraint()),
-      "bar" -> Param(
-        id = "bar",
-        name = "bar",
-        description = None,
-        defaultvalue = 3,
-        ui = ParamUI(),
-        constraint = ParamIntegerConstraint())),
-    paramsections = Seq(),
-    paramorder = Seq()))
-
-  "PredictionIO Forms" should {
-    "bind from good request 1" in new WithApplication {
-      val f = Form(single("algoinfoid" -> mapOfStringToAny))
-      val bf = f.bind(Map(
-        "algoinfoid" -> "dummy",
-        "infotype" -> "algo",
-        "ab" -> "123",
-        "cd" -> "false",
-        "ef" -> "deadbeef",
-        "gh" -> "456.789"))
-      bf.hasErrors must beFalse and
-        (bf.fold(
-          f => 1 must be_==(2),
-          params => {
-            params("ef") must be_==("deadbeef") and
-              (params("ab") must be_==(123)) and
-              (params("cd") must be_==(false)) and
-              (params("gh") must be_==(456.789))
-          }
-        ))
-    }
-
-    "bind from good request 2" in new WithApplication {
-      val f = Form(single("anyid" -> mapOfStringToAny))
-      val bf = f.bind(Map(
-        "anyid" -> "v12",
-        "infotype" -> "engine",
-        "freshness" -> "4",
-        "similarityFunction" -> "tanimoto"))
-      bf.hasErrors must beFalse and
-        (bf.fold(
-          f => 1 must be_==(2),
-          params => {
-            params("freshness") must be_==(4) and
-              (params("similarityFunction") must be_==("tanimoto"))
-          }
-        ))
-    }
-
-    "bind from good request 3" in new WithApplication {
-      val f = Form(single("anyid" -> mapOfStringToAny))
-      val bf = f.bind(Map(
-        "anyid" -> "v12",
-        "infotype" -> "engine",
-        "freshness" -> "4",
-        "similarityFunction" -> "city"))
-      bf.hasErrors must beFalse and
-        (bf.fold(
-          f => 1 must be_==(2),
-          params => {
-            params("freshness") must be_==(4)
-          }
-        ))
-    }
-
-    "bind from good request 4" in new WithApplication {
-      val f = Form(single("infoid" -> seqOfMapOfStringToAny))
-      val bf = f.bind(Map(
-        "infoid[1]" -> "dummy-splitter",
-        "infoid[0]" -> "dummy-metric",
-        "infotype[1]" -> "offlineevalsplitter",
-        "infotype[0]" -> "offlineevalmetric",
-        "foo[0]" -> "baz",
-        "bar[0]" -> "12.345",
-        "foo[1]" -> "false",
-        "bar[1]" -> "54321"))
-      bf.hasErrors must beFalse and
-        (bf.fold(
-          f => 1 must be_==(2),
-          params => {
-            (params(0)("foo") must be_==("baz")) and
-              (params(0)("bar") must be_==(12.345)) and
-              (params(1)("foo") must be_==(false)) and
-              (params(1)("bar") must be_==(54321))
-          }
-        ))
-    }
-
-    "bind from bad request 1" in new WithApplication {
-      val f = Form(tuple(
-        "algoinfoid" -> mapOfStringToAny,
-        "dummy" -> nonEmptyText))
-      val bf = f.bind(Map(
-        "dummy" -> "something"))
-      bf.hasErrors must beTrue
-    }
-
-    "bind from bad request 2" in new WithApplication {
-      val f = Form(single("algoinfoid" -> mapOfStringToAny))
-      val bf = f.bind(Map(
-        "algoinfoid" -> "dummy",
-        "infotype" -> "algo",
-        "ab" -> "123asdf",
-        "cd" -> "false",
-        "ef" -> "deadbeef",
-        "gh" -> "456.789"))
-      bf.hasErrors must beTrue and
-        (bf.errors(0).key must be_==("ab"))
-    }
-
-    "bind from bad request 3" in new WithApplication {
-      val f = Form(single("algoinfoid" -> mapOfStringToAny))
-      val bf = f.bind(Map(
-        "algoinfoid" -> "dummy",
-        "infotype" -> "algo",
-        "scope" -> "manual",
-        "ab" -> "123",
-        "cd" -> "fals",
-        "ef" -> "deadbeef",
-        "gh" -> "456.789"))
-      bf.hasErrors must beTrue and
-        (bf.errors(0).key must be_==("cd"))
-    }
-
-    "bind from bad request 4" in new WithApplication {
-      val f = Form(single("algoinfoid" -> mapOfStringToAny))
-      val bf = f.bind(Map(
-        "algoinfoid" -> "dummy",
-        "infotype" -> "algo",
-        "scope" -> "auto",
-        "ab" -> "123",
-        "cd" -> "false",
-        "ef" -> "deadbeef",
-        "gh" -> "d456.789d"))
-      bf.hasErrors must beTrue and
-        (bf.errors(0).key must be_==("gh"))
-    }
-
-    "bind from bad request 5" in new WithApplication {
-      val f = Form(single("algoinfoid" -> mapOfStringToAny))
-      val bf = f.bind(Map(
-        "algoinfoid" -> "dummy",
-        "ab" -> "123",
-        "cd" -> "false",
-        "ef" -> "deadbeef",
-        "gh" -> "d456.789d"))
-      bf.hasErrors must beTrue and
-        (bf.errors(0).key must be_==("infotype"))
-    }
-
-    "bind from bad request 6" in new WithApplication {
-      val f = Form(single("algoinfoid" -> mapOfStringToAny))
-      val bf = f.bind(Map(
-        "algoinfoid" -> "dummy",
-        "infotype" -> "bad",
-        "ab" -> "123",
-        "cd" -> "false",
-        "ef" -> "deadbeef",
-        "gh" -> "d456.789d"))
-      bf.hasErrors must beTrue and
-        (bf.errors(0).key must be_==("infotype"))
-    }
-
-    "bind from bad request 7" in new WithApplication {
-      val f = Form(single("engineinfoid" -> mapOfStringToAny))
-      val bf = f.bind(Map(
-        "engineinfoid" -> "bad",
-        "infotype" -> "engine",
-        "ab" -> "123",
-        "cd" -> "false",
-        "ef" -> "deadbeef",
-        "gh" -> "d456.789d"))
-      bf.hasErrors must beTrue and
-        (bf.errors(0).key must be_==("engineinfoid"))
-    }
-
-    "bind from good request 8" in new WithApplication {
-      val f = Form(single("infoid" -> seqOfMapOfStringToAny))
-      val bf = f.bind(Map(
-        "infoid[0]" -> "dummy-splitter",
-        "infoid[1]" -> "dummy-metric",
-        "infotype[0]" -> "offlineevalsplitter",
-        "infotype[1]" -> "offlineevalmetric",
-        "foo[0]" -> "baz",
-        "bar[0]" -> "12.345",
-        "foo[1]" -> "false",
-        "bar[1]" -> "54321"))
-      bf.hasErrors must beTrue and
-        (bf.errors(0).key must be_==("foo[0]")) and
-        (bf.errors(1).key must be_==("bar[0]"))
-    }
-  }
-
-  "Helper.offlineEvalSplitterParamToString()" should {
-    "convert splitter param to string correctly" in {
-      val splitterInfo = OfflineEvalSplitterInfo(
-        id = "dummy-splitter-x",
-        name = "dummy-splitter",
-        description = None,
-        engineinfoids = Seq("itemsim"),
-        commands = None,
-        params = Map(
-          "foo" -> Param(
-            id = "foo",
-            name = "Foo Name",
-            description = None,
-            defaultvalue = true,
-            ui = ParamUI(),
-            constraint = ParamBooleanConstraint()),
-          "bar" -> Param(
-            id = "bar",
-            name = "Bar Name",
-            description = None,
-            defaultvalue = 3,
-            ui = ParamUI(
-              uitype = "selection",
-              selections = Some(Seq(
-                ParamSelectionUI("3", "Three"),
-                ParamSelectionUI("4", "Four"),
-                ParamSelectionUI("5", "Five")
-              ))
-            ),
-            constraint = ParamIntegerConstraint())),
-        paramsections = Seq(),
-        paramorder = Seq("foo", "bar"))
-
-      val splitter = OfflineEvalSplitter(
-        id = 4,
-        evalid = 5,
-        name = "some name",
-        infoid = "dummy-splitter-x",
-        settings = Map("foo" -> false, "bar" -> 5)
-      )
-
-      val settingString = Helper.offlineEvalSplitterParamToString(splitter, Some(splitterInfo))
-      val expectedString = "Foo Name: false, Bar Name: Five"
-
-      val splitter2 = OfflineEvalSplitter(
-        id = 4,
-        evalid = 5,
-        name = "some name",
-        infoid = "dummy-splitter-x",
-        settings = Map("foo" -> true, "bar" -> 3)
-      )
-
-      val settingString2 = Helper.offlineEvalSplitterParamToString(splitter2, Some(splitterInfo))
-      val expectedString2 = "Foo Name: true, Bar Name: Three"
-
-      settingString must beEqualTo(expectedString) and
-        (settingString2 must beEqualTo(expectedString2))
-    }
-  }
-
-  step {
-    MongoConnection()(config.settingsDbName).dropDatabase()
-    MongoConnection()(config.appdataDbName).dropDatabase()
-    MongoConnection()(config.modeldataDbName).dropDatabase()
-  }
-}
diff --git a/servers/api/.gitignore b/servers/api/.gitignore
deleted file mode 100644
index 4cb1d05..0000000
--- a/servers/api/.gitignore
+++ /dev/null
@@ -1,14 +0,0 @@
-logs
-project/project
-project/target
-target
-tmp
-.history
-dist
-/.idea
-/*.iml
-/out
-/.idea_modules
-/.classpath
-/.project
-/RUNNING_PID
diff --git a/servers/api/README.md b/servers/api/README.md
deleted file mode 100644
index 247cab5..0000000
--- a/servers/api/README.md
+++ /dev/null
@@ -1,26 +0,0 @@
-How to build and run API server
-===============================
-
-## Prereq
-
-1. Install [sbt](http://www.scala-sbt.org/release/docs/Getting-Started/Setup.html).
-2. Install [play framework](http://www.playframework.com/download).
-
-## Build and run
-```
-# From the repository root. API server depends on other pio modules, need to compile and publish them first.
-sbt commons/publish output/publish
-
-# Go to API server directory and run play framework
-cd server/api/
-play
-
-# In play framework console
-run
-# Or, if you need to specify port number.
-run -Dhttp.port=8000
-
-# Everytime when pio modules are updated (and published).
-# Need to update the dependency in Play console.
-update 
-```
diff --git a/servers/api/app/io/prediction/api/API.scala b/servers/api/app/io/prediction/api/API.scala
deleted file mode 100644
index ff9a378..0000000
--- a/servers/api/app/io/prediction/api/API.scala
+++ /dev/null
@@ -1,725 +0,0 @@
-package io.prediction.api
-
-import io.prediction.commons._
-import io.prediction.commons.appdata.{ Item, U2IAction, User }
-import io.prediction.commons.settings.{ App, Engine }
-import io.prediction.output.AlgoOutputSelector
-
-import play.api._
-import play.api.mvc._
-import play.api.data._
-import play.api.data.Forms._
-import play.api.data.format.Formats._
-import play.api.data.validation._
-import play.api.i18n._
-import play.api.libs.concurrent.Execution.Implicits.defaultContext
-import play.api.libs.json._
-import play.api.libs.iteratee.Enumerator
-import play.api.Play.current
-
-//import com.codahale.jerkson.Json._
-import org.joda.time._
-import org.joda.time.format._
-
-object API extends Controller {
-  /** Set up commons. */
-  val config = new Config()
-
-  val apps = config.getSettingsApps()
-  val engines = config.getSettingsEngines()
-  val algos = config.getSettingsAlgos()
-
-  val users = config.getAppdataUsers()
-  val items = config.getAppdataItems()
-  val u2iActions = config.getAppdataU2IActions()
-
-  /** Set up output. */
-  val algoOutputSelector = new AlgoOutputSelector(algos)
-
-  val notFound = NotFound("Your request is not supported.")
-
-  /** Implicits for JSON conversion. */
-  trait APIResponse {
-    def status: Int
-  }
-  case class APIMessageResponse(status: Int, body: Map[String, Any]) extends APIResponse
-  case class APIUserResponse(status: Int, user: User) extends APIResponse
-  case class APIItemResponse(status: Int, item: Item) extends APIResponse
-  case class APIErrors(errors: Seq[Map[String, String]])
-
-  implicit object APIResponseToJson extends Writes[APIResponse] {
-    def writes(r: APIResponse) = r match {
-      case msg: APIMessageResponse => Json.toJson(msg.asInstanceOf[APIMessageResponse].body.mapValues { anyToJsValue(_) })
-      case user: APIUserResponse => Json.toJson(user.asInstanceOf[APIUserResponse].user)
-      case item: APIItemResponse => Json.toJson(item.asInstanceOf[APIItemResponse].item)
-    }
-  }
-
-  implicit object APIErrorsToJson extends Writes[APIErrors] {
-    def writes(e: APIErrors) = {
-      Json.toJson(e.errors)
-    }
-  }
-
-  implicit object UserToJson extends Writes[User] {
-    def writes(user: User) =
-      Json.obj(
-        "pio_uid" -> user.id) ++
-        //"pio_ct" -> user.ct) ++
-        (user.latlng map { l => Json.obj("pio_latlng" -> Json.arr(l._1, l._2)) } getOrElse emptyJsonObj) ++
-        (user.inactive map { i => Json.obj("pio_inactive" -> i) } getOrElse emptyJsonObj) ++
-        (user.attributes.map { a => JsObject((a mapValues { anyToJsValue(_) }).toSeq) } getOrElse emptyJsonObj)
-    //(user.attributes.map { a => Json.obj("attributes" -> Json.toJson(a mapValues { anyToJsValue(_) })) } getOrElse emptyJsonObj)
-  }
-
-  implicit object ItemToJson extends Writes[Item] {
-    def writes(item: Item) =
-      Json.obj(
-        "pio_iid" -> item.id,
-        //"pio_ct" -> item.ct,
-        "pio_itypes" -> item.itypes) ++
-        (item.starttime map { v => Json.obj("pio_startT" -> v) } getOrElse emptyJsonObj) ++
-        (item.endtime map { v => Json.obj("pio_endT" -> v) } getOrElse emptyJsonObj) ++
-        (item.price map { v => Json.obj("pio_price" -> v) } getOrElse emptyJsonObj) ++
-        (item.profit map { v => Json.obj("pio_profit" -> v) } getOrElse emptyJsonObj) ++
-        (item.latlng map { v => Json.obj("pio_latlng" -> latlngToList(v)) } getOrElse emptyJsonObj) ++
-        (item.inactive map { v => Json.obj("pio_inactive" -> v) } getOrElse emptyJsonObj) ++
-        (item.attributes.map { a => JsObject((a mapValues { anyToJsValue(_) }).toSeq) } getOrElse emptyJsonObj)
-    //(item.attributes.map { a => Json.obj("attributes" -> Json.toJson(a mapValues { anyToJsValue(_) })) } getOrElse emptyJsonObj)
-  }
-
-  def anyToJsValue(v: Any): JsValue = v match {
-    case x: Int => Json.toJson(v.asInstanceOf[Int])
-    case x: String => Json.toJson(v.asInstanceOf[String])
-    case x: Seq[_] => Json.toJson(v.asInstanceOf[Seq[String]])
-    case x: APIErrors => Json.toJson(v.asInstanceOf[APIErrors])
-    case _ => JsNull
-  }
-
-  /** Control structures used by the API. */
-  def FormattedResponse(format: String)(r: APIResponse) = {
-    format match {
-      case "json" => (new Status(r.status)(Json.stringify(Json.toJson(r)))).as(JSON)
-      case "png" => Play.resourceAsStream("public/images/spacer.png") map { stream =>
-        val fileContent: Enumerator[Array[Byte]] = Enumerator.fromStream(stream)
-        SimpleResult(
-          header = ResponseHeader(200),
-          body = fileContent)
-      } getOrElse notFound
-      case _ => notFound
-    }
-  }
-
-  def AuthenticatedApp(appkey: String)(f: App => APIResponse) = {
-    apps.getByAppkey(appkey) map { f(_) } getOrElse APIMessageResponse(FORBIDDEN, Map("message" -> "Invalid appkey."))
-  }
-
-  def ValidEngine(enginename: String)(f: Engine => APIResponse)(implicit app: App) = {
-    engines.getByAppidAndName(app.id, enginename) map { f(_) } getOrElse APIMessageResponse(
-      NOT_FOUND,
-      Map(
-        "message" -> (enginename + " is not a valid engine. Please make sure it is defined in your app's control panel.")
-      )
-    )
-  }
-
-  /**
-   * In order to override default error messages, use Lang("en") for
-   * Messages() to enforce framwork to use conf/messages.en because
-   * default messages cannot be overridden by simply using conf/messages
-   * without specifying a language.
-   */
-  def bindFailed(loe: Seq[FormError]) = APIMessageResponse(
-    BAD_REQUEST,
-    Map(
-      "errors" -> APIErrors(loe.map(e => Map("field" -> e.key, "message" -> Messages(e.message, e.args: _*)(Lang("en")))))
-    )
-  )
-
-  /** Form validation constraints. */
-  val numeric: Mapping[String] = of[String] verifying Constraints.pattern("""-?\d+(\.\d*)?""".r, "numeric", "Must be a number.")
-  val gender: Mapping[String] = of[String] verifying Constraints.pattern("""[MmFf]""".r, "gender", "Must be either 'M' or 'F'.")
-  val listOfInts: Mapping[String] = of[String] verifying Constraint[String]("listOfInts") {
-    o =>
-      {
-        try {
-          o.split(",").map { _.toInt }
-          Valid
-        } catch {
-          case _: Throwable => Invalid(ValidationError("Must be a list of integers separated by commas."))
-        }
-      }
-  }
-  val itypes: Mapping[String] = of[String] verifying Constraint[String]("itypes") { o =>
-    """[^\t]+""".r.unapplySeq(o) map { _ =>
-      val splitted = o.split(",")
-      if (splitted.size == 0)
-        Invalid(ValidationError("Must specify at least one valid item type."))
-      else if (splitted.exists(_.size == 0))
-        Invalid(ValidationError("Must not contain any empty item types."))
-      else
-        Valid
-    } getOrElse (Invalid(ValidationError("Must not contain any tab characters.")))
-  }
-  val listOfIids: Mapping[String] = of[String] verifying Constraint[String]("iids") { o =>
-    """[^\t]+""".r.unapplySeq(o) map { _ =>
-      val splitted = o.split(",")
-      if (splitted.size == 0)
-        Invalid(ValidationError("Must specify at least one valid Item ID."))
-      else if (splitted.exists(_.size == 0))
-        Invalid(ValidationError("Must not contain any empty Item ID."))
-      else
-        Valid
-    } getOrElse (Invalid(ValidationError("Must not contain any tab characters.")))
-  }
-  val latlngRegex = """-?\d+(\.\d*)?,-?\d+(\.\d*)?""".r
-  val latlng: Mapping[String] = of[String] verifying Constraint[String]("latlng", () => latlngRegex) {
-    o =>
-      latlngRegex.unapplySeq(o).map(_ => {
-        val coord = o.split(",") map { _.toDouble }
-        if (coord(0) >= -90 && coord(0) < 90 && coord(1) >= -180 && coord(1) < 180) Valid
-        else Invalid(ValidationError("Cooordinates exceed valid range (-90 <= lat < 90,-180 <= long < 180)."))
-      }).getOrElse(Invalid(ValidationError("Must be in the format of '<latitude>,<longitude>'.")))
-  }
-  val timestamp: Mapping[String] = of[String] verifying Constraint[String]("timestamp") {
-    o =>
-      {
-        try {
-          o.toLong
-          Valid
-        } catch {
-          case e: RuntimeException => try {
-            ISODateTimeFormat.dateTimeParser().parseDateTime(o)
-            Valid
-          } catch {
-            case e: IllegalArgumentException => Invalid(ValidationError("Must either be a Unix time in milliseconds, or an ISO 8601 date and time."))
-          }
-        }
-      }
-  }
-  val date: Mapping[String] = of[String] verifying Constraint[String]("date") {
-    o =>
-      {
-        try {
-          o.toLong
-          Valid
-        } catch {
-          case _: Throwable => try {
-            ISODateTimeFormat.localDateParser().parseLocalDate(o)
-            Valid
-          } catch {
-            case _: Throwable => Invalid(ValidationError("Must be an ISO 8601 date."))
-          }
-        }
-      }
-  }
-
-  /** Utilties. */
-  val emptyMap = Map()
-  val emptyJsonObj = Json.obj()
-
-  def parseLatlng(latlng: String): Tuple2[Double, Double] = {
-    val splitted = latlng.split(",")
-    (splitted(0).toDouble, splitted(1).toDouble)
-  }
-
-  def latlngToList(latlng: Tuple2[Double, Double]): List[Double] = List(latlng._1, latlng._2)
-
-  /** Accepts UNIX timestamp, ISO 8601 time format, with optional timezone conversion from app settings. */
-  def parseDateTimeFromString(timestring: String)(implicit app: App) = {
-    try {
-      new DateTime(timestring.toLong)
-    } catch {
-      case e: RuntimeException => try {
-        val dt = ISODateTimeFormat.localDateOptionalTimeParser.parseLocalDateTime(timestring)
-        dt.toDateTime(DateTimeZone.forID(app.timezone))
-      } catch {
-        case e: IllegalArgumentException => ISODateTimeFormat.dateTimeParser.parseDateTime(timestring)
-      }
-    }
-  }
-
-  /** API. */
-  def status = Action {
-    Ok("PredictionIO Output API is online.")
-  }
-
-  def options(path: String) = Action {
-    Ok("")
-  }
-
-  def createUser(format: String) = Action { implicit request =>
-    FormattedResponse(format) {
-      Attributes(tuple(
-        "pio_appkey" -> nonEmptyText,
-        "pio_uid" -> nonEmptyText,
-        "pio_latlng" -> optional(latlng),
-        "pio_inactive" -> optional(boolean)
-      ), Set( // all reserved attributes
-        "pio_appkey",
-        "pio_ct",
-        "pio_uid",
-        "pio_latlng",
-        "pio_inactive"
-      )).bindFromRequestAndFold(
-        f => bindFailed(f.errors),
-        (t, attributes) => {
-          val (appkey, uid, latlng, inactive) = t
-          AuthenticatedApp(t._1) { app =>
-            users.insert(User(
-              id = uid,
-              appid = app.id,
-              ct = DateTime.now,
-              latlng = latlng map { parseLatlng(_) },
-              inactive = inactive,
-              attributes = if (attributes.isEmpty) None else Some(attributes)
-            ))
-            APIMessageResponse(CREATED, Map("message" -> "User created."))
-          }
-        }
-      )
-    }
-  }
-
-  def getUser(format: String, uid: String) = Action { implicit request =>
-    FormattedResponse(format) {
-      Form("pio_appkey" -> nonEmptyText).bindFromRequest.fold(
-        f => bindFailed(f.errors),
-        t => AuthenticatedApp(t) { app =>
-          users.get(app.id, uid) map { user =>
-            APIUserResponse(OK, user)
-          } getOrElse APIMessageResponse(NOT_FOUND, Map("message" -> "Cannot find user."))
-        }
-      )
-    }
-  }
-
-  def deleteUser(format: String, uid: String) = Action { implicit request =>
-    FormattedResponse(format) {
-      Form("pio_appkey" -> nonEmptyText).bindFromRequest.fold(
-        f => bindFailed(f.errors),
-        t => AuthenticatedApp(t) { app =>
-          users.delete(app.id, uid)
-          APIMessageResponse(OK, Map("message" -> "User deleted."))
-        }
-      )
-    }
-  }
-
-  def createItem(format: String) = Action { implicit request =>
-    FormattedResponse(format) {
-      Attributes(tuple(
-        "pio_appkey" -> nonEmptyText,
-        "pio_iid" -> nonEmptyText,
-        "pio_itypes" -> itypes,
-        "pio_price" -> optional(numeric),
-        "pio_profit" -> optional(numeric),
-        "pio_startT" -> optional(timestamp),
-        "pio_endT" -> optional(timestamp),
-        "pio_latlng" -> optional(latlng),
-        "pio_inactive" -> optional(boolean)
-      ), Set( // all reserved attributes
-        "pio_appkey",
-        "pio_ct",
-        "pio_iid",
-        "pio_itypes",
-        "pio_price",
-        "pio_profit",
-        "pio_startT",
-        "pio_endT",
-        "pio_latlng",
-        "pio_inactive"
-      )).bindFromRequestAndFold(
-        f => bindFailed(f.errors),
-        (t, attributes) => {
-          val (appkey, iid, itypes, price, profit, startT, endT, latlng, inactive) = t
-          AuthenticatedApp(appkey) { implicit app =>
-            items.insert(Item(
-              id = iid,
-              appid = app.id,
-              ct = DateTime.now,
-              itypes = itypes.split(",").toList,
-              starttime = startT map { t => Some(parseDateTimeFromString(t)) } getOrElse Some(DateTime.now),
-              endtime = endT map { parseDateTimeFromString(_) },
-              price = price map { _.toDouble },
-              profit = profit map { _.toDouble },
-              latlng = latlng map { parseLatlng(_) },
-              inactive = inactive,
-              attributes = if (attributes.isEmpty) None else Some(attributes)
-            ))
-            APIMessageResponse(CREATED, Map("message" -> "Item created."))
-          }
-        }
-      )
-    }
-  }
-
-  def getItem(format: String, iid: String) = Action { implicit request =>
-    FormattedResponse(format) {
-      Form("pio_appkey" -> nonEmptyText).bindFromRequest.fold(
-        f => bindFailed(f.errors),
-        t => AuthenticatedApp(t) { app =>
-          items.get(app.id, iid) map { item =>
-            APIItemResponse(OK, item)
-          } getOrElse APIMessageResponse(NOT_FOUND, Map("message" -> "Cannot find item."))
-        }
-      )
-    }
-  }
-
-  def deleteItem(format: String, iid: String) = Action { implicit request =>
-    FormattedResponse(format) {
-      Form("pio_appkey" -> nonEmptyText).bindFromRequest.fold(
-        f => bindFailed(f.errors),
-        t => AuthenticatedApp(t) { app =>
-          items.delete(app.id, iid)
-          APIMessageResponse(OK, Map("message" -> "Item deleted."))
-        }
-      )
-    }
-  }
-
-  /** unified user to item action handler */
-  def userToItemAction(format: String) = Action { implicit request =>
-    FormattedResponse(format) {
-      Form(tuple(
-        "pio_appkey" -> nonEmptyText,
-        "pio_action" -> nonEmptyText,
-        "pio_uid" -> nonEmptyText,
-        "pio_iid" -> nonEmptyText,
-        "pio_t" -> optional(timestamp),
-        "pio_latlng" -> optional(latlng),
-        "pio_rate" -> optional(number(1, 5)),
-        "pio_price" -> optional(numeric)
-      )).bindFromRequest.fold(
-        f => bindFailed(f.errors),
-        fdata => AuthenticatedApp(fdata._1) { implicit app =>
-          val (appkey, action, uid, iid, t, latlng, rate, price) = fdata
-
-          val vValue: Option[Int] = action match {
-            case "rate" => rate
-            case _ => None
-          }
-          val validActions = List(u2iActions.rate, u2iActions.like, u2iActions.dislike, u2iActions.view, u2iActions.conversion)
-
-          // additional user input checking
-          if ((action == u2iActions.rate) && (vValue == None)) {
-            APIMessageResponse(BAD_REQUEST, Map("errors" -> APIErrors(Seq(Map("field" -> "pio_rate", "message" -> "Required for rate action.")))))
-          } else if (!validActions.contains(action)) {
-            APIMessageResponse(BAD_REQUEST, Map("errors" -> APIErrors(Seq(Map("field" -> "pio_action", "message" -> "Custom action is not supported yet.")))))
-          } else {
-            u2iActions.insert(U2IAction(
-              appid = app.id,
-              action = action,
-              uid = uid,
-              iid = iid,
-              t = t map { parseDateTimeFromString(_) } getOrElse DateTime.now,
-              latlng = latlng map { parseLatlng(_) },
-              v = vValue,
-              price = price map { _.toDouble }
-            ))
-            APIMessageResponse(CREATED, Map("message" -> ("Action " + action + " recorded.")))
-          }
-        }
-      )
-    }
-  }
-
-  /** legacy API for pixel tracking, no prefix pio_ */
-  def createUserLegacy(format: String) = Action { implicit request =>
-    FormattedResponse(format) {
-      Attributes(tuple(
-        "appkey" -> nonEmptyText,
-        "uid" -> nonEmptyText,
-        "latlng" -> optional(latlng),
-        "inactive" -> optional(boolean)
-      ), Set( // all reserved attributes
-        "appkey",
-        "ct",
-        "uid",
-        "latlng",
-        "inactive"
-      )).bindFromRequestAndFold(
-        f => bindFailed(f.errors),
-        (t, attributes) => {
-          val (appkey, uid, latlng, inactive) = t
-          AuthenticatedApp(t._1) { app =>
-            users.insert(User(
-              id = uid,
-              appid = app.id,
-              ct = DateTime.now,
-              latlng = latlng map { parseLatlng(_) },
-              inactive = inactive,
-              attributes = if (attributes.isEmpty) None else Some(attributes)
-            ))
-            APIMessageResponse(CREATED, Map("message" -> "User created."))
-          }
-        }
-      )
-    }
-  }
-
-  def createItemLegacy(format: String) = Action { implicit request =>
-    FormattedResponse(format) {
-      Attributes(tuple(
-        "appkey" -> nonEmptyText,
-        "iid" -> nonEmptyText,
-        "itypes" -> itypes,
-        "price" -> optional(numeric),
-        "profit" -> optional(numeric),
-        "startT" -> optional(timestamp),
-        "endT" -> optional(timestamp),
-        "latlng" -> optional(latlng),
-        "inactive" -> optional(boolean)
-      ), Set( // all reserved attributes
-        "appkey",
-        "ct",
-        "iid",
-        "itypes",
-        "price",
-        "profit",
-        "startT",
-        "endT",
-        "latlng",
-        "inactive"
-      )).bindFromRequestAndFold(
-        f => bindFailed(f.errors),
-        (t, attributes) => {
-          val (appkey, iid, itypes, price, profit, startT, endT, latlng, inactive) = t
-          AuthenticatedApp(appkey) { implicit app =>
-            items.insert(Item(
-              id = iid,
-              appid = app.id,
-              ct = DateTime.now,
-              itypes = itypes.split(",").toList,
-              starttime = startT map { t => Some(parseDateTimeFromString(t)) } getOrElse Some(DateTime.now),
-              endtime = endT map { parseDateTimeFromString(_) },
-              price = price map { _.toDouble },
-              profit = profit map { _.toDouble },
-              latlng = latlng map { parseLatlng(_) },
-              inactive = inactive,
-              attributes = if (attributes.isEmpty) None else Some(attributes)
-            ))
-            APIMessageResponse(CREATED, Map("message" -> "Item created."))
-          }
-        }
-      )
-    }
-  }
-
-  def userToItemActionLegacy(format: String, action: String) = Action { implicit request =>
-    FormattedResponse(format) {
-      Form(tuple(
-        "appkey" -> nonEmptyText,
-        //"action" -> nonEmptyText,
-        "uid" -> nonEmptyText,
-        "iid" -> nonEmptyText,
-        "t" -> optional(timestamp),
-        "latlng" -> optional(latlng),
-        "rate" -> optional(number(1, 5)),
-        "price" -> optional(numeric)
-      )).bindFromRequest.fold(
-        f => bindFailed(f.errors),
-        fdata => AuthenticatedApp(fdata._1) { implicit app =>
-          val (appkey, uid, iid, t, latlng, rate, price) = fdata
-
-          val vValue: Option[Int] = action match {
-            case "rate" => rate
-            case _ => None
-          }
-          val validActions = List(u2iActions.rate, u2iActions.like, u2iActions.dislike, u2iActions.view, u2iActions.conversion)
-
-          // additional user input checking
-          if ((action == u2iActions.rate) && (vValue == None)) {
-            APIMessageResponse(BAD_REQUEST, Map("errors" -> APIErrors(Seq(Map("field" -> "rate", "message" -> "Required for rate action.")))))
-          } else if (!validActions.contains(action)) {
-            APIMessageResponse(BAD_REQUEST, Map("errors" -> APIErrors(Seq(Map("field" -> "action", "message" -> "Custom action is not supported yet.")))))
-          } else {
-
-            u2iActions.insert(U2IAction(
-              appid = app.id,
-              action = action,
-              uid = uid,
-              iid = iid,
-              t = t map { parseDateTimeFromString(_) } getOrElse DateTime.now,
-              latlng = latlng map { parseLatlng(_) },
-              v = vValue,
-              price = price map { _.toDouble }
-            ))
-            APIMessageResponse(CREATED, Map("message" -> ("Action " + action + " recorded.")))
-          }
-        }
-      )
-    }
-  }
-
-  /** item rec topN */
-  def itemRecTopN(format: String, enginename: String) = Action { implicit request =>
-    FormattedResponse(format) {
-      Form(tuple(
-        "pio_appkey" -> nonEmptyText,
-        "pio_uid" -> nonEmptyText,
-        "pio_n" -> number(1, 100),
-        "pio_itypes" -> optional(itypes),
-        "pio_latlng" -> optional(latlng),
-        "pio_within" -> optional(numeric),
-        "pio_unit" -> optional(text),
-        "pio_attributes" -> optional(text)
-      )).bindFromRequest.fold(
-        f => bindFailed(f.errors),
-        t => {
-          val (appkey, uid, n, itypes, latlng, within, unit, attributes) = t
-          AuthenticatedApp(appkey) { implicit app =>
-            ValidEngine(enginename) { implicit engine =>
-              try {
-                val res = algoOutputSelector.itemRecSelection(
-                  uid = uid,
-                  n = n,
-                  itypes = itypes map { _.split(",") },
-                  latlng = latlng map { latlng =>
-                    val ll = latlng.split(",")
-                    (ll(0).toDouble, ll(1).toDouble)
-                  },
-                  within = within map { _.toDouble },
-                  unit = unit
-                )
-                if (res.length > 0) {
-                  val attributesToGet: Seq[String] = attributes map { _.split(",").toSeq } getOrElse Seq()
-
-                  if (attributesToGet.length > 0) {
-                    val attributedItems = items.getByIds(app.id, res).map(i => (i.id, i)).toMap
-                    val ar = attributesToGet map { atg =>
-                      Map(atg -> res.map(ri =>
-                        attributedItems(ri).attributes map { attribs =>
-                          attribs.get(atg) getOrElse null
-                        } getOrElse null
-                      ))
-                    }
-
-                    APIMessageResponse(OK, Map("pio_iids" -> res) ++ ar.reduceLeft((a, b) => a ++ b))
-                  } else {
-                    APIMessageResponse(OK, Map("pio_iids" -> res))
-                  }
-                } else {
-                  APIMessageResponse(NOT_FOUND, Map("message" -> "Cannot find recommendation for user."))
-                }
-              } catch {
-                case e: Exception =>
-                  APIMessageResponse(INTERNAL_SERVER_ERROR, Map("message" -> e.getMessage()))
-              }
-            }
-          }
-        }
-      )
-    }
-  }
-
-  def itemSimTopN(format: String, enginename: String) = Action { implicit request =>
-    FormattedResponse(format) {
-      Form(tuple(
-        "pio_appkey" -> nonEmptyText,
-        "pio_iid" -> nonEmptyText,
-        "pio_n" -> number(1, 100),
-        "pio_itypes" -> optional(itypes),
-        "pio_latlng" -> optional(latlng),
-        "pio_within" -> optional(numeric),
-        "pio_unit" -> optional(text),
-        "pio_attributes" -> optional(text)
-      )).bindFromRequest.fold(
-        f => bindFailed(f.errors),
-        t => {
-          val (appkey, iid, n, itypes, latlng, within, unit, attributes) = t
-          AuthenticatedApp(appkey) { implicit app =>
-            ValidEngine(enginename) { implicit engine =>
-              try {
-                val res = algoOutputSelector.itemSimSelection(
-                  iid = iid,
-                  n = n,
-                  itypes = itypes map { _.split(",") },
-                  latlng = latlng map { latlng =>
-                    val ll = latlng.split(",")
-                    (ll(0).toDouble, ll(1).toDouble)
-                  },
-                  within = within map { _.toDouble },
-                  unit = unit
-                )
-                if (res.length > 0) {
-                  val attributesToGet: Seq[String] = attributes map { _.split(",").toSeq } getOrElse Seq()
-
-                  if (attributesToGet.length > 0) {
-                    val attributedItems = items.getByIds(app.id, res).map(i => (i.id, i)).toMap
-                    val ar = attributesToGet map { atg =>
-                      Map(atg -> res.map(ri =>
-                        attributedItems(ri).attributes map { attribs =>
-                          attribs.get(atg) getOrElse null
-                        } getOrElse null
-                      ))
-                    }
-
-                    APIMessageResponse(OK, Map("pio_iids" -> res) ++ ar.reduceLeft((a, b) => a ++ b))
-                  } else {
-                    APIMessageResponse(OK, Map("pio_iids" -> res))
-                  }
-                } else {
-                  APIMessageResponse(NOT_FOUND, Map("message" -> "Cannot find similar items for item."))
-                }
-              } catch {
-                case e: Exception =>
-                  APIMessageResponse(INTERNAL_SERVER_ERROR, Map("message" -> e.getMessage(), "trace" -> e.getStackTrace().map(_.toString).mkString("\n")))
-              }
-            }
-          }
-        }
-      )
-    }
-  }
-
-  def itemRank(format: String, enginename: String) = Action { implicit request =>
-    FormattedResponse(format) {
-      Form(tuple(
-        "pio_appkey" -> nonEmptyText,
-        "pio_uid" -> nonEmptyText,
-        "pio_iids" -> listOfIids,
-        "pio_attributes" -> optional(text)
-      )).bindFromRequest.fold(
-        f => bindFailed(f.errors),
-        t => {
-          val (appkey, uid, iids, attributes) = t
-          AuthenticatedApp(appkey) { implicit app =>
-            ValidEngine(enginename) { implicit engine =>
-              try {
-                val res = algoOutputSelector.itemRankSelection(
-                  uid = uid,
-                  iids = iids.split(",")
-                )
-                if (res.length > 0) {
-                  val attributesToGet: Seq[String] = attributes map { _.split(",").toSeq } getOrElse Seq()
-
-                  if (attributesToGet.length > 0) {
-                    val attributedItems = items.getByIds(app.id, res).map(i => (i.id, i)).toMap
-                    val ar = attributesToGet map { atg =>
-                      Map(atg -> res.map(ri =>
-                        attributedItems(ri).attributes map { attribs =>
-                          attribs.get(atg) getOrElse null
-                        } getOrElse null
-                      ))
-                    }
-
-                    APIMessageResponse(OK, Map("pio_iids" -> res) ++ ar.reduceLeft((a, b) => a ++ b))
-                  } else {
-                    APIMessageResponse(OK, Map("pio_iids" -> res))
-                  }
-                } else {
-                  APIMessageResponse(NOT_FOUND, Map("message" -> "Cannot find item ranking for user."))
-                }
-              } catch {
-                case e: Exception =>
-                  APIMessageResponse(INTERNAL_SERVER_ERROR, Map("message" -> e.getMessage()))
-              }
-            }
-          }
-        }
-      )
-    }
-  }
-}
diff --git a/servers/api/app/io/prediction/api/Attributes.scala b/servers/api/app/io/prediction/api/Attributes.scala
deleted file mode 100644
index 42594f9..0000000
--- a/servers/api/app/io/prediction/api/Attributes.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package io.prediction.api
-
-import play.api.data._
-
-class Attributes[T](mandatory: Mapping[T], remove: Set[String]) {
-  val form = Form(mandatory)
-
-  def bindFromRequestAndFold[R](hasErrors: Form[T] => R, success: (T, Map[String, String]) => R)(implicit request: play.api.mvc.Request[_]): R = {
-    val requestData = (request.body match {
-      case body: play.api.mvc.AnyContent if body.asFormUrlEncoded.isDefined => body.asFormUrlEncoded.get
-      case _ => Map.empty[String, Seq[String]]
-    })
-    val formWithData = form.bindFromRequest
-    val extras = formWithData.data -- remove
-    formWithData.value.map(success(_, extras)).getOrElse(hasErrors(formWithData))
-  }
-}
-
-object Attributes {
-  def apply[T](mandatory: Mapping[T], remove: Set[String]): Attributes[T] = new Attributes[T](mandatory, remove)
-}
diff --git a/servers/api/app/io/prediction/api/CORSFilter.scala b/servers/api/app/io/prediction/api/CORSFilter.scala
deleted file mode 100644
index cede10c..0000000
--- a/servers/api/app/io/prediction/api/CORSFilter.scala
+++ /dev/null
@@ -1,41 +0,0 @@
-package io.prediction.api
-
-import controllers.Default
-import play.api.mvc.{ SimpleResult, RequestHeader, Filter }
-
-case class CORSFilter(allowedDomainString: Option[String] = None) extends Filter {
-  import scala.concurrent._
-  import ExecutionContext.Implicits.global
-  lazy val allowedDomains = allowedDomainString.orElse(play.api.Play.current.configuration.getString("cors.allowed.domains"))
-    .getOrElse("").split(",")
-
-  def isPreflight(r: RequestHeader) = {
-    r.method.toLowerCase.equals("options") && r.headers.get("Access-Control-Request-Method").nonEmpty
-  }
-
-  /**
-   * If the origin of the request is allowed, return the origin.
-   * Otherwise, return "" (no CORS access allowed).
-   */
-  def getOriginAllowed(requestOrigin: String): String = {
-    for (allowedDomain <- allowedDomains) {
-      if (allowedDomain == "*" || requestOrigin == allowedDomain) {
-        return requestOrigin
-      }
-    }
-    return ""
-  }
-
-  def apply(f: (RequestHeader) => Future[SimpleResult])(request: RequestHeader): Future[SimpleResult] = {
-    if (isPreflight(request)) {
-      Future.successful(Default.Ok.withHeaders(
-        "Access-Control-Allow-Origin" -> getOriginAllowed(request.headers.get("Origin").getOrElse("")),
-        "Access-Control-Allow-Methods" -> "GET, POST, DELETE"
-      ))
-    } else {
-      f(request).map(_.withHeaders(
-        "Access-Control-Allow-Origin" -> getOriginAllowed(request.headers.get("Origin").getOrElse(""))
-      ))
-    }
-  }
-}
\ No newline at end of file
diff --git a/servers/api/app/io/prediction/api/Global.scala b/servers/api/app/io/prediction/api/Global.scala
deleted file mode 100644
index bf79a56..0000000
--- a/servers/api/app/io/prediction/api/Global.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-import io.prediction.api.CORSFilter
-
-import play.api._
-import play.api.mvc._
-import play.api.mvc.Results._
-import scala.concurrent.Future
-
-object Global extends WithFilters(CORSFilter()) with GlobalSettings {
-  val notFound = NotFound("Your request is not supported.")
-
-  override def onHandlerNotFound(request: RequestHeader) = {
-    Future.successful(notFound)
-  }
-
-  override def onBadRequest(request: RequestHeader, error: String) = {
-    Future.successful(notFound)
-  }
-}
diff --git a/servers/api/build.sbt b/servers/api/build.sbt
deleted file mode 100644
index 4136040..0000000
--- a/servers/api/build.sbt
+++ /dev/null
@@ -1,15 +0,0 @@
-name := "predictionio-api"
-
-version := "0.7.3"
-
-organization := "io.prediction"
-
-libraryDependencies ++= Seq(
-  "io.prediction" %% "predictionio-commons" % version.value,
-  "io.prediction" %% "predictionio-output" % version.value)
-
-javaOptions in Test += "-Dconfig.file=conf/test.conf"
-
-play.Project.playScalaSettings
-
-scalariformSettings
diff --git a/servers/api/conf/application.conf b/servers/api/conf/application.conf
deleted file mode 100644
index ad1e8db..0000000
--- a/servers/api/conf/application.conf
+++ /dev/null
@@ -1,82 +0,0 @@
-# This is the main configuration file for the application.
-# ~~~~~
-
-# Secret key
-# ~~~~~
-# The secret key is used to secure cryptographics functions.
-# If you deploy your application to several instances be sure to use the same key!
-application.secret="LXWfyDJiEh];Q]w;6W[97aRF;[TR[2Q0yZCrZP0pbpUC2KpNFov1w5u@bpl=4/Ck"
-
-# The application languages
-# ~~~~~
-application.langs="en"
-
-# Global object class
-# ~~~~~
-# Define the Global object class for this application.
-# Default to Global in the root package.
-# global=Global
-
-# Database configuration
-# ~~~~~
-# You can declare as many datasources as you want.
-# By convention, the default datasource is named `default`
-#
-# db.default.driver=org.h2.Driver
-# db.default.url="jdbc:h2:mem:play"
-# db.default.user=sa
-# db.default.password=
-
-# Evolutions
-# ~~~~~
-# You can disable evolutions if needed
-# evolutionplugin=disabled
-
-# Logger
-# ~~~~~
-# You can also configure logback (http://logback.qos.ch/), by providing a logger.xml file in the conf directory .
-
-# Root logger:
-logger.root=ERROR
-
-# Logger used by the framework:
-logger.play=INFO
-
-# Logger provided to your application:
-logger.application=DEBUG
-
-# Domains allowed to access your API server through cross-site scripts, comma-separated.
-# Default to all domains.
-cors.allowed.domains = "*"
-
-# PredictionIO Repository Base (For Development Only)
-io.prediction.base=../..
-
-# PredictionIO Commons Settings
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.host=localhost
-io.prediction.commons.settings.db.port=27017
-
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.host=localhost
-io.prediction.commons.appdata.db.port=27017
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.host=localhost
-io.prediction.commons.appdata.test.db.port=27017
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.host=localhost
-io.prediction.commons.appdata.training.db.port=27017
-
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.host=localhost
-io.prediction.commons.appdata.validation.db.port=27017
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.host=localhost
-io.prediction.commons.modeldata.db.port=27017
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.host=localhost
-io.prediction.commons.modeldata.training.db.port=27017
diff --git a/servers/api/conf/routes b/servers/api/conf/routes
deleted file mode 100644
index 8225de3..0000000
--- a/servers/api/conf/routes
+++ /dev/null
@@ -1,26 +0,0 @@
-# Routes
-# This file defines all application routes (Higher priority routes first)
-# ~~~~
-
-OPTIONS	/*path									  io.prediction.api.API.options(path)
-
-GET     /                                         io.prediction.api.API.status()
-
-POST    /users.:format                            io.prediction.api.API.createUser(format)
-GET     /users/:uid.:format                       io.prediction.api.API.getUser(format, uid)
-DELETE  /users/:uid.:format                       io.prediction.api.API.deleteUser(format, uid)
-
-POST    /items.:format                            io.prediction.api.API.createItem(format)
-GET     /items/:iid.:format                       io.prediction.api.API.getItem(format, iid)
-DELETE  /items/:iid.:format                       io.prediction.api.API.deleteItem(format, iid)
-
-POST    /actions/u2i.:format                      io.prediction.api.API.userToItemAction(format)
-
-# For pixel tracking (legacy version, no prefix pio_)
-GET     /p/users.:format                          io.prediction.api.API.createUserLegacy(format)
-GET     /p/items.:format                          io.prediction.api.API.createItemLegacy(format)
-GET     /p/actions/u2i/:action.:format            io.prediction.api.API.userToItemActionLegacy(format, action)
-
-GET     /engines/itemrec/:engine/topn.:format     io.prediction.api.API.itemRecTopN(format, engine)
-GET     /engines/itemsim/:engine/topn.:format     io.prediction.api.API.itemSimTopN(format, engine)
-GET     /engines/itemrank/:engine/ranked.:format  io.prediction.api.API.itemRank(format, engine)
diff --git a/servers/api/conf/test.conf b/servers/api/conf/test.conf
deleted file mode 100644
index 2d69baa..0000000
--- a/servers/api/conf/test.conf
+++ /dev/null
@@ -1,81 +0,0 @@
-# This is the main configuration file for the application.
-# ~~~~~
-
-# Secret key
-# ~~~~~
-# The secret key is used to secure cryptographics functions.
-# If you deploy your application to several instances be sure to use the same key!
-application.secret="LXWfyDJiEh];Q]w;6W[97aRF;[TR[2Q0yZCrZP0pbpUC2KpNFov1w5u@bpl=4/Ck"
-
-# The application languages
-# ~~~~~
-application.langs="en"
-
-# Global object class
-# ~~~~~
-# Define the Global object class for this application.
-# Default to Global in the root package.
-# global=Global
-
-# Database configuration
-# ~~~~~
-# You can declare as many datasources as you want.
-# By convention, the default datasource is named `default`
-#
-# db.default.driver=org.h2.Driver
-# db.default.url="jdbc:h2:mem:play"
-# db.default.user=sa
-# db.default.password=
-
-# Evolutions
-# ~~~~~
-# You can disable evolutions if needed
-# evolutionplugin=disabled
-
-# Logger
-# ~~~~~
-# You can also configure logback (http://logback.qos.ch/), by providing a logger.xml file in the conf directory .
-
-# Root logger:
-logger.root=ERROR
-
-# Logger used by the framework:
-logger.play=INFO
-
-# Logger provided to your application:
-logger.application=DEBUG
-
-# PredictionIO Repository Base (For Development Only)
-io.prediction.base=../..
-
-# PredictionIO Commons Settings
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.host=localhost
-io.prediction.commons.settings.db.port=27017
-io.prediction.commons.settings.db.name=test_api_predictionio
-
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.host=localhost
-io.prediction.commons.appdata.db.port=27017
-io.prediction.commons.appdata.db.name=test_api_predictionio_appdata
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.host=localhost
-io.prediction.commons.appdata.test.db.port=27017
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.host=localhost
-io.prediction.commons.appdata.training.db.port=27017
-
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.host=localhost
-io.prediction.commons.appdata.validation.db.port=27017
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.host=localhost
-io.prediction.commons.modeldata.db.port=27017
-io.prediction.commons.modeldata.db.name=test_api_predictionio_modeldata
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.host=localhost
-io.prediction.commons.modeldata.training.db.port=27017
diff --git a/servers/api/project/build.properties b/servers/api/project/build.properties
deleted file mode 100644
index 0974fce..0000000
--- a/servers/api/project/build.properties
+++ /dev/null
@@ -1 +0,0 @@
-sbt.version=0.13.0
diff --git a/servers/api/project/plugins.sbt b/servers/api/project/plugins.sbt
deleted file mode 100644
index 16ba183..0000000
--- a/servers/api/project/plugins.sbt
+++ /dev/null
@@ -1,10 +0,0 @@
-// Comment to get more information during initialization
-logLevel := Level.Warn
-
-// The Typesafe repository
-resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
-
-// Use the Play sbt plugin for Play projects
-addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.2.2")
-
-addSbtPlugin("com.typesafe.sbt" % "sbt-scalariform" % "1.2.1")
diff --git a/servers/api/public/images/spacer.png b/servers/api/public/images/spacer.png
deleted file mode 100644
index 37c28e7..0000000
--- a/servers/api/public/images/spacer.png
+++ /dev/null
Binary files differ
diff --git a/servers/api/test/APISpec.scala b/servers/api/test/APISpec.scala
deleted file mode 100644
index 58eb16f..0000000
--- a/servers/api/test/APISpec.scala
+++ /dev/null
@@ -1,355 +0,0 @@
-package io.prediction.scheduler
-
-import io.prediction.commons.Config
-import io.prediction.commons.settings._
-import io.prediction.commons.appdata._
-import io.prediction.commons.modeldata._
-
-import play.api.libs.json._
-import play.api.test._
-import play.api.test.Helpers._
-
-import org.specs2.mutable._
-
-import com.mongodb.casbah.Imports._
-import com.github.nscala_time.time.Imports._
-
-class APISpec extends Specification {
-  "PredictionIO API Specification".txt
-
-  /** Setup test data. */
-  val config = new Config
-  val apps = config.getSettingsApps()
-  val engines = config.getSettingsEngines()
-  val algos = config.getSettingsAlgos()
-  val items = config.getAppdataItems()
-  val itemRecScores = config.getModeldataItemRecScores()
-  val itemSimScores = config.getModeldataItemSimScores()
-
-  val userid = 1
-
-  val appid = apps.insert(App(
-    id = 0,
-    userid = userid,
-    appkey = "appkey",
-    display = "",
-    url = None,
-    cat = None,
-    desc = None,
-    timezone = "UTC"))
-
-  val dac = Item(
-    id = "dac",
-    appid = appid,
-    ct = DateTime.now,
-    itypes = List("fresh", "meat"),
-    starttime = Some(DateTime.now),
-    endtime = None,
-    price = Some(49.394),
-    profit = None,
-    latlng = Some((37.3197611, -122.0466141)),
-    inactive = None,
-    attributes = Some(Map("foo" -> "bar", "foo2" -> "bar2")))
-  val hsh = Item(
-    id = "hsh",
-    appid = appid,
-    ct = DateTime.now,
-    itypes = List("fresh", "meat"),
-    starttime = Some(DateTime.now),
-    endtime = None,
-    price = Some(49.394),
-    profit = None,
-    latlng = Some((37.3370801, -122.0493201)),
-    inactive = None,
-    attributes = None)
-  val mvh = Item(
-    id = "mvh",
-    appid = appid,
-    ct = DateTime.now,
-    itypes = List("fresh", "meat"),
-    starttime = Some(DateTime.now),
-    endtime = None,
-    price = Some(49.394),
-    profit = None,
-    latlng = Some((37.3154153, -122.0566829)),
-    inactive = None,
-    attributes = Some(Map("foo3" -> "bar3")))
-  val lbh = Item(
-    id = "lbh",
-    appid = appid,
-    ct = DateTime.now,
-    itypes = List("fresh", "meat"),
-    starttime = Some(DateTime.now),
-    endtime = None,
-    price = Some(49.394),
-    profit = None,
-    latlng = Some((37.2997029, -122.0034684)),
-    inactive = None,
-    attributes = Some(Map("foo4" -> "bar4", "foo5" -> "bar5")))
-  val allItems = Seq(dac, hsh, lbh, mvh)
-  allItems foreach { items.insert(_) }
-
-  "ItemRec" should {
-    val enginename = "itemrec"
-
-    val engineid = engines.insert(Engine(
-      id = 0,
-      appid = appid,
-      name = "itemrec",
-      infoid = "itemrec",
-      itypes = None,
-      params = Map()))
-
-    val algoid = algos.insert(Algo(
-      id = 0,
-      engineid = engineid,
-      name = enginename,
-      infoid = "pdio-knnitembased",
-      command = "itemr",
-      params = Map("foo" -> "bar"),
-      settings = Map("dead" -> "beef"),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed",
-      offlineevalid = None))
-
-    itemRecScores.insert(ItemRecScore(
-      uid = "user1",
-      iids = Seq("hsh", "mvh", "lbh", "dac"),
-      scores = Seq(4, 3, 2, 1),
-      itypes = Seq(Seq("fresh", "meat"), Seq("fresh", "meat"), Seq("fresh", "meat"), Seq("fresh", "meat")),
-      appid = appid,
-      algoid = algoid,
-      modelset = true))
-
-    "get top N" in new WithServer {
-      val response = Helpers.await(wsUrl(s"/engines/itemrec/${enginename}/topn.json")
-        .withQueryString(
-          "pio_appkey" -> "appkey",
-          "pio_uid" -> "user1",
-          "pio_n" -> "10")
-        .get())
-      response.status must beEqualTo(OK) and
-        (response.body must beEqualTo("""{"pio_iids":["hsh","mvh","lbh","dac"]}"""))
-    }
-
-    "get top N with geo" in new WithServer {
-      val response = Helpers.await(wsUrl(s"/engines/itemrec/${enginename}/topn.json")
-        .withQueryString(
-          "pio_appkey" -> "appkey",
-          "pio_uid" -> "user1",
-          "pio_n" -> "10",
-          "pio_latlng" -> "37.3229978,-122.0321823",
-          "pio_within" -> "2.2")
-        .get())
-      response.status must beEqualTo(OK) and
-        (response.body must beEqualTo("""{"pio_iids":["hsh","dac"]}"""))
-    }
-  }
-
-  "ItemSim" should {
-    val enginename = "itemsim"
-
-    val engineid = engines.insert(Engine(
-      id = 0,
-      appid = appid,
-      name = "itemsim",
-      infoid = "itemsim",
-      itypes = None,
-      params = Map()))
-
-    val algoid = algos.insert(Algo(
-      id = 0,
-      engineid = engineid,
-      name = enginename,
-      infoid = "pdio-itembasedcf",
-      command = "items",
-      params = Map("foo" -> "bar"),
-      settings = Map("dead" -> "beef"),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed",
-      offlineevalid = None))
-
-    itemSimScores.insert(ItemSimScore(
-      iid = "user1",
-      simiids = Seq("hsh", "mvh", "lbh", "dac"),
-      scores = Seq(4, 3, 2, 1),
-      itypes = Seq(Seq("fresh", "meat"), Seq("fresh", "meat"), Seq("fresh", "meat"), Seq("fresh", "meat")),
-      appid = appid,
-      algoid = algoid,
-      modelset = true))
-
-    "get top N" in new WithServer {
-      val response = Helpers.await(wsUrl(s"/engines/itemsim/${enginename}/topn.json")
-        .withQueryString(
-          "pio_appkey" -> "appkey",
-          "pio_iid" -> "user1",
-          "pio_n" -> "10")
-        .get())
-      response.status must beEqualTo(OK) and
-        (response.body must beEqualTo("""{"pio_iids":["hsh","mvh","lbh","dac"]}"""))
-    }
-
-    "get top N with geo" in new WithServer {
-      val response = Helpers.await(wsUrl(s"/engines/itemsim/${enginename}/topn.json")
-        .withQueryString(
-          "pio_appkey" -> "appkey",
-          "pio_iid" -> "user1",
-          "pio_n" -> "10",
-          "pio_latlng" -> "37.3229978,-122.0321823",
-          "pio_within" -> "2.2")
-        .get())
-      response.status must beEqualTo(OK) and
-        (response.body must beEqualTo("""{"pio_iids":["hsh","dac"]}"""))
-    }
-  }
-
-  "ItemRank" should {
-    val enginename = "itemrank"
-
-    val engineid = engines.insert(Engine(
-      id = 0,
-      appid = appid,
-      name = "itemrank",
-      infoid = "itemrank",
-      itypes = None,
-      params = Map()))
-
-    val algoid = algos.insert(Algo(
-      id = 0,
-      engineid = engineid,
-      name = enginename,
-      infoid = "pio-itemrank-single-knnitembased",
-      command = "itemr",
-      params = Map("foo" -> "bar"),
-      settings = Map("dead" -> "beef"),
-      modelset = true,
-      createtime = DateTime.now,
-      updatetime = DateTime.now,
-      status = "deployed",
-      offlineevalid = None))
-
-    itemRecScores.insert(ItemRecScore(
-      uid = "user1",
-      iids = Seq("hsh", "mvh", "lbh", "dac"),
-      scores = Seq(4, 3, 2, 1),
-      itypes = Seq(Seq("fresh", "meat"), Seq("fresh", "meat"), Seq("fresh", "meat"), Seq("fresh", "meat")),
-      appid = appid,
-      algoid = algoid,
-      modelset = true))
-
-    "ranked" in new WithServer {
-      val response = Helpers.await(wsUrl(s"/engines/itemrank/${enginename}/ranked.json")
-        .withQueryString(
-          "pio_appkey" -> "appkey",
-          "pio_uid" -> "user1",
-          "pio_iids" -> "lbh,dac,mvh,hsh")
-        .get())
-      response.status must beEqualTo(OK) and
-        (response.body must beEqualTo("""{"pio_iids":["hsh","mvh","lbh","dac"]}"""))
-    }
-
-    "ranked and unranked" in new WithServer {
-      val response = Helpers.await(wsUrl(s"/engines/itemrank/${enginename}/ranked.json")
-        .withQueryString(
-          "pio_appkey" -> "appkey",
-          "pio_uid" -> "user1",
-          "pio_iids" -> "foobar,lbh,dac,mvh,hsh")
-        .get())
-      response.status must beEqualTo(OK) and
-        (response.body must beEqualTo("""{"pio_iids":["hsh","mvh","lbh","dac","foobar"]}"""))
-    }
-  }
-
-  "Items" should {
-    "fail creation with tabs in itypes" in new WithServer {
-      val response = Helpers.await(wsUrl(s"/items.json").post(Map(
-        "pio_appkey" -> Seq("appkey"),
-        "pio_iid" -> Seq("fooitem"),
-        "pio_itypes" -> Seq("footype\tbartype"))))
-      response.status must beEqualTo(BAD_REQUEST)
-    }
-  }
-
-  "CORSFilter" should {
-    import play.api.mvc.WithFilters
-    import io.prediction.api.CORSFilter
-
-    "send correct CORS headers for OPTIONS request" in new WithServer {
-      val response = Helpers.await(wsUrl(s"/apiurl").withHeaders(
-        "Access-Control-Request-Method" -> "POST").options())
-
-      def allowsCorrectMethods(allowedMethodHeader: String): Boolean = {
-        val allowedMethods = allowedMethodHeader.split(", ")
-        return allowedMethods.sameElements(Array("GET", "POST", "DELETE"))
-      }
-
-      response.header("Access-Control-Allow-Origin").nonEmpty must beTrue and
-        (response.header("Access-Control-Allow-Methods").exists(allowsCorrectMethods) must beTrue)
-    }
-
-    "not allow any origin if setting is empty" in new WithServer() {
-      val origin = "http://www.test-domain.com"
-      val originHeader = Helpers.await(wsUrl(s"/apiurl").withHeaders("Origin" -> origin).get())
-        .header("Access-Control-Allow-Origin").getOrElse("")
-      originHeader mustNotEqual origin
-    }
-
-    val appWithOneAllowedDomain = FakeApplication(withGlobal = Some(new WithFilters(CORSFilter(Some("http://www.test-domain.com")))))
-    val appWithSeveralAllowedDomains = FakeApplication(
-      withGlobal = Some(new WithFilters(CORSFilter(Some("http://www.test-domain.com,http://www.other-domain.com,http://www.abcd.efgh")))))
-    val appWithAllDomains = FakeApplication(withGlobal = Some(new WithFilters(CORSFilter(Some("*")))))
-
-    "allow specified origin if setting contains one domain" in new WithServer(app = appWithOneAllowedDomain) {
-      val origin = "http://www.test-domain.com"
-      val originHeader = Helpers.await(wsUrl(s"/apiurl").withHeaders("Origin" -> origin).get())
-        .header("Access-Control-Allow-Origin").getOrElse("")
-      originHeader mustEqual origin or (originHeader mustEqual "*")
-    }
-
-    "not allow unspecified origin if setting contains one domain" in new WithServer(app = appWithOneAllowedDomain) {
-      val origin = "http://www.other-domain.com"
-      val originHeader = Helpers.await(wsUrl(s"/apiurl").withHeaders("Origin" -> origin).get())
-        .header("Access-Control-Allow-Origin").getOrElse("")
-      originHeader mustNotEqual origin
-    }
-
-    "allow specified origin 1 if setting contains several domains" in new WithServer(app = appWithSeveralAllowedDomains) {
-      val origin = "http://www.test-domain.com"
-      val originHeader = Helpers.await(wsUrl(s"/apiurl").withHeaders("Origin" -> origin).get())
-        .header("Access-Control-Allow-Origin").getOrElse("")
-      originHeader mustEqual origin or (originHeader mustEqual "*")
-    }
-
-    "allow specified origin 2 if setting contains several domains" in new WithServer(app = appWithSeveralAllowedDomains) {
-      val origin = "http://www.other-domain.com"
-      val originHeader = Helpers.await(wsUrl(s"/apiurl").withHeaders("Origin" -> origin).get())
-        .header("Access-Control-Allow-Origin").getOrElse("")
-      originHeader mustEqual origin or (originHeader mustEqual "*")
-    }
-
-    "not allow unspecified origin if setting contains several domains" in new WithServer(app = appWithSeveralAllowedDomains) {
-      val origin = "http://www.unallowed-domain.com"
-      val originHeader = Helpers.await(wsUrl(s"/apiurl").withHeaders("Origin" -> origin).get())
-        .header("Access-Control-Allow-Origin").getOrElse("")
-      originHeader mustNotEqual origin
-    }
-
-    "allow any origin if setting is *" in new WithServer(app = appWithAllDomains) {
-      val origin = "http://www.random-domain.com"
-      val originHeader = Helpers.await(wsUrl(s"/apiurl").withHeaders("Origin" -> origin).get())
-        .header("Access-Control-Allow-Origin").getOrElse("")
-      originHeader mustEqual origin or (originHeader mustEqual "*")
-    }
-
-  }
-
-  step {
-    MongoConnection()(config.settingsDbName).dropDatabase()
-    MongoConnection()(config.appdataDbName).dropDatabase()
-    MongoConnection()(config.modeldataDbName).dropDatabase()
-  }
-}
diff --git a/servers/api/test/basic.sh b/servers/api/test/basic.sh
deleted file mode 100755
index 2effcfa..0000000
--- a/servers/api/test/basic.sh
+++ /dev/null
@@ -1,165 +0,0 @@
-
-
-
-curl --request GET http://localhost:9124/
-echo ""
-
-## JSON format
-curl --header 'Content-Type: application/json' --request POST \
---data '{"pio_appkey": "jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO", "pio_uid" : "testuid", "custom1" : "value1", "custom2" : 2, "custom3" : 4.123, "custom4" : false }' http://localhost:9124/users.json
-echo ""
-
-curl --header 'Content-Type: application/json' --request POST \
---data '{"pio_appkey": "jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO", "pio_uid" : "testuid", "pio_latlng" : "1.23,4.56", "pio_inactive" : true,  "custom1" : "value1", "custom2" : 2, "custom3" : 4.123, "custom4" : false }' http://localhost:9124/users.json
-echo ""
-
-curl --request GET http://localhost:9124/users/testuid.json?pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO
-echo ""
-
-curl --request DELETE http://localhost:9124/users/testuid.json?pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO
-echo ""
-
-### form-urlencoded
-
-echo "user without custom attributes"
-curl --request POST http://localhost:9124/users.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_uid=testuid3" \
---data-urlencode "pio_latlng=12.34,5.678" \
---data-urlencode "pio_inactive=true"
-echo ""
-
-echo "user with custom attributes"
-curl --request POST http://localhost:9124/users.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_uid=testuid2" \
---data-urlencode "pio_latlng=12.34,5.678" \
---data-urlencode "custom1=value1" \
---data-urlencode "pio_inactive=true"
-echo ""
-
-echo "get user"
-curl --request GET http://localhost:9124/users/testuid2.json?pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO
-echo ""
-
-echo "delete user"
-curl --request DELETE http://localhost:9124/users/testuid3.json?pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO
-echo ""
-
-# item
-echo "create item"
-curl --request POST http://localhost:9124/items.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_iid=testiid2" \
---data-urlencode "pio_itypes=type1,type2" \
---data-urlencode "pio_price=1.23" \
---data-urlencode "pio_profit=9.87" \
---data-urlencode "pio_startT=123456789" \
---data-urlencode "pio_endT=2013-02-12T05:43:21.4" \
---data-urlencode "pio_latlng=12.34,5.678" \
---data-urlencode "pio_inactive=true" \
---data-urlencode "custom1=value1" \
---data-urlencode "custom2=2.34"
-echo ""
-
-curl --request POST http://localhost:9124/items.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_iid=testiid3" \
---data-urlencode "pio_itypes=type1,type2" \
---data-urlencode "pio_price=1.23" \
---data-urlencode "pio_profit=9.87" \
---data-urlencode "pio_startT=123456789" \
---data-urlencode "pio_endT=2013-02-12T05:43:21.4" \
---data-urlencode "pio_latlng=12.34,5.678" \
---data-urlencode "pio_inactive=true" \
---data-urlencode "custom1=value1" \
---data-urlencode "custom2=2.34"
-echo ""
-
-echo "get item"
-curl --request GET http://localhost:9124/items/testiid2.json?pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO
-echo ""
-
-echo "delete item"
-curl --request DELETE http://localhost:9124/items/testiid2.json?pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO
-echo ""
-
-# u2iactions
-
-echo "rate action"
-curl --request POST http://localhost:9124/actions/u2i.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_action=rate" \
---data-urlencode "pio_uid=user2" \
---data-urlencode "pio_iid=item3" \
---data-urlencode "pio_rate=3"
-echo ""
-
-echo "rate with latlng and t"
-curl --request POST http://localhost:9124/actions/u2i.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_action=rate" \
---data-urlencode "pio_uid=user2" \
---data-urlencode "pio_iid=item3" \
---data-urlencode "pio_rate=3" \
---data-urlencode "pio_latlng=1.234,5.678" \
---data-urlencode "pio_t=2012-09-10T12:34:56.6"
-echo ""
-
-echo "missing rate field in rate action"
-curl --request POST http://localhost:9124/actions/u2i.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_action=rate" \
---data-urlencode "pio_uid=user2" \
---data-urlencode "pio_iid=item4"
-echo ""
-
-echo "like action"
-curl --request POST http://localhost:9124/actions/u2i.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_action=like" \
---data-urlencode "pio_uid=user3" \
---data-urlencode "pio_iid=item4"
-echo ""
-
-echo "dislike"
-curl --request POST http://localhost:9124/actions/u2i.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_action=dislike" \
---data-urlencode "pio_uid=user4" \
---data-urlencode "pio_iid=item5"
-echo ""
-
-echo "view"
-curl --request POST http://localhost:9124/actions/u2i.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_action=view" \
---data-urlencode "pio_uid=user6" \
---data-urlencode "pio_iid=item7"
-echo ""
-
-
-echo "conversion"
-curl --request POST http://localhost:9124/actions/u2i.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_action=conversion" \
---data-urlencode "pio_uid=user7" \
---data-urlencode "pio_iid=item8"
-echo ""
-
-echo "conversion with price"
-curl --request POST http://localhost:9124/actions/u2i.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_action=conversion" \
---data-urlencode "pio_uid=user8" \
---data-urlencode "pio_iid=item9" \
---data-urlencode "pio_price=5.99"
-echo ""
-
-echo "custom action"
-curl --request POST http://localhost:9124/actions/u2i.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_action=custom_action" \
---data-urlencode "pio_uid=user2" \
---data-urlencode "pio_iid=item4"
-echo ""
diff --git a/servers/api/test/basic_itemrectopn.sh b/servers/api/test/basic_itemrectopn.sh
deleted file mode 100755
index 3ea35d2..0000000
--- a/servers/api/test/basic_itemrectopn.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-
-curl --request GET http://localhost:9124/
-
-# get topN
-
-curl --request GET "http://localhost:9124/engines/itemrec/cus-eng/topn.json?pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO&pio_uid=u0&pio_n=2&pio_attributes=custom1,custom2"
-
diff --git a/servers/api/test/basic_pixel.sh b/servers/api/test/basic_pixel.sh
deleted file mode 100755
index e0d48fd..0000000
--- a/servers/api/test/basic_pixel.sh
+++ /dev/null
@@ -1,129 +0,0 @@
-
-
-echo "user without custom attributes"
-curl --request GET -L "http://localhost:9124/p/users.json\
-?pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO\
-&pio_uid=testuid3\
-&pio_latlng=12.34,5.678\
-&pio_inactive=true"
-echo ""
-
-echo "user with custom attributes"
-curl --request GET -L "http://localhost:9124/p/users.json\
-?pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO\
-&pio_uid=testuid2\
-&pio_latlng=12.34,5.678\
-&custom1=value1\
-&pio_inactive=true"
-echo ""
-
-
-# item
-echo "create item"
-curl --request GET -L "http://localhost:9124/p/items.json\
-?pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO\
-&pio_iid=testiid2\
-&pio_itypes=type1,type2\
-&pio_price=1.23\
-&pio_profit=9.87\
-&pio_startT=123456789\
-&pio_endT=2013-02-12T05:43:21.4\
-&pio_latlng=12.34,5.678\
-&pio_inactive=true\
-&custom1=value1\
-&custom2=2.34"
-echo ""
-
-curl --request GET -L "http://localhost:9124/p/items.json\
-?pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO\
-&pio_iid=testiid3\
-&pio_itypes=type1,type2\
-&pio_price=1.23\
-&pio_profit=9.87\
-&pio_startT=123456789\
-&pio_endT=2013-02-12T05:43:21.4\
-&pio_latlng=12.34,5.678\
-&pio_inactive=true\
-&custom1=value1\
-&custom2=2.34"
-echo ""
-
-
-
-echo "rate action"
-curl --request GET -L "http://localhost:9124/p/actions/u2i.json\
-?pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO\
-&pio_action=rate\
-&pio_uid=user2\
-&pio_iid=item3\
-&pio_rate=3"
-echo ""
-
-echo "rate with latlng and t"
-curl --request GET -L "http://localhost:9124/p/actions/u2i.json\
-?pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO\
-&pio_action=rate\
-&pio_uid=user2\
-&pio_iid=item3\
-&pio_rate=3\
-&pio_latlng=1.234,5.678\
-&pio_t=2012-09-10T12:34:56.6"
-echo ""
-
-echo "missing rate field in rate action"
-curl --request GET -L "http://localhost:9124/p/actions/u2i.json\
-?pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO\
-&pio_action=rate\
-&pio_uid=user2\
-&pio_iid=item4"
-echo ""
-
-echo "like action"
-curl --request GET -L "http://localhost:9124/p/actions/u2i.json\
-?pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO\
-&pio_action=like\
-&pio_uid=user3\
-&pio_iid=item4"
-echo ""
-
-echo "dislike"
-curl --request GET -L "http://localhost:9124/p/actions/u2i.json\
-?pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO\
-&pio_action=dislike\
-&pio_uid=user4\
-&pio_iid=item5"
-echo ""
-
-echo "view"
-curl --request GET -L "http://localhost:9124/p/actions/u2i.json\
-?pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO\
-&pio_action=view\
-&pio_uid=user6\
-&pio_iid=item7"
-echo ""
-
-
-echo "conversion"
-curl --request GET -L "http://localhost:9124/p/actions/u2i.json\
-?pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO\
-&pio_action=conversion\
-&pio_uid=user7\
-&pio_iid=item8"
-echo ""
-
-echo "conversion with price"
-curl --request GET -L "http://localhost:9124/p/actions/u2i.json\
-?pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO\
-&pio_action=conversion\
-&pio_uid=user8\
-&pio_iid=item9\
-&pio_price=5.99"
-echo ""
-
-echo "custom action"
-curl --request GET -L "http://localhost:9124/p/actions/u2i.json\
-?pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO\
-&pio_action=custom_action\
-&pio_uid=user2\
-&pio_iid=item4"
-echo ""
diff --git a/servers/api/test/basic_pixel_legacy.sh b/servers/api/test/basic_pixel_legacy.sh
deleted file mode 100755
index 4019ea9..0000000
--- a/servers/api/test/basic_pixel_legacy.sh
+++ /dev/null
@@ -1,121 +0,0 @@
-
-# legacy pixel tracking format
-
-echo "user without custom attributes"
-curl --request GET -L "http://localhost:9124/p/users.json\
-?appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO\
-&uid=testuid3\
-&latlng=12.34,5.678\
-&inactive=true"
-echo ""
-
-echo "user with custom attributes"
-curl --request GET -L "http://localhost:9124/p/users.json\
-?appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO\
-&uid=testuid2\
-&latlng=12.34,5.678\
-&custom1=value1\
-&inactive=true"
-echo ""
-
-
-# item
-echo "create item"
-curl --request GET -L "http://localhost:9124/p/items.json\
-?appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO\
-&iid=testiid2\
-&itypes=type1,type2\
-&price=1.23\
-&profit=9.87\
-&startT=123456789\
-&endT=2013-02-12T05:43:21.4\
-&latlng=12.34,5.678\
-&inactive=true\
-&custom1=value1\
-&custom2=2.34"
-echo ""
-
-curl --request GET -L "http://localhost:9124/p/items.json\
-?appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO\
-&iid=testiid3\
-&itypes=type1,type2\
-&price=1.23\
-&profit=9.87\
-&startT=123456789\
-&endT=2013-02-12T05:43:21.4\
-&latlng=12.34,5.678\
-&inactive=true\
-&custom1=value1\
-&custom2=2.34"
-echo ""
-
-
-
-echo "rate action"
-curl --request GET -L "http://localhost:9124/p/actions/u2i/rate.json\
-?appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO\
-&uid=user2\
-&iid=item3\
-&rate=3"
-echo ""
-
-echo "rate with latlng and t"
-curl --request GET -L "http://localhost:9124/p/actions/u2i/rate.json\
-?appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO\
-&uid=user2\
-&iid=item3\
-&rate=3\
-&latlng=1.234,5.678\
-&t=2012-09-10T12:34:56.6"
-echo ""
-
-echo "missing rate field in rate action"
-curl --request GET -L "http://localhost:9124/p/actions/u2i/rate.json\
-?appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO\
-&uid=user2\
-&iid=item4"
-echo ""
-
-echo "like action"
-curl --request GET -L "http://localhost:9124/p/actions/u2i/like.json\
-?appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO\
-&uid=user3\
-&iid=item4"
-echo ""
-
-echo "dislike"
-curl --request GET -L "http://localhost:9124/p/actions/u2i/dislike.json\
-?appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO\
-&uid=user4\
-&iid=item5"
-echo ""
-
-echo "view"
-curl --request GET -L "http://localhost:9124/p/actions/u2i/view.json\
-?appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO\
-&uid=user6\
-&iid=item7"
-echo ""
-
-
-echo "conversion"
-curl --request GET -L "http://localhost:9124/p/actions/u2i/conversion.json\
-?appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO\
-&uid=user7\
-&iid=item8"
-echo ""
-
-echo "conversion with price"
-curl --request GET -L "http://localhost:9124/p/actions/u2i/conversion.json\
-?appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO\
-&uid=user8\
-&iid=item9\
-&price=5.99"
-echo ""
-
-echo "custom action"
-curl --request GET -L "http://localhost:9124/p/actions/u2i/custom_action.json\
-?appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO\
-&uid=user2\
-&iid=item4"
-echo ""
diff --git a/servers/api/test/simple_dataset.sh b/servers/api/test/simple_dataset.sh
deleted file mode 100755
index 93f0be2..0000000
--- a/servers/api/test/simple_dataset.sh
+++ /dev/null
@@ -1,127 +0,0 @@
-
-
-curl --request POST http://localhost:9124/users.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_uid=u0" \
---data-urlencode "pio_latlng=12.34,5.678" \
---data-urlencode "custom1=value0"
-
-curl --request POST http://localhost:9124/users.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_uid=u1" \
---data-urlencode "pio_latlng=12.34,5.678" \
---data-urlencode "custom1=value1"
-
-curl --request POST http://localhost:9124/users.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_uid=u2" \
---data-urlencode "pio_latlng=12.34,5.678" \
---data-urlencode "custom1=value2"
-
-curl --request POST http://localhost:9124/users.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_uid=u3" \
---data-urlencode "pio_latlng=12.34,5.678" \
---data-urlencode "custom1=value3"
-
-curl --request POST http://localhost:9124/items.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_iid=i0" \
---data-urlencode "pio_itypes=t1" \
---data-urlencode "custom1=ic0"
-
-curl --request POST http://localhost:9124/items.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_iid=i1" \
---data-urlencode "pio_itypes=t1" \
---data-urlencode "custom1=ic1"
-
-curl --request POST http://localhost:9124/items.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_iid=i2" \
---data-urlencode "pio_itypes=t1" \
---data-urlencode "custom1=ic2"
-
-curl --request POST http://localhost:9124/items.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_iid=i3" \
---data-urlencode "pio_itypes=t1" \
---data-urlencode "custom1=ic3"
-
-##
-curl --request POST http://localhost:9124/actions/u2i.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_action=rate" \
---data-urlencode "pio_uid=u0" \
---data-urlencode "pio_iid=i0" \
---data-urlencode "pio_rate=2"
-
-curl --request POST http://localhost:9124/actions/u2i.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_action=rate" \
---data-urlencode "pio_uid=u0" \
---data-urlencode "pio_iid=i1" \
---data-urlencode "pio_rate=3"
-
-curl --request POST http://localhost:9124/actions/u2i.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_action=rate" \
---data-urlencode "pio_uid=u0" \
---data-urlencode "pio_iid=i2" \
---data-urlencode "pio_rate=4"
-
-curl --request POST http://localhost:9124/actions/u2i.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_action=rate" \
---data-urlencode "pio_uid=u1" \
---data-urlencode "pio_iid=i2" \
---data-urlencode "pio_rate=4"
-
-curl --request POST http://localhost:9124/actions/u2i.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_action=rate" \
---data-urlencode "pio_uid=u1" \
---data-urlencode "pio_iid=i3" \
---data-urlencode "pio_rate=1"
-
-curl --request POST http://localhost:9124/actions/u2i.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_action=rate" \
---data-urlencode "pio_uid=u2" \
---data-urlencode "pio_iid=i1" \
---data-urlencode "pio_rate=2"
-
-curl --request POST http://localhost:9124/actions/u2i.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_action=rate" \
---data-urlencode "pio_uid=u2" \
---data-urlencode "pio_iid=i2" \
---data-urlencode "pio_rate=1"
-
-curl --request POST http://localhost:9124/actions/u2i.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_action=rate" \
---data-urlencode "pio_uid=u2" \
---data-urlencode "pio_iid=i3" \
---data-urlencode "pio_rate=3"
-
-curl --request POST http://localhost:9124/actions/u2i.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_action=rate" \
---data-urlencode "pio_uid=u3" \
---data-urlencode "pio_iid=i0" \
---data-urlencode "pio_rate=5"
-
-curl --request POST http://localhost:9124/actions/u2i.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_action=rate" \
---data-urlencode "pio_uid=u3" \
---data-urlencode "pio_iid=i1" \
---data-urlencode "pio_rate=3"
-
-curl --request POST http://localhost:9124/actions/u2i.json --header 'Content-Type: application/x-www-form-urlencoded' \
---data-urlencode "pio_appkey=jLIvMU9FNydsJHpO7otA4Dh4FQTDDyP3hFA9DltuyAdadcxXdtpMXYLnOLtCTsWO" \
---data-urlencode "pio_action=rate" \
---data-urlencode "pio_uid=u3" \
---data-urlencode "pio_iid=i3" \
---data-urlencode "pio_rate=2"
diff --git a/servers/scheduler/.gitignore b/servers/scheduler/.gitignore
deleted file mode 100644
index 6902034..0000000
--- a/servers/scheduler/.gitignore
+++ /dev/null
@@ -1,15 +0,0 @@
-logs
-project/project
-project/target
-target
-tmp
-.history
-dist
-/.idea
-/*.iml
-/out
-/.idea_modules
-/.classpath
-/.project
-/RUNNING_PID
-/lib
diff --git a/servers/scheduler/app/controllers/Contexts.scala b/servers/scheduler/app/controllers/Contexts.scala
deleted file mode 100644
index f7adea9..0000000
--- a/servers/scheduler/app/controllers/Contexts.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package io.prediction.scheduler
-
-import play.api.Play.current
-import play.api.libs.concurrent.Akka
-
-object Contexts {
-  implicit val stepExecutionContext = Akka.system.dispatchers.lookup("io.prediction.scheduler.steps")
-}
diff --git a/servers/scheduler/app/controllers/Global.scala b/servers/scheduler/app/controllers/Global.scala
deleted file mode 100644
index 2202d63..0000000
--- a/servers/scheduler/app/controllers/Global.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-import java.util.Date
-
-import play.api._
-import play.api.mvc._
-
-import scala.concurrent.ExecutionContext.Implicits.global
-import scala.concurrent.future
-
-object Global extends GlobalSettings {
-  override def onStart(app: Application) = {
-    Logger.info("Quartz scheduler is starting...")
-
-    io.prediction.scheduler.Scheduler.scheduler.start()
-
-    future { io.prediction.scheduler.Scheduler.syncAllUsers() }
-  }
-
-  override def onStop(app: Application) = {
-    Logger.info("Quartz scheduler is shutting down...")
-
-    io.prediction.scheduler.Scheduler.scheduler.shutdown()
-  }
-}
\ No newline at end of file
diff --git a/servers/scheduler/app/controllers/JobTreeJobListener.scala b/servers/scheduler/app/controllers/JobTreeJobListener.scala
deleted file mode 100644
index 0d5db8e..0000000
--- a/servers/scheduler/app/controllers/JobTreeJobListener.scala
+++ /dev/null
@@ -1,36 +0,0 @@
-package io.prediction.scheduler
-
-import org.quartz.{ JobExecutionContext, JobExecutionException, JobKey, SchedulerException }
-import org.quartz.listeners.JobListenerSupport
-
-class JobTreeJobListener(name: String) extends JobListenerSupport {
-  private var treeLinks = collection.mutable.Map[JobKey, collection.mutable.ListBuffer[JobKey]]()
-
-  def getName(): String = {
-    name
-  }
-
-  def addJobTreeLink(firstJob: JobKey, secondJob: JobKey) {
-    treeLinks.get(firstJob) map { links =>
-      links += secondJob
-    } getOrElse {
-      treeLinks += (firstJob -> collection.mutable.ListBuffer(secondJob))
-    }
-  }
-
-  override def jobWasExecuted(context: JobExecutionContext, jobException: JobExecutionException) = {
-    val executedJobKey = context.getJobDetail().getKey()
-
-    treeLinks.get(executedJobKey) map { links =>
-      links foreach { link =>
-        getLog().info("Job '" + executedJobKey + "' will now link to Job '" + link + "'")
-
-        try {
-          context.getScheduler().triggerJob(link)
-        } catch {
-          case se: SchedulerException => getLog().error("Error encountered during chaining to Job '" + link + "'", se)
-        }
-      }
-    }
-  }
-}
diff --git a/servers/scheduler/app/controllers/Jobs.scala b/servers/scheduler/app/controllers/Jobs.scala
deleted file mode 100644
index e17b29b..0000000
--- a/servers/scheduler/app/controllers/Jobs.scala
+++ /dev/null
@@ -1,992 +0,0 @@
-package io.prediction.scheduler
-
-import io.prediction.commons._
-import io.prediction.commons.filepath._
-import io.prediction.commons.settings.{ Algo, App, Engine, OfflineEval, OfflineEvalMetric, OfflineTune }
-
-import com.github.nscala_time.time.Imports._
-import org.clapper.scalasti.StringTemplate
-import org.quartz.{ DisallowConcurrentExecution, PersistJobDataAfterExecution }
-import org.quartz.{ InterruptableJob, Job, JobDetail, JobExecutionContext }
-import org.quartz.JobBuilder.newJob
-import org.quartz.JobKey.jobKey
-import org.quartz.jobs.NativeJob
-
-import play.api.Logger
-
-import scala.collection.mutable.{ HashMap, Map, SynchronizedMap }
-import scala.concurrent.future
-import scala.sys.process._
-
-import Contexts.stepExecutionContext
-
-object Jobs {
-  val algoJobGroup = "predictionio-algo"
-  val offlineEvalJobGroup = "predictionio-offlineeval"
-  val offlineTuneJobGroup = "predictionio-offlinetune"
-
-  def algoJob(config: Config, app: App, engine: Engine, algo: Algo, batchcommands: Seq[String]) = {
-    /**
-     * Add a job, then build a trigger for it.
-     * This is necessary for updating any existing job,
-     * and make sure the trigger will fire.
-     */
-    val job = newJob(classOf[AlgoJob]) withIdentity (algo.id.toString, algoJobGroup) storeDurably (true) build ()
-    job.getJobDataMap().put("algoid", algo.id)
-    job.getJobDataMap().put("engineinfoid", engine.infoid)
-
-    job
-  }
-
-  /**
-   * Offline Evaluation Flow
-   *
-   * 1. Iterate the following for a specified number of times
-   *    1. Perform data splitting
-   *    2. For each algo to be evaluated
-   *       1. Run algo on training set
-   *       2. Run all metrics on model data from the above against test set
-   * 2. Mark offline evaluation as finished
-   */
-  def offlineEvalJob(config: Config, app: App, engine: Engine, offlineEval: OfflineEval) = {
-    /**
-     * Add a job, then build a trigger for it.
-     * This is necessary for updating any existing job,
-     * and make sure the trigger will fire.
-     */
-    val job = newJob(classOf[OfflineEvalJob]) withIdentity (offlineEval.id.toString, offlineEvalJobGroup) storeDurably (true) build ()
-    job.getJobDataMap().put("evalid", offlineEval.id)
-    job
-  }
-
-  /**
-   * Offline Tuning Flow
-   *
-   * 1. Perform multiple set of data splitting
-   * 2. Train and evaluate baseline algo against data sets from 1.
-   * 3. For a specified number of iterations:
-   *    1. Parameter generator generates new parameters based on previous evaluation results.
-   *    2. Train algo and run metrics against both validation and test sets.
-   * 4. Mark offline evaluation as finished
-   */
-  def offlineTuneJob(config: Config, app: App, engine: Engine, offlineTune: OfflineTune) = {
-    /**
-     * Add a job, then build a trigger for it.
-     * This is necessary for updating any existing job,
-     * and make sure the trigger will fire.
-     */
-    val job = newJob(classOf[OfflineTuneJob]) withIdentity (offlineTune.id.toString, offlineTuneJobGroup) storeDurably (true) build ()
-    job.getJobDataMap().put("tuneid", offlineTune.id)
-    job
-  }
-
-  def setSharedAttributes(command: StringTemplate, config: Config, app: App,
-    engine: Engine, algo: Option[Algo], offlineEval: Option[OfflineEval],
-    metric: Option[OfflineEvalMetric],
-    params: Option[collection.immutable.Map[String, Any]] = None) = {
-    /** Custom attributes */
-    params map { command.setAttributes(_) }
-
-    /** OfflineEvalMetric-specific attributes */
-    metric map { met =>
-      command.setAttributes(command.attributes ++ met.params)
-      command.setAttribute("metricid", met.id)
-      command.attributes.get("iteration").getOrElse(command.setAttribute("iteration", 0))
-      command.attributes.get("splitset").getOrElse(command.setAttribute("splitset", "test"))
-    }
-
-    /** OfflineEval-specific attributes */
-    offlineEval map { oe =>
-      command.setAttribute("evalid", oe.id)
-      command.setAttribute("modelset", "false")
-    }
-
-    /** Algo-specific attributes */
-    algo map { alg =>
-      val defaultParams = Scheduler.algoInfos.get(alg.infoid) map { _.params.mapValues(_.defaultvalue) } getOrElse Map[String, String]()
-      command.setAttributes(command.attributes ++ defaultParams ++ alg.params)
-      command.setAttribute("algoid", alg.id)
-      command.setAttribute("localTempDir", BaseDir.algoDir(config.settingsLocalTempRoot, app.id, engine.id, alg.id, offlineEval.map(_.id)))
-      command.setAttribute("mahoutTempDir", BaseDir.algoDir(config.settingsHdfsRoot + "mahout_temp/", app.id, engine.id, alg.id, offlineEval.map(_.id)))
-      command.setAttribute("algoDir", BaseDir.algoDir(config.settingsHdfsRoot, app.id, engine.id, alg.id, offlineEval.map(_.id)))
-      command.setAttribute("dataFilePrefix", DataFile(config.settingsHdfsRoot, app.id, engine.id, alg.id, offlineEval.map(_.id), ""))
-      command.setAttribute("algoFilePrefix", AlgoFile(config.settingsHdfsRoot, app.id, engine.id, alg.id, offlineEval.map(_.id), ""))
-    }
-
-    /** Engine-specific attributes */
-    val engineDefaultParams = Scheduler.engineInfos.get(engine.infoid) map {
-      _.params.mapValues(_.defaultvalue)
-    } getOrElse Map[String, String]()
-    command.setAttributes(command.attributes ++ engineDefaultParams ++ engine.params)
-
-    /** Common attributes */
-    val appdataItems = config.getAppdataItems
-    command.setAttribute("base", config.base)
-    command.setAttribute("hadoop", Scheduler.hadoopCommand)
-    command.setAttribute("itemCount", appdataItems.countByAppid(app.id))
-
-    /**
-     * Locate JAR names
-     * Use those from config file first, then override with SystemInfos.
-     */
-    config.jars foreach { kv => command.setAttribute(kv._1, kv._2) }
-    val systemInfosJarsR = """^jars\.(.*)""".r
-    config.getSettingsSystemInfos.getAll foreach { e =>
-      systemInfosJarsR findFirstIn e.id match {
-        case Some(systemInfosJarsR(jarKey)) => command.setAttribute(jarKey, e.value)
-        case None => Unit
-      }
-    }
-
-    command.setAttribute("configFile", Option(System.getProperty("config.file")).map(c => "-Dconfig.file=" + c).getOrElse("-Dconfig.file=conf/application.conf"))
-    command.setAttribute("appid", app.id)
-    command.setAttribute("engineid", engine.id)
-    command.setAttribute("hdfsRoot", config.settingsHdfsRoot)
-    command.setAttribute("hadoopOptions", Seq(
-      config.schedulerMapredMinSplitSize map { x => s"-Dmapred.min.split.size=${x}" } getOrElse "",
-      config.schedulerMapredMapTasks map { x => s"-Dmapred.map.tasks=${x}" } getOrElse "",
-      config.schedulerMapredReduceTasks map { x => s"-Dmapred.reduce.tasks=${x}" } getOrElse "").mkString(" "))
-    command.setAttribute("localTempRoot", config.settingsLocalTempRoot)
-    command.setAttribute("javaOpts", config.schedulerChildJavaOpts)
-    command.setAttribute("settingsDbType", config.settingsDbType)
-    command.setAttribute("settingsDbName", config.settingsDbName)
-    command.setAttribute("settingsDbHost", config.settingsDbHost.mkString(" "))
-    command.setAttribute("settingsDbPort", config.settingsDbPort.mkString(" "))
-    command.setAttribute("appdataDbType", config.appdataDbType)
-    command.setAttribute("appdataDbName", config.appdataDbName)
-    command.setAttribute("appdataDbHost", config.appdataDbHost.mkString(" "))
-    command.setAttribute("appdataDbPort", config.appdataDbPort.mkString(" "))
-    command.setAttribute("appdataTrainingDbType", config.appdataTrainingDbType)
-    command.setAttribute("appdataTrainingDbName", config.appdataTrainingDbName)
-    command.setAttribute("appdataTrainingDbHost", config.appdataTrainingDbHost.mkString(" "))
-    command.setAttribute("appdataTrainingDbPort", config.appdataTrainingDbPort.mkString(" "))
-    command.setAttribute("appdataValidationDbType", config.appdataValidationDbType)
-    command.setAttribute("appdataValidationDbName", config.appdataValidationDbName)
-    command.setAttribute("appdataValidationDbHost", config.appdataValidationDbHost.mkString(" "))
-    command.setAttribute("appdataValidationDbPort", config.appdataValidationDbPort.mkString(" "))
-    command.attributes.get("appdataTestDbType").getOrElse(command.setAttribute("appdataTestDbType", config.appdataTestDbType))
-    command.attributes.get("appdataTestDbName").getOrElse(command.setAttribute("appdataTestDbName", config.appdataTestDbName))
-    command.attributes.get("appdataTestDbHost").getOrElse(command.setAttribute("appdataTestDbHost", config.appdataTestDbHost.mkString(" ")))
-    command.attributes.get("appdataTestDbPort").getOrElse(command.setAttribute("appdataTestDbPort", config.appdataTestDbPort.mkString(" ")))
-    command.setAttribute("modeldataDbType", config.modeldataDbType)
-    command.setAttribute("modeldataDbName", config.modeldataDbName)
-    command.setAttribute("modeldataDbHost", config.modeldataDbHost.mkString(" "))
-    command.setAttribute("modeldataDbPort", config.modeldataDbPort.mkString(" "))
-    command.setAttribute("modeldataTrainingDbType", config.modeldataTrainingDbType)
-    command.setAttribute("modeldataTrainingDbName", config.modeldataTrainingDbName)
-    command.setAttribute("modeldataTrainingDbHost", config.modeldataTrainingDbHost.mkString(" "))
-    command.setAttribute("modeldataTrainingDbPort", config.modeldataTrainingDbPort.mkString(" "))
-    engine.itypes foreach { it =>
-      command.setAttribute("itypes", "--itypes " + it.mkString(" ")) // NOTE: a space ' ' is necessary after --itypes
-      command.setAttribute("itypesCSV", "--itypes " + it.mkString(","))
-    }
-    command.setAttribute("unseenOnly", engine.params.getOrElse("unseenonly", false))
-    command.setAttribute("recommendationTime", System.currentTimeMillis)
-  }
-}
-
-class UpdateCheckJob extends Job {
-  override def execute(context: JobExecutionContext) = {
-    Logger.info("Checking for new release...")
-    "bin/updatecheck --answer n".!
-  }
-}
-
-@DisallowConcurrentExecution
-@PersistJobDataAfterExecution
-class AlgoJob extends InterruptableJob {
-  @volatile
-  var kill = false
-
-  var exitCode: Int = 0
-  var finishFlag: Boolean = false
-
-  @volatile
-  var proc: Option[Process] = None
-
-  override def execute(context: JobExecutionContext) = {
-    val jobDataMap = context.getMergedJobDataMap
-    val algoid = jobDataMap.getInt("algoid")
-    val engineinfoid = jobDataMap.getString("engineinfoid")
-    val config = Scheduler.config
-    val apps = Scheduler.apps
-    val engines = Scheduler.engines
-    val algos = Scheduler.algos
-    val algoInfos = Scheduler.algoInfos
-    val logPrefix = s"Algo ID ${algoid}: "
-
-    algos.get(algoid) map { algo =>
-      engines.get(algo.engineid) map { engine =>
-        apps.get(engine.appid) map { app =>
-          algoInfos.get(algo.infoid) map { info =>
-            info.batchcommands map { batchcommands =>
-              Logger.info(s"${logPrefix}Current model set is ${algo.modelset}")
-              Logger.info(s"${logPrefix}Running database specific before-logic for model set ${!algo.modelset}")
-              val modelData = config.getModeldata(engine.infoid)
-              modelData.before(algo.id, !algo.modelset)
-              Logger.info(s"${logPrefix}Launching algo job for model set ${!algo.modelset}")
-              val commands = batchcommands map { c => Jobs.setSharedAttributes(new StringTemplate(c), config, app, engine, Some(algo), None, None, Some(collection.immutable.Map("modelset" -> !algo.modelset))).toString }
-
-              commands map { _.trim } foreach { c =>
-                this.synchronized {
-                  if (!kill && !c.isEmpty && exitCode == 0) {
-                    Logger.info(s"${logPrefix}Going to run: $c")
-                    proc = Some(Process(c, None, "JVM_OPT" -> config.schedulerChildJavaOpts).run)
-                    Logger.info(s"${logPrefix}Scheduler waiting for sub-process to finish")
-                  }
-                }
-
-                if (!kill && !c.isEmpty && exitCode == 0) {
-                  exitCode = proc.get.exitValue
-                  Logger.info(s"${logPrefix}Sub-process has finished with exit code ${exitCode}")
-                }
-              }
-
-              finishFlag = true
-
-              /** Display completion information */
-              if (kill) {
-                Logger.info(s"${logPrefix}Sub-process was killed upon request")
-                Logger.info(s"${logPrefix}Not flipping model set flag because the algo job was killed")
-              } else if (exitCode == 0) {
-                Logger.info(s"${logPrefix}Running database specific after-logic for model set ${!algo.modelset}")
-                modelData.after(algo.id, !algo.modelset)
-                Logger.info(s"${logPrefix}Flipping model set flag to ${!algo.modelset}")
-                algos.update(algo.copy(modelset = !algo.modelset, lasttraintime = Some(DateTime.now)))
-                Logger.info(s"${logPrefix}Running database specific deletion for model set ${algo.modelset}")
-                modelData.delete(algo.id, algo.modelset)
-                Logger.info(s"${logPrefix}Job completed")
-              } else {
-                Logger.warn(s"${logPrefix}Not flipping model set flag because the algo job returned non-zero exit code")
-              }
-            } getOrElse {
-              Logger.warn(s"${logPrefix}Not starting algorithm training because this algorithm has no command")
-            }
-          } getOrElse {
-            Logger.warn(s"${logPrefix}Not starting algorithm training because information of this algorithm cannot be found from the database")
-          }
-        } getOrElse {
-          Logger.warn(s"${logPrefix}Not starting algorithm training because the app that owns this algorithm cannot be found from the database")
-        }
-      } getOrElse {
-        Logger.warn(s"${logPrefix}Not starting algorithm training because the engine that owns this algorithm cannot be found from the database")
-      }
-    } getOrElse {
-      Logger.warn(s"${logPrefix}Not starting algorithm training because the algorithm cannot be found from the database")
-    }
-  }
-
-  override def interrupt() = {
-    this.synchronized {
-      kill = true
-      proc map { _.destroy }
-    }
-  }
-}
-
-@DisallowConcurrentExecution
-@PersistJobDataAfterExecution
-class OfflineEvalJob extends InterruptableJob {
-  @volatile
-  var kill = false
-
-  val exitCodes: Map[String, Int] = new HashMap[String, Int] with SynchronizedMap[String, Int]
-  val finishFlags: Map[String, Boolean] = new HashMap[String, Boolean] with SynchronizedMap[String, Boolean]
-  val procs: Map[String, Process] = new HashMap[String, Process] with SynchronizedMap[String, Process]
-
-  def step(evalid: Int, iteration: Int, steptype: String, commands: Seq[String], algoid: Option[Int] = None, metricid: Option[Int] = None, algoids: Option[Seq[Int]] = None, metricids: Option[Seq[Int]] = None) = future {
-    val logPrefix = s"OfflineEval ID $evalid: Iteration ${iteration}: " + algoid.map(id => s"Algo ID ${id}: ").getOrElse("") + metricid.map(id => s"Metric ID ${id}: ").getOrElse("")
-    val key = s"${steptype}-${iteration}" + algoid.map(id => s"-${id}").getOrElse("") + metricid.map(id => s"-${id}").getOrElse("")
-    var abort = false
-
-    Some(steptype) collect {
-      case "split" => {
-        if (iteration > 1) {
-          val iterationkey = s"iteration-${iteration - 1}"
-          while (!finishFlags(iterationkey)) {
-            Thread.sleep(1000)
-          }
-        }
-
-        /** Delete old model data, if any (for recovering from an incomplete run, and clean old score for multi-iterations) */
-        Scheduler.offlineEvals.get(evalid) map { offlineEval =>
-          Scheduler.engines.get(offlineEval.engineid) map { engine =>
-            val algosToRun = Scheduler.algos.getByOfflineEvalid(offlineEval.id).toSeq
-            val modelData = Scheduler.config.getModeldataTraining(engine.infoid)
-            algosToRun foreach { algo =>
-              Logger.info(s"${logPrefix}Algo ID ${algo.id}: Deleting any old model data")
-              modelData.delete(algo.id, false)
-            }
-            Logger.info(s"${logPrefix}Deleting any old user-to-item actions")
-            Scheduler.appdataTrainingU2IActions.deleteByAppid(offlineEval.id)
-            Scheduler.appdataTestU2IActions.deleteByAppid(offlineEval.id)
-          }
-        }
-      }
-      case "training" => {
-        val splitkey = s"split-${iteration}"
-        val trainingkey = s"training-${iteration}-${algoid.get}"
-        while (!finishFlags(splitkey)) {
-          Thread.sleep(1000)
-        }
-        if (exitCodes(splitkey) != 0) {
-          abort = true
-          exitCodes(trainingkey) = 1
-          Logger.info(s"${logPrefix}(${steptype}) Aborted due to split error")
-        }
-      }
-      case "metric" => {
-        val trainingkey = s"training-${iteration}-${algoid.get}"
-        val metrickey = s"metric-${iteration}-${algoid.get}-${metricid.get}"
-        while (!finishFlags(trainingkey)) {
-          Thread.sleep(1000)
-        }
-        if (exitCodes(trainingkey) != 0) {
-          abort = true
-          exitCodes(metrickey) = 1
-          Logger.info(s"${logPrefix}(${steptype}) Aborted due to training error")
-        }
-      }
-      case "iteration" => {
-        val keys = for {
-          aid <- algoids.get
-          mid <- metricids.get
-        } yield s"metric-${iteration}-${aid}-${mid}"
-
-        while (!finishFlags.filterKeys(keys.contains(_)).values.reduce((a, b) => a && b)) {
-          Thread.sleep(1000)
-        }
-
-        Logger.info(s"${logPrefix}(${steptype}) Finished iteration")
-      }
-    }
-
-    commands map { _.trim } foreach { c =>
-      var exception = false
-      this.synchronized {
-        if (!kill && !abort && !c.isEmpty && exitCodes(key) == 0) {
-          Logger.info(s"${logPrefix}(${steptype}) Going to run: $c")
-          try {
-            procs(key) = Process(c).run
-            Logger.info(s"${logPrefix}(${steptype}) Scheduler waiting for sub-process to finish")
-          } catch {
-            case e: java.io.IOException => {
-              exception = true
-              Logger.info(s"${logPrefix}(${steptype}) ${e.getMessage}")
-            }
-          }
-        }
-      }
-
-      // Continue if the last command succeeded
-      if (exitCodes(key) == 0) {
-        procs.get(key) map { p =>
-          val exitCode = if (exception) 1 else p.exitValue
-
-          /** Save completion information for global access */
-          exitCodes(key) = exitCode
-
-          if (exception)
-            Logger.info(s"${logPrefix}(${steptype}) Exception trying to run sub-process")
-          else
-            Logger.info(s"${logPrefix}(${steptype}) Sub-process has finished with exit code ${exitCode}")
-        }
-      }
-    }
-
-    finishFlags(key) = true
-
-    /** Display completion information */
-    if (kill) Logger.info(s"${logPrefix}(${steptype}) Sub-process was killed upon request")
-  }
-
-  override def execute(context: JobExecutionContext): Unit = {
-    val jobDataMap = context.getMergedJobDataMap
-    val evalid = jobDataMap.getInt("evalid")
-
-    val config = Scheduler.config
-    val apps = Scheduler.apps
-    val engines = Scheduler.engines
-    val algos = Scheduler.algos
-    val algoInfos = Scheduler.algoInfos
-    val offlineEvals = Scheduler.offlineEvals
-    val offlineEvalSplitters = Scheduler.offlineEvalSplitters
-    val offlineEvalSplitterInfos = Scheduler.offlineEvalSplitterInfos
-    val offlineEvalMetrics = Scheduler.offlineEvalMetrics
-    val offlineEvalMetricInfos = Scheduler.offlineEvalMetricInfos
-
-    val logPrefix = s"OfflineEval ID $evalid: "
-
-    offlineEvals.get(evalid) map { offlineEval =>
-      engines.get(offlineEval.engineid) map { engine =>
-        apps.get(engine.appid) map { app =>
-
-          val totalIterations = offlineEval.iterations
-          val splittersToRun = offlineEvalSplitters.getByEvalid(offlineEval.id).toSeq
-          val algosToRun = algos.getByOfflineEvalid(offlineEval.id).toSeq
-          val metricsToRun = offlineEvalMetrics.getByEvalid(offlineEval.id).toSeq
-
-          val algoids = algosToRun map { _.id }
-          val metricids = metricsToRun map { _.id }
-
-          Logger.info(s"${logPrefix}Starting offline evaluation with ${totalIterations} iteration(s)")
-
-          /** Mark the start time */
-          val offlineEvalWithStartTime = offlineEval.copy(starttime = Some(DateTime.now))
-          offlineEvals.update(offlineEvalWithStartTime)
-
-          for (currentIteration <- 1 to totalIterations) {
-            val iterationParam = collection.immutable.Map("iteration" -> currentIteration)
-
-            /** Spiltters setup (support 1 splitter for now) */
-            if (splittersToRun.length > 0) {
-              val splitkey = s"split-${currentIteration}"
-              exitCodes(splitkey) = 0
-              finishFlags(splitkey) = false
-
-              val splitter = splittersToRun(0)
-              offlineEvalSplitterInfos.get(splitter.infoid) map { splitterInfo =>
-                splitterInfo.commands map { commands =>
-                  val splitterCommands = commands map { c => Jobs.setSharedAttributes(new StringTemplate(c), config, app, engine, None, Some(offlineEval), None, Some(splitterInfo.params.mapValues(_.defaultvalue) ++ splitter.settings ++ iterationParam)).toString }
-                  step(evalid, currentIteration, "split", splitterCommands)
-                } getOrElse {
-                  Logger.warn(s"${logPrefix}Not doing data split because splitter information for ${splitter.infoid} contains no command")
-                  step(evalid, currentIteration, "split", Seq())
-                }
-              } getOrElse {
-                Logger.warn(s"${logPrefix}Not doing data split because splitter information for ${splitter.infoid} is missing")
-                step(evalid, currentIteration, "split", Seq())
-              }
-            }
-
-            /** Training and metric setup */
-            algosToRun foreach { algo =>
-              val trainingkey = s"training-${currentIteration}-${algo.id}"
-              exitCodes(trainingkey) = 0
-              finishFlags(trainingkey) = false
-
-              algoInfos.get(algo.infoid) map { algoInfo =>
-                algoInfo.offlineevalcommands map { commands =>
-                  val trainingCommands = commands map { c => Jobs.setSharedAttributes(new StringTemplate(c), config, app, engine, Some(algo), Some(offlineEval), None, Some(iterationParam)).toString }
-                  step(evalid, currentIteration, "training", trainingCommands, Some(algo.id))
-                } getOrElse {
-                  Logger.warn(s"${logPrefix}Algo ID ${algo.id}: Not doing training because algo information for ${algo.infoid} contains no command for offline evaluation")
-                  step(evalid, currentIteration, "training", Seq(), Some(algo.id))
-                }
-              } getOrElse {
-                Logger.warn(s"${logPrefix}Algo ID ${algo.id}: Not doing training because algo information for ${algo.infoid} is missing")
-                step(evalid, currentIteration, "training", Seq(), Some(algo.id))
-              }
-
-              /** Run metrics */
-              metricsToRun foreach { metric =>
-                val metrickey = s"metric-${currentIteration}-${algo.id}-${metric.id}"
-                exitCodes(metrickey) = 0
-                finishFlags(metrickey) = false
-
-                offlineEvalMetricInfos.get(metric.infoid) map { metricInfo =>
-                  metricInfo.commands map { commands =>
-                    val metricCommands = commands map { c => Jobs.setSharedAttributes(new StringTemplate(c), config, app, engine, Some(algo), Some(offlineEval), Some(metric), Some(iterationParam)).toString }
-                    step(evalid, currentIteration, "metric", metricCommands, Some(algo.id), Some(metric.id))
-                  } getOrElse {
-                    Logger.warn(s"${logPrefix}Algo ID ${algo.id}: Metric ID ${metric.id}: Not doing training because algo information for ${algo.infoid} contains no command for offline evaluation")
-                    step(evalid, currentIteration, "metric", Seq(), Some(algo.id), Some(metric.id))
-                  }
-                } getOrElse {
-                  Logger.warn(s"${logPrefix}Algo ID ${algo.id}: Metric ID ${metric.id}: Not doing training because algo information for ${algo.infoid} is missing")
-                  step(evalid, currentIteration, "metric", Seq(), Some(algo.id), Some(metric.id))
-                }
-              }
-            }
-
-            val iterationkey = s"iteration-${currentIteration}"
-            exitCodes(iterationkey) = 0
-            finishFlags(iterationkey) = false
-
-            step(evalid, currentIteration, "iteration", Seq(), None, None, Some(algoids), Some(metricids))
-          }
-
-          /** Block on the last iteration */
-          while (!finishFlags(s"iteration-${totalIterations}")) {
-            Thread.sleep(1000)
-          }
-
-          /** Clean up if ended normally or killed */
-          val sumExitCodes = exitCodes.values.sum
-          if (kill || sumExitCodes == 0) {
-            val modelData = config.getModeldataTraining(engine.infoid)
-            algosToRun foreach { algo =>
-              Logger.info(s"${logPrefix}Algo ID ${algo.id}: Deleting used model data")
-              modelData.delete(algo.id, false)
-            }
-            Logger.info(s"${logPrefix}Deleting used app data")
-            Scheduler.appdataTrainingUsers.deleteByAppid(offlineEval.id)
-            Scheduler.appdataTrainingItems.deleteByAppid(offlineEval.id)
-            Scheduler.appdataTrainingU2IActions.deleteByAppid(offlineEval.id)
-            Scheduler.appdataTestUsers.deleteByAppid(offlineEval.id)
-            Scheduler.appdataTestItems.deleteByAppid(offlineEval.id)
-            Scheduler.appdataTestU2IActions.deleteByAppid(offlineEval.id)
-          }
-
-          /** Check for errors from metric */
-          Logger.info(s"${logPrefix}Exit code summary:")
-
-          for (currentIteration <- 1 to totalIterations) {
-            Logger.info(s"${logPrefix}Iteration ${currentIteration}:")
-            Logger.info(s"${logPrefix}  Split: " + exitCodes(s"split-${currentIteration}"))
-            algoids foreach { algoid =>
-              Logger.info(s"${logPrefix}  Algo ID ${algoid}: " + exitCodes(s"training-${currentIteration}-${algoid}"))
-              metricids foreach { metricid =>
-                Logger.info(s"${logPrefix}    Metric ID ${metricid}: " + exitCodes(s"metric-${currentIteration}-${algoid}-${metricid}"))
-              }
-            }
-          }
-
-          if (sumExitCodes != 0)
-            Logger.warn(s"${logPrefix}Offline evaluation completed with error(s)")
-          else
-            Logger.info(s"${logPrefix}Offline evaluation completed")
-
-          /** Mark the end time since this is used to determine whether the run has finished */
-          offlineEvals.update(offlineEvalWithStartTime.copy(endtime = Some(DateTime.now)))
-
-        } getOrElse {
-          Logger.warn(s"${logPrefix}Not starting offline evaluation because the app that owns this offline evaluation cannot be found from the database")
-        }
-      } getOrElse {
-        Logger.warn(s"${logPrefix}Not starting offline evaluation because the engine that owns this offline evaluation cannot be found from the database")
-      }
-    } getOrElse {
-      Logger.warn(s"${logPrefix}Not starting offline evaluation because the offline evaluation cannot be found from the database")
-    }
-  }
-
-  override def interrupt() = {
-    this.synchronized {
-      kill = true
-      procs.values map { _.destroy }
-    }
-  }
-}
-
-@DisallowConcurrentExecution
-@PersistJobDataAfterExecution
-class OfflineTuneJob extends InterruptableJob {
-  @volatile
-  var kill = false
-
-  val exitCodes: Map[String, Int] = new HashMap[String, Int] with SynchronizedMap[String, Int]
-  val finishFlags: Map[String, Boolean] = new HashMap[String, Boolean] with SynchronizedMap[String, Boolean]
-  val procs: Map[String, Process] = new HashMap[String, Process] with SynchronizedMap[String, Process]
-
-  def step(tuneid: Int, evalid: Int, iteration: Int, steptype: String, commands: Seq[String], algoid: Option[Int] = None, metricid: Option[Int] = None, algoids: Option[Seq[Int]] = None, metricids: Option[Seq[Int]] = None) = future {
-    val logPrefix = s"OfflineTune ID $tuneid: OfflineEval ID $evalid: Iteration ${iteration}: " + algoid.map(id => s"Algo ID ${id}: ").getOrElse("") + metricid.map(id => s"Metric ID ${id}: ").getOrElse("")
-    val key = s"${steptype}-${evalid}-${iteration}" + algoid.map(id => s"-${id}").getOrElse("") + metricid.map(id => s"-${id}").getOrElse("")
-    var abort = false
-
-    steptype match {
-      case "split" => {
-        /**
-         * if (iteration > 1) {
-         * val iterationkey = s"iteration-${iteration-1}"
-         * while (!finishFlags(iterationkey)) {
-         * Thread.sleep(1000)
-         * }
-         * }
-         */
-      }
-      case "paramgen" => {
-        val keys = Scheduler.offlineEvals.getByTuneid(tuneid).toSeq.map(oe => s"iteration-${oe.id}-${iteration - 1}")
-        while (!finishFlags.filterKeys(keys.contains(_)).values.reduce((a, b) => a && b)) {
-          Thread.sleep(1000)
-        }
-      }
-      case "training" => {
-        if (iteration == 0) {
-          val splitkey = s"split-${evalid}-${iteration}"
-          while (!finishFlags(splitkey)) {
-            Thread.sleep(1000)
-          }
-          if (exitCodes(splitkey) != 0) {
-            abort = true
-            Logger.info(s"${logPrefix}(${steptype}) Aborted due to split error")
-          }
-        }
-      }
-      case "metric" => {
-        val trainingkey = s"training-${evalid}-${iteration}-${algoid.get}"
-        while (!finishFlags(trainingkey)) {
-          Thread.sleep(1000)
-        }
-        if (exitCodes(trainingkey) != 0) {
-          abort = true
-          Logger.info(s"${logPrefix}(${steptype}) Aborted due to training error")
-        }
-      }
-      case "iteration" => {
-        val keys = for {
-          aid <- algoids.get
-          mid <- metricids.get
-        } yield s"metric-${evalid}-${iteration}-${aid}-${mid}"
-
-        while (!finishFlags.filterKeys(keys.contains(_)).values.reduce((a, b) => a && b)) {
-          Thread.sleep(1000)
-        }
-
-        Logger.info(s"${logPrefix}(${steptype}) Finished iteration")
-      }
-    }
-
-    //val scommands = if (steptype == "iteration" || steptype == "paramgen") commands else Seq("sleep 3")
-    commands map { _.trim } foreach { c =>
-      this.synchronized {
-        if (!kill && !abort && !c.isEmpty && exitCodes(key) == 0) {
-          Logger.info(s"${logPrefix}(${steptype}) Going to run: $c")
-          procs(key) = Process(c).run
-          Logger.info(s"${logPrefix}(${steptype}) Scheduler waiting for sub-process to finish")
-        }
-      }
-
-      procs.get(key) map { p =>
-        val exitCode = p.exitValue
-
-        /** Save completion information for global access */
-        exitCodes(key) = exitCode
-
-        Logger.info(s"${logPrefix}(${steptype}) Sub-process has finished with exit code ${exitCode}")
-      }
-    }
-
-    finishFlags(key) = true
-
-    /** Display completion information */
-    if (kill) Logger.info(s"${logPrefix}(${steptype}) Sub-process was killed upon request")
-  }
-
-  override def execute(context: JobExecutionContext): Unit = {
-    val jobDataMap = context.getMergedJobDataMap
-    val tuneid = jobDataMap.getInt("tuneid")
-
-    val config = Scheduler.config
-    val apps = Scheduler.apps
-    val engines = Scheduler.engines
-    val algos = Scheduler.algos
-    val algoInfos = Scheduler.algoInfos
-    val offlineEvals = Scheduler.offlineEvals
-    val offlineEvalSplitters = Scheduler.offlineEvalSplitters
-    val offlineEvalSplitterInfos = Scheduler.offlineEvalSplitterInfos
-    val offlineEvalMetrics = Scheduler.offlineEvalMetrics
-    val offlineEvalMetricInfos = Scheduler.offlineEvalMetricInfos
-    val offlineTunes = Scheduler.offlineTunes
-    val paramGens = Scheduler.paramGens
-    val paramGenInfos = Scheduler.paramGenInfos
-
-    val logPrefix = s"OfflineTune ID $tuneid: "
-
-    val testMetricParams = collection.immutable.Map("splitset" -> "test")
-    val validationMetricParams = collection.immutable.Map(
-      "splitset" -> "validation",
-      "appdataTestDbType" -> config.appdataValidationDbType,
-      "appdataTestDbName" -> config.appdataValidationDbName,
-      "appdataTestDbHost" -> config.appdataValidationDbHost,
-      "appdataTestDbPort" -> config.appdataValidationDbPort)
-
-    offlineTunes.get(tuneid) map { offlineTune =>
-      engines.get(offlineTune.engineid) map { engine =>
-        val modelData = config.getModeldataTraining(engine.infoid)
-        apps.get(engine.appid) map { app =>
-          val totalLoops = offlineTune.loops
-          val offlineEvalsToRun = offlineEvals.getByTuneid(offlineTune.id).toSeq
-
-          Logger.info(s"${logPrefix}Starting offline tuning with ${offlineEvalsToRun.size} data set(s) and ${totalLoops} iteration(s) of parameter generation")
-
-          /** Mark the start time */
-          val offlineTuneWithStartTime = offlineTune.copy(starttime = Some(DateTime.now))
-          offlineTunes.update(offlineTuneWithStartTime)
-
-          /** Data splitting (done only once for each evaluation), and baseline algo evaluation */
-          offlineEvalsToRun foreach { offlineEval =>
-            val splittersToRun = offlineEvalSplitters.getByEvalid(offlineEval.id).toSeq
-            val algosToRun = algos.getByOfflineEvalid(offlineEval.id).toSeq.filter(_.loop.map(_ == 0).getOrElse(false))
-            val metricsToRun = offlineEvalMetrics.getByEvalid(offlineEval.id).toSeq
-            val algoids = algosToRun map { _.id }
-            val metricids = metricsToRun map { _.id }
-
-            /** Delete old model data, if any (usually recovering from an incomplete run) */
-            val algosToClean = algos.getByOfflineEvalid(offlineEval.id).toSeq.filter(_.loop.map(_ != 0).getOrElse(false))
-            algosToClean foreach { algo =>
-              Logger.info(s"${logPrefix}OfflineEval ID ${offlineEval.id}: Algo ID ${algo.id}: Deleting any old model data")
-              modelData.delete(algo.id, false)
-              algos.delete(algo.id)
-            }
-            Logger.info(s"${logPrefix}OfflineEval ID ${offlineEval.id}: Deleting any old app data")
-            Scheduler.appdataTrainingUsers.deleteByAppid(offlineEval.id)
-            Scheduler.appdataTrainingItems.deleteByAppid(offlineEval.id)
-            Scheduler.appdataTrainingU2IActions.deleteByAppid(offlineEval.id)
-            Scheduler.appdataTestUsers.deleteByAppid(offlineEval.id)
-            Scheduler.appdataTestItems.deleteByAppid(offlineEval.id)
-            Scheduler.appdataTestU2IActions.deleteByAppid(offlineEval.id)
-            Scheduler.appdataValidationUsers.deleteByAppid(offlineEval.id)
-            Scheduler.appdataValidationItems.deleteByAppid(offlineEval.id)
-            Scheduler.appdataValidationU2IActions.deleteByAppid(offlineEval.id)
-
-            val currentIteration = 0
-            val iterationParam = collection.immutable.Map("iteration" -> currentIteration)
-            val splitIterationParam = collection.immutable.Map("iteration" -> 1)
-
-            /** Spiltters setup (support 1 splitter for now) */
-            if (splittersToRun.length > 0) {
-              val splitter = splittersToRun(0)
-              val splitkey = s"split-${offlineEval.id}-${currentIteration}"
-              exitCodes(splitkey) = 0
-              finishFlags(splitkey) = false
-
-              offlineEvalSplitterInfos.get(splitter.infoid) map { splitterInfo =>
-                splitterInfo.commands map { commands =>
-                  val splitterCommands = commands map { c => Jobs.setSharedAttributes(new StringTemplate(c), config, app, engine, None, Some(offlineEval), None, Some(splitterInfo.params.mapValues(_.defaultvalue) ++ splitter.settings ++ splitIterationParam)).toString }
-                  step(tuneid, offlineEval.id, currentIteration, "split", splitterCommands)
-                } getOrElse {
-                  Logger.warn(s"${logPrefix}OfflineEval ID ${offlineEval.id}: Not doing data split because splitter information for ${splitter.infoid} contains no command")
-                  step(tuneid, offlineEval.id, currentIteration, "split", Seq())
-                }
-              } getOrElse {
-                Logger.warn(s"${logPrefix}OfflineEval ID ${offlineEval.id}: Not doing data split because splitter information for ${splitter.infoid} is missing")
-                step(tuneid, offlineEval.id, currentIteration, "split", Seq())
-              }
-            }
-
-            algosToRun foreach { algo =>
-              val trainingkey = s"training-${offlineEval.id}-${currentIteration}-${algo.id}"
-
-              exitCodes(trainingkey) = 0
-              finishFlags(trainingkey) = false
-
-              algoInfos.get(algo.infoid) map { algoInfo =>
-                algoInfo.offlineevalcommands map { commands =>
-                  val trainingCommands = commands map { c => Jobs.setSharedAttributes(new StringTemplate(c), config, app, engine, Some(algo), Some(offlineEval), None, Some(iterationParam)).toString }
-                  step(tuneid, offlineEval.id, currentIteration, "training", trainingCommands, Some(algo.id))
-                } getOrElse {
-                  Logger.warn(s"${logPrefix}OfflineEval ID ${offlineEval.id}: Algo ID ${algo.id}: Not doing training because algo information for ${algo.infoid} contains no command for offline evaluation")
-                  step(tuneid, offlineEval.id, currentIteration, "training", Seq(), Some(algo.id))
-                }
-              } getOrElse {
-                Logger.warn(s"${logPrefix}OfflineEval ID ${offlineEval.id}: Algo ID ${algo.id}: Not doing training because algo information for ${algo.infoid} is missing")
-                step(tuneid, offlineEval.id, currentIteration, "training", Seq(), Some(algo.id))
-              }
-
-              /** Run metrics */
-              metricsToRun foreach { metric =>
-                val metrickey = s"metric-${offlineEval.id}-${currentIteration}-${algo.id}-${metric.id}"
-
-                exitCodes(metrickey) = 0
-                finishFlags(metrickey) = false
-
-                offlineEvalMetricInfos.get(metric.infoid) map { metricInfo =>
-                  metricInfo.commands map { commands =>
-                    val metricCommands = commands map { c => Jobs.setSharedAttributes(new StringTemplate(c), config, app, engine, Some(algo), Some(offlineEval), Some(metric), Some(testMetricParams ++ iterationParam)).toString }
-                    step(tuneid, offlineEval.id, currentIteration, "metric", metricCommands, Some(algo.id), Some(metric.id))
-                  } getOrElse {
-                    Logger.warn(s"${logPrefix}OfflineEval ID ${offlineEval.id}: Algo ID ${algo.id}: Metric ID ${metric.id}: Not doing training because algo information for ${algo.infoid} contains no command for offline evaluation")
-                    step(tuneid, offlineEval.id, currentIteration, "metric", Seq(), Some(algo.id), Some(metric.id))
-                  }
-                } getOrElse {
-                  Logger.warn(s"${logPrefix}OfflineEval ID ${offlineEval.id}: Algo ID ${algo.id}: Metric ID ${metric.id}: Not doing training because algo information for ${algo.infoid} is missing")
-                  step(tuneid, offlineEval.id, currentIteration, "metric", Seq(), Some(algo.id), Some(metric.id))
-                }
-              }
-            }
-
-            /** Block on baseline training and metric */
-            val iterationkey = s"iteration-${offlineEval.id}-${currentIteration}"
-            exitCodes(iterationkey) = 0
-            finishFlags(iterationkey) = false
-
-            step(tuneid, offlineEval.id, currentIteration, "iteration", Seq(), None, None, Some(algoids), Some(metricids))
-          }
-
-          /** Start iterative tuning */
-
-          /** Parameter generator setup (support 1 param gen for now) */
-          /** Parameter generator is run once for all offline evaluations */
-          val tuneSubject = algos.getTuneSubjectByOfflineTuneid(tuneid).get
-          val paramGensToRun = paramGens.getByTuneid(tuneid).toSeq
-          val paramGen = paramGensToRun(0)
-          val paramGenInfo = paramGenInfos.get(paramGen.infoid)
-          val paramGenParams = collection.immutable.Map("algoid" -> tuneSubject.id, "paramsets" -> 1, "evalids" -> offlineEvalsToRun.map(_.id.toString).reduce((a, b) => s"${a},${b}"))
-
-          for (currentLoop <- 1 to totalLoops) {
-            val iterationParam = collection.immutable.Map("iteration" -> currentLoop)
-            val loopParam = collection.immutable.Map("loop" -> currentLoop)
-
-            val paramGenKey = s"paramgen-0-${currentLoop}"
-            if (paramGensToRun.length > 0) {
-              val paramGen = paramGensToRun(0)
-              exitCodes(paramGenKey) = 0
-              finishFlags(paramGenKey) = false
-
-              paramGenInfo map { paramGenInfo =>
-                paramGenInfo.commands map { commands =>
-                  val paramGenCommands = commands map { c => Jobs.setSharedAttributes(new StringTemplate(c), config, app, engine, None, None, None, Some(paramGenInfo.paramdefaults ++ paramGen.params ++ loopParam ++ paramGenParams)).toString }
-                  step(tuneid, 0, currentLoop, "paramgen", paramGenCommands)
-                } getOrElse {
-                  Logger.warn(s"${logPrefix}: Not generating parameters because generator information for ${paramGen.infoid} contains no command")
-                  step(tuneid, 0, currentLoop, "paramgen", Seq())
-                }
-              } getOrElse {
-                Logger.warn(s"${logPrefix}: Not generating parameters because generator information for ${paramGen.infoid} is missing")
-                step(tuneid, 0, currentLoop, "paramgen", Seq())
-              }
-            }
-
-            /** Block on param gen */
-            while (!finishFlags(paramGenKey)) {
-              Thread.sleep(1000)
-            }
-
-            /** Evaluate generated algos */
-            offlineEvalsToRun foreach { offlineEval =>
-              /** Only 1 param set for now */
-              val algosToRun = algos.getByOfflineEvalid(offlineEval.id, Some(currentLoop), Some(1)).toSeq
-              val metricsToRun = offlineEvalMetrics.getByEvalid(offlineEval.id).toSeq
-              val algoids = algosToRun map { _.id }
-              val metricids = metricsToRun map { _.id }
-
-              algosToRun foreach { algo =>
-                val trainingkey = s"training-${offlineEval.id}-${currentLoop}-${algo.id}"
-
-                exitCodes(trainingkey) = 0
-                finishFlags(trainingkey) = false
-
-                algoInfos.get(algo.infoid) map { algoInfo =>
-                  algoInfo.offlineevalcommands map { commands =>
-                    val trainingCommands = commands map { c => Jobs.setSharedAttributes(new StringTemplate(c), config, app, engine, Some(algo), Some(offlineEval), None, Some(loopParam)).toString }
-                    step(tuneid, offlineEval.id, currentLoop, "training", trainingCommands, Some(algo.id))
-                  } getOrElse {
-                    Logger.warn(s"${logPrefix}OfflineEval ID ${offlineEval.id}: Algo ID ${algo.id}: Not doing training because algo information for ${algo.infoid} contains no command for offline evaluation")
-                    step(tuneid, offlineEval.id, currentLoop, "training", Seq(), Some(algo.id))
-                  }
-                } getOrElse {
-                  Logger.warn(s"${logPrefix}OfflineEval ID ${offlineEval.id}: Algo ID ${algo.id}: Not doing training because algo information for ${algo.infoid} is missing")
-                  step(tuneid, offlineEval.id, currentLoop, "training", Seq(), Some(algo.id))
-                }
-
-                /** Run metrics */
-                metricsToRun foreach { metric =>
-                  val metrickey = s"metric-${offlineEval.id}-${currentLoop}-${algo.id}-${metric.id}"
-
-                  exitCodes(metrickey) = 0
-                  finishFlags(metrickey) = false
-
-                  offlineEvalMetricInfos.get(metric.infoid) map { metricInfo =>
-                    metricInfo.commands map { commands =>
-                      val validationMetricCommands = commands map { c => Jobs.setSharedAttributes(new StringTemplate(c), config, app, engine, Some(algo), Some(offlineEval), Some(metric), Some(validationMetricParams ++ iterationParam)).toString }
-                      val testMetricCommands = commands map { c => Jobs.setSharedAttributes(new StringTemplate(c), config, app, engine, Some(algo), Some(offlineEval), Some(metric), Some(testMetricParams ++ iterationParam)).toString }
-                      step(tuneid, offlineEval.id, currentLoop, "metric", validationMetricCommands ++ testMetricCommands, Some(algo.id), Some(metric.id))
-                    } getOrElse {
-                      Logger.warn(s"${logPrefix}OfflineEval ID ${offlineEval.id}: Algo ID ${algo.id}: Metric ID ${metric.id}: Not doing training because algo information for ${algo.infoid} contains no command for offline evaluation")
-                      step(tuneid, offlineEval.id, currentLoop, "metric", Seq(), Some(algo.id), Some(metric.id))
-                    }
-                  } getOrElse {
-                    Logger.warn(s"${logPrefix}OfflineEval ID ${offlineEval.id}: Algo ID ${algo.id}: Metric ID ${metric.id}: Not doing training because algo information for ${algo.infoid} is missing")
-                    step(tuneid, offlineEval.id, currentLoop, "metric", Seq(), Some(algo.id), Some(metric.id))
-                  }
-                }
-              }
-
-              /** Block on training and metric */
-              val iterationkey = s"iteration-${offlineEval.id}-${currentLoop}"
-              exitCodes(iterationkey) = 0
-              finishFlags(iterationkey) = false
-
-              step(tuneid, offlineEval.id, currentLoop, "iteration", Seq(), None, None, Some(algoids), Some(metricids))
-            }
-          }
-
-          /** Block on last iterations of all offline evaluations */
-          val offlineEvalKeys = offlineEvalsToRun map { o => s"iteration-${o.id}-${totalLoops}" }
-
-          while (!finishFlags.filterKeys(offlineEvalKeys.contains(_)).values.reduce((a, b) => a && b)) {
-            Thread.sleep(1000)
-          }
-
-          /** Check for errors from metric */
-          Logger.info(s"${logPrefix}Exit code summary:")
-
-          Logger.info(s"${logPrefix}Iteration 0:")
-          offlineEvalsToRun foreach { offlineEval =>
-            val currentIteration = 0
-            val algosToRun = algos.getByOfflineEvalid(offlineEval.id).toSeq.filter(_.loop.map(_ == currentIteration).getOrElse(false))
-            val metricsToRun = offlineEvalMetrics.getByEvalid(offlineEval.id).toSeq
-            val algoids = algosToRun map { _.id }
-            val metricids = metricsToRun map { _.id }
-            Logger.info(s"${logPrefix}OfflineEval ID ${offlineEval.id}:   Split: " + exitCodes(s"split-${offlineEval.id}-${currentIteration}"))
-            algoids foreach { algoid =>
-              Logger.info(s"${logPrefix}OfflineEval ID ${offlineEval.id}:   Algo ID ${algoid}: " + exitCodes(s"training-${offlineEval.id}-${currentIteration}-${algoid}"))
-              metricids foreach { metricid =>
-                Logger.info(s"${logPrefix}OfflineEval ID ${offlineEval.id}:     Metric ID ${metricid}: " + exitCodes(s"metric-${offlineEval.id}-${currentIteration}-${algoid}-${metricid}"))
-              }
-            }
-          }
-          for (currentLoop <- 1 to totalLoops) {
-            Logger.info(s"${logPrefix}Iteration ${currentLoop}:")
-            offlineEvalsToRun foreach { offlineEval =>
-              val algosToRun = algos.getByOfflineEvalid(offlineEval.id, Some(currentLoop), Some(1)).toSeq
-              val metricsToRun = offlineEvalMetrics.getByEvalid(offlineEval.id).toSeq
-              val algoids = algosToRun map { _.id }
-              val metricids = metricsToRun map { _.id }
-              algoids foreach { algoid =>
-                Logger.info(s"${logPrefix}OfflineEval ID ${offlineEval.id}:   Algo ID ${algoid}: " + exitCodes(s"training-${offlineEval.id}-${currentLoop}-${algoid}"))
-                metricids foreach { metricid =>
-                  Logger.info(s"${logPrefix}OfflineEval ID ${offlineEval.id}:     Metric ID ${metricid}: " + exitCodes(s"metric-${offlineEval.id}-${currentLoop}-${algoid}-${metricid}"))
-                }
-              }
-            }
-          }
-
-          if (exitCodes.values.sum != 0)
-            Logger.warn(s"${logPrefix}Offline tuning completed with error(s)")
-          else
-            Logger.info(s"${logPrefix}Offline tuning completed")
-
-          /** Mark the end time since this is used to determine whether the run has finished */
-          offlineTunes.update(offlineTuneWithStartTime.copy(endtime = Some(DateTime.now)))
-
-          /** Mark subject algo as tuned */
-          algos.update(tuneSubject.copy(status = "tuned"))
-
-          /** Clean up */
-          offlineEvalsToRun foreach { offlineEval =>
-            val algosToClean = algos.getByOfflineEvalid(offlineEval.id).toSeq.filter(_.loop.map(_ != 0).getOrElse(false))
-            algosToClean foreach { algo =>
-              Logger.info(s"${logPrefix}OfflineEval ID ${offlineEval.id}: Algo ID ${algo.id}: Deleting used model data")
-              modelData.delete(algo.id, false)
-            }
-            Logger.info(s"${logPrefix}OfflineEval ID ${offlineEval.id}: Deleting used app data")
-            Scheduler.appdataTrainingUsers.deleteByAppid(offlineEval.id)
-            Scheduler.appdataTrainingItems.deleteByAppid(offlineEval.id)
-            Scheduler.appdataTrainingU2IActions.deleteByAppid(offlineEval.id)
-            Scheduler.appdataTestUsers.deleteByAppid(offlineEval.id)
-            Scheduler.appdataTestItems.deleteByAppid(offlineEval.id)
-            Scheduler.appdataTestU2IActions.deleteByAppid(offlineEval.id)
-            Scheduler.appdataValidationUsers.deleteByAppid(offlineEval.id)
-            Scheduler.appdataValidationItems.deleteByAppid(offlineEval.id)
-            Scheduler.appdataValidationU2IActions.deleteByAppid(offlineEval.id)
-          }
-        } getOrElse {
-          Logger.warn(s"${logPrefix}Not starting offline tuning because the app that owns this offline tuning cannot be found from the database")
-        }
-      } getOrElse {
-        Logger.warn(s"${logPrefix}Not starting offline tuning because the engine that owns this offline tuning cannot be found from the database")
-      }
-    } getOrElse {
-      Logger.warn(s"${logPrefix}Not starting offline tuning because the offline tuning cannot be found from the database")
-    }
-  }
-
-  override def interrupt() = {
-    this.synchronized {
-      kill = true
-      procs.values map { _.destroy }
-    }
-  }
-}
diff --git a/servers/scheduler/app/controllers/Operations.scala b/servers/scheduler/app/controllers/Operations.scala
deleted file mode 100644
index 286f3df..0000000
--- a/servers/scheduler/app/controllers/Operations.scala
+++ /dev/null
@@ -1,116 +0,0 @@
-package io.prediction.scheduler
-
-import io.prediction.commons.filepath.BaseDir
-import io.prediction.commons.Config
-
-import scala.sys.process._
-import java.io.File
-
-import org.apache.commons.io.FileUtils
-import play.api._
-import play.api.libs.json._
-import play.api.mvc._
-
-object Operations extends Controller {
-  val config = new Config
-
-  def hadoopRequired(request: Request[_]) = request.queryString.contains("hadoop")
-
-  def deleteApp(appid: Int) = Action { implicit request =>
-    val localPath = BaseDir.appDir(config.settingsLocalTempRoot, appid)
-    val localFile = new File(localPath)
-    localFile.mkdirs()
-    val localCode = FileUtils.deleteQuietly(localFile)
-    val hadoopPath = BaseDir.appDir(config.settingsHdfsRoot, appid)
-    // mkdir again to make sure that rmr failure is not due to non existing dir.
-    // mkdir error can be ignored.
-    val hadoopCode = if (hadoopRequired(request)) {
-      try {
-        val mkdir = s"${Scheduler.hadoopCommand} fs -mkdir $hadoopPath".!
-        val code = s"${Scheduler.hadoopCommand} fs -rmr $hadoopPath".!
-        if (code == 0) true else false
-      } catch {
-        case e: java.io.IOException => true // allow deletion if hadoop command is absent         
-      }
-    } else true
-    if (localCode && hadoopCode)
-      Ok(Json.obj("message" -> s"Deleted local (and HDFS, if applicable) storage for App ID: $appid (local: $localPath; HDFS: $hadoopPath)"))
-    else if (localCode)
-      InternalServerError(Json.obj("message" -> s"Unable to delete HDFS storage for App ID: $appid ($hadoopPath). Please check logs/scheduler.log, logs/scheduler.err and Hadoop log files."))
-    else
-      InternalServerError(Json.obj("message" -> s"Unable to delete local temporary storage for App ID: $appid ($localPath). Please check logs/scheduler.log, logs/scheduler.err and Hadoop log files."))
-  }
-
-  def deleteEngine(appid: Int, engineid: Int) = Action { implicit request =>
-    val localPath = BaseDir.engineDir(config.settingsLocalTempRoot, appid, engineid)
-    val localFile = new File(localPath)
-    localFile.mkdirs()
-    val localCode = FileUtils.deleteQuietly(localFile)
-    val hadoopPath = BaseDir.engineDir(config.settingsHdfsRoot, appid, engineid)
-    // mkdir again to make sure that rmr failure is not due to non existing dir.
-    // mkdir error can be ignored.
-    val hadoopCode = if (hadoopRequired(request)) {
-      try {
-        val mkdir = s"${Scheduler.hadoopCommand} fs -mkdir $hadoopPath".!
-        val code = s"${Scheduler.hadoopCommand} fs -rmr $hadoopPath".!
-        if (code == 0) true else false
-      } catch {
-        case e: java.io.IOException => true // allow deletion if hadoop command is absent         
-      }
-    } else true
-    if (localCode && hadoopCode)
-      Ok(Json.obj("message" -> s"Deleted local (and HDFS, if applicable) storage for App ID: $appid, Engine ID: $engineid (local: $localPath; HDFS: $hadoopPath)"))
-    else if (localCode)
-      InternalServerError(Json.obj("message" -> s"Unable to delete HDFS storage for App ID: $appid, Engine ID: $engineid ($hadoopPath). Please check logs/scheduler.log, logs/scheduler.err and Hadoop log files."))
-    else
-      InternalServerError(Json.obj("message" -> s"Unable to delete local temporary storage for App ID: $appid, Engine ID: $engineid ($localPath). Please check logs/scheduler.log, logs/scheduler.err and Hadoop log files."))
-  }
-
-  def deleteAlgo(appid: Int, engineid: Int, algoid: Int) = Action { implicit request =>
-    val localPath = BaseDir.algoDir(config.settingsLocalTempRoot, appid, engineid, algoid, None)
-    val localFile = new File(localPath)
-    localFile.mkdirs()
-    val localCode = FileUtils.deleteQuietly(localFile)
-    val hadoopPath = BaseDir.algoDir(config.settingsHdfsRoot, appid, engineid, algoid, None)
-    val hadoopCode = if (hadoopRequired(request)) {
-      try {
-        val mkdir = s"${Scheduler.hadoopCommand} fs -mkdir $hadoopPath".!
-        val code = s"${Scheduler.hadoopCommand} fs -rmr $hadoopPath".!
-        if (code == 0) true else false
-      } catch {
-        case e: java.io.IOException => true // allow deletion if hadoop command is absent         
-      }
-    } else true
-    if (localCode && hadoopCode)
-      Ok(Json.obj("message" -> s"Deleted HDFS storage for App ID: $appid, Engine ID: $engineid, Algo ID: $algoid (local: $localPath; HDFS: $hadoopPath)"))
-    else if (localCode)
-      InternalServerError(Json.obj("message" -> s"Unable to delete HDFS storage for App ID: $appid, Engine ID: $engineid, Algo ID: $algoid ($hadoopPath). Please check logs/scheduler.log, logs/scheduler.err and Hadoop log files."))
-    else
-      InternalServerError(Json.obj("message" -> s"Unable to delete local temporary storage for App ID: $appid, Engine ID: $engineid, Algo ID: $algoid ($localPath). Please check logs/scheduler.log, logs/scheduler.err and Hadoop log files."))
-  }
-
-  def deleteOfflineEval(appid: Int, engineid: Int, offlineevalid: Int) = Action { implicit request =>
-    val localPath = BaseDir.offlineEvalDir(config.settingsLocalTempRoot, appid, engineid, offlineevalid)
-    val localFile = new File(localPath)
-    localFile.mkdirs()
-    val localCode = FileUtils.deleteQuietly(localFile)
-    val hadoopPath = BaseDir.offlineEvalDir(config.settingsHdfsRoot, appid, engineid, offlineevalid)
-    // mkdir again to make sure that rmr failure is not due to non existing dir.
-    // mkdir error can be ignored.
-    val hadoopCode = if (hadoopRequired(request)) {
-      try {
-        val mkdir = s"${Scheduler.hadoopCommand} fs -mkdir $hadoopPath".!
-        val code = s"${Scheduler.hadoopCommand} fs -rmr $hadoopPath".!
-        if (code == 0) true else false
-      } catch {
-        case e: java.io.IOException => true // allow deletion if hadoop command is absent         
-      }
-    } else true
-    if (localCode && hadoopCode)
-      Ok(Json.obj("message" -> s"Deleted local (and HDFS, if applicable) storage for App ID: $appid, Engine ID: $engineid, OfflineEval ID: $offlineevalid (local: $localPath; HDFS: $hadoopPath)"))
-    else if (localCode)
-      InternalServerError(Json.obj("message" -> s"Unable to delete HDFS storage for App ID: $appid, Engine ID: $engineid, OfflineEval ID: $offlineevalid ($hadoopPath). Please check logs/scheduler.log, logs/scheduler.err and Hadoop log files."))
-    else
-      InternalServerError(Json.obj("message" -> s"Unable to delete local temporary storage for App ID: $appid, Engine ID: $engineid, OfflineEval ID: $offlineevalid ($localPath). Please check logs/scheduler.log, logs/scheduler.err and Hadoop log files."))
-  }
-}
diff --git a/servers/scheduler/app/controllers/Scheduler.scala b/servers/scheduler/app/controllers/Scheduler.scala
deleted file mode 100644
index e2a41c6..0000000
--- a/servers/scheduler/app/controllers/Scheduler.scala
+++ /dev/null
@@ -1,304 +0,0 @@
-package io.prediction.scheduler
-
-import io.prediction.commons._
-
-import collection.JavaConversions._
-import play.api._
-import play.api.libs.json._
-import play.api.mvc._
-import org.quartz.CronExpression
-import org.quartz.CronScheduleBuilder.cronSchedule
-import org.quartz.impl.matchers.GroupMatcher._
-import org.quartz.impl.StdSchedulerFactory
-import org.quartz.JobBuilder.newJob
-import org.quartz.JobKey.jobKey
-import org.quartz.SimpleScheduleBuilder.simpleSchedule
-import org.quartz.TriggerBuilder.newTrigger
-import org.quartz.TriggerKey.triggerKey
-import org.quartz.UnableToInterruptJobException
-
-object Scheduler extends Controller {
-  /** Get settings. */
-  val config = new Config
-  val users = config.getSettingsUsers
-  val apps = config.getSettingsApps
-  val engines = config.getSettingsEngines
-  val engineInfos = config.getSettingsEngineInfos
-  val algos = config.getSettingsAlgos
-  val algoInfos = config.getSettingsAlgoInfos
-  val offlineEvals = config.getSettingsOfflineEvals
-  val offlineEvalSplitters = config.getSettingsOfflineEvalSplitters
-  val offlineEvalSplitterInfos = config.getSettingsOfflineEvalSplitterInfos
-  val offlineEvalMetrics = config.getSettingsOfflineEvalMetrics
-  val offlineEvalMetricInfos = config.getSettingsOfflineEvalMetricInfos
-  val offlineEvalResults = config.getSettingsOfflineEvalResults
-  val offlineTunes = config.getSettingsOfflineTunes
-  val paramGens = config.getSettingsParamGens
-  val paramGenInfos = config.getSettingsParamGenInfos
-  val systemInfos = config.getSettingsSystemInfos
-  val itemRecScores = config.getModeldataItemRecScores
-  val trainingItemRecScores = config.getModeldataTrainingItemRecScores
-  val itemSimScores = config.getModeldataItemSimScores
-  val trainingItemSimScores = config.getModeldataTrainingItemSimScores
-
-  val appdataTrainingUsers = config.getAppdataTrainingUsers()
-  val appdataTrainingItems = config.getAppdataTrainingItems()
-  val appdataTrainingU2IActions = config.getAppdataTrainingU2IActions()
-  val appdataTestUsers = config.getAppdataTestUsers()
-  val appdataTestItems = config.getAppdataTestItems()
-  val appdataTestU2IActions = config.getAppdataTestU2IActions()
-  val appdataValidationUsers = config.getAppdataValidationUsers()
-  val appdataValidationItems = config.getAppdataValidationItems()
-  val appdataValidationU2IActions = config.getAppdataValidationU2IActions()
-
-  val scheduler = StdSchedulerFactory.getDefaultScheduler()
-  val jobTree = new JobTreeJobListener("predictionio-algo")
-  scheduler.getListenerManager.addJobListener(jobTree)
-
-  /** Try search path if hadoop home is not set. */
-  val hadoopCommand = config.settingsHadoopHome map { h => h + "/bin/hadoop" } getOrElse { "hadoop" }
-
-  /** Schedule update check if enabled. */
-  if (config.settingsSchedulerUpdatecheck) {
-    val updateCheckJob = newJob(classOf[UpdateCheckJob]) withIdentity ("updatecheck", "updatecheck") build ()
-    val updateCheckTrigger = newTrigger() forJob (jobKey("updatecheck", "updatecheck")) withIdentity ("updatecheck", "updatecheck") startNow () withSchedule (simpleSchedule() withIntervalInHours (24) repeatForever ()) build ()
-    scheduler.scheduleJob(updateCheckJob, updateCheckTrigger)
-  }
-
-  /** Sync the scheduler once against settings database. */
-  def syncAllUsers() = {
-    users.getAll foreach { user =>
-      syncUserJobs(user.id)
-    }
-  }
-
-  def online() = Action { Ok("PredictionIO Scheduler is online.") }
-
-  def userSync(userid: Int) = Action {
-    try {
-      syncUserJobs(userid)
-      /** Complete synchronization. */
-      Ok(Json.obj("message" -> "Synchronized algorithms settings with scheduler successfully."))
-    } catch {
-      case e: RuntimeException =>
-        e.printStackTrace; NotFound(Json.obj("message" -> ("Synchronization failed: " + e.getMessage())))
-      case e: Exception => InternalServerError(Json.obj("message" -> ("Synchronization failed: " + e.getMessage())))
-    }
-  }
-
-  def syncUserJobs(userid: Int) = {
-    /** Remove jobs that do not correspond to an algo. */
-    scheduler.getJobKeys(groupEquals(Jobs.algoJobGroup)) foreach { jobKey =>
-      val algoid = jobKey.getName().toInt
-      algos.get(algoid) getOrElse {
-        Logger.info("Found job for algo ID " + algoid + " in scheduler but not in settings. Removing job from scheduler.")
-        scheduler.deleteJob(jobKey)
-      }
-    }
-
-    /** Synchronize every app of the user. */
-    Logger.info(s"User ID ${userid}: Synchronizing settings")
-    apps.getByUserid(userid) foreach { app =>
-      engines.getByAppid(app.id) foreach { engine =>
-        /** Algos. */
-        syncAlgoJobs(app, engine, false)
-
-        /** Offline evaluations. */
-        offlineEvals.getByEngineid(engine.id) foreach { offlineEval =>
-          /** Work on those that is not part of auto tuning */
-          offlineEval.tuneid getOrElse {
-            val offlineEvalid = offlineEval.id.toString
-            val triggerkey = triggerKey(offlineEvalid, Jobs.offlineEvalJobGroup)
-            offlineEval.createtime foreach { ct =>
-              if (scheduler.checkExists(triggerkey) == false) {
-                offlineEval.endtime getOrElse {
-                  val offlineEvalJob = Jobs.offlineEvalJob(config, app, engine, offlineEval)
-                  scheduler.addJob(offlineEvalJob, true)
-
-                  val trigger = newTrigger() forJob (jobKey(offlineEvalid, Jobs.offlineEvalJobGroup)) withIdentity (offlineEvalid, Jobs.offlineEvalJobGroup) startNow () build ()
-                  scheduler.scheduleJob(trigger)
-                }
-              }
-            }
-          }
-        }
-
-        /** Auto tunings. */
-        offlineTunes.getByEngineid(engine.id) foreach { offlineTune =>
-          /** Work on those that is not part of auto tuning */
-          val offlineTuneid = offlineTune.id.toString
-          val triggerkey = triggerKey(offlineTuneid, Jobs.offlineTuneJobGroup)
-          offlineTune.createtime foreach { ct =>
-            if (scheduler.checkExists(triggerkey) == false) {
-              offlineTune.endtime getOrElse {
-                val offlineTuneJob = Jobs.offlineTuneJob(config, app, engine, offlineTune)
-                scheduler.addJob(offlineTuneJob, true)
-
-                val trigger = newTrigger() forJob (jobKey(offlineTuneid, Jobs.offlineTuneJobGroup)) withIdentity (offlineTuneid, Jobs.offlineTuneJobGroup) startNow () build ()
-                scheduler.scheduleJob(trigger)
-              }
-            }
-          }
-        }
-      }
-    }
-  }
-
-  /** Run training of deployed algorithms immediately */
-  def syncAlgoJobs(app: settings.App, engine: settings.Engine, runoncenow: Boolean = false) = {
-    /** Algos. */
-    algos.getByEngineid(engine.id) foreach { algo =>
-      val logPrefix = s"Algo ID ${algo.id}: "
-      algoInfos.get(algo.infoid) map { algoinfo =>
-        val algoid = algo.id.toString
-        val triggerkey = triggerKey(algoid, Jobs.algoJobGroup)
-        if (algo.status == "deployed") {
-          /** Running once now is independent of whether the trigger exist or not */
-          if (runoncenow) {
-            Logger.info(s"${logPrefix}Setting up batch algo job (run once now)")
-            algoinfo.batchcommands map { batchcommands =>
-              val job = Jobs.algoJob(config, app, engine, algo, batchcommands)
-              scheduler.addJob(job, true)
-              val trigger = newTrigger() forJob (jobKey(algoid, Jobs.algoJobGroup)) withIdentity (s"${algoid}-runonce", Jobs.algoJobGroup) startNow () build ()
-              scheduler.scheduleJob(trigger)
-            } getOrElse {
-              Logger.info(s"${logPrefix}Giving up setting up batch algo job because it does not have any batch command")
-            }
-          } else {
-            if (scheduler.checkExists(triggerkey)) {
-              Logger.info(s"${logPrefix}Resetting existing trigger")
-              scheduler.unscheduleJob(triggerkey)
-            }
-            val trainingdisabled = engine.trainingdisabled.getOrElse(false)
-            if (trainingdisabled) {
-              Logger.info(s"${logPrefix}Training disabled")
-            } else {
-              // Append a 0 in front since Quartz support granularity to seconds
-              val trainingscheduleUnvalidated = engine.trainingschedule.getOrElse("0 0 * * * ?")
-              val trainingschedule = if (CronExpression.isValidExpression(trainingscheduleUnvalidated)) trainingscheduleUnvalidated else "0 0 * * * ?"
-              Logger.info(s"${logPrefix}Setting up batch algo job with schedule ${trainingschedule}")
-              algoinfo.batchcommands map { batchcommands =>
-                val job = Jobs.algoJob(config, app, engine, algo, batchcommands)
-                scheduler.addJob(job, true)
-                val trigger = newTrigger() forJob (jobKey(algoid, Jobs.algoJobGroup)) withIdentity (algoid, Jobs.algoJobGroup) startNow () withSchedule (cronSchedule(trainingschedule) withMisfireHandlingInstructionFireAndProceed ()) build ()
-                scheduler.scheduleJob(trigger)
-              } getOrElse {
-                Logger.info(s"${logPrefix}Giving up setting up batch algo job because it does not have any batch command")
-              }
-            }
-          }
-        } else {
-          /** Stop any algo job if it is undeployed */
-          val algoJobKey = jobKey(algoid, Jobs.algoJobGroup)
-          if (scheduler.checkExists(algoJobKey)) {
-            /** The following checks only jobs in this particular scheduler node. */
-            /** TODO: Clustering support. */
-            try {
-              val running = scheduler.getCurrentlyExecutingJobs() map { context =>
-                val jobDetail = context.getJobDetail()
-                val jobKey = jobDetail.getKey()
-                jobKey.getName() == algoid
-              } reduce { (a, b) => a || b }
-              if (running) {
-                try {
-                  scheduler.interrupt(algoJobKey)
-                  Logger.info(s"${logPrefix}Stopping training")
-                } catch {
-                  case e: UnableToInterruptJobException => Logger.warn(s"${logPrefix}Unable to stop training")
-                }
-              }
-            } catch {
-              case e: UnsupportedOperationException => Logger.info(s"${logPrefix}No training is running")
-            }
-          }
-
-          if (scheduler.checkExists(triggerkey) == true) {
-            scheduler.unscheduleJob(triggerkey)
-          }
-        }
-      } getOrElse {
-        Logger.info(s"${logPrefix}Skipping batch algo job setup because information about this algo (${algo.infoid}) cannot be found")
-      }
-    }
-  }
-
-  def trainEngineOnceNow(appid: Int, engineid: Int) = Action {
-    try {
-      apps.get(appid) map { app =>
-        engines.get(engineid) map { engine =>
-          syncAlgoJobs(app, engine, true)
-          Ok(Json.obj("message" -> "Immediate engine training request has been accepted."))
-        } getOrElse {
-          NotFound(Json.obj("message" -> s"Engine ID $engineid is invalid"))
-        }
-      } getOrElse {
-        NotFound(Json.obj("message" -> s"App ID $appid is invalid"))
-      }
-    } catch {
-      case e: RuntimeException =>
-        e.printStackTrace; NotFound(Json.obj("message" -> ("Request failed: " + e.getMessage())))
-      case e: Exception => InternalServerError(Json.obj("message" -> ("Request failed: " + e.getMessage())))
-    }
-  }
-
-  def algoStatus(appid: Int, engineid: Int, algoid: Int) = Action {
-    if (scheduler.checkExists(jobKey(algoid.toString(), Jobs.algoJobGroup))) {
-      /** The following checks only jobs in this particular scheduler node. */
-      /** TODO: Clustering support. */
-      try {
-        val running = scheduler.getCurrentlyExecutingJobs() map { context =>
-          val jobDetail = context.getJobDetail()
-          val jobKey = jobDetail.getKey()
-          jobKey.getName() == algoid.toString()
-        } reduce { (a, b) => a || b }
-        if (running)
-          Ok(Json.obj("algoid" -> algoid, "status" -> "jobrunning"))
-        else
-          Ok(Json.obj("algoid" -> algoid, "status" -> "jobnotrunning"))
-      } catch {
-        case e: UnsupportedOperationException => Ok(Json.obj("algoid" -> algoid, "status" -> "jobnotrunning"))
-      }
-    } else {
-      Ok(Json.obj("algoid" -> algoid, "status" -> "jobnotexist"))
-    }
-  }
-
-  def stopOfflineEval(appid: Int, engineid: Int, offlineevalid: Int) = Action {
-    val offlineEvalJobKey = jobKey(offlineevalid.toString(), Jobs.offlineEvalJobGroup)
-    if (scheduler.checkExists(offlineEvalJobKey)) {
-      /** The following checks only jobs in this particular scheduler node. */
-      /** TODO: Clustering support. */
-      try {
-        val running = scheduler.getCurrentlyExecutingJobs() map { context =>
-          val jobDetail = context.getJobDetail()
-          val jobKey = jobDetail.getKey()
-          jobKey.getName() == offlineevalid.toString()
-        } reduce { (a, b) => a || b }
-        if (running)
-          try {
-            scheduler.interrupt(offlineEvalJobKey)
-            Ok(Json.obj("offlineevalid" -> offlineevalid, "status" -> "jobkilled"))
-          } catch {
-            case e: UnableToInterruptJobException => Ok(Json.obj("offlineevalid" -> offlineevalid, "status" -> "jobnotkilled"))
-          }
-        else
-          Ok(Json.obj("offlineevalid" -> offlineevalid, "status" -> "jobnotrunning"))
-      } catch {
-        case e: UnsupportedOperationException => Ok(Json.obj("offlineevalid" -> offlineevalid, "status" -> "jobnotrunning"))
-      }
-    } else {
-      Ok(Json.obj("offlineevalid" -> offlineevalid, "status" -> "jobnotexist"))
-    }
-  }
-
-  def stopOfflineTune(appid: Int, engineid: Int, offlinetuneid: Int) = Action {
-    val offlineTuneJobKey = jobKey(offlinetuneid.toString(), Jobs.offlineTuneJobGroup)
-    try {
-      scheduler.interrupt(offlineTuneJobKey)
-      Ok(Json.obj("offlinetuneid" -> offlinetuneid, "status" -> "jobkilled"))
-    } catch {
-      case e: UnableToInterruptJobException => Ok(Json.obj("offlinetuneid" -> offlinetuneid, "status" -> "jobnotkilled"))
-    }
-  }
-
-}
diff --git a/servers/scheduler/build.sbt b/servers/scheduler/build.sbt
deleted file mode 100644
index 8f1483f..0000000
--- a/servers/scheduler/build.sbt
+++ /dev/null
@@ -1,20 +0,0 @@
-name := "predictionio-scheduler"
-
-version := "0.7.3"
-
-organization := "io.prediction"
-
-libraryDependencies ++= Seq(
-  "io.prediction" %% "predictionio-commons" % version.value,
-  "io.prediction" %% "predictionio-output" % version.value,
-  "commons-io" % "commons-io" % "2.4",
-  "mysql" % "mysql-connector-java" % "5.1.22",
-  "org.clapper" %% "scalasti" % "1.0.0",
-  "org.quartz-scheduler" % "quartz" % "2.1.7",
-  "org.specs2" %% "specs2" % "1.14" % "test")
-
-javaOptions in Test += "-Dconfig.file=conf/test.conf"
-
-play.Project.playScalaSettings
-
-scalariformSettings
diff --git a/servers/scheduler/conf/application.conf b/servers/scheduler/conf/application.conf
deleted file mode 100644
index 727c099..0000000
--- a/servers/scheduler/conf/application.conf
+++ /dev/null
@@ -1,119 +0,0 @@
-# This is the main configuration file for the application.
-# ~~~~~
-
-# Secret key
-# ~~~~~
-# The secret key is used to secure cryptographics functions.
-# If you deploy your application to several instances be sure to use the same key!
-application.secret="L2CruW9v9v4lHuh5ObC>RLJXNu7f59m]o>pU0P6JW/8yGd6a2?uNPB?E^ohv;p?M"
-
-# The application languages
-# ~~~~~
-application.langs="en"
-
-# Global object class
-# ~~~~~
-# Define the Global object class for this application.
-# Default to Global in the root package.
-# global=Global
-
-# Database configuration
-# ~~~~~
-# You can declare as many datasources as you want.
-# By convention, the default datasource is named `default`
-#
-# db.default.driver=org.h2.Driver
-# db.default.url="jdbc:h2:mem:play"
-# db.default.user=sa
-# db.default.password=
-
-# Evolutions
-# ~~~~~
-# You can disable evolutions if needed
-# evolutionplugin=disabled
-
-# Logger
-# ~~~~~
-# You can also configure logback (http://logback.qos.ch/), by providing a logger.xml file in the conf directory .
-
-# Root logger:
-logger.root=ERROR
-
-# Logger used by the framework:
-logger.play=INFO
-
-# Logger provided to your application:
-logger.application=DEBUG
-
-# Logger used by Quartz
-logger.org.quartz=INFO
-
-# Logger used by PredictionIO Scheduler
-logger.io.prediction.scheduler=INFO
-
-# PredictionIO Repository Base (For Development Only)
-io.prediction.base=../..
-io.prediction.itemrec.base=${io.prediction.base}/process/engines/itemrec
-io.prediction.itemsim.base=${io.prediction.base}/process/engines/itemsim
-
-# Used by PredictionIO Commons
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.host=localhost
-io.prediction.commons.appdata.db.port=27017
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.host=localhost
-io.prediction.commons.appdata.test.db.port=27017
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.host=localhost
-io.prediction.commons.appdata.training.db.port=27017
-
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.host=localhost
-io.prediction.commons.appdata.validation.db.port=27017
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.host=localhost
-io.prediction.commons.modeldata.db.port=27017
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.host=localhost
-io.prediction.commons.modeldata.training.db.port=27017
-
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.host=localhost
-io.prediction.commons.settings.db.port=27017
-
-# PredictionIO Algorithms
-pdio-knnitembased.jar=${io.prediction.itemrec.base}/algorithms/hadoop/scalding/target/scala-2.10/PredictionIO-Process-ItemRec-Algorithms-Hadoop-Scalding-assembly-0.7.3.jar
-pdio-latestrank.jar=${io.prediction.itemrec.base}/algorithms/hadoop/scalding/target/scala-2.10/PredictionIO-Process-ItemRec-Algorithms-Hadoop-Scalding-assembly-0.7.3.jar
-pdio-randomrank.jar=${io.prediction.itemrec.base}/algorithms/hadoop/scalding/target/scala-2.10/PredictionIO-Process-ItemRec-Algorithms-Hadoop-Scalding-assembly-0.7.3.jar
-mahout-itembased.jar=${io.prediction.itemrec.base}/algorithms/hadoop/scalding/target/scala-2.10/PredictionIO-Process-ItemRec-Algorithms-Hadoop-Scalding-assembly-0.7.3.jar
-mahout-parallelals.jar=${io.prediction.itemrec.base}/algorithms/hadoop/scalding/target/scala-2.10/PredictionIO-Process-ItemRec-Algorithms-Hadoop-Scalding-assembly-0.7.3.jar
-mahout-knnuserbased.jar=${io.prediction.itemrec.base}/algorithms/hadoop/scalding/target/scala-2.10/PredictionIO-Process-ItemRec-Algorithms-Hadoop-Scalding-assembly-0.7.3.jar
-mahout-thresholduserbased.jar=${io.prediction.itemrec.base}/algorithms/hadoop/scalding/target/scala-2.10/PredictionIO-Process-ItemRec-Algorithms-Hadoop-Scalding-assembly-0.7.3.jar
-mahout-slopeone.jar=${io.prediction.itemrec.base}/algorithms/hadoop/scalding/target/scala-2.10/PredictionIO-Process-ItemRec-Algorithms-Hadoop-Scalding-assembly-0.7.3.jar
-mahout-alswr.jar=${io.prediction.itemrec.base}/algorithms/hadoop/scalding/target/scala-2.10/PredictionIO-Process-ItemRec-Algorithms-Hadoop-Scalding-assembly-0.7.3.jar
-mahout-svdsgd.jar=${io.prediction.itemrec.base}/algorithms/hadoop/scalding/target/scala-2.10/PredictionIO-Process-ItemRec-Algorithms-Hadoop-Scalding-assembly-0.7.3.jar
-mahout-svdplusplus.jar=${io.prediction.itemrec.base}/algorithms/hadoop/scalding/target/scala-2.10/PredictionIO-Process-ItemRec-Algorithms-Hadoop-Scalding-assembly-0.7.3.jar
-
-pdio-itemsimcf.jar=${io.prediction.itemsim.base}/algorithms/hadoop/scalding/target/scala-2.10/PredictionIO-Process-ItemSim-Algorithms-Hadoop-Scalding-assembly-0.7.3.jar
-pdio-itemsimlatestrank.jar=${io.prediction.itemsim.base}/algorithms/hadoop/scalding/target/scala-2.10/PredictionIO-Process-ItemSim-Algorithms-Hadoop-Scalding-assembly-0.7.3.jar
-pdio-itemsimrandomrank.jar=${io.prediction.itemsim.base}/algorithms/hadoop/scalding/target/scala-2.10/PredictionIO-Process-ItemSim-Algorithms-Hadoop-Scalding-assembly-0.7.3.jar
-mahout-itemsimcf.jar=${io.prediction.itemsim.base}/algorithms/hadoop/scalding/target/scala-2.10/PredictionIO-Process-ItemSim-Algorithms-Hadoop-Scalding-assembly-0.7.3.jar
-
-# PredictionIO generic scalding job
-io.prediction.algorithms.scalding.itemrec.generic.jar=${io.prediction.itemrec.base}/algorithms/hadoop/scalding/target/scala-2.10/PredictionIO-Process-ItemRec-Algorithms-Hadoop-Scalding-assembly-0.7.3.jar
-
-# Itemrec Scala Mahout Algorithms
-io.prediction.algorithms.mahout.itemrec.jar=${io.prediction.itemrec.base}/algorithms/scala/mahout/target/scala-2.10/PredictionIO-Process-ItemRec-Algorithms-Scala-Mahout-assembly-0.7.3.jar
-
-# Mahout core job
-io.prediction.algorithms.mahout-core-job.jar=${io.prediction.base}/vendors/mahout-distribution-0.8/mahout-core-0.8-job.jar
-
-# PredictionIO Offline Evaluation
-io.prediction.evaluations.scalding.itemrec.jar=${io.prediction.itemrec.base}/evaluations/hadoop/scalding/target/scala-2.10/PredictionIO-Process-ItemRec-Evaluations-Hadoop-Scalding-assembly-0.4.3.jar
-io.prediction.evaluations.itemrec.topkitems.jar=${io.prediction.itemrec.base}/evaluations/scala/topkitems/target/scala-2.10/PredictionIO-Process-ItemRec-Evaluations-TopKItems-assembly-0.4.3.jar
-io.prediction.evaluations.itemrec.trainingtestsplit.jar=${io.prediction.itemrec.base}/evaluations/scala/trainingtestsplit/target/scala-2.10/PredictionIO-Process-ItemRec-Evaluations-Scala-TrainingTestSplitTime-assembly-0.4.3.jar
-io.prediction.evaluations.itemrec.paramgen.jar=${io.prediction.itemrec.base}/evaluations/scala/paramgen/target/scala-2.10/PredictionIO-Process-ItemRec-Evaluations-ParamGen-assembly-0.4.3.jar
diff --git a/servers/scheduler/conf/quartz.properties.sample b/servers/scheduler/conf/quartz.properties.sample
deleted file mode 100644
index 9ea2c5e..0000000
--- a/servers/scheduler/conf/quartz.properties.sample
+++ /dev/null
@@ -1,36 +0,0 @@
-#============================================================================
-# Configure Main Scheduler Properties
-#============================================================================
-org.quartz.scheduler.instanceName = PredictionIOScheduler
-org.quartz.scheduler.instanceId = AUTO
-org.quartz.scheduler.skipUpdateCheck = true
-
-#============================================================================
-# Configure ThreadPool
-#============================================================================
-org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
-org.quartz.threadPool.threadCount = 25
-org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
-
-#============================================================================
-# Configure JobStore
-#============================================================================
-org.quartz.jobStore.misfireThreshold = 60000
-org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
-org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
-org.quartz.jobStore.useProperties = false
-org.quartz.jobStore.dataSource = myDS
-org.quartz.jobStore.tablePrefix = QRTZ_
-
-org.quartz.jobStore.isClustered = true
-org.quartz.jobStore.clusterCheckinInterval = 20000
-
-#============================================================================
-# Configure Datasources
-#============================================================================
-org.quartz.dataSource.myDS.driver = com.mysql.jdbc.Driver
-org.quartz.dataSource.myDS.URL = jdbc:mysql://localhost:3306/predictionio_scheduler_test
-org.quartz.dataSource.myDS.user = pioschtest
-org.quartz.dataSource.myDS.password = pioschtest
-org.quartz.dataSource.myDS.maxConnections = 20
-org.quartz.dataSource.myDS.validationQuery = select 0 from dual
diff --git a/servers/scheduler/conf/routes b/servers/scheduler/conf/routes
deleted file mode 100644
index 79a9740..0000000
--- a/servers/scheduler/conf/routes
+++ /dev/null
@@ -1,20 +0,0 @@
-# Routes
-# This file defines all application routes (Higher priority routes first)
-# ~~~~
-
-GET     /                               io.prediction.scheduler.Scheduler.online()
-
-GET     /users/:userid/sync                       io.prediction.scheduler.Scheduler.userSync(userid: Int)
-
-GET     /apps/:appid/delete                       io.prediction.scheduler.Operations.deleteApp(appid: Int)
-
-GET     /apps/:appid/engines/:engineid/delete               io.prediction.scheduler.Operations.deleteEngine(appid: Int, engineid: Int)
-GET     /apps/:appid/engines/:engineid/trainoncenow         io.prediction.scheduler.Scheduler.trainEngineOnceNow(appid: Int, engineid: Int)
-
-GET     /apps/:appid/engines/:engineid/algos/:algoid/status                     io.prediction.scheduler.Scheduler.algoStatus(appid: Int, engineid: Int, algoid: Int)
-GET     /apps/:appid/engines/:engineid/algos/:algoid/delete                     io.prediction.scheduler.Operations.deleteAlgo(appid: Int, engineid: Int, algoid: Int)
-
-GET     /apps/:appid/engines/:engineid/offlineevals/:offlineevalid/delete       io.prediction.scheduler.Operations.deleteOfflineEval(appid: Int, engineid: Int, offlineevalid: Int)
-GET     /apps/:appid/engines/:engineid/offlineevals/:offlineevalid/stop         io.prediction.scheduler.Scheduler.stopOfflineEval(appid: Int, engineid: Int, offlineevalid: Int)
-
-GET     /apps/:appid/engines/:engineid/offlinetunes/:offlinetuneid/stop         io.prediction.scheduler.Scheduler.stopOfflineTune(appid: Int, engineid: Int, offlinetuneid: Int)
diff --git a/servers/scheduler/conf/test.conf b/servers/scheduler/conf/test.conf
deleted file mode 100644
index 7a4fc8c..0000000
--- a/servers/scheduler/conf/test.conf
+++ /dev/null
@@ -1,93 +0,0 @@
-# This is the main configuration file for the application.
-# ~~~~~
-
-# Secret key
-# ~~~~~
-# The secret key is used to secure cryptographics functions.
-# If you deploy your application to several instances be sure to use the same key!
-application.secret="LXWfyDJiEh];Q]w;6W[97aRF;[TR[2Q0yZCrZP0pbpUC2KpNFov1w5u@bpl=4/Ck"
-
-# The application languages
-# ~~~~~
-application.langs="en"
-
-# Global object class
-# ~~~~~
-# Define the Global object class for this application.
-# Default to Global in the root package.
-# global=Global
-
-# Database configuration
-# ~~~~~
-# You can declare as many datasources as you want.
-# By convention, the default datasource is named `default`
-#
-# db.default.driver=org.h2.Driver
-# db.default.url="jdbc:h2:mem:play"
-# db.default.user=sa
-# db.default.password=
-
-# Evolutions
-# ~~~~~
-# You can disable evolutions if needed
-# evolutionplugin=disabled
-
-# Logger
-# ~~~~~
-# You can also configure logback (http://logback.qos.ch/), by providing a logger.xml file in the conf directory .
-
-# Root logger:
-logger.root=ERROR
-
-# Logger used by the framework:
-logger.play=INFO
-
-# Logger provided to your application:
-logger.application=DEBUG
-
-# PredictionIO Repository Base (For Development Only)
-io.prediction.base=../..
-
-# Disable update check
-io.prediction.commons.settings.scheduler.updatecheck=false
-
-# PredictionIO Commons Settings
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.host=localhost
-io.prediction.commons.settings.db.port=27017
-io.prediction.commons.settings.db.name=test_scheduler_api_predictionio
-
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.host=localhost
-io.prediction.commons.appdata.db.port=27017
-io.prediction.commons.appdata.db.name=test_scheduler_api_predictionio_appdata
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.host=localhost
-io.prediction.commons.appdata.test.db.port=27017
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.host=localhost
-io.prediction.commons.appdata.training.db.port=27017
-
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.host=localhost
-io.prediction.commons.appdata.validation.db.port=27017
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.host=localhost
-io.prediction.commons.modeldata.db.port=27017
-io.prediction.commons.modeldata.db.name=test_scheduler_api_predictionio_modeldata
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.host=localhost
-io.prediction.commons.modeldata.training.db.port=27017
-
-# PredictionIO generic scalding job
-io.prediction.jars.pdio_itemrec_generic=${io.prediction.base}/lib/predictionio-process-itemrec-algorithms-hadoop-scalding-assembly-0.7.0-SNAPSHOT.jar
-
-# Itemrec Scala Mahout Algorithms
-io.prediction.jars.mahout_itemrec=${io.prediction.base}/lib/predictionio-process-itemrec-algorithms-scala-mahout-assembly-0.7.0-SNAPSHOT.jar
-
-# Mahout core job
-io.prediction.jars.mahout_core_job=${io.prediction.base}/vendors/mahout-distribution-0.8/mahout-core-0.8-job.jar
diff --git a/servers/scheduler/project/build.properties b/servers/scheduler/project/build.properties
deleted file mode 100644
index 0974fce..0000000
--- a/servers/scheduler/project/build.properties
+++ /dev/null
@@ -1 +0,0 @@
-sbt.version=0.13.0
diff --git a/servers/scheduler/project/plugins.sbt b/servers/scheduler/project/plugins.sbt
deleted file mode 100644
index 16ba183..0000000
--- a/servers/scheduler/project/plugins.sbt
+++ /dev/null
@@ -1,10 +0,0 @@
-// Comment to get more information during initialization
-logLevel := Level.Warn
-
-// The Typesafe repository
-resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
-
-// Use the Play sbt plugin for Play projects
-addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.2.2")
-
-addSbtPlugin("com.typesafe.sbt" % "sbt-scalariform" % "1.2.1")
diff --git a/servers/scheduler/public/images/favicon.png b/servers/scheduler/public/images/favicon.png
deleted file mode 100644
index c7d92d2..0000000
--- a/servers/scheduler/public/images/favicon.png
+++ /dev/null
Binary files differ
diff --git a/servers/scheduler/public/javascripts/jquery-1.7.1.min.js b/servers/scheduler/public/javascripts/jquery-1.7.1.min.js
deleted file mode 100644
index 198b3ff..0000000
--- a/servers/scheduler/public/javascripts/jquery-1.7.1.min.js
+++ /dev/null
@@ -1,4 +0,0 @@
-/*! jQuery v1.7.1 jquery.com | jquery.org/license */
-(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function cb(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function ca(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bE.test(a)?d(a,e):ca(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)ca(a+"["+e+"]",b[e],c,d);else d(a,b)}function b_(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function b$(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bT,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=b$(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=b$(a,c,d,e,"*",g));return l}function bZ(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bP),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bC(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?bx:by,g=0,h=e.length;if(d>0){if(c!=="border")for(;g<h;g++)c||(d-=parseFloat(f.css(a,"padding"+e[g]))||0),c==="margin"?d+=parseFloat(f.css(a,c+e[g]))||0:d-=parseFloat(f.css(a,"border"+e[g]+"Width"))||0;return d+"px"}d=bz(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0;if(c)for(;g<h;g++)d+=parseFloat(f.css(a,"padding"+e[g]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+e[g]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+e[g]))||0);return d+"px"}function bp(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c+(i[c][d].namespace?".":"")+i[c][d].namespace,i[c][d],i[c][d].data)}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?m(g):h==="function"&&(!a.unique||!o.has(g))&&c.push(g)},n=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,l=j||0,j=0,k=c.length;for(;c&&l<k;l++)if(c[l].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}i=!1,c&&(a.once?e===!0?o.disable():c=[]:d&&d.length&&(e=d.shift(),o.fireWith(e[0],e[1])))},o={add:function(){if(c){var a=c.length;m(arguments),i?k=c.length:e&&e!==!0&&(j=a,n(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){i&&f<=k&&(k--,f<=l&&l--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&o.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(i?a.once||d.push([b,c]):(!a.once||!e)&&n(b,c));return this},fire:function(){o.fireWith(this,arguments);return this},fired:function(){return!!e}};return o};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p,q=c.createElement("div"),r=c.documentElement;q.setAttribute("className","t"),q.innerHTML="   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="<div "+n+"><div></div></div>"+"<table "+n+" cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="<div style='width:4px;'></div>",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h=null;if(typeof a=="undefined"){if(this.length){h=f.data(this[0]);if(this[0].nodeType===1&&!f._data(this[0],"parsedAttrs")){e=this[0].attributes;for(var i=0,j=e.length;i<j;i++)g=e[i].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),l(this[0],g,h[g]));f._data(this[0],"parsedAttrs",!0)}}return h}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split("."),d[1]=d[1]?"."+d[1]:"";if(c===b){h=this.triggerHandler("getData"+d[1]+"!",[d[0]]),h===b&&this.length&&(h=f.data(this[0],a),h=l(this[0],a,h));return h===b&&d[1]?this.data(d[0]):h}return this.each(function(){var b=f(this),e=[d[0],c];b.triggerHandler("setData"+d[1]+"!",e),f.data(this,a,c),b.triggerHandler("changeData"+d[1]+"!",e)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise()}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h<g;h++)e=d[h],e&&(c=f.propFix[e]||e,f.attr(a,e,""),a.removeAttribute(v?e:c),u.test(e)&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};
-f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=[],j,k,l,m,n,o,p,q,r,s,t;g[0]=c,c.delegateTarget=this;if(e&&!c.target.disabled&&(!c.button||c.type!=="click")){m=f(this),m.context=this.ownerDocument||this;for(l=c.target;l!=this;l=l.parentNode||this){o={},q=[],m[0]=l;for(j=0;j<e;j++)r=d[j],s=r.selector,o[s]===b&&(o[s]=r.quick?H(l,r.quick):m.is(s)),o[s]&&q.push(r);q.length&&i.push({elem:l,matches:q})}}d.length>e&&i.push({elem:this,matches:d.slice(e)});for(j=0;j<i.length&&!c.isPropagationStopped();j++){p=i[j],c.currentTarget=p.elem;for(k=0;k<p.matches.length&&!c.isImmediatePropagationStopped();k++){r=p.matches[k];if(h||!c.namespace&&!r.namespace||c.namespace_re&&c.namespace_re.test(r.namespace))c.data=r.data,c.handleObj=r,n=((f.event.special[r.origType]||{}).handle||r.handler).apply(p.elem,g),n!==b&&(c.result=n,n===!1&&(c.preventDefault(),c.stopPropagation()))}}return c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0)}),d._submit_attached=!0)})},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on.call(this,a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.type+"."+e.namespace:e.type,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.POS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function()
-{for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,bp)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||!bc.test("<"+a.nodeName)?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1></$2>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");b===c?bh.appendChild(o):U(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]==="<table>"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i<r;i++)bn(k[i]);else bn(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||be.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bq=/alpha\([^)]*\)/i,br=/opacity=([^)]*)/,bs=/([A-Z]|^ms)/g,bt=/^-?\d+(?:px)?$/i,bu=/^-?\d/,bv=/^([\-+])=([\-+.\de]+)/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Left","Right"],by=["Top","Bottom"],bz,bA,bB;f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bz(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bv.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bz)return bz(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){if(a.offsetWidth!==0)return bC(a,b,d);f.swap(a,bw,function(){e=bC(a,b,d)});return e}},set:function(a,b){if(!bt.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return br.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bq,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bq.test(g)?g.replace(bq,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,b){var c,d,e;b=b.replace(bs,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b)));return c}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bt.test(f)&&bu.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bD=/%20/g,bE=/\[\]$/,bF=/\r?\n/g,bG=/#.*$/,bH=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bI=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bJ=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bK=/^(?:GET|HEAD)$/,bL=/^\/\//,bM=/\?/,bN=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bO=/^(?:select|textarea)/i,bP=/\s+/,bQ=/([?&])_=[^&]*/,bR=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bS=f.fn.load,bT={},bU={},bV,bW,bX=["*/"]+["*"];try{bV=e.href}catch(bY){bV=c.createElement("a"),bV.href="",bV=bV.href}bW=bR.exec(bV.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bS)return bS.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bN,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bO.test(this.nodeName)||bI.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bF,"\r\n")}}):{name:b.name,value:c.replace(bF,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b_(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b_(a,b);return a},ajaxSettings:{url:bV,isLocal:bJ.test(bW[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bX},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bZ(bT),ajaxTransport:bZ(bU),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cb(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cc(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bH.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bG,"").replace(bL,bW[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bP),d.crossDomain==null&&(r=bR.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bW[1]&&r[2]==bW[2]&&(r[3]||(r[1]==="http:"?80:443))==(bW[3]||(bW[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bT,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bK.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bM.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bQ,"$1_="+x);d.url=y+(y===d.url?(bM.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bX+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bU,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)ca(g,a[g],c,e);return d.join("&").replace(bD,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cd=f.now(),ce=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cd++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ce.test(b.url)||e&&ce.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ce,l),b.url===j&&(e&&(k=k.replace(ce,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cf=a.ActiveXObject?function(){for(var a in ch)ch[a](0,1)}:!1,cg=0,ch;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ci()||cj()}:ci,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cf&&delete ch[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cg,cf&&(ch||(ch={},f(a).unload(cf)),ch[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var ck={},cl,cm,cn=/^(?:toggle|show|hide)$/,co=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cp,cq=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cr;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cv(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cu("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cu("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cv(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cn.test(h)?(o=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),o?(f._data(this,"toggle"+i,o==="show"?"hide":"show"),j[o]()):j[h]()):(k=co.exec(h),l=j.cur(),k?(m=parseFloat(k[2]),n=k[3]||(f.cssNumber[i]?"":"px"),n!=="px"&&(f.style(this,i,(m||1)+n),l=(m||1)/j.cur()*l,f.style(this,i,l+n)),k[1]&&(m=(k[1]==="-="?-1:1)*m+l),j.custom(l,m,n)):j.custom(l,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:cu("show",1),slideUp:cu("hide",1),slideToggle:cu("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cr||cs(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){e.options.hide&&f._data(e.elem,"fxshow"+e.prop)===b&&f._data(e.elem,"fxshow"+e.prop,e.start)},h()&&f.timers.push(h)&&!cp&&(cp=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cr||cs(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(cp),cp=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(["width","height"],function(a,b){f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cy(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.support.fixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.support.fixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window);
\ No newline at end of file
diff --git a/servers/scheduler/public/stylesheets/main.css b/servers/scheduler/public/stylesheets/main.css
deleted file mode 100644
index e69de29..0000000
--- a/servers/scheduler/public/stylesheets/main.css
+++ /dev/null
diff --git a/servers/scheduler/test/SchedulerSpec.scala b/servers/scheduler/test/SchedulerSpec.scala
deleted file mode 100644
index 25d5254..0000000
--- a/servers/scheduler/test/SchedulerSpec.scala
+++ /dev/null
@@ -1,142 +0,0 @@
-package io.prediction.scheduler
-
-import io.prediction.commons.Config
-import io.prediction.commons.settings._
-
-import play.api.test._
-import play.api.test.Helpers._
-
-import java.io.File
-
-import com.github.nscala_time.time.Imports._
-import com.mongodb.casbah.Imports._
-import org.apache.commons.io.FileUtils
-import org.clapper.scalasti.StringTemplate
-import org.specs2._
-import org.specs2.matcher.ContentMatchers
-import org.specs2.specification.Step
-
-class SchedulerSpec extends Specification with ContentMatchers {
-  def is = s2"""
-  PredictionIO Scheduler Specification
-                                                  ${Step(helloFile.delete())}
-                                                  ${Step(FileUtils.touch(helloFile))}
-    Synchronize a user                            $userSync
-    Setting shared attributes                     $setSharedAttributes
-                                                  ${Step(MongoConnection()(config.settingsDbName).dropDatabase())}
-  """
-
-  lazy val helloFilename = "test/hello.txt"
-  lazy val helloFile = new File(helloFilename)
-
-  /** Setup test data. */
-  val config = new Config
-  val apps = config.getSettingsApps
-  val engines = config.getSettingsEngines
-  val engineInfos = config.getSettingsEngineInfos
-  val algos = config.getSettingsAlgos
-  val algoInfos = config.getSettingsAlgoInfos
-  val systemInfos = config.getSettingsSystemInfos
-
-  val userid = 1
-  val app = App(
-    id = 0,
-    userid = userid,
-    appkey = "appkey",
-    display = "",
-    url = None,
-    cat = None,
-    desc = None,
-    timezone = "UTC")
-  val appid = apps.insert(app)
-
-  val engine = Engine(
-    id = 0,
-    appid = appid,
-    name = "myengine",
-    infoid = "itemrec",
-    itypes = Some(Seq("movies")),
-    params = Map("goal" -> "foobar"))
-  val engineid = engines.insert(engine)
-
-  engineInfos.insert(EngineInfo(
-    id = "itemrec",
-    name = "myengine",
-    description = None,
-    params = Map(),
-    paramsections = Seq(),
-    defaultalgoinfoid = "mypkg",
-    defaultofflineevalmetricinfoid = "metric",
-    defaultofflineevalsplitterinfoid = "splitter"))
-
-  val algo = Algo(
-    id = 0,
-    engineid = engineid,
-    name = "myalgo",
-    infoid = "mypkg",
-    status = "deployed",
-    command = "",
-    params = Map(
-      "viewParam" -> "2",
-      "likeParam" -> "5",
-      "dislikeParam" -> "1",
-      "conversionParam" -> "4",
-      "conflictParam" -> "latest"),
-    settings = Map(),
-    modelset = false,
-    createtime = DateTime.now,
-    updatetime = DateTime.now,
-    offlineevalid = Some(1),
-    offlinetuneid = None)
-  val algoid = algos.insert(algo)
-
-  algoInfos.insert(AlgoInfo(
-    id = "mypkg",
-    name = "mypkg",
-    description = None,
-    batchcommands = Some(Seq("test/echo.sh $appid$ $engineid$ $algoid$ $conflictParam$ " + helloFilename)),
-    offlineevalcommands = None,
-    params = Map(),
-    paramsections = Seq(),
-    paramorder = Seq(),
-    engineinfoid = "itemrec",
-    techreq = Seq(),
-    datareq = Seq()))
-
-  systemInfos.insert(SystemInfo(
-    id = "jars.my_custom_algo",
-    value = "my.jar",
-    description = None))
-
-  systemInfos.insert(SystemInfo(
-    id = "jars.foobar",
-    value = "foobar.jar",
-    description = None))
-
-  def userSync = {
-    running(TestServer(5555), HTMLUNIT) { browser =>
-      browser.goTo(s"http://localhost:5555/users/${userid}/sync")
-      browser.goTo(s"http://localhost:5555/apps/${appid}/engines/${engineid}/trainoncenow")
-      helloFile.deleteOnExit()
-      helloFile must haveSameLinesAs(Seq(
-        Seq(appid, engineid, algoid, "latest") mkString " "
-      )).eventually(60, new org.specs2.time.Duration(1000))
-    }
-  }
-
-  def setSharedAttributes = {
-    val template = new StringTemplate("hadoop jar $mahout_core_job$ and $mahout_itemrec$ and $base$/$my_custom_algo$ plus $foobar$")
-    val result = Jobs.setSharedAttributes(
-      template,
-      config,
-      app,
-      engine,
-      Some(algo),
-      None,
-      None,
-      Some(Map(
-        "modelset" -> !algo.modelset))).toString
-
-    result must beEqualTo("hadoop jar ../../vendors/mahout-distribution-0.8/mahout-core-0.8-job.jar and ../../lib/predictionio-process-itemrec-algorithms-scala-mahout-assembly-0.7.0-SNAPSHOT.jar and ../../my.jar plus foobar.jar")
-  }
-}
diff --git a/servers/scheduler/test/echo.sh b/servers/scheduler/test/echo.sh
deleted file mode 100755
index e491a4e..0000000
--- a/servers/scheduler/test/echo.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-echo $1 $2 $3 $4 > $5
\ No newline at end of file
diff --git a/tools/conncheck/.gitignore b/tools/conncheck/.gitignore
deleted file mode 100644
index 27722ba..0000000
--- a/tools/conncheck/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-project/project/
-project/target/
-target/
diff --git a/tools/conncheck/build.sbt b/tools/conncheck/build.sbt
deleted file mode 100644
index 0b9c78a..0000000
--- a/tools/conncheck/build.sbt
+++ /dev/null
@@ -1,19 +0,0 @@
-import xerial.sbt.Pack._
-
-name := "conncheck"
-
-scalariformSettings
-
-libraryDependencies += "org.slf4j" % "slf4j-nop" % "1.6.0"
-
-packSettings
-
-packJarNameConvention := "full"
-
-packExpandedClasspath := true
-
-packGenerateWindowsBatFile := false
-
-packMain := Map("conncheck" -> "io.prediction.tools.conncheck.ConnCheck")
-
-packJvmOpts := Map("conncheck" -> Common.packCommonJvmOpts)
diff --git a/tools/conncheck/project/Build.scala b/tools/conncheck/project/Build.scala
deleted file mode 100644
index 2c8a03a..0000000
--- a/tools/conncheck/project/Build.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-//import sbt._
-//import sbt.Keys._
-//import xerial.sbt.Pack._
-//
-//object Build extends sbt.Build {
-//  lazy val root = Project(
-//    base = file("."),
-//    settings = Defaults.defaultSettings ++ packSettings ++
-//      Seq(
-//        // Map from program name -> Main class (full path)
-//        packMain := Map("conncheck" -> "io.prediction.tools.conncheck.ConnCheck")
-//        // Add custom settings here
-//      )
-//  )
-//}
diff --git a/tools/conncheck/src/main/scala/io/prediction/tools/conncheck/ConnCheck.scala b/tools/conncheck/src/main/scala/io/prediction/tools/conncheck/ConnCheck.scala
deleted file mode 100644
index 1836157..0000000
--- a/tools/conncheck/src/main/scala/io/prediction/tools/conncheck/ConnCheck.scala
+++ /dev/null
@@ -1,40 +0,0 @@
-package io.prediction.tools.conncheck
-
-import io.prediction.commons._
-
-object ConnCheck {
-  val config = new Config()
-
-  def main(args: Array[String]) {
-    val connchecks = Seq(
-      config.settingsDbConnectable(),
-      config.appdataDbConnectable(),
-      config.appdataTrainingDbConnectable(),
-      config.appdataTestDbConnectable(),
-      config.modeldataDbConnectable(),
-      config.modeldataTrainingDbConnectable())
-
-    if (!connchecks.reduce((a, b) => a && b)) {
-      if (!connchecks(0)) {
-        println(s"Cannot connect to settings database ${config.settingsDbType}://${config.settingsDbHost}:${config.settingsDbPort}/${config.settingsDbName}.")
-      }
-      if (!connchecks(1)) {
-        println(s"Cannot connect to app data database ${config.appdataDbType}://${config.appdataDbHost}:${config.appdataDbPort}/${config.appdataDbName}.")
-      }
-      if (!connchecks(2)) {
-        println(s"Cannot connect to app data training database ${config.appdataTrainingDbType}://${config.appdataTrainingDbHost}:${config.appdataTrainingDbPort}/${config.appdataTrainingDbName}.")
-      }
-      if (!connchecks(3)) {
-        println(s"Cannot connect to app data test database ${config.appdataTestDbType}://${config.appdataTestDbHost}:${config.appdataTestDbPort}/${config.appdataTestDbName}.")
-      }
-      if (!connchecks(4)) {
-        println(s"Cannot connect to model data database ${config.modeldataDbType}://${config.modeldataDbHost}:${config.modeldataDbPort}/${config.modeldataDbName}.")
-      }
-      if (!connchecks(5)) {
-        println(s"Cannot connect to model data training database ${config.modeldataTrainingDbType}://${config.modeldataTrainingDbHost}:${config.modeldataTrainingDbPort}/${config.modeldataTrainingDbName}.")
-      }
-      println("Aborting.")
-      sys.exit(1)
-    }
-  }
-}
diff --git a/tools/migration/0.2/algoinfos/.gitignore b/tools/migration/0.2/algoinfos/.gitignore
deleted file mode 100644
index 27722ba..0000000
--- a/tools/migration/0.2/algoinfos/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-project/project/
-project/target/
-target/
diff --git a/tools/migration/0.2/algoinfos/build.sbt b/tools/migration/0.2/algoinfos/build.sbt
deleted file mode 100644
index bef0655..0000000
--- a/tools/migration/0.2/algoinfos/build.sbt
+++ /dev/null
@@ -1,12 +0,0 @@
-name := "PredictionIO 0.1 to 0.2 (AlgoInfos)"
-
-version := "0.2-SNAPSHOT"
-
-organization := "io.prediction"
-
-scalaVersion := "2.10.0"
-
-libraryDependencies ++= Seq(
-  "org.mongodb" %% "casbah" % "2.5.0",
-  "com.typesafe" % "config" % "1.0.0"
-)
diff --git a/tools/migration/0.2/algoinfos/src/main/scala/io/prediction/tools/migration/AlgoInfos.scala b/tools/migration/0.2/algoinfos/src/main/scala/io/prediction/tools/migration/AlgoInfos.scala
deleted file mode 100644
index 686e000..0000000
--- a/tools/migration/0.2/algoinfos/src/main/scala/io/prediction/tools/migration/AlgoInfos.scala
+++ /dev/null
@@ -1,41 +0,0 @@
-package io.prediction.tools.migration
-
-import com.mongodb.casbah.Imports._
-import com.typesafe.config._
-
-object AlgoInfos {
-  val config = ConfigFactory.load()
-
-  val dbHost: String = try { config.getString("db.host") } catch { case _: Throwable => "127.0.0.1" }
-  val dbPort: Int = try { config.getInt("db.port") } catch { case _: Throwable => 27017 }
-  val dbName: String = try { config.getString("db.name") } catch { case _: Throwable => "predictionio" }
-  val db = MongoConnection(dbHost, dbPort)(dbName)
-  val algoColl = db("algos")
-
-  def main(args: Array[String]) {
-    println("PredictionIO 0.2 Migration")
-    println("Fill in AlgoInfos infoid in MongoDB")
-    println()
-    println(s"Database host: $dbHost")
-    println(s"Database port: $dbPort")
-    println(s"Database name: $dbName")
-    println()
-    println("Looking for Algos without infoid...")
-    val algos = algoColl.find(MongoDBObject("infoid" -> MongoDBObject("$exists" -> false))).toList
-    if (algos.length > 0) {
-      println(s"Found ${algos.length} Algos without infoid. Proceed to fill that in with default value 'pdio-knnitembased'?")
-      val choice = readLine("Enter 'YES' to proceed: ")
-      choice match {
-        case "YES" => {
-          algos map { algo =>
-            algoColl.update(MongoDBObject("_id" -> algo.as[Int]("_id")), MongoDBObject("$set" -> MongoDBObject("infoid" -> "pdio-knnitembased"), "$unset" -> MongoDBObject("pkgname" -> 1)))
-          }
-          println("Done")
-        }
-        case _ => println("Aborted")
-      }
-    } else {
-      println("None found")
-    }
-  }
-}
diff --git a/tools/migration/0.4/settings04/.gitignore b/tools/migration/0.4/settings04/.gitignore
deleted file mode 100644
index 27722ba..0000000
--- a/tools/migration/0.4/settings04/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-project/project/
-project/target/
-target/
diff --git a/tools/migration/0.4/settings04/build.sbt b/tools/migration/0.4/settings04/build.sbt
deleted file mode 100644
index 50e60bd..0000000
--- a/tools/migration/0.4/settings04/build.sbt
+++ /dev/null
@@ -1,12 +0,0 @@
-name := "PredictionIO 0.3 to 0.4 Settings Migration"
-
-version := "0.4"
-
-organization := "io.prediction"
-
-scalaVersion := "2.10.0"
-
-libraryDependencies ++= Seq(
-  "org.mongodb" %% "casbah" % "2.5.0",
-  "com.typesafe" % "config" % "1.0.0"
-)
diff --git a/tools/migration/0.4/settings04/project/Build.scala b/tools/migration/0.4/settings04/project/Build.scala
deleted file mode 100644
index c0aa391..0000000
--- a/tools/migration/0.4/settings04/project/Build.scala
+++ /dev/null
@@ -1,16 +0,0 @@
-import sbt._
-import sbt.Keys._
-import xerial.sbt.Pack._
-
-object Build extends sbt.Build {
-  lazy val root = Project(
-    id = "predictionio-tools-migration-settings04",
-    base = file("."),
-    settings = Defaults.defaultSettings ++ packSettings ++
-      Seq(
-        // Map from program name -> Main class (full path)
-        packMain := Map("settings04" -> "io.prediction.tools.migration.Settings04")
-        // Add custom settings here
-      )
-  )
-}
diff --git a/tools/migration/0.4/settings04/project/plugins.sbt b/tools/migration/0.4/settings04/project/plugins.sbt
deleted file mode 100644
index 7adaaae..0000000
--- a/tools/migration/0.4/settings04/project/plugins.sbt
+++ /dev/null
@@ -1 +0,0 @@
-addSbtPlugin("org.xerial.sbt" % "sbt-pack" % "0.1.7")
diff --git a/tools/migration/0.4/settings04/src/main/scala/io/prediction/tools/migration/Settings04.scala b/tools/migration/0.4/settings04/src/main/scala/io/prediction/tools/migration/Settings04.scala
deleted file mode 100644
index 6d28892..0000000
--- a/tools/migration/0.4/settings04/src/main/scala/io/prediction/tools/migration/Settings04.scala
+++ /dev/null
@@ -1,242 +0,0 @@
-package io.prediction.tools.migration
-
-//import com.mongodb.casbah.Imports._
-import com.typesafe.config._
-import com.mongodb.casbah.query.Imports._
-import com.mongodb.casbah.Imports.{MongoConnection}
-
-object Settings04 {
-  val config = ConfigFactory.load()
-
-  val dbHost: String = try { config.getString("db.host") } catch { case _: Throwable => "127.0.0.1" }
-  val dbPort: Int = try { config.getInt("db.port") } catch { case _: Throwable => 27017 }
-  val dbName: String = try { config.getString("db.name") } catch { case _: Throwable => "predictionio" }
-  val db = MongoConnection(dbHost, dbPort)(dbName)
-  val engineColl = db("engines")
-  val offlineEvalColl = db("offlineEvals")
-  val offlineEvalSplitterColl = db("offlineEvalSplitters")
-  val offlineEvalResultsColl = db("offlineEvalResults")
-  val algoColl = db("algos")
-
-  val seqColl = db("seq")
-
-  /** Get the next sequence number from the given sequence name. */
-  def genNext(name: String): Int = {
-    val qFind = MongoDBObject("_id" -> name)
-    val qField = MongoDBObject("next" -> 1)
-    val qSort = MongoDBObject()
-    val qRemove = false
-    val qModify = $inc("next" -> 1)
-    val qReturnNew = true
-    val qUpsert = true
-    seqColl.findAndModify(qFind, qField, qSort, qRemove, qModify, qReturnNew, qUpsert).get.getAsOrElse[Number]("next", 0).intValue
-  }
-
-  def main(args: Array[String]) {
-    println("PredictionIO 0.4 Migration")
-    println("Convert Engine.enginetype to Engine.infoid in MongoDB")
-    println()
-    println(s"Database host: $dbHost")
-    println(s"Database port: $dbPort")
-    println(s"Database name: $dbName")
-    println()
-    println("Looking for Engines without infoid...")
-    val engines = engineColl.find(MongoDBObject("infoid" -> MongoDBObject("$exists" -> false))).toList
-    if (engines.length > 0) {
-      println(s"Found ${engines.length} Engines without infoid. Proceed to convert enginetype to infoid?")
-      val choice = readLine("Enter 'YES' to proceed: ")
-      choice match {
-        case "YES" => {
-          engines map { engine =>
-            engineColl.update(MongoDBObject("_id" -> engine.as[Int]("_id")), MongoDBObject("$set" -> MongoDBObject("infoid" -> engine.as[String]("enginetype")), "$unset" -> MongoDBObject("enginetype" -> 1)))
-          }
-          println("Done")
-        }
-        case _ => println("Aborted")
-      }
-    } else {
-      println("None found")
-    }
-
-    //
-    println()
-    println("Looking for OfflineEvals without OfflineEvalSplitter...")
-    // create OfflineEvalSplitter for existing offlineEvalRecords which don't have one
-    val offlineEvals = offlineEvalColl.find()
-    val offlineEvalWithoutSplitter = (offlineEvals filter { eval => (offlineEvalSplitterColl.find(MongoDBObject("evalid" -> eval.as[Int]("_id"))).count == 0) }).toStream
-    val offlineEvalWithoutSplitterSize = offlineEvalWithoutSplitter.size
-    if (offlineEvalWithoutSplitterSize > 0) {
-      println(s"Found ${offlineEvalWithoutSplitterSize} OfflineEvals without OfflineEvalSplitter. Proceed to add OfflineEvalSplitter for these records?")   
-      val choice = readLine("Enter 'YES' to proceed: ")
-      choice match {
-        case "YES" => {
-          offlineEvalWithoutSplitter foreach { eval =>
-            val id = genNext("offlineEvalSplitterId")
-            val evalid = eval.as[Int]("_id")
-            println(s"Insert OfflineEvalSplitter for OfflineEval ID = $evalid")
-            offlineEvalSplitterColl.insert(MongoDBObject(
-              "_id" -> id,
-              "evalid" -> evalid,
-              "name" -> ("sim-eval-" + evalid + "-splitter"),
-              "infoid" -> "trainingtestsplit",
-              "settings" -> Map(
-                "trainingPercent" -> 0.8,
-                "validationPercent" -> 0.0,
-                "testPercent" -> 0.2,
-                "timeorder" -> false
-                )
-            ))
-          }
-          
-          println("Done")
-        }
-        case _ => println("Aborted")
-      }
-    } else {
-      println("None found")
-    }
-
-    //
-    println()
-    println("Looking for OfflineEvals with obsolete fields trainingsize, testsize, timeorder...")
-    val oldFieldExists = $or(("trainingsize" -> MongoDBObject("$exists" -> true)),
-      ("testsize" -> MongoDBObject("$exists" -> true)),
-      ("timeorder" -> MongoDBObject("$exists" -> true)))
-
-    val offlineEvalsWithOldFields = offlineEvalColl.find(oldFieldExists)
-    if (offlineEvalsWithOldFields.length > 0) {
-      println(s"Found ${offlineEvalsWithOldFields.length} OfflineEvals with obsolete fields. Proceed to remove these obsolete fields from the records?")
-      val choice = readLine("Enter 'YES' to proceed: ")
-      choice match {
-        case "YES" => {
-          offlineEvalsWithOldFields foreach { eval =>
-            val evalid = eval.as[Int]("_id")
-            println(s"Remove obsolete fields for OfflineEval ID = $evalid")
-            offlineEvalColl.update(MongoDBObject("_id" -> evalid), MongoDBObject("$unset" -> MongoDBObject("trainingsize" -> 1, "testsize" -> 1, "timeorder" -> 1)) )
-          }
-          println("Done")
-        }
-        case _ => println("Aborted")
-      }
-    } else {
-      println("None found")
-    }
-
-    //
-    println()
-    println("Looking for OfflineEvals without iterations...")
-    val offlineEvalsWithoutIterations = offlineEvalColl.find(MongoDBObject("iterations" -> MongoDBObject("$exists" -> false)))
-
-    if (offlineEvalsWithoutIterations.length > 0) {
-      println(s"Found ${offlineEvalsWithoutIterations.length} OfflineEvals without iterations. Proceed to add the 'iterations' field to these records?")
-      val choice = readLine("Enter 'YES' to proceed: ")
-      choice match {
-        case "YES" => {
-          offlineEvalsWithoutIterations foreach { eval =>
-            val evalid = eval.as[Int]("_id")
-            println(s"Update OfflineEval ID = $evalid with 'iterations'")
-            offlineEvalColl.update(MongoDBObject("_id" -> evalid), MongoDBObject("$set" -> MongoDBObject("iterations" -> 1)) )
-          }
-          println("Done")
-        }
-        case _ => println("Aborted")
-      }
-    } else {
-      println("None Found")
-    }
-
-    //
-    println()
-    println("Looking for OfflineEvalResults without iteration or splitset...")
-    val offlineEvalResultsAll = offlineEvalResultsColl.find()
-
-    val offlineEvalResultsSelected = (offlineEvalResultsAll filter { result =>
-      val iteration: Option[Int] = result.getAs[Int]("iteration")
-      val splitset: Option[String] = result.getAs[String]("splitset")
-
-      ((iteration == None) || ((splitset != Some("test")) && (splitset != Some("validation"))) )}).toStream
-
-    val offlineEvalResultsSelectedSize = offlineEvalResultsSelected.size
-    if (offlineEvalResultsSelectedSize > 0) {
-      println(s"Found ${offlineEvalResultsSelectedSize} OfflineEvalResults without proper iteration or splitset field. Proceed to update?")
-
-      val choice = readLine("Enter 'YES' to proceed: ")
-      choice match {
-        case "YES" => {
-          offlineEvalResultsSelected foreach { result =>
-
-            val resultid = result.as[String]("_id")
-            val evalid = result.as[Int]("evalid")
-            val metricid = result.as[Int]("metricid")
-            val algoid = result.as[Int]("algoid")
-            val score = result.as[Double]("score")
-            val iteration: Option[Int] = result.getAs[Int]("iteration")
-            val splitset: Option[String] = result.getAs[String]("splitset")
-
-            val newIteration: Int = iteration match {
-              case None => 1
-              case Some(x) => x
-            }
-            val newSplitset: String = splitset match {
-              case Some("test") => "test"
-              case Some("validation") => "validation"
-              case _ => "test"
-            }
-                      
-            val newResultid = (evalid + "_" + metricid + "_" + algoid + "_" + newIteration + "_" + newSplitset)
-            println(s"Update OfflineEvalResult ID = $resultid. New ID = $newResultid")
-            
-            offlineEvalResultsColl.save(MongoDBObject(
-              "_id" -> newResultid,
-              "evalid" -> evalid,
-              "metricid" -> metricid,
-              "algoid" -> algoid,
-              "score" -> score,
-              "iteration" -> newIteration,
-              "splitset" -> newSplitset
-            ))
-            offlineEvalResultsColl.remove(MongoDBObject("_id" -> resultid))
-              
-          }
-          println("Done")
-        }
-        case _ => println("Aborted")
-      }
-
-    } else {
-      println("None Found")
-    }
-
-    //
-    println()
-    println("Looking for Algo without status...")
-    val algoWithoutStatus = algoColl.find(MongoDBObject("status" -> MongoDBObject("$exists" -> false)))
-    if (algoWithoutStatus.length > 0) {
-      println(s"Found ${algoWithoutStatus.length} Algos without status. Proceed to add the 'status' field to these records?")
-      val choice = readLine("Enter 'YES' to proceed: ")
-      choice match {
-        case "YES" => {
-          algoWithoutStatus foreach { algo =>
-            val offlineevalid = algo.getAs[Int]("offlineevalid")
-            val deployed = algo.as[Boolean]("deployed")
-            val status: String = (offlineevalid, deployed) match {
-              case (None, true) => "deployed"
-              case (None, false) => "ready"
-              case (Some(x), _) => "simeval"
-            }
-            val algoid = algo.as[Int]("_id")
-            println(s"Update Algo ID = $algoid with 'status'")
-            algoColl.update(MongoDBObject("_id" -> algoid), 
-              MongoDBObject("$set" -> MongoDBObject("status" -> status)))
-          }
-          println("Done")
-        }
-        case _ => println("Aborted")
-      } 
-    } else {
-      println("None Found")
-    }
-
-  }
-
-}
diff --git a/tools/migration/0.5/appdata/build.sbt b/tools/migration/0.5/appdata/build.sbt
deleted file mode 100644
index fd7bf59..0000000
--- a/tools/migration/0.5/appdata/build.sbt
+++ /dev/null
@@ -1,15 +0,0 @@
-name := "PredictionIO 0.4 to 0.5 appdata Migration"
-
-version := "0.6.4"
-
-organization := "io.prediction"
-
-scalaVersion := "2.10.2"
-
-libraryDependencies ++= Seq(
-  "io.prediction" %% "predictionio-commons" % "0.6.4",
-  "org.mongodb" %% "casbah" % "2.6.2",
-  "org.slf4j" % "slf4j-nop" % "1.6.0"
-)
-
-resolvers += "Local Maven Repository" at "file://"+Path.userHome.absolutePath+"/.m2/repository"
diff --git a/tools/migration/0.5/appdata/project/Build.scala b/tools/migration/0.5/appdata/project/Build.scala
deleted file mode 100644
index dc37a97..0000000
--- a/tools/migration/0.5/appdata/project/Build.scala
+++ /dev/null
@@ -1,16 +0,0 @@
-import sbt._
-import sbt.Keys._
-import xerial.sbt.Pack._
-
-object Build extends sbt.Build {
-  lazy val root = Project(
-    id = "predictionio-tools-migration-appdata",
-    base = file("."),
-    settings = Defaults.defaultSettings ++ packSettings ++
-      Seq(
-        // Map from program name -> Main class (full path)
-        packMain := Map("appdata" -> "io.prediction.tools.migration.Appdata")
-        // Add custom settings here
-      )
-  )
-}
diff --git a/tools/migration/0.5/appdata/project/plugins.sbt b/tools/migration/0.5/appdata/project/plugins.sbt
deleted file mode 100644
index 7adaaae..0000000
--- a/tools/migration/0.5/appdata/project/plugins.sbt
+++ /dev/null
@@ -1 +0,0 @@
-addSbtPlugin("org.xerial.sbt" % "sbt-pack" % "0.1.7")
diff --git a/tools/migration/0.5/appdata/src/main/scala/io/prediction/tools/migration/Appdata.scala b/tools/migration/0.5/appdata/src/main/scala/io/prediction/tools/migration/Appdata.scala
deleted file mode 100644
index ed0bdb8..0000000
--- a/tools/migration/0.5/appdata/src/main/scala/io/prediction/tools/migration/Appdata.scala
+++ /dev/null
@@ -1,135 +0,0 @@
-package io.prediction.tools.migration
-
-//import com.typesafe.config._
-import io.prediction.commons.{Config}
-import com.mongodb.casbah.query.Imports._
-import com.mongodb.casbah.Imports.{MongoConnection}
-import com.mongodb.WriteResult
-
-object Appdata {
-  //val config = ConfigFactory.load()
-  val config = new Config()
-
-  val appdataDbName = config.appdataDbName
-  val appdataTrainingDbName = config.appdataTrainingDbName
-  val appdataValidationDbName = config.appdataValidationDbName
-  val appdataTestDbName = config.appdataTestDbName
-
-  val appdataDb = config.appdataMongoDb.get
-  val trainingDb = config.appdataTrainingMongoDb.get
-  val validationDb = config.appdataValidationMongoDb.get
-  val testDb = config.appdataTestMongoDb.get
-
-  val dbSeq = Seq(
-    appdataDbName -> appdataDb, 
-    appdataTrainingDbName -> trainingDb,
-    appdataValidationDbName -> validationDb,
-    appdataTestDbName -> testDb )
-
-  def main(args: Array[String]) {
-    println("PredictionIO 0.4 to 0.5 appdata Migration")
-    println()
-    println()
-
-    val emptyObj = MongoDBObject()
-
-    for ( (name, db) <- dbSeq ) {
-     
-      println(s"\nChecking ${name} DB...")
-
-      val usersColl = db("users")
-      val itemsColl = db("items")
-      val u2iActionsColl = db("u2iActions")
-
-      // users
-      print("Updating user records with custom attributes...")
-
-      val usersWithAttributes = usersColl.find(MongoDBObject("attributes" -> MongoDBObject("$exists" -> true)))
-      var userCount = 0
-      while (usersWithAttributes.hasNext) {
-        val dbObj = usersWithAttributes.next
-        userCount += 1
-        val attributes = dbObj.getAs[DBObject]("attributes") map { dbObjToMap(_) }
-        val flattenedObj = attributes map { a => attributesToMongoDBObject(a) } getOrElse emptyObj
-       
-        usersColl.update(MongoDBObject("_id" -> dbObj.as[String]("_id")), MongoDBObject("$set" -> flattenedObj, "$unset" -> MongoDBObject("attributes" -> 1)))
-      }
-      println(s"${userCount} users were updated.")
-
-      // items
-      print("Updating item records with custom attributes...")
-      val itemsWithAttributes = itemsColl.find(MongoDBObject("attributes" -> MongoDBObject("$exists" -> true)))
-
-      var itemCount = 0
-      while (itemsWithAttributes.hasNext) {
-        val dbObj = itemsWithAttributes.next
-        itemCount += 1
-        val attributes = dbObj.getAs[DBObject]("attributes") map { dbObjToMap(_) }
-        val flattenedObj = attributes map { a => attributesToMongoDBObject(a) } getOrElse emptyObj
-       
-        itemsColl.update(MongoDBObject("_id" -> dbObj.as[String]("_id")), MongoDBObject("$set" -> flattenedObj, "$unset" -> MongoDBObject("attributes" -> 1)))
-      }
-      println(s"${itemCount} items were updated.")
-   
-      // u2iActions
-      val rate: Int = 0
-      val likeDislike: Int = 1 //(v==1 => like, v==0 => dislike)
-      val view: Int = 2
-      val viewDetails: Int = 3
-      val conversion: Int = 4
-
-      def checkWriteResult(wr: WriteResult) = {
-        if (wr.getLastError().ok()) {
-          println(s"${wr.getN} records were updated.")
-        } else {
-          wr.getLastError().throwOnError()
-        }
-      }
-
-      print("Updating rate actions to new action name (may take a while)...")
-      val rateResult = u2iActionsColl.update(MongoDBObject("action" -> rate), MongoDBObject("$set" -> MongoDBObject("action" -> "rate")), false, true)
-      checkWriteResult(rateResult)
-
-      print("Updating like actions to new action name (may take a while)...") 
-      val likeResult = u2iActionsColl.update(MongoDBObject("action" -> likeDislike, "v" -> 1), MongoDBObject("$set" -> MongoDBObject("action" -> "like"), "$unset" -> MongoDBObject("v" -> 1)), false, true)
-      checkWriteResult(likeResult)
-
-      print("Updating dislike actions to new action name (may take a while)...")
-      val dislikeResult = u2iActionsColl.update(MongoDBObject("action" -> likeDislike, "v" -> 0), MongoDBObject("$set" -> MongoDBObject("action" -> "dislike"), "$unset" -> MongoDBObject("v" -> 1)), false, true)
-      checkWriteResult(dislikeResult)
-
-      print("Updating view actions to new action name (may take a while)...")
-      val viewResult = u2iActionsColl.update(MongoDBObject("action" -> view), MongoDBObject("$set" -> MongoDBObject("action" -> "view")), false, true)
-      checkWriteResult(viewResult)
-
-      print("Updating viewDetails actions to new action name (may take a while)...")
-      val viewDetailsResult = u2iActionsColl.update(MongoDBObject("action" -> viewDetails), MongoDBObject("$set" -> MongoDBObject("action" -> "viewDetails")), false, true)
-      checkWriteResult(viewDetailsResult)
-
-      print("Updating conversion actions to new action name (may take a while)...")
-      val conversionResult = u2iActionsColl.update(MongoDBObject("action" -> conversion), MongoDBObject("$set" -> MongoDBObject("action" -> "conversion")), false, true)
-      checkWriteResult(conversionResult)
-      
-    }
-
-    println("Done.")
-
-  }
-
-  /** Modified from Salat. */
-  def dbObjToMap(dbObj: DBObject): Map[String, Any] = {
-    val builder = Map.newBuilder[String, Any]
-
-    dbObj foreach {
-      case (field, value) =>
-        builder += field -> value
-    }
-
-    builder.result()
-  }
-
-  def attributesToMongoDBObject(attributes: Map[String, Any]) = {
-    MongoDBObject( (attributes map { case (k, v) => ("ca_" + k, v) }).toList )
-  }
-
-}
diff --git a/tools/migration/0.7/infos/build.sbt b/tools/migration/0.7/infos/build.sbt
deleted file mode 100644
index 894c71e..0000000
--- a/tools/migration/0.7/infos/build.sbt
+++ /dev/null
@@ -1,22 +0,0 @@
-import xerial.sbt.Pack._
-
-name := "standardized-info-ids"
-
-scalariformSettings
-
-libraryDependencies ++= Seq(
-  "ch.qos.logback" % "logback-classic" % "1.1.1",
-  "ch.qos.logback" % "logback-core" % "1.1.1",
-  "org.clapper" %% "grizzled-slf4j" % "1.0.1")
-
-packSettings
-
-packJarNameConvention := "full"
-
-packExpandedClasspath := true
-
-packGenerateWindowsBatFile := false
-
-packMain := Map("standardized-info-ids" -> "io.prediction.tools.migration.StandardizedInfoIDs")
-
-packJvmOpts := Map("standardized-info-ids" -> Common.packCommonJvmOpts)
diff --git a/tools/migration/0.7/infos/src/main/resources/application.conf b/tools/migration/0.7/infos/src/main/resources/application.conf
deleted file mode 100644
index d6f0db9..0000000
--- a/tools/migration/0.7/infos/src/main/resources/application.conf
+++ /dev/null
@@ -1,30 +0,0 @@
-# Used by PredictionIO Commons
-io.prediction.base=../..
-
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.host=localhost
-io.prediction.commons.appdata.db.port=27017
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.host=localhost
-io.prediction.commons.appdata.test.db.port=27017
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.host=localhost
-io.prediction.commons.appdata.training.db.port=27017
-
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.host=localhost
-io.prediction.commons.appdata.validation.db.port=27017
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.host=localhost
-io.prediction.commons.modeldata.db.port=27017
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.host=localhost
-io.prediction.commons.modeldata.training.db.port=27017
-
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.host=localhost
-io.prediction.commons.settings.db.port=27017
diff --git a/tools/migration/0.7/infos/src/main/scala/StandardizedInfoIDs.scala b/tools/migration/0.7/infos/src/main/scala/StandardizedInfoIDs.scala
deleted file mode 100644
index f634705..0000000
--- a/tools/migration/0.7/infos/src/main/scala/StandardizedInfoIDs.scala
+++ /dev/null
@@ -1,68 +0,0 @@
-package io.prediction.tools.migration
-
-import io.prediction.commons.Config
-
-import grizzled.slf4j.Logger
-
-object StandardizedInfoIDs {
-  def main(args: Array[String]) {
-    val logger = Logger(StandardizedInfoIDs.getClass)
-    val config = new Config()
-    val algos = config.getSettingsAlgos()
-    val algoOldToNew = Map[String, String](
-      "pdio-local-itemrec-random" -> "pio-itemrec-single-random",
-      "pdio-local-itemsim-random" -> "pio-itemsim-single-random",
-      "pdio-randomrank" -> "pio-itemrec-distributed-random",
-      "pdio-latestrank" -> "pio-itemrec-distributed-latest",
-      "mahout-itembased" -> "pio-itemrec-distributed-mahout-itembased",
-      "mahout-parallelals" -> "pio-itemrec-distributed-mahout-parallelals",
-      "mahout-knnitembased" -> "pio-itemrec-single-mahout-knnitembased",
-      "mahout-knnuserbased" -> "pio-itemrec-single-mahout-knnuserbased",
-      "mahout-thresholduserbased" -> "pio-itemrec-single-mahout-thresholduserbased",
-      "mahout-alswr" -> "pio-itemrec-single-mahout-alswr",
-      "mahout-svdsgd" -> "pio-itemrec-single-mahout-svdsgd",
-      "mahout-svdplusplus" -> "pio-itemrec-single-mahout-svdplusplus",
-      "pdio-itemsimrandomrank" -> "pio-itemsim-distributed-random",
-      "pdio-itemsimlatestrank" -> "pio-itemsim-distributed-latest",
-      "mahout-itemsimcf-single" -> "pio-itemsim-single-mahout-itemsimcf",
-      "mahout-itemsimcf" -> "pio-itemsim-distributed-mahout-itemsimcf",
-      "graphchi-als" -> "pio-itemrec-single-graphchi-als",
-      "graphchi-climf" -> "pio-itemrec-single-graphchi-climf")
-    algos.getAll foreach { algo =>
-      val newAlgoInfoID = algoOldToNew.get(algo.infoid).getOrElse(algo.infoid)
-      logger.info(s"Algo ID ${algo.id}: ${algo.infoid} -> ${newAlgoInfoID}")
-      algos.update(algo.copy(infoid = newAlgoInfoID))
-    }
-
-    val offlineEvalSplitters = config.getSettingsOfflineEvalSplitters()
-    val splittersOldToNew = Map[String, String](
-      "trainingtestsplit" -> "pio-distributed-trainingtestsplit",
-      "u2isplit" -> "pio-single-trainingtestsplit")
-    offlineEvalSplitters.getAll foreach { splitter =>
-      val newSplitterInfoID = splittersOldToNew.get(splitter.infoid).getOrElse(splitter.infoid)
-      logger.info(s"OfflineEvalSplitter ID ${splitter.id}: ${splitter.infoid} -> ${newSplitterInfoID}")
-      offlineEvalSplitters.update(splitter.copy(infoid = newSplitterInfoID))
-    }
-
-    val offlineEvalMetrics = config.getSettingsOfflineEvalMetrics()
-    val metricsOldToNew = Map[String, String](
-      "map_k" -> "pio-itemrec-distributed-map_k",
-      "map_k_nd" -> "pio-itemrec-single-map_k",
-      "ismap_k" -> "pio-itemsim-distributed-ismap_k",
-      "ismap_k_nd" -> "pio-itemsim-single-ismap_k")
-    offlineEvalMetrics.getAll foreach { metric =>
-      val newMetricInfoID = metricsOldToNew.get(metric.infoid).getOrElse(metric.infoid)
-      logger.info(s"OfflineEvalMetric ID ${metric.id}: ${metric.infoid} -> ${newMetricInfoID}")
-      offlineEvalMetrics.update(metric.copy(infoid = newMetricInfoID))
-    }
-
-    val paramGens = config.getSettingsParamGens()
-    val paramGensOldToNew = Map[String, String](
-      "random" -> "pio-single-random")
-    paramGens.getAll foreach { paramGen =>
-      val newParamGenInfoID = paramGensOldToNew.get(paramGen.infoid).getOrElse(paramGen.infoid)
-      logger.info(s"ParamGen ID ${paramGen.id}: ${paramGen.infoid} -> ${newParamGenInfoID}")
-      paramGens.update(paramGen.copy(infoid = newParamGenInfoID))
-    }
-  }
-}
diff --git a/tools/settingsinit/.gitignore b/tools/settingsinit/.gitignore
deleted file mode 100644
index 27722ba..0000000
--- a/tools/settingsinit/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-project/project/
-project/target/
-target/
diff --git a/tools/settingsinit/build.sbt b/tools/settingsinit/build.sbt
deleted file mode 100644
index 6473c34..0000000
--- a/tools/settingsinit/build.sbt
+++ /dev/null
@@ -1,19 +0,0 @@
-import xerial.sbt.Pack._
-
-name := "settingsinit"
-
-scalariformSettings
-
-libraryDependencies += "org.slf4j" % "slf4j-nop" % "1.6.0"
-
-packSettings
-
-packJarNameConvention := "full"
-
-packExpandedClasspath := true
-
-packGenerateWindowsBatFile := false
-
-packMain := Map("settingsinit" -> "io.prediction.tools.settingsinit.SettingsInit")
-
-packJvmOpts := Map("settingsinit" -> Common.packCommonJvmOpts)
diff --git a/tools/settingsinit/src/main/resources/application.conf b/tools/settingsinit/src/main/resources/application.conf
deleted file mode 100644
index d6f0db9..0000000
--- a/tools/settingsinit/src/main/resources/application.conf
+++ /dev/null
@@ -1,30 +0,0 @@
-# Used by PredictionIO Commons
-io.prediction.base=../..
-
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.host=localhost
-io.prediction.commons.appdata.db.port=27017
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.host=localhost
-io.prediction.commons.appdata.test.db.port=27017
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.host=localhost
-io.prediction.commons.appdata.training.db.port=27017
-
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.host=localhost
-io.prediction.commons.appdata.validation.db.port=27017
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.host=localhost
-io.prediction.commons.modeldata.db.port=27017
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.host=localhost
-io.prediction.commons.modeldata.training.db.port=27017
-
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.host=localhost
-io.prediction.commons.settings.db.port=27017
diff --git a/tools/settingsinit/src/main/scala/io/prediction/tools/settingsinit/SettingsInit.scala b/tools/settingsinit/src/main/scala/io/prediction/tools/settingsinit/SettingsInit.scala
deleted file mode 100644
index dd17fa0..0000000
--- a/tools/settingsinit/src/main/scala/io/prediction/tools/settingsinit/SettingsInit.scala
+++ /dev/null
@@ -1,339 +0,0 @@
-package io.prediction.tools.settingsinit
-
-import io.prediction.commons._
-import io.prediction.commons.settings._
-
-import scala.reflect.ClassTag
-import scala.util.parsing.json.JSON
-
-/** Extractors: http://stackoverflow.com/questions/4170949/how-to-parse-json-in-scala-using-standard-scala-classes */
-class CC[T: ClassTag] {
-  def unapply(a: Any)(implicit e: ClassTag[T]): Option[T] = {
-    try { Some(e.runtimeClass.cast(a).asInstanceOf[T]) } catch { case _: Throwable => None }
-  }
-}
-
-object M extends CC[Map[String, Any]]
-object SM extends CC[Seq[Map[String, Any]]]
-object MSS extends CC[Map[String, String]]
-object SS extends CC[Seq[String]]
-object OSS extends CC[Option[Seq[String]]]
-object S extends CC[String]
-object OS extends CC[Option[String]]
-object D extends CC[Double]
-object B extends CC[Boolean]
-
-object SettingsInit {
-  val config = new Config()
-
-  def main(args: Array[String]) {
-    val algoInfos = config.getSettingsAlgoInfos
-    val engineInfos = config.getSettingsEngineInfos
-    val offlineEvalSplitterInfos = config.getSettingsOfflineEvalSplitterInfos
-    val offlineEvalMetricInfos = config.getSettingsOfflineEvalMetricInfos
-    val paramGenInfos = config.getSettingsParamGenInfos
-    val systemInfos = config.getSettingsSystemInfos
-
-    val settingsFile = try { args(0) } catch {
-      case e: Throwable =>
-        println("Please specify the location of the initial settings file in the command line. Aborting.")
-        sys.exit(1)
-    }
-
-    val settingsString = try { scala.io.Source.fromFile(settingsFile).mkString } catch {
-      case e: Throwable =>
-        println(s"Unable to open ${settingsFile}: ${e.getMessage}. Aborting.")
-        sys.exit(1)
-    }
-
-    val settingsJson = JSON.parseFull(settingsString) getOrElse {
-      println(s"Unable to parse initial settings file ${settingsFile}. Aborting.")
-    }
-
-    println("PredictionIO settings initialization starting")
-
-    M.unapply(settingsJson) map { settings =>
-      println("Deleting old SystemInfo entries...")
-      systemInfos.getAll() foreach { info =>
-        println(s"- ${info.id}")
-        systemInfos.delete(info.id)
-      }
-      M.unapply(settings("systeminfos")) map { infos =>
-        println("Populating SystemInfos...")
-        for {
-          id <- infos.keys
-          M(info) = infos(id)
-          S(value) = info("value")
-          OS(description) = info.get("description")
-        } yield {
-          val si = SystemInfo(
-            id = id,
-            value = value,
-            description = description)
-
-          println(s"Deleting any old SystemInfo ID: ${id}")
-          systemInfos.delete(id)
-          println(s"Adding SystemInfo ID: ${id}")
-          systemInfos.insert(si)
-        }
-      } getOrElse println("Cannot find any SystemInfo information. Skipping.")
-
-      println("Deleting old EngineInfo entries...")
-      engineInfos.getAll() foreach { info =>
-        println(s"- ${info.id}")
-        engineInfos.delete(info.id)
-      }
-      M.unapply(settings("engineinfos")) map { infos =>
-        println("Populating EngineInfos...")
-        for {
-          id <- infos.keys
-          M(info) = infos(id)
-          S(name) = info("name")
-          OS(description) = info.get("description")
-          M(params) = info("params")
-          SM(paramsections) = info("paramsections")
-          S(defaultalgoinfoid) = info("defaultalgoinfoid")
-          S(defaultofflineevalmetricinfoid) = info("defaultofflineevalmetricinfoid")
-          S(defaultofflineevalsplitterinfoid) = info("defaultofflineevalsplitterinfoid")
-        } yield {
-          println(s"Processing EngineInfo ID: ${id}")
-          val castedparams = mapToParams(params)
-          val castedparamsections = mapToParamSections(paramsections.asInstanceOf[Seq[Map[String, Any]]])
-          val ei = EngineInfo(
-            id = id,
-            name = name,
-            description = description,
-            params = castedparams,
-            paramsections = castedparamsections,
-            defaultalgoinfoid = defaultalgoinfoid,
-            defaultofflineevalmetricinfoid = defaultofflineevalmetricinfoid,
-            defaultofflineevalsplitterinfoid = defaultofflineevalsplitterinfoid)
-
-          println(s"Deleting any old EngineInfo ID: ${id}")
-          engineInfos.delete(id)
-          println(s"Adding EngineInfo ID: ${id}")
-          engineInfos.insert(ei)
-        }
-      } getOrElse println("Cannot find any EngineInfo information. Skipping.")
-
-      println("Deleting old AlgoInfo entries...")
-      algoInfos.getAll() foreach { info =>
-        println(s"- ${info.id}")
-        algoInfos.delete(info.id)
-      }
-      M.unapply(settings("algoinfos")) map { infos =>
-        println("Populating AlgoInfos...")
-        for {
-          id <- infos.keys
-          M(info) = infos(id)
-          S(name) = info("name")
-          OS(description) = info.get("description")
-          OSS(batchcommands) = info.get("batchcommands")
-          OSS(offlineevalcommands) = info.get("offlineevalcommands")
-          SS(paramorder) = info("paramorder")
-          M(params) = info("params")
-          SM(paramsections) = info("paramsections")
-          S(engineinfoid) = info("engineinfoid")
-          SS(techreq) = info("techreq")
-          SS(datareq) = info("datareq")
-          OSS(capabilities) = info.get("capabilities")
-        } yield {
-          println(s"Processing AlgoInfo ID: ${id}")
-          val castedparams = mapToParams(params)
-          val castedparamsections = mapToParamSections(paramsections.asInstanceOf[Seq[Map[String, Any]]])
-          val ai = AlgoInfo(
-            id = id,
-            name = name,
-            description = description,
-            batchcommands = batchcommands,
-            offlineevalcommands = offlineevalcommands,
-            params = castedparams,
-            paramsections = castedparamsections,
-            paramorder = paramorder,
-            engineinfoid = engineinfoid,
-            techreq = techreq,
-            datareq = datareq,
-            capabilities = capabilities.getOrElse(Seq()))
-
-          println(s"Deleting any old AlgoInfo ID: ${id}")
-          algoInfos.delete(id)
-          println(s"Adding AlgoInfo ID: ${id}")
-          algoInfos.insert(ai)
-        }
-      } getOrElse println("Cannot find any AlgoInfo information. Skipping.")
-
-      println("Deleting old OfflineEvalSplitterInfo entries...")
-      offlineEvalSplitterInfos.getAll() foreach { info =>
-        println(s"- ${info.id}")
-        offlineEvalSplitterInfos.delete(info.id)
-      }
-      M.unapply(settings("offlineevalsplitterinfos")) map { infos =>
-        println("Populating OfflineEvalSplitterInfos...")
-        for {
-          id <- infos.keys
-          M(info) = infos(id)
-          S(name) = info("name")
-          SS(engineinfoids) = info("engineinfoids")
-          OS(description) = info.get("description")
-          OSS(commands) = info.get("commands")
-          M(params) = info("params")
-          SM(paramsections) = info("paramsections")
-          SS(paramorder) = info("paramorder")
-        } yield {
-          println(s"Processing OfflineEvalSplitterInfo ID: ${id}")
-          val castedparams = mapToParams(params)
-          val castedparamsections = mapToParamSections(paramsections.asInstanceOf[Seq[Map[String, Any]]])
-          val mi = OfflineEvalSplitterInfo(
-            id = id,
-            name = name,
-            engineinfoids = engineinfoids,
-            description = description,
-            commands = commands,
-            params = castedparams,
-            paramsections = castedparamsections,
-            paramorder = paramorder)
-
-          println(s"Deleting any old OfflineEvalSplitterInfo ID: ${id}")
-          offlineEvalSplitterInfos.delete(id)
-          println(s"Adding OfflineEvalSplitterInfo ID: ${id}")
-          offlineEvalSplitterInfos.insert(mi)
-        }
-      } getOrElse println("Cannot find any OfflineEvalSplitterInfo information. Skipping.")
-
-      println("Deleting old OfflineEvalMetricInfo entries...")
-      offlineEvalMetricInfos.getAll() foreach { info =>
-        println(s"- ${info.id}")
-        offlineEvalMetricInfos.delete(info.id)
-      }
-      M.unapply(settings("offlineevalmetricinfos")) map { infos =>
-        println("Populating OfflineEvalMetricInfos...")
-        for {
-          id <- infos.keys
-          M(info) = infos(id)
-          S(name) = info("name")
-          SS(engineinfoids) = info("engineinfoids")
-          OS(description) = info.get("description")
-          OSS(commands) = info.get("commands")
-          M(params) = info("params")
-          SM(paramsections) = info("paramsections")
-          SS(paramorder) = info("paramorder")
-        } yield {
-          println(s"Processing OfflineEvalMetricInfo ID: ${id}")
-          val castedparams = mapToParams(params)
-          val castedparamsections = mapToParamSections(paramsections.asInstanceOf[Seq[Map[String, Any]]])
-          val mi = OfflineEvalMetricInfo(
-            id = id,
-            name = name,
-            engineinfoids = engineinfoids,
-            description = description,
-            commands = commands,
-            params = castedparams,
-            paramsections = castedparamsections,
-            paramorder = paramorder)
-
-          println(s"Deleting any old OfflineEvalMetricInfo ID: ${id}")
-          offlineEvalMetricInfos.delete(id)
-          println(s"Adding OfflineEvalMetricInfo ID: ${id}")
-          offlineEvalMetricInfos.insert(mi)
-        }
-      } getOrElse println("Cannot find any OfflineEvalMetricInfo information. Skipping.")
-
-      println("Deleting old ParamGenInfo entries...")
-      paramGenInfos.getAll() foreach { info =>
-        println(s"- ${info.id}")
-        paramGenInfos.delete(info.id)
-      }
-      M.unapply(settings("paramgeninfos")) map { infos =>
-        println("Populating ParamGenInfos...")
-        for {
-          id <- infos.keys
-          M(info) = infos(id)
-          S(name) = info("name")
-          OS(description) = info.get("description")
-          OSS(commands) = info.get("commands")
-          SS(paramorder) = info("paramorder")
-          MSS(paramnames) = info("paramnames")
-          MSS(paramdescription) = info("paramdescription")
-          MSS(paramdefaults) = info("paramdefaults")
-        } yield {
-          val mi = ParamGenInfo(
-            id = id,
-            name = name,
-            description = description,
-            commands = commands,
-            paramorder = paramorder,
-            paramnames = paramnames,
-            paramdescription = paramdescription,
-            paramdefaults = paramdefaults)
-
-          paramGenInfos.get(id) map { m =>
-            println(s"Updating ParamGenInfo ID: ${id}")
-            paramGenInfos.update(mi)
-          } getOrElse {
-            println(s"Adding ParamGenInfo ID: ${id}")
-            paramGenInfos.insert(mi)
-          }
-        }
-      } getOrElse println("Cannot find any ParamGenInfo information. Skipping.")
-    } getOrElse println("Root level is not an object. Aborting.")
-
-    println("PredictionIO settings initialization finished")
-  }
-
-  def mapToParams(params: Map[String, Any]): Map[String, Param] = {
-    /**
-     * Take care of integers that are parsed as double from JSON
-     * http://www.ecma-international.org/ecma-262/5.1/#sec-4.3.19
-     */
-    params map { p =>
-      val param = p._2.asInstanceOf[Map[String, Any]]
-      val paramconstraint = param("constraint").asInstanceOf[Map[String, Any]]
-      val paramui = param("ui").asInstanceOf[Map[String, Any]]
-      val constraint = paramconstraint("paramtype").asInstanceOf[String] match {
-        case "boolean" => ParamBooleanConstraint()
-        case "double" => ParamDoubleConstraint(min = paramconstraint.get("min").map(_.asInstanceOf[Double]), max = paramconstraint.get("max").map(_.asInstanceOf[Double]))
-        case "integer" => ParamIntegerConstraint(min = paramconstraint.get("min").map(_.asInstanceOf[Int]), max = paramconstraint.get("max").map(_.asInstanceOf[Int]))
-        case "long" => ParamLongConstraint(min = paramconstraint.get("min").map(_.asInstanceOf[Long]), max = paramconstraint.get("max").map(_.asInstanceOf[Long]))
-        case "string" => ParamStringConstraint()
-        case _ => ParamStringConstraint()
-      }
-      val uitype = paramui("uitype").asInstanceOf[String]
-      val ui = uitype match {
-        case "selection" => {
-          val selectionsSeq = paramui("selections").asInstanceOf[Seq[Map[String, String]]]
-          ParamUI(uitype = "selection", selections = Some(selectionsSeq.map(s => ParamSelectionUI(name = s("name"), value = s("value")))))
-        }
-        case "slider" =>
-          ParamUI(
-            uitype = "slider",
-            slidermin = paramui.get("slidermin").map(_.asInstanceOf[Double].toInt),
-            slidermax = paramui.get("slidermax").map(_.asInstanceOf[Double].toInt),
-            sliderstep = paramui.get("sliderstep").map(_.asInstanceOf[Double].toInt))
-        case _ => ParamUI(uitype = uitype)
-      }
-      val casteddefault = constraint.paramtype match {
-        case "integer" => param("defaultvalue").asInstanceOf[Double].toInt
-        case "long" => param("defaultvalue").asInstanceOf[Double].toLong
-        case _ => param("defaultvalue")
-      }
-      (p._1, Param(
-        id = p._1,
-        name = param("name").asInstanceOf[String],
-        description = param.get("description") map { _.asInstanceOf[String] },
-        defaultvalue = casteddefault,
-        constraint = constraint,
-        ui = ui))
-    }
-  }
-
-  def mapToParamSections(paramsections: Seq[Map[String, Any]]): Seq[ParamSection] = {
-    paramsections map { paramsection =>
-      ParamSection(
-        name = paramsection("name").asInstanceOf[String],
-        sectiontype = paramsection("sectiontype").asInstanceOf[String],
-        description = paramsection.get("description").map(_.asInstanceOf[String]),
-        subsections = paramsection.get("subsections").map(ss => mapToParamSections(ss.asInstanceOf[Seq[Map[String, Any]]])),
-        params = paramsection.get("params").map(_.asInstanceOf[Seq[String]]))
-    }
-  }
-}
diff --git a/tools/softwaremanager/build.sbt b/tools/softwaremanager/build.sbt
deleted file mode 100644
index 2b595e5..0000000
--- a/tools/softwaremanager/build.sbt
+++ /dev/null
@@ -1,30 +0,0 @@
-import xerial.sbt.Pack._
-
-name := "softwaremanager"
-
-scalariformSettings
-
-libraryDependencies ++= Seq(
-  "com.github.scopt" %% "scopt" % "3.1.0",
-  "commons-io" % "commons-io" % "2.4",
-  "org.slf4j" % "slf4j-nop" % "1.6.0")
-
-packSettings
-
-packJarNameConvention := "full"
-
-packExpandedClasspath := true
-
-packGenerateWindowsBatFile := false
-
-packMain := Map(
-  "backup"      -> "io.prediction.tools.softwaremanager.Backup",
-  "restore"     -> "io.prediction.tools.softwaremanager.Restore",
-  "updatecheck" -> "io.prediction.tools.softwaremanager.UpdateCheck",
-  "upgrade"     -> "io.prediction.tools.softwaremanager.Upgrade")
-
-packJvmOpts := Map(
-  "backup"      -> Common.packCommonJvmOpts,
-  "restore"     -> Common.packCommonJvmOpts,
-  "updatecheck" -> Common.packCommonJvmOpts,
-  "upgrade"     -> Common.packCommonJvmOpts)
diff --git a/tools/softwaremanager/src/main/scala/io/prediction/tools/softwaremanager/Backup.scala b/tools/softwaremanager/src/main/scala/io/prediction/tools/softwaremanager/Backup.scala
deleted file mode 100644
index 3f9fe91..0000000
--- a/tools/softwaremanager/src/main/scala/io/prediction/tools/softwaremanager/Backup.scala
+++ /dev/null
@@ -1,79 +0,0 @@
-package io.prediction.tools.softwaremanager
-
-import io.prediction.commons._
-
-case class BackupConfig(backupDir: String = "")
-
-object Backup {
-  val config = new Config()
-
-  val settingsMap = Map(
-    "algoInfos" -> config.getSettingsAlgoInfos,
-    "algos" -> config.getSettingsAlgos,
-    "apps" -> config.getSettingsApps,
-    "engineInfos" -> config.getSettingsEngineInfos,
-    "engines" -> config.getSettingsEngines,
-    "offlineEvalMetricInfos" -> config.getSettingsOfflineEvalMetricInfos,
-    "offlineEvalMetrics" -> config.getSettingsOfflineEvalMetrics,
-    "offlineEvalResults" -> config.getSettingsOfflineEvalResults,
-    "offlineEvals" -> config.getSettingsOfflineEvals,
-    "offlineEvalSplitterInfos" -> config.getSettingsOfflineEvalSplitterInfos,
-    "offlineEvalSplitters" -> config.getSettingsOfflineEvalSplitters,
-    "offlineTunes" -> config.getSettingsOfflineTunes,
-    "paramGenInfos" -> config.getSettingsParamGenInfos,
-    "paramGens" -> config.getSettingsParamGens,
-    "systemInfos" -> config.getSettingsSystemInfos,
-    "users" -> config.getSettingsUsers)
-
-  def main(args: Array[String]) {
-    val parser = new scopt.OptionParser[BackupConfig]("backup") {
-      head("PredictionIO Backup Utility", "0.7.3")
-      help("help") text ("prints this usage text")
-      arg[String]("<backup directory>") action { (x, c) =>
-        c.copy(backupDir = x)
-      } text ("directory containing backup files")
-    }
-
-    parser.parse(args, BackupConfig()) map { backupConfig =>
-      println("PredictionIO Backup Utility")
-      println()
-
-      val backupDir = backupConfig.backupDir
-
-      val backupDirFile = new java.io.File(backupDir)
-      if (!backupDirFile.exists && !backupDirFile.mkdirs) {
-        println(s"Unable to create directory ${backupDir}. Aborting...")
-        sys.exit(1)
-      }
-
-      settingsMap map { s =>
-        val fn = s"${backupDir}/${s._1}.json"
-        val fos = new java.io.FileOutputStream(fn)
-        try {
-          fos.write(s._2.backup())
-          println(s"Backed up to ${fn}")
-        } finally {
-          fos.close()
-        }
-      }
-
-      config.settingsDbType match {
-        case "mongodb" => {
-          val metadata = new settings.mongodb.MongoMetadata(config.settingsMongoDb.get)
-          val fn = s"${backupDir}/metadata.json"
-          val fos = new java.io.FileOutputStream(fn)
-          try {
-            fos.write(metadata.backup())
-            println(s"Metadata backed up to ${fn}")
-          } finally {
-            fos.close()
-          }
-        }
-        case _ => println(s"Unknown settings database type ${config.settingsDbType}. Skipping metadata backup.")
-      }
-
-      println()
-      println("Backup completed.")
-    }
-  }
-}
diff --git a/tools/softwaremanager/src/main/scala/io/prediction/tools/softwaremanager/Restore.scala b/tools/softwaremanager/src/main/scala/io/prediction/tools/softwaremanager/Restore.scala
deleted file mode 100644
index 25e791c..0000000
--- a/tools/softwaremanager/src/main/scala/io/prediction/tools/softwaremanager/Restore.scala
+++ /dev/null
@@ -1,86 +0,0 @@
-package io.prediction.tools.softwaremanager
-
-import io.prediction.commons._
-
-case class RestoreConfig(backupDir: String = "", upgrade: Boolean = false)
-
-object Restore {
-  val config = new Config()
-
-  val settingsMap = Map(
-    "algoInfos" -> config.getSettingsAlgoInfos,
-    "algos" -> config.getSettingsAlgos,
-    "apps" -> config.getSettingsApps,
-    "engineInfos" -> config.getSettingsEngineInfos,
-    "engines" -> config.getSettingsEngines,
-    "offlineEvalMetricInfos" -> config.getSettingsOfflineEvalMetricInfos,
-    "offlineEvalMetrics" -> config.getSettingsOfflineEvalMetrics,
-    "offlineEvalResults" -> config.getSettingsOfflineEvalResults,
-    "offlineEvals" -> config.getSettingsOfflineEvals,
-    "offlineEvalSplitterInfos" -> config.getSettingsOfflineEvalSplitterInfos,
-    "offlineEvalSplitters" -> config.getSettingsOfflineEvalSplitters,
-    "offlineTunes" -> config.getSettingsOfflineTunes,
-    "paramGenInfos" -> config.getSettingsParamGenInfos,
-    "paramGens" -> config.getSettingsParamGens,
-    "systemInfos" -> config.getSettingsSystemInfos,
-    "users" -> config.getSettingsUsers)
-
-  def main(args: Array[String]) {
-    val parser = new scopt.OptionParser[RestoreConfig]("restore") {
-      head("PredictionIO Restore Utility", "0.7.3")
-      help("help") text ("prints this usage text")
-      opt[Unit]("upgrade") action { (_, c) =>
-        c.copy(upgrade = true)
-      } text ("upgrade from previous version backup data")
-      arg[String]("<backup directory>") action { (x, c) =>
-        c.copy(backupDir = x)
-      } text ("directory containing backup files")
-    }
-
-    parser.parse(args, RestoreConfig()) map { restoreConfig =>
-      println("PredictionIO Restore Utility")
-      println()
-
-      val backupDir = restoreConfig.backupDir
-      val upgrade = restoreConfig.upgrade
-
-      if (upgrade) {
-        println("Upgrading from data backed up by a previous version software...")
-        println()
-      }
-
-      settingsMap map { s =>
-        val fn = s"${backupDir}/${s._1}.json"
-        try {
-          s._2.restore(scala.io.Source.fromFile(fn)(scala.io.Codec.ISO8859).map(_.toByte).toArray, true, upgrade) map { x =>
-            println(s"Restored from ${fn}")
-          } getOrElse {
-            println(s"Cannot restore from ${fn}. Skipping...")
-          }
-        } catch {
-          case e: java.io.FileNotFoundException => println(s"Error: ${e.getMessage}. Skipping...")
-        }
-      }
-
-      config.settingsDbType match {
-        case "mongodb" => {
-          val metadata = new settings.mongodb.MongoMetadata(config.settingsMongoDb.get)
-          val fn = s"${backupDir}/metadata.json"
-          try {
-            metadata.restore(scala.io.Source.fromFile(fn)(scala.io.Codec.ISO8859).map(_.toByte).toArray, true, upgrade) map { x =>
-              println(s"Restored metadata from ${fn}")
-            } getOrElse {
-              println(s"Cannot restore metadata from ${fn}. Skipping...")
-            }
-          } catch {
-            case e: java.io.FileNotFoundException => println(s"Error: ${e.getMessage}. Skipping...")
-          }
-        }
-        case _ => println(s"Unknown settings database type ${config.settingsDbType}. Skipping metadata restore.")
-      }
-
-      println()
-      println("Restore finished.")
-    }
-  }
-}
diff --git a/tools/softwaremanager/src/main/scala/io/prediction/tools/softwaremanager/UpdateCheck.scala b/tools/softwaremanager/src/main/scala/io/prediction/tools/softwaremanager/UpdateCheck.scala
deleted file mode 100644
index b1ee60b..0000000
--- a/tools/softwaremanager/src/main/scala/io/prediction/tools/softwaremanager/UpdateCheck.scala
+++ /dev/null
@@ -1,111 +0,0 @@
-package io.prediction.tools.softwaremanager
-
-import io.prediction.commons._
-
-import scala.reflect.ClassTag
-import scala.sys.process._
-import scala.util.parsing.json.JSON
-
-import org.apache.commons.io.FileUtils._
-
-case class UpdateCheckConfig(localVersion: String = "", answer: String = "")
-
-object UpdateCheck {
-  val config = new Config()
-  val systemInfos = config.getSettingsSystemInfos
-
-  def main(args: Array[String]) {
-    val parser = new scopt.OptionParser[UpdateCheckConfig]("updatecheck") {
-      head("PredictionIO Update Checker", "0.7.3")
-      help("help") text ("prints this usage text")
-      opt[String]("localVersion") action { (x, c) =>
-        c.copy(localVersion = x)
-      } text ("read version information from a local file instead")
-      opt[String]("answer") action { (x, c) =>
-        c.copy(answer = x)
-      } text ("'y' to proceed downloading update if found; 'n' to skip")
-    }
-
-    parser.parse(args, UpdateCheckConfig()) map { updateCheckConfig =>
-      println("PredictionIO Update Checker")
-      println()
-
-      val installed = systemInfos.get("version") map { _.value } getOrElse {
-        println("Cannot detect any previous version. Possible causes:")
-        println("- PredictionIO version < 0.5.0")
-        println("- misconfiguration (wrong settings database pointers)")
-        println("- settings database has been corrupted")
-        println()
-        println("Update check aborted.")
-        sys.exit(1)
-      }
-
-      val localVersion = updateCheckConfig.localVersion
-      val versions = if (localVersion != "") {
-        println(s"Using local version file ${localVersion}...")
-        println()
-        try {
-          Versions(localVersion)
-        } catch {
-          case e: java.io.FileNotFoundException => {
-            println(s"Error: ${e.getMessage}. Aborting.")
-            sys.exit(1)
-          }
-        }
-      } else {
-        try {
-          println(s"Using ${Versions.versionsUrl}...")
-          println()
-          Versions()
-        } catch {
-          case e: java.net.UnknownHostException => {
-            println(s"Error: Unknown host: ${e.getMessage}. Aborting.")
-            sys.exit(1)
-          }
-          case e: java.io.FileNotFoundException => {
-            println(s"Error: File not found: ${e.getMessage}. Aborting.")
-            sys.exit(1)
-          }
-        }
-      }
-
-      val latest = versions.latestVersion
-      println(s"   Latest version: ${latest}")
-      println(s"Installed version: ${installed}")
-      println()
-
-      if (latest != installed) {
-        val answer = updateCheckConfig.answer
-        val choice = if (answer == "") {
-          println("Your PredictionIO is not the latest version. Do you want to download and install the latest binaries?")
-          val input = readLine("Enter 'YES' to proceed: ")
-          input match {
-            case "YES" => "y"
-            case _ => "a"
-          }
-        } else answer
-        choice match {
-          case "y" => {
-            val binaries = versions.binaries(latest) map { b =>
-              println(s"Retrieving ${b}...")
-              s"curl -O ${b}".!
-              val filename = b.split('/').reverse.head
-              val dirname = filename.split('.').dropRight(1).mkString(".")
-              val extractedDir = getFile(dirname)
-              if (extractedDir.exists) { deleteDirectory(extractedDir) }
-              s"unzip ${filename}".!
-              if (localVersion != "")
-                s"${dirname}/bin/upgrade --localVersion ${localVersion} ${config.base} ${dirname}".!
-              else
-                s"${dirname}/bin/upgrade ${config.base} ${dirname}".!
-            }
-          }
-          case "n" => println(s"Your PredictionIO is not the latest version. A new version ${latest} is available.")
-          case "a" => println("Aborting.")
-        }
-      } else {
-        println("Your PredictionIO version is already the latest.")
-      }
-    }
-  }
-}
diff --git a/tools/softwaremanager/src/main/scala/io/prediction/tools/softwaremanager/Upgrade.scala b/tools/softwaremanager/src/main/scala/io/prediction/tools/softwaremanager/Upgrade.scala
deleted file mode 100644
index 75a9479..0000000
--- a/tools/softwaremanager/src/main/scala/io/prediction/tools/softwaremanager/Upgrade.scala
+++ /dev/null
@@ -1,279 +0,0 @@
-package io.prediction.tools.softwaremanager
-
-import scala.collection.JavaConversions._
-import scala.sys.process._
-
-import java.io.File
-
-import com.typesafe.config._
-import org.apache.commons.io.FileUtils._
-
-case class UpgradeConfig(
-  current: File = new File("."),
-  latest: File = new File("."),
-  nomigrate: Boolean = false,
-  localVersion: String = "")
-
-/** Upgrades previous version to current version. */
-object Upgrade {
-  def main(args: Array[String]) {
-    val thisVersion = "0.7.3"
-    val parser = new scopt.OptionParser[UpgradeConfig]("upgrade") {
-      head("PredictionIO Software Upgrade Utility", thisVersion)
-      help("help") text ("prints this usage text")
-      opt[Unit]("nomigrate") action { (_, c) =>
-        c.copy(nomigrate = true)
-      } text ("upgrade from previous version backup data")
-      opt[String]("localVersion") action { (x, c) =>
-        c.copy(localVersion = x)
-      } text ("use a local file for version information")
-      arg[File]("<current>") action { (x, c) =>
-        c.copy(current = x)
-      } text ("directory containing current PredictionIO setup")
-      arg[File]("<latest>") action { (x, c) =>
-        c.copy(latest = x)
-      } text ("directory containing latest PredictionIO files")
-    }
-
-    parser.parse(args, UpgradeConfig()) map { upgradeConfig =>
-      var stepcount = 1
-      val steps = 9
-      val currentDir = upgradeConfig.current
-      val latestDir = upgradeConfig.latest
-      val current = currentDir.getCanonicalPath
-      val latest = latestDir.getCanonicalPath
-      var nomigrate = upgradeConfig.nomigrate
-
-      println("PredictionIO Software Upgrade Utility")
-      println()
-
-      if (!currentDir.exists) {
-        println(s"${current} does not exist. Aborting.")
-        sys.exit(1)
-      }
-
-      if (!latestDir.exists) {
-        println(s"${latest} does not exist. Aborting.")
-        sys.exit(1)
-      }
-
-      if ((getFile(currentDir, "backup")).exists) {
-        println(s"${current}/backup already exists. Please move away any previous backups and try again.")
-        sys.exit(1)
-      }
-
-      val dirs = Seq("bin", "conf", "lib")
-
-      /** Determine current version */
-      System.setProperty("config.file", s"${current}/conf/predictionio.conf")
-      val config = new io.prediction.commons.Config()
-      val systemInfos = config.getSettingsSystemInfos
-      val installed = systemInfos.get("version") map { _.value }
-      installed getOrElse {
-        println("Cannot detect any previous version. Possible causes:")
-        println("- PredictionIO version < 0.5.0")
-        println("- misconfiguration (wrong settings database pointers)")
-        println("- settings database has been corrupted")
-        println()
-        println("No migration of settings will be performed if you choose to continue the upgrade.")
-        val input = readLine("Enter 'YES' to proceed: ")
-        val interrupt = input match {
-          case "YES" => false
-          case _ => true
-        }
-        if (interrupt) { sys.exit(1) } else { nomigrate = true }
-      }
-      val installedVersion = installed.get
-
-      /** Backup existing data. */
-      println(s"Step ${stepcount} of ${steps}: Backup existing settings...")
-      println()
-
-      if (nomigrate) {
-        println("Not migrating settings. Skipping backup.")
-      } else {
-        backup(s"${current}/bin/backup", s"${current}/backup/settings/${installedVersion}", current)
-      }
-
-      println()
-      stepcount += 1
-
-      /** Determine updaters to download. */
-      println(s"Step ${stepcount} of ${steps}: Downloading any additional settings updaters...")
-      println()
-
-      val versions = if (upgradeConfig.localVersion == "") { Versions() } else { Versions(upgradeConfig.localVersion) }
-      val updateSequence = versions.updateSequence(installedVersion, thisVersion)
-
-      if (nomigrate) {
-        println("Not migrating settings. Skipping...")
-      } else {
-        if (updateSequence.size == 0) {
-          println(s"Upgrading from ${installedVersion} to ${thisVersion} requires no additional updaters.")
-        } else {
-          val updaterDirFile = new java.io.File(s"${current}/updaters")
-          if (!updaterDirFile.exists && !updaterDirFile.mkdirs) {
-            println(s"Unable to create directory ${updaterDirFile}. Aborting...")
-            sys.exit(1)
-          }
-          var i = 0
-          updateSequence foreach { v =>
-            versions.updater(v) map { u =>
-              println(s"Downloading ${u}...")
-              if (Process(s"curl -O ${u}", updaterDirFile).! != 0) {
-                println("Download failed. Aborting...")
-                sys.exit(1)
-              }
-              val filename = u.split('/').reverse.head
-              val dirname = filename.split('.').dropRight(1).mkString(".")
-              val extractedUpdaterDir = getFile(updaterDirFile, dirname)
-              if (extractedUpdaterDir.exists) { deleteDirectory(extractedUpdaterDir) }
-              if (Process(s"unzip ${filename}", updaterDirFile).! != 0) {
-                println("Updater extraction failed. Aborting...")
-                sys.exit(1)
-              }
-              if (i == 0)
-                restore(s"${updaterDirFile}/${dirname}/bin/restore", s"${current}/backup/settings/${installedVersion}", current)
-              else
-                restore(s"${updaterDirFile}/${dirname}/bin/restore", s"${current}/backup/settings/${updateSequence(i - 1)}", current)
-
-              backup(s"${updaterDirFile}/${dirname}/bin/backup", s"${current}/backup/settings/${v}", current)
-            }
-            i += 1
-          }
-        }
-      }
-      println()
-      stepcount += 1
-
-      println(s"Step ${stepcount} of ${steps}: Creating backup of PredictionIO installation files...")
-      println()
-      for (backupDir <- dirs) {
-        println(s"Backing up ${backupDir}...")
-        moveDirectoryToDirectory(getFile(currentDir, backupDir), getFile(currentDir, "backup"), true)
-      }
-      println()
-      stepcount += 1
-
-      /** Copy new files. */
-      println(s"Step ${stepcount} of ${steps}: Placing new files...")
-      println()
-      for (dir <- dirs) {
-        println(s"Placing ${dir}...")
-        moveDirectoryToDirectory(getFile(latestDir, dir), currentDir, true)
-      }
-      println()
-      stepcount += 1
-
-      /** Merge old config to new config. */
-      println(s"Step ${stepcount} or ${steps}: Merging old configuration to new configuration...")
-      System.setProperty("io.prediction.base", "${io.prediction.base}")
-      System.setProperty("config.file", s"${current}/backup/conf/predictionio.conf")
-      val currentConfig = ConfigFactory.load()
-      System.setProperty("config.file", s"${current}/conf/predictionio.conf")
-      ConfigFactory.invalidateCaches()
-      val latestConfig = ConfigFactory.load()
-
-      val newConfig = currentConfig.withOnlyPath("io.prediction.commons").withFallback(latestConfig)
-        .withoutPath("config")
-        .withoutPath("file")
-        .withoutPath("io.prediction.base")
-        .withoutPath("java")
-        .withoutPath("line")
-        .withoutPath("os")
-        .withoutPath("path")
-        .withoutPath("prog")
-        .withoutPath("sun")
-        .withoutPath("user")
-
-      val newConfFile = getFile(currentDir, "conf", "predictionio.conf")
-      val newConfWriter = new java.io.PrintWriter(newConfFile)
-
-      try {
-        newConfig.entrySet.toSeq sortBy { entry => entry.getKey } foreach { entry =>
-          val v = entry.getValue.render.replace("\"${io.prediction.base}", "${io.prediction.base}\"")
-          newConfWriter.println(s"${entry.getKey}=${v}")
-        }
-      } finally {
-        newConfWriter.close
-      }
-      println()
-      stepcount += 1
-
-      println(s"Step ${stepcount} of ${steps}: Retaining old logger configuration...")
-      println()
-      val loggerConfs = Seq("admin-logger.xml", "api-logger.xml", "scheduler-logger.xml")
-      loggerConfs foreach { conf =>
-        println(s"Retaining ${conf}...")
-        copyFileToDirectory(getFile(currentDir, "backup", "conf", conf), getFile(currentDir, "conf"))
-      }
-      println()
-      stepcount += 1
-
-      println(s"Step ${stepcount} of ${steps}: Clean up temporary files...")
-      deleteDirectory(latestDir)
-      println()
-      stepcount += 1
-
-      println(s"Step ${stepcount} of ${steps}: Upgrading settings to new version...")
-      println()
-      if (nomigrate) {
-        println("Not migrating settings. Skipping restore.")
-      } else {
-        if (updateSequence.size > 0)
-          restore(s"${current}/bin/restore", s"${current}/backup/settings/${updateSequence.last}", current)
-        else
-          restore(s"${current}/bin/restore", s"${current}/backup/settings/${installedVersion}", current)
-      }
-      println()
-      stepcount += 1
-
-      println(s"Step ${stepcount} of ${steps}: Running setup for new version...")
-      println()
-      s"${current}/bin/setup.sh".!
-      println()
-
-      println("Upgrade completed.")
-    }
-  }
-
-  private def backup(backupBin: String, backupDir: String, base: String) = {
-    val backupBinFile = new File(backupBin)
-    if (!backupBinFile.exists) {
-      println("Backup utility cannot be found. Possible causes:")
-      println("- PredictionIO version < 0.5.0")
-      println("- the binary is missing")
-      println()
-      println("To force upgrading without migrating settings, add --nomigrate to the command. Aborting.")
-      sys.exit(1)
-    } else {
-      if (Process(
-        s"${backupBin} ${backupDir}",
-        None,
-        ("JVM_OPT", s"-Dconfig.file=${base}/conf/predictionio.conf -Dio.prediction.base=${base}")).! != 0) {
-        println("Backup utility returned non-zero exit code. Aborting.")
-        sys.exit(1)
-      }
-    }
-  }
-
-  private def restore(restoreBin: String, restoreDir: String, base: String) = {
-    val restoreBinFile = new File(restoreBin)
-    if (!restoreBinFile.exists) {
-      println("Restore utility cannot be found. Possible causes:")
-      println("- PredictionIO version < 0.5.0")
-      println("- the binary is missing")
-      println()
-      println("To force upgrading without migrating settings, add --nomigrate to the command. Aborting.")
-      sys.exit(1)
-    } else {
-      if (Process(
-        s"${restoreBin} --upgrade ${restoreDir}",
-        None,
-        ("JVM_OPT", s"-Dconfig.file=${base}/conf/predictionio.conf -Dio.prediction.base=${base}")).! != 0) {
-        println("Restore utility returned non-zero exit code. Aborting.")
-        sys.exit(1)
-      }
-    }
-  }
-}
diff --git a/tools/softwaremanager/src/main/scala/io/prediction/tools/softwaremanager/Versions.scala b/tools/softwaremanager/src/main/scala/io/prediction/tools/softwaremanager/Versions.scala
deleted file mode 100644
index f6d5311..0000000
--- a/tools/softwaremanager/src/main/scala/io/prediction/tools/softwaremanager/Versions.scala
+++ /dev/null
@@ -1,87 +0,0 @@
-package io.prediction.tools.softwaremanager
-
-import scala.reflect.ClassTag
-import scala.util.parsing.json.JSON
-
-/** Extractors: http://stackoverflow.com/questions/4170949/how-to-parse-json-in-scala-using-standard-scala-classes */
-class CC[T: ClassTag] {
-  def unapply(a: Any)(implicit e: ClassTag[T]): Option[T] = {
-    try { Some(e.runtimeClass.cast(a).asInstanceOf[T]) } catch { case _: Throwable => None }
-  }
-}
-
-object M extends CC[Map[String, Any]]
-object MSS extends CC[Map[String, String]]
-object SS extends CC[Seq[String]]
-object OSS extends CC[Option[Seq[String]]]
-object S extends CC[String]
-object OS extends CC[Option[String]]
-
-class JSONParseException(message: String) extends Exception(message)
-class VersionsFormatException(message: String) extends Exception(message)
-
-class Versions(localVersion: Option[String]) {
-  private val versionsString = localVersion map { lv =>
-    scala.io.Source.fromFile(lv).mkString
-  } getOrElse {
-    scala.io.Source.fromURL(Versions.versionsUrl).mkString
-  }
-
-  private val versionsJson = JSON.parseFull(versionsString) getOrElse { throw new JSONParseException("Invalid JSON file.") }
-
-  private val meta = M.unapply(versionsJson) getOrElse { throw new JSONParseException("Root level is not a valid JSON object.") }
-
-  val latestVersion = S.unapply(meta("latest")) getOrElse { throw new VersionsFormatException("Cannot find the latest version.") }
-
-  private val versions = M.unapply(meta("versions")) getOrElse { throw new VersionsFormatException("Cannot find versions information.") }
-
-  private def versionToParts(version: String): Seq[Int] = version.split('.').map(_.toInt)
-
-  private def versionLessThan(x: String, y: String): Boolean = {
-    val versionX = versionToParts(x)
-    val versionY = versionToParts(y)
-
-    if (versionX(0) == versionY(0))
-      if (versionX(1) == versionY(1))
-        versionX(2) < versionY(2)
-      else
-        versionX(1) < versionY(1)
-    else
-      versionX(0) < versionY(0)
-  }
-
-  val sequence = versions.keys.toSeq.sortWith { (x, y) => versionLessThan(x, y) }
-
-  def version(version: String): Option[Map[String, String]] = versions.get(version) map { MSS.unapply(_) map { Some(_) } getOrElse None } getOrElse None
-
-  def binaries(ver: String): Option[String] = version(ver) map { _.get("binaries") map { Some(_) } getOrElse None } getOrElse None
-
-  def sources(ver: String): Option[String] = version(ver) map { _.get("sources") map { Some(_) } getOrElse None } getOrElse None
-
-  def updater(ver: String): Option[String] = version(ver) map { _.get("updater") map { Some(_) } getOrElse None } getOrElse None
-
-  def updateRequired(ver: String): Boolean = updater(ver) map { _ => true } getOrElse false
-
-  def updateSequence(fromVersion: String, toVersion: String): Seq[String] = {
-    val seqWithAllUpdates = sequence filter { updateRequired(_) }
-    val seqWithUpdatesUntilTo = seqWithAllUpdates filter { v =>
-      versionLessThan(v, toVersion) || v == toVersion
-    }
-    val seqWithUpdates = seqWithUpdatesUntilTo filterNot { v =>
-      versionLessThan(v, fromVersion) || v == fromVersion
-    }
-    seqWithUpdates.dropRight(1)
-  }
-}
-
-object Versions {
-  def apply() = {
-    new Versions(None)
-  }
-
-  def apply(localVersion: String) = {
-    new Versions(Some(localVersion))
-  }
-
-  val versionsUrl = "http://direct.prediction.io/versions.json"
-}
diff --git a/tools/softwaremanager/src/test/resources/versions.json b/tools/softwaremanager/src/test/resources/versions.json
deleted file mode 100644
index 2414e19..0000000
--- a/tools/softwaremanager/src/test/resources/versions.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
-    "latest": "0.5.0",
-    "versions": {
-        "0.5.0": {
-            "binaries": "http://download.prediction.io/PredictionIO-0.5.0.zip",
-            "sources": "http://download.prediction.io/PredictionIO-0.5.0-sources.zip",
-            "updater": "http://download.prediction.io/PredictionIO-0.5.0-updater.zip"
-        },
-        "0.5.1": {
-            "binaries": "http://download.prediction.io/PredictionIO-0.5.1.zip",
-            "sources": "http://download.prediction.io/PredictionIO-0.5.1-sources.zip"
-        },
-        "0.6.0": {
-            "binaries": "http://download.prediction.io/PredictionIO-0.6.0.zip",
-            "sources": "http://download.prediction.io/PredictionIO-0.6.0-sources.zip"
-        },
-        "0.6.1": {
-            "binaries": "http://download.prediction.io/PredictionIO-0.6.1.zip",
-            "sources": "http://download.prediction.io/PredictionIO-0.6.1-sources.zip",
-            "updater": "http://download.prediction.io/PredictionIO-0.6.1-updater.zip"
-        },
-        "0.6.2": {
-            "binaries": "http://download.prediction.io/PredictionIO-0.6.2.zip",
-            "sources": "http://download.prediction.io/PredictionIO-0.6.2-sources.zip"
-        },
-        "0.7.0": {
-            "binaries": "http://download.prediction.io/PredictionIO-0.7.0.zip",
-            "sources": "http://download.prediction.io/PredictionIO-0.7.0-sources.zip",
-            "updater": "http://download.prediction.io/PredictionIO-0.7.0-updater.zip"
-        },
-        "0.20.0": {
-            "binaries": "http://download.prediction.io/PredictionIO-0.20.0.zip",
-            "sources": "http://download.prediction.io/PredictionIO-0.20.0-sources.zip",
-            "updater": "http://download.prediction.io/PredictionIO-0.20.0-updater.zip"
-        },
-        "0.20.1": {
-            "binaries": "http://download.prediction.io/PredictionIO-0.20.1.zip",
-            "sources": "http://download.prediction.io/PredictionIO-0.20.1-sources.zip"
-        },
-        "1.0.0": {
-            "binaries": "http://download.prediction.io/PredictionIO-1.0.0.zip",
-            "sources": "http://download.prediction.io/PredictionIO-1.0.0-sources.zip",
-            "updater": "http://download.prediction.io/PredictionIO-1.0.0-updater.zip"
-        }
-    }
-}
diff --git a/tools/softwaremanager/src/test/scala/io/prediction/tools/softwaremanager/VersionsSpec.scala b/tools/softwaremanager/src/test/scala/io/prediction/tools/softwaremanager/VersionsSpec.scala
deleted file mode 100644
index 53ebe1b..0000000
--- a/tools/softwaremanager/src/test/scala/io/prediction/tools/softwaremanager/VersionsSpec.scala
+++ /dev/null
@@ -1,40 +0,0 @@
-package io.prediction.tools.softwaremanager
-
-import org.specs2._
-import org.specs2.specification.Step
-
-class VersionsSpec extends Specification {
-  def is =
-    "PredictionIO Software Manager Versions Specification" ^
-      p ^
-      "load version file" ! load() ^
-      "get latest version" ! latestVersion() ^
-      "get latest version binaries" ! latestBinaries() ^
-      "get latest version sources" ! latestSources() ^
-      "get a non-existent updater" ! latestUpdater() ^
-      "get version sequence" ! sequence() ^
-      "get a version that requires update" ! updateRequired() ^
-      "get an update sequence" ! updateSequence() ^
-      end
-
-  lazy val versions = Versions(getClass.getResource("/versions.json").getPath)
-
-  def load() = versions must beAnInstanceOf[Versions]
-
-  def latestVersion() = versions.latestVersion must_== "0.5.0"
-
-  def latestBinaries() = versions.binaries(versions.latestVersion) must beSome("http://download.prediction.io/PredictionIO-0.5.0.zip")
-
-  def latestSources() = versions.sources(versions.latestVersion) must beSome("http://download.prediction.io/PredictionIO-0.5.0-sources.zip")
-
-  def latestUpdater() = versions.updater("0.5.1") must beNone
-
-  def sequence() = versions.sequence must_== Seq("0.5.0", "0.5.1", "0.6.0", "0.6.1", "0.6.2", "0.7.0", "0.20.0", "0.20.1", "1.0.0")
-
-  def updateRequired() = versions.updateRequired("0.6.1") must_== true
-
-  def updateSequence() = {
-    (versions.updateSequence("0.5.0", "0.20.1") must_== Seq("0.6.1", "0.7.0")) and
-      (versions.updateSequence("0.6.0", "1.0.0") must_== Seq("0.6.1", "0.7.0", "0.20.0"))
-  }
-}
diff --git a/tools/users/.gitignore b/tools/users/.gitignore
deleted file mode 100644
index 27722ba..0000000
--- a/tools/users/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-project/project/
-project/target/
-target/
diff --git a/tools/users/build.sbt b/tools/users/build.sbt
deleted file mode 100644
index 8183f4a..0000000
--- a/tools/users/build.sbt
+++ /dev/null
@@ -1,23 +0,0 @@
-import xerial.sbt.Pack._
-
-name := "users"
-
-scalariformSettings
-
-libraryDependencies ++= Seq(
-  "commons-codec" % "commons-codec" % "1.8",
-  "jline" % "jline" % "2.9",
-  "org.slf4j" % "slf4j-nop" % "1.6.0"
-)
-
-packSettings
-
-packJarNameConvention := "full"
-
-packExpandedClasspath := true
-
-packGenerateWindowsBatFile := false
-
-packMain := Map("users" -> "io.prediction.tools.users.Users")
-
-packJvmOpts := Map("users" -> Common.packCommonJvmOpts)
diff --git a/tools/users/src/main/resources/application.conf b/tools/users/src/main/resources/application.conf
deleted file mode 100644
index d6f0db9..0000000
--- a/tools/users/src/main/resources/application.conf
+++ /dev/null
@@ -1,30 +0,0 @@
-# Used by PredictionIO Commons
-io.prediction.base=../..
-
-io.prediction.commons.appdata.db.type=mongodb
-io.prediction.commons.appdata.db.host=localhost
-io.prediction.commons.appdata.db.port=27017
-
-io.prediction.commons.appdata.test.db.type=mongodb
-io.prediction.commons.appdata.test.db.host=localhost
-io.prediction.commons.appdata.test.db.port=27017
-
-io.prediction.commons.appdata.training.db.type=mongodb
-io.prediction.commons.appdata.training.db.host=localhost
-io.prediction.commons.appdata.training.db.port=27017
-
-io.prediction.commons.appdata.validation.db.type=mongodb
-io.prediction.commons.appdata.validation.db.host=localhost
-io.prediction.commons.appdata.validation.db.port=27017
-
-io.prediction.commons.modeldata.db.type=mongodb
-io.prediction.commons.modeldata.db.host=localhost
-io.prediction.commons.modeldata.db.port=27017
-
-io.prediction.commons.modeldata.training.db.type=mongodb
-io.prediction.commons.modeldata.training.db.host=localhost
-io.prediction.commons.modeldata.training.db.port=27017
-
-io.prediction.commons.settings.db.type=mongodb
-io.prediction.commons.settings.db.host=localhost
-io.prediction.commons.settings.db.port=27017
diff --git a/tools/users/src/main/scala/io/prediction/tools/users/Users.scala b/tools/users/src/main/scala/io/prediction/tools/users/Users.scala
deleted file mode 100644
index 751d24a..0000000
--- a/tools/users/src/main/scala/io/prediction/tools/users/Users.scala
+++ /dev/null
@@ -1,116 +0,0 @@
-package io.prediction.tools.users
-
-import io.prediction.commons._
-import jline.console._
-import org.apache.commons.codec.digest.DigestUtils
-import util.control.Breaks._
-
-object Users {
-  val config = new Config()
-  val users = config.getSettingsUsers()
-
-  private def md5password(password: String) = DigestUtils.md5Hex(password)
-
-  def main(args: Array[String]) {
-    if (!config.settingsDbConnectable()) {
-      println(s"Cannot connect to ${config.settingsDbType}://${config.settingsDbHost}:${config.settingsDbPort}/${config.settingsDbName}. Aborting.")
-      sys.exit(1)
-    }
-    println()
-    println("PredictionIO CLI User Management")
-    println()
-    println("1 - Add a new user")
-    println("2 - Update email of an existing user")
-    println("3 - Change password of an existing user")
-    val choice = readLine("Please enter a choice (1-3): ")
-    choice match {
-      case "1" => adduser()
-      case "2" => updateEmail()
-      case "3" => changePassword()
-      case _ => println("Unknown choice")
-    }
-    println()
-  }
-
-  def adduser() = {
-    val cr = new ConsoleReader()
-    println("Adding a new user")
-    val email = cr.readLine("Email: ")
-
-    if (users.emailExists(email)) {
-      println("Email already exists. Not adding.")
-    } else {
-
-      var password = ""
-      var retyped = ""
-      breakable {
-        while (true) {
-          password = cr.readLine("Password: ", new java.lang.Character('*'));
-          retyped = cr.readLine("Retype password: ", new java.lang.Character('*'));
-          if (password == retyped)
-            break
-          println("Passwords do not match. Please enter again.")
-        }
-      }
-
-      val firstName = cr.readLine("First name: ")
-      val lastName = cr.readLine("Last name: ")
-
-      users.insert(
-        email = email,
-        password = md5password(password),
-        firstname = firstName,
-        lastname = lastName match {
-          case "" => None
-          case _ => Some(lastName)
-        },
-        confirm = email
-      )
-      users.confirm(email)
-      println("User added")
-    }
-  }
-
-  def updateEmail() = {
-    val cr = new ConsoleReader()
-    println("Updating email of an existing user")
-    val email = cr.readLine("Current email: ")
-    val password = cr.readLine("Password: ", new java.lang.Character('*'));
-    users.authenticateByEmail(email, md5password(password)) map { id: Int =>
-      val newEmail = cr.readLine("New email: ")
-      if (users.emailExists(newEmail)) {
-        println("New email already exists. Not updating.")
-      } else {
-        users.updateEmail(id, newEmail)
-        println("Email updated.")
-      }
-    } getOrElse {
-      println("Invalid email or password. Please try again.")
-    }
-  }
-
-  def changePassword() = {
-    val cr = new ConsoleReader()
-    println("Changing password of an existing user")
-    val email = cr.readLine("Email: ")
-    val password = cr.readLine("Old password: ", new java.lang.Character('*'));
-    users.authenticateByEmail(email, md5password(password)) map { id: Int =>
-      var newPassword = ""
-      var retyped = ""
-      breakable {
-        while (true) {
-          newPassword = cr.readLine("New password: ", new java.lang.Character('*'));
-          retyped = cr.readLine("Retype new password: ", new java.lang.Character('*'));
-          if (newPassword == retyped)
-            break
-          println("New passwords do not match. Please enter again.")
-        }
-      }
-      users.updatePassword(id, md5password(newPassword))
-      println("Password updated.")
-    } getOrElse {
-      println("Invalid email or password. Please try again.")
-    }
-  }
-
-}