text:
package android

import com.android.builder.internal.ClassFieldImpl
import com.android.ide.common.signing.KeystoreHelper
import com.android.manifmerger.ManifestMerger2
import sbt._
import sbt.Keys._
import sbt.classpath.ClasspathUtilities

import scala.collection.JavaConverters._
import scala.util.Try
import scala.xml._
import language.postfixOps

import java.util.Properties
import java.io.File

import com.android.SdkConstants
import com.android.builder.signing.DefaultSigningConfig
import com.android.builder.core._
import com.android.ddmlib.{IDevice, DdmPreferences}
import com.android.ddmlib.testrunner.ITestRunListener
import com.android.sdklib.IAndroidTarget
import com.android.sdklib.BuildToolInfo.PathId
import com.android.sdklib.build.RenderScriptProcessor
import com.android.sdklib.build.RenderScriptProcessor.CommandLineLauncher

import Keys._
import Keys.Internal._
import Dependencies.{LibraryProject => _, AutoLibraryProject => _, _}
import com.android.builder.compiling.{ResValueGenerator, BuildConfigGenerator}
import java.net.URLEncoder

object Tasks {
  val ANDROID_NS = "http://schemas.android.com/apk/res/android"
  val TOOLS_NS = "http://schemas.android.com/tools"
  val INSTRUMENTATION_TAG = "instrumentation"
  val USES_LIBRARY_TAG = "uses-library"
  val APPLICATION_TAG = "application"
  val ANDROID_PREFIX = "android"
  val TEST_RUNNER_LIB = "android.test.runner"

  val reservedWords = Set(
    "def",
    "forSome",
    "implicit",
    "lazy",
    "match",
    "object",
    "override",
    "sealed",
    "trait",
    "type",
    "val",
    "var",
    "with",
    "yield"
  )

  def resourceUrl =
    Plugin.getClass.getClassLoader.getResource _

  val resValuesGeneratorTaskDef = Def.task {
    val resources = resValues.value
    val items = resources map { case (typ, n, value) =>
      new ClassFieldImpl(typ, n, value)
    }
    val resTarget = projectLayout.value.bin / "resources" / "res"
    val generator = new ResValueGenerator(resTarget)
    generator.addItems((items: Seq[Object]).asJava)
    generator.generate()
  }

  val buildConfigGeneratorTaskDef = ( platformTarget
                                    , genPath
                                    , libraryProjects
                                    , packageForR
                                    , buildConfigOptions
                                    , apkbuildDebug
                                    ) map {
    (t, g, l, p, o, d) =>
    val b = new BuildConfigGenerator(g, p)
    b.addField("boolean", "DEBUG", d.toString)
    o foreach {
      case (tpe, n, value) => b.addField(tpe, n, value)
    }
    b.generate()
    l collect {
      case a: ApkLibrary         => a
      case a: AutoLibraryProject => a
    } foreach { lib =>
      val b = new BuildConfigGenerator(g, lib.pkg)
      b.addField("boolean", "DEBUG", d.toString)
      o foreach {
        case (tpe, n, value) => b.addField(tpe, n, value)
      }
      b.generate()
    }
    g ** "BuildConfig.java" get
  }

  def moduleForFile(u: UpdateReport, f: File): ModuleID = {
    val map: Map[File,ModuleID] =
      u.configurations.flatMap(_.modules).distinct.flatMap { m =>
        m.artifacts map { case (_,file) => (file,m.module) }
      } toMap

    map(f)
  }
  // takeWhile hack to bypass cross versions, I hope no real artifacts have
  // underscores in the name as a delimiter
  def moduleString(m: ModuleID) =
    m.organization + ":" + m.name.takeWhile(_ != '_')

  val aarsTaskDef = ( update in Compile
                    , localAars
                    , libraryDependencies in Compile
                    , transitiveAndroidLibs
                    , transitiveAndroidWarning
                    , localProjects
                    , thisProjectRef
                    , state
                    , buildStructure
                    , target
                    , streams
                    ) map {
    (u,local,d,tx,tw,lp,ref, st, struct, t,s) =>

    def collectSubAar(ps: Seq[ProjectRef]): Seq[AarLibrary] = ps flatMap { p =>
      val aarlibs = Project.runTask(libraryProjects in(p, Android), st).collect {
        case (_, Value(value)) => value
      }.fold(Seq.empty[AarLibrary])(_ collect {
        case a: AarLibrary => a
      })
      val sub = Project.getProject(p, struct)
      aarlibs ++ sub.fold(Seq.empty[AarLibrary])(s => collectSubAar(s.dependencies.map(_.project)))
    }
    val subaars = collectSubAar(
      Project.getProject(ref, struct).fold(
        Seq.empty[ProjectRef])(_.dependencies map (_.project))).map (m =>
      moduleString(m.moduleID)).toSet
    s.log.debug("dependencies: " + Project.getProject(ref, struct).map(_.dependencies))
    s.log.debug("aars in subprojects: " + subaars)
    val libs = u.matching(artifactFilter(`type` = "aar"))
    val dest = t / "aars"

    val deps = d.filterNot(_.configurations.exists(
      _ contains "test")).map(moduleString).toSet
    (libs flatMap { l =>
      val m = moduleForFile(u, l)
      if (tx || deps(moduleString(m))) {
        val d = dest / (m.organization + "-" + m.name + "-" + m.revision)
        if (!subaars(moduleString(m)))
          Some(unpackAar(l, d, m, s.log): LibraryDependency)
        else {
          s.log.debug(m + " was already included by a dependent project, skipping")
          None
        }
      } else {
        if (tw)
          s.log.warn(m + " is not an explicit dependency, skipping")
        None
      }
    }) ++ (local map { a =>
      unpackAar(a, dest / ("localAAR-" + a.getName), "localAAR" % a.getName % "LOCAL", s.log)
    })
  }

  def unpackAar(aar: File, dest: File, m: ModuleID, log: Logger): LibraryDependency = {
    val lib = AarLibrary(dest)
    if (dest.lastModified < aar.lastModified || !lib.getManifest.exists) {
      IO.delete(dest)
      val mfile = Dependencies.moduleIdFile(dest)
      val mline = s"${m.organization}:${m.name}:${m.revision}"
      IO.writeLines(mfile, mline :: Nil)
      log.info("Unpacking aar: %s to %s" format (aar.getName, dest.getName))
      dest.mkdirs()
      IO.unzip(aar, dest)
    }
    // rename for sbt-idea when using multiple aar packages
    val renamedJar = lib.getJarFile.getParentFile / (dest.getName + ".jar")
    if (lib.getJarFile.exists) {
      lib.getJarFile.renameTo(renamedJar)
    }
    new AarLibrary(dest) {
      override def getJarFile = renamedJar
    }
  }

  val autolibsTaskDef = ( localProjects
                        , genPath
                        , libraryProject
                        , builder
                        , ilogger
                        , apkbuildDebug
                        , streams ) map {
   (prjs,gen,isLib,bldr,logger,debug,s) =>
     prjs collect { case a: AutoLibraryProject => a } flatMap { lib =>
      s.log.info("Processing library project: " + lib.pkg)

      lib.getProguardRules.getParentFile.mkdirs
      // TODO collect resources from apklibs and aars
//      doCollectResources(bldr, true, true, Seq.empty, lib.layout,
//        logger, file("/"), s)
      Resources.aapt(bldr, lib.getManifest, null, Seq.empty, true, debug(),
          lib.getResFolder, lib.getAssetsFolder, null,
          lib.layout.gen, lib.getProguardRules.getAbsolutePath,
          s.log)

      def copyDirectory(src: File, dst: File) {
        IO.copy(((src ***) --- (src ** "R.txt")) pair Path.rebase(src, dst),
          false, true)
      }
      if (isLib)
        copyDirectory(lib.layout.gen, gen)
      Some(lib: LibraryDependency)
    }
  }

  val apklibsTaskDef = ( update in Compile
                       , libraryDependencies in Compile
                       , genPath
                       , libraryProject
                       , transitiveAndroidLibs
                       , target
                       , streams
                       , builder
                       , apkbuildDebug
                       , streams
                       ) map {
    (u,d,gen,isLib,tx,t,s,bldr,debug,st) =>
    val libs = u.matching(artifactFilter(`type` = "apklib"))
    val dest = t / "apklibs"
    val deps = d.filterNot(_.configurations.exists(
      _ contains "test")).map(moduleString).toSet
    libs flatMap { l =>
      val m = moduleForFile(u, l)
      if (tx || deps(moduleString(m))) {
        val d = dest / (m.organization + "-" + m.name + "-" + m.revision)
        val lib = ApkLibrary(d)
        if (d.lastModified < l.lastModified || !lib.getManifest.exists) {
          s.log.info("Unpacking apklib: " + m)
          d.mkdirs()
          IO.unzip(l, d)

          Resources.aapt(bldr, lib.getManifest, null, Seq.empty, true, debug(),
              lib.getResFolder, lib.getAssetsFolder, null,
              lib.layout.gen, lib.getProguardRules.getAbsolutePath,
              st.log)

        }
        def copyDirectory(src: File, dst: File) {
          IO.copy(((src ***) --- (src ** "R.txt")) pair Path.rebase(src, dst),
            false, true)
        }
        if (isLib)
          copyDirectory(lib.layout.gen, gen)
        Some(lib: LibraryDependency)
      } else {
        s.log.warn(m + " is not an explicit dependency, skipping")
        None
      }
    }
  }

  val typedResourcesGeneratorTaskDef = ( typedResources
                                       , rGenerator
                                       , packageForR
                                       , projectLayout
                                       , platformJars
                                       , scalaVersion in ThisProject
                                       , libraryProjects
                                       , typedResourcesIgnores
                                       , streams
                                       ) map {
    case (t, a, p, layout, (j, x), sv, l, i, s) =>

    val r = layout.res
    val g = layout.gen
    val ignores = i.toSet

    val tr = p.split("\\.").foldLeft (g) { _ / _ } / "TR.scala"

    if (!t)
      Seq.empty[File]
    else
      FileFunction.cached(s.cacheDirectory / "typed-resources-generator",
          FilesInfo.hash, FilesInfo.hash) { in =>
        if (in.nonEmpty) {
          s.log.info("Regenerating TR.scala because R.java has changed")
          val androidjar = ClasspathUtilities.toLoader(file(j))
          val layouts = (r ** "layout*" ** "*.xml" get) ++
            (for {
              lib <- l filterNot {
                case p: Pkg => ignores(p.pkg)
                case _      => false
              }
              xml <- lib.getResFolder ** "layout*" ** "*.xml" get
            } yield xml)

          s.log.debug("Layouts: " + layouts)
          // XXX handle package references? @id/android:ID or @id:android/ID
          val re = "@\\+id/(.*)".r

          def classForLabel(l: String) = {
            if (l contains ".") Some(l)
            else {
              Seq("android.widget."
                , "android.view."
                , "android.webkit.").flatMap {
                pkg => Try(androidjar.loadClass(pkg + l).getName).toOption
              }.headOption
            }
          }

          def warn(res: Seq[(String,String)]) = {
            // nice to have:
            //   merge to a common ancestor, this is possible for androidJar
            //   but to do so is perilous/impossible for project code...
            // instead:
            //   reduce to ViewGroup for *Layout, and View for everything else
            val overrides = res.groupBy(r => r._1) filter (
              _._2.toSet.size > 1) collect {
              case (k,v) =>
                s.log.warn("%s was reassigned: %s" format (k,
                  v map (_._2) mkString " => "))
                k -> (if (v endsWith "Layout")
                  "android.view.ViewGroup" else "android.view.View")
            }

            (res ++ overrides).toMap
          }
          val layoutTypes = warn(for {
            file   <- layouts
            layout  = XML loadFile file
            l      <- classForLabel(layout.label)
          } yield file.getName.stripSuffix(".xml") -> l)

          val resources = warn(for {
            b      <- layouts
            layout  = XML loadFile b
            n      <- layout.descendant_or_self
            re(id) <- n.attribute(ANDROID_NS, "id") map { _.head.text }
            l      <- classForLabel(n.label)
          } yield id -> l)

          val trTemplate = IO.readLinesURL(
            resourceUrl("tr.scala.template")) mkString "\n"

          tr.delete()
          def wrap(s: String) = if (reservedWords(s)) "`%s`" format s else s
          IO.write(tr, trTemplate format (p,
            resources map { case (k,v) =>
              "  val %s = TypedResource[%s](R.id.%s)" format (wrap(k),v,wrap(k))
            } mkString "\n",
            layoutTypes map { case (k,v) =>
              "    val %s = TypedLayout[%s](R.layout.%s)" format (wrap(k),v,wrap(k))
            } mkString "\n"))
          Set(tr)
        } else Set.empty
      }(a.toSet).toSeq
  }

  def ndkbuild(layout: ProjectLayout,
               ndkHome: Option[String], srcs: File, log: Logger, debug: Boolean) = {
    val hasJni = (layout.jni ** "Android.mk" get).nonEmpty
    if (hasJni) {
      if (ndkHome.isEmpty) {
        log.warn(
          "Android.mk found, but neither ndk.dir nor ANDROID_NDK_HOME are set")
      }
      ndkHome flatMap { ndk =>
        val env = Seq("NDK_PROJECT_PATH" -> (layout.jni / "..").getAbsolutePath,
          "NDK_OUT" -> (layout.bin / "obj").getAbsolutePath,
          "NDK_LIBS_OUT" -> (layout.bin / "jni").getAbsolutePath,
          "SBT_SOURCE_MANAGED" -> srcs.getAbsolutePath)

        log.info("Executing NDK build")
        val ndkbuildFile = if (!Commands.isWindows) file(ndk) / "ndk-build" else  {
          val f = file(ndk) / "ndk-build.cmd"
          if (f.exists) f else file(ndk) / "ndk-build.bat"
        }
        val ndkBuildInvocation = Seq(
          ndkbuildFile.getAbsolutePath,
          if (debug) "NDK_DEBUG=1" else "NDK_DEBUG=0"
        )

        val rc = Process(ndkBuildInvocation, layout.base, env: _*) !

        if (rc != 0)
          Plugin.fail("ndk-build failed!")

        Option(layout.bin / "jni")
      }
    } else None
  }

  val ndkJavahTaskDef = ( sourceManaged in Compile
                        , compile in Compile
                        , classDirectory in Compile
                        , fullClasspath in Compile
                        , builder
                        , streams
                        ) map { (src, c, classes, cp, bldr, s) =>
    val natives = NativeFinder(classes)

    if (natives.nonEmpty) {
      val javah = Seq("javah",
        "-d", src.getAbsolutePath,
        "-classpath", cp map (_.data.getAbsolutePath) mkString File.pathSeparator,
        "-bootclasspath", bldr.getBootClasspath.asScala mkString File.pathSeparator) ++ natives

      s.log.debug(javah mkString " ")

      val rc = javah !

      if (rc != 0)
        Plugin.fail("Failed to execute: " + (javah mkString " "))

      src ** "*.h" get
    } else Seq.empty
  }
  val ndkBuildTaskDef = ( projectLayout
                        , libraryProjects
                        , sourceManaged in Compile
                        , ndkJavah
                        , ndkPath
                        , properties
                        , streams
                        , apkbuildDebug
                        ) map { (layout, libs, srcs, h, ndkHome, p, s, debug) =>

    val subndk = libs flatMap { l =>
      ndkbuild(l.layout, ndkHome, srcs, s.log, debug()).toSeq
    }

    ndkbuild(layout, ndkHome, srcs, s.log, debug()).toSeq ++ subndk
  }

  val collectProjectJniTaskDef = Def.task {
    ndkBuild.value ++ Seq(projectLayout.value.jniLibs, rsBinPath.value / "lib").filter(_.isDirectory)
  }

  val collectJniTaskDef = Def.task {
    def libJni(lib: LibraryDependency): Seq[File] =
      Seq(lib.getJniFolder).filter(_.isDirectory) ++
        lib.getDependencies.asScala.flatMap(l => libJni(l.asInstanceOf[LibraryDependency]))

    collectProjectJni.value ++ libraryProjects.value.flatMap(libJni)
  }

  val collectResourcesTaskDef = ( builder
                                , debugIncludesTests
                                , libraryProject
                                , libraryProjects
                                , extraResDirectories
                                , projectLayout
                                , ilogger
                                , streams
                                ) map {
    (bldr, noTestApk, isLib, libs, er, layout, logger, s) =>
      Resources.doCollectResources(bldr, noTestApk, isLib, libs, layout, er, logger, s.cacheDirectory, s)
  }

  val packageApklibMappings = Def.task {
    val layout = projectLayout.value
    import layout._

    (PathFinder(manifest)                 pair flat) ++
    (PathFinder(javaSource) ** "*.java"   pair rebase(javaSource,  "src"))  ++
    (PathFinder(scalaSource) ** "*.scala" pair rebase(scalaSource, "src"))  ++
    ((PathFinder(libs) ***)               pair rebase(libs,        "libs")) ++
    ((PathFinder(res) ***)                pair rebase(res,         "res"))  ++
    ((PathFinder(assets) ***)             pair rebase(assets,      "assets"))
  }
  val packageApklibTaskDef = Def.task {
    val outfile = projectLayout.value.bin / (name.value + ".apklib")
    streams.value.log.info("Packaging " + outfile.getName)
    val mapping = (mappings in packageApklib).value
    IO.jar(mapping, outfile, new java.util.jar.Manifest)
    outfile
  }

  val packageAarMappings = Def.task {
    val layout = projectLayout.value
    import layout._

    val so = collectProjectJni.value
    val j = (packageT in Compile).value
    val rs = rsBinPath.value
    val rsLibs = rs / "lib"
    val rsRes = bin / "renderscript" / "res"

    (PathFinder(manifest)             pair flat) ++
    (PathFinder(gen / "R.txt")        pair flat) ++
    (PathFinder(bin / "proguard.txt") pair flat) ++
    (PathFinder(j)                    pair flat) ++
    ((PathFinder(libs) ** "*.jar")    pair rebase(libs,   "libs")) ++
    ((PathFinder(rsLibs) * "*.jar")   pair rebase(rsLibs, "libs")) ++
    ((PathFinder(res) ***)            pair rebase(res,    "res"))  ++
    ((PathFinder(rsRes) ***)          pair rebase(rsRes,  "res"))  ++
    ((PathFinder(assets) ***)         pair rebase(assets, "assets")) ++
    so.flatMap { d => (PathFinder(d) ** "*.so") pair rebase(d, "jni") }
  }

  val packageAarTaskDef = Def.task {
    val outfile = projectLayout.value.bin / (name.value + ".aar")
    val mapping = (mappings in packageAar).value
    streams.value.log.info("Packaging " + outfile.getName)

    IO.jar(mapping, outfile, new java.util.jar.Manifest)
    outfile
  }

  val packageResourcesTaskDef = ( builder
                                , projectLayout
                                , processManifest
                                , collectResources
                                , packageForR
                                , libraryProject
                                , libraryProjects
                                , apkbuildDebug
                                , streams
                                ) map {
    case (bldr, layout, manif, (assets, res), pkg, lib, libs, debug, s) =>
    val cache = s.cacheDirectory
    val proguardTxt = (layout.bin / "proguard.txt").getAbsolutePath

    val rel = if (debug()) "-debug" else "-release"
    val basename = "resources" + rel + ".ap_"
    val p = layout.bin / basename

    val inputs = (res ***).get ++ (assets ***).get ++
      Seq(manif)filter (
        n => !n.getName.startsWith(".") && !n.getName.startsWith("_"))

    FileFunction.cached(cache / basename, FilesInfo.hash) { _ =>
      s.log.info("Packaging resources: " + p.getName)
      Resources.aapt(bldr, manif, pkg, libs, lib, debug(), res, assets,
        p.getAbsolutePath, layout.gen, proguardTxt, s.log)
      Set(p)
    }(inputs.toSet)
    p
  }

  val apkbuildAggregateTaskDef = Def.task {
    Aggregate.Apkbuild(packagingOptions.value,
      apkbuildDebug.value(), dex.value, predex.value,
      collectJni.value, resourceShrinker.value)
  }

  val apkbuildTaskDef = ( apkbuildAggregate
                        , name
                        , builder
                        , projectLayout
                        , libraryProject
                        , ilogger
                        , unmanagedJars in Compile
                        , managedClasspath
                        , dependencyClasspath in Compile
                        , streams
                        ) map {
    (a, n, bldr, layout, isLib, logger, u, m, dcp, s) =>

    if (isLib)
      Plugin.fail("This project cannot build APK, it has set 'libraryProject in Android := true'")
    val options = a.packagingOptions
    val r = a.resourceShrinker
    val d = a.dex
    val pd = a.predex
    val jni = a.collectJni
    val debug = a.apkbuildDebug
    val cacheDir = s.cacheDirectory
    val predexed = pd flatMap (_._2 * "*.dex" get)

    val jars = (m ++ u ++ dcp).filter {
      a => (a.get(moduleID.key) map { mid =>
        mid.organization != "org.scala-lang" &&
          !(mid.configurations exists (_ contains "provided"))
      } getOrElse true) && a.data.exists
    }.groupBy(_.data.getName).collect {
      case ("classes.jar",xs) => xs.distinct
      case (_,xs) if xs.head.data.isFile => xs.head :: Nil
    }.flatten.map (_.data).toList

    // workaround for https://code.google.com/p/android/issues/detail?id=73437
    val collectedJni = layout.bin / "collect-jni"
    if (jni.nonEmpty) {
      collectedJni.mkdirs()
      val copyList = for {
        j <- jni
        l <- (j ** "*.so").get ++ (j ** "gdbserver").get ++ (j ** "gdb.setup").get
      } yield (l, collectedJni / (l relativeTo j).get.getPath)

      IO.copy(copyList)
    } else {
      IO.delete(collectedJni)
    }
    val jniInputs = (collectedJni ** new SimpleFileFilter(_.isFile)).get
    // end workaround

    s.log.debug("jars to process for resources: " + jars)

    val debugConfig = new DefaultSigningConfig("debug")
    debugConfig.initDebug()
    if (!debugConfig.getStoreFile.exists) {
      KeystoreHelper.createDebugStore(null, debugConfig.getStoreFile,
        debugConfig.getStorePassword, debugConfig.getKeyPassword,
        debugConfig.getKeyAlias, logger(s.log))
    }

    val rel = if (debug) "-debug-unaligned.apk"
      else "-release-unsigned.apk"
    val pkg = n + rel
    val output = layout.bin / pkg

    // filtering out org.scala-lang above should not cause an issue
    // they should not be changing on us anyway
    val deps = Set(r +: ((d * "*.dex" get) ++ jars ++ jniInputs):_*)

    FileFunction.cached(cacheDir / pkg, FilesInfo.hash) { in =>
      s.log.debug("bldr.packageApk(%s, %s, %s, null, %s, %s, %s, %s, %s)" format (
        r.getAbsolutePath, d.getAbsolutePath, jars,
          if (collectedJni.exists) Seq(collectedJni).asJava else Seq.empty.asJava, debug,
          if (debug) debugConfig else null, output.getAbsolutePath,
          options
      ))
      bldr.packageApk(r.getAbsolutePath, d, predexed.asJava, jars.asJava,
        layout.resources.getAbsolutePath,
        (if (collectedJni.exists) Seq(collectedJni) else Seq.empty).asJava,
        s.cacheDirectory / "apkbuild-merging", null, debug,
        if (debug) debugConfig else null, options.asAndroid, output.getAbsolutePath)
      s.log.debug("Including predexed: " + predexed)
      s.log.info("Packaged: %s (%s)" format (
        output.getName, sizeString(output.length)))
      Set(output)
    }(deps)

    output
  }

  val signReleaseTaskDef = (apkSigningConfig, apkbuild, apkbuildDebug, streams) map {
    (c, a, d, s) =>
    val bin = a.getParentFile
    if (d()) {
      s.log.info("Debug package does not need signing: " + a.getName)
      a
    } else {
      c map { cfg =>
        import SignJar._
        val signed = bin / a.getName.replace("-unsigned", "-unaligned")
        val options = Seq( storeType(cfg.storeType)
          , storePassword(cfg.storePass)
          , signedJar(signed)
          , keyStore(cfg.keystore.toURI.toURL)
        )

        val kp = cfg.keyPass map { p => keyPassword(p) }
        sign(a, cfg.alias, options ++ kp) { (jarsigner, args) =>
          (jarsigner +: (args ++ Seq(
            "-digestalg", "SHA1", "-sigalg", "MD5withRSA"))) !
        }

        s.log.info("Signed: " + signed.getName)
        signed
      } getOrElse {
        s.log.warn("Package needs signing: " + a.getName)
        a
      }
    }
  }

  val zipalignTaskDef = (zipalignPath, signRelease, apkFile, streams) map {
    (z, r, a, s) =>
    if (r.getName.contains("-unsigned")) {
      s.log.warn("Package needs signing and zipaligning: " + r.getName)
      a.delete()
      r
    } else {
      val bin = r.getParentFile
      val aligned = bin / r.getName.replace("-unaligned", "")

      val rv = Seq(z, "-f", "4", r.getAbsolutePath, aligned.getAbsolutePath) !

      if (rv != 0) {
        Plugin.fail("zipalign failed")
      }

      s.log.info("zipaligned: " + aligned.getName)
      IO.copyFile(aligned, a)
      aligned
    }
  }

  val renderscriptTaskDef = Def.task {
    val layout = projectLayout.value
    val scripts = (layout.renderscript ** "*.rs").get
    val target = Try(rsTargetApi.value.toInt).getOrElse(11) max 11
    val rsOutput = rsBinPath.value

    val processor = new RenderScriptProcessor(
      scripts.asJava,
      List.empty.asJava,
      binPath.value,
      genPath.value,
      rsOutput / "res",
      rsOutput / "obj",
      rsOutput / "lib",
      buildTools.value,
      target,
      false, // debug flag -g, not used
      rsOptimLevel.value,
      rsSupportMode.value)

    processor.build(new CommandLineLauncher {
      override def launch(executable: sbt.File, arguments: java.util.List[String],
                          envVariableMap: java.util.Map[String, String]): Unit = {

        val cmd = executable.getAbsolutePath +: arguments.asScala
        streams.value.log.debug(s"renderscript command: $cmd, env: ${envVariableMap.asScala.toSeq}")

        val r = Process(cmd, None, envVariableMap.asScala.toSeq: _*).!
        if (r != 0)
          Plugin.fail("renderscript failed: " + r)
      }
    })

    if (rsSupportMode.value) { // copy support library
      val in = buildTools.value.getLocation / "renderscript" / "lib"
      val out = rsOutput / "lib"
      IO.copy(
        (in * "*.jar" pair rebase(in, out)) ++
        (in / "packaged" ** "*.so" pair rebase(in / "packaged", out))
      )
    }

    val JavaSource = """\s*(\S+\.java).*""".r
    (binPath.value / "rsDeps" ** "*.d").get
      .flatMap(IO.readLines(_))
      .collect { case JavaSource(path) => new File(path) }
  }

  val aidlTaskDef = ( sdkPath
                    , sdkManager
                    , projectLayout
                    , platform
                    , streams
                    ) map { (s, m, layout, p, l) =>
    import SdkConstants._
    val tools = Option(m.getLatestBuildTool)
    val aidl          = tools map (_.getPath(PathId.AIDL)) getOrElse {
        s + OS_SDK_PLATFORM_TOOLS_FOLDER + FN_AIDL
    }
    val frameworkAidl = p.getPath(IAndroidTarget.ANDROID_AIDL)
    val aidls = layout.aidl ** "*.aidl" get

    aidls flatMap { idl =>
      val out = layout.gen ** (idl.getName.stripSuffix(".aidl") + ".java") get
      val cmd = Seq(aidl,
        "-p" + frameworkAidl,
        "-o" + layout.gen.getAbsolutePath,
        "-a",
        "-I" + layout.aidl.getAbsolutePath
        ) :+ idl.getAbsolutePath

      // TODO FIXME this doesn't account for other dependencies
      if (out.isEmpty || (out exists { idl.lastModified > _.lastModified })) {
        val r = cmd !

        if (r != 0)
          Plugin.fail("aidl failed")

        layout.gen ** (idl.getName.stripSuffix(".aidl") + ".java") get
      } else out
    }
  }

  val processManifestTaskDef = ( builder
                               , libraryProject
                               , libraryProjects
                               , manifestAggregate
                               , mergeManifests
                               , instrumentTestRunner
                               , projectLayout
                               , debugIncludesTests
                               ) map {
    (bldr, isLib, libs, a, merge, trunner, layout, noTestApk) =>
    val pkg = a.applicationId
    val ph = a.placeholders
    val vc = a.versionCode
    val vn = a.versionName
    val sdk = a.targetSdkVersion
    val minSdk = a.minSdkVersion

    layout.bin.mkdirs()
    val output = layout.bin / "AndroidManifest.xml"
    if (isLib)
      layout.manifest
    else {
      bldr.mergeManifests(layout.manifest, Seq.empty.asJava,
        if (merge) libs.asJava else Seq.empty.asJava,
        pkg, vc getOrElse -1, vn orNull, minSdk.toString, sdk.toString, null,
        output.getAbsolutePath, null,
        if (isLib) ManifestMerger2.MergeType.LIBRARY else
          ManifestMerger2.MergeType.APPLICATION, ph.asJava,
        layout.bin / "manifestmerge-report.txt")
      if (noTestApk) {
         val top = XML.loadFile(output)
        val prefix = top.scope.getPrefix(ANDROID_NS)
        val application = top \ APPLICATION_TAG
        val usesLibraries = top \ APPLICATION_TAG \ USES_LIBRARY_TAG
        val instrument = top \ INSTRUMENTATION_TAG
        if (application.isEmpty) Plugin.fail("no manifest application node")
        val hasTestRunner = usesLibraries exists (
          _.attribute(ANDROID_NS, "name") exists (_ == TEST_RUNNER_LIB))

        val last = Some(top) map { top =>
          if  (!hasTestRunner) {
            val runnerlib = new PrefixedAttribute(
              prefix, "name", TEST_RUNNER_LIB, Null)
            val usesLib = new Elem(null, USES_LIBRARY_TAG, runnerlib, TopScope,
                                   minimizeEmpty = true)
            val u = top.copy(
              child = top.child.updated(top.child.indexOf(application.head),
                application.head.asInstanceOf[Elem].copy(
                  child = application.head.child ++ usesLib)))
            u
          } else top
        } map { top =>
          if (instrument.isEmpty) {
             val target = new PrefixedAttribute(prefix,
               "targetPackage", pkg, Null)
             val label = new PrefixedAttribute(prefix,
               "label", "Test Runner", target)
             val name = new PrefixedAttribute(
               prefix, "name", trunner, label)
             val instrumentation = new Elem(null,
               INSTRUMENTATION_TAG, name, TopScope, minimizeEmpty = true)
            val u = top.copy(child = top.child ++ instrumentation)
            u
          } else top
        }

        XML.save(output.getAbsolutePath, last.get, "utf-8", true, null)
      }
      output
    }
  }

  val rGeneratorTaskDef = ( builder
                          , projectLayout
                          , processManifest
                          , collectResources
                          , packageForR
                          , libraryProject
                          , libraryProjects
                          , apkbuildDebug
                          , streams
                          ) map {
    case (bldr, layout, manif, (assets, res), pkg, lib, libs, debug, s) =>
    val cache = s.cacheDirectory
    val proguardTxt = (layout.bin / "proguard.txt").getAbsolutePath

    val inputs = (res ***).get ++ (assets ***).get ++ Seq(manif) filter (
        n => !n.getName.startsWith(".") && !n.getName.startsWith("_"))

    // need to check output changes, otherwise compile fails after gen-idea
    FileFunction.cached(cache / "r-generator")(
        FilesInfo.lastModified, FilesInfo.hash) { (in,out) =>
      s.log.info("Processing resources")
      if (!res.exists)
        s.log.warn("No resources found at " + res.getAbsolutePath)
      Resources.aapt(bldr, manif, pkg, libs, lib, debug(), res, assets, null,
        layout.gen, proguardTxt, s.log)
      s.log.debug(
        "In modified: %s\nInRemoved: %s\nOut checked: %s\nOut modified: %s"
          format (in.modified, in.removed, out.checked, out.modified))
      (layout.gen ** "R.java" get) ++ (layout.gen ** "Manifest.java" get) toSet
    }(inputs.toSet).toSeq
  }

  val proguardConfigTaskDef = ( projectLayout
                              , sdkPath
                              , useSdkProguard
                              , aars
                              , streams) map {
    (layout, p, u, a, s) =>
    val proguardTxt     = layout.bin  / "proguard.txt"
    val proguardProject = layout.base / "proguard-project.txt"

    val base = if (!u) {
      IO.readLinesURL(resourceUrl("android-proguard.config"))
    } else {
      import SdkConstants._
      import File.{separator => S}
      val c1 = file(p + OS_SDK_TOOLS_FOLDER + FD_PROGUARD + S +
        FN_ANDROID_PROGUARD_FILE)

      if (c1.exists)
        IO.readLines(c1)
      else
        List.empty[String]
    }
    def lines(file: File): Seq[String] =
      if (file.exists) IO.readLines(file) else Seq.empty

    val aarConfig = a.flatMap { l =>
      val pc = l.path / "proguard.txt"
      if (pc.isFile) IO.readLines(pc) else Seq.empty
    }
    (base ++ lines(proguardProject) ++ lines(proguardTxt) ++ aarConfig).toSeq: Seq[String]
  }

  val dexMainFileClassesConfigTaskDef = Def.task {
    Dex.dexMainFileClassesConfig(projectLayout.value, dexMulti.value,
      dexInputs.value._2, dexMainFileClasses.value, buildTools.value,
      streams.value)
  }

  val retrolambdaAggregateTaskDef = Def.task {
    Aggregate.Retrolambda(retrolambdaEnable.value,
      Project.extract(state.value).currentUnit.classpath, builder.value)
  }
  val dexInputsTaskDef = ( proguard
                         , proguardInputs
                         , proguardAggregate
                         , retrolambdaAggregate
                         , dexMulti
                         , binPath
                         , dependencyClasspath
                         , classesJar
                         , apkbuildDebug
                         , streams) map {
    (progOut, in, pa, ra, multiDex, b, deps, classJar, debug, s) =>

      Dex.dexInputs(progOut, in, pa, ra, multiDex, b, deps, classJar, debug(), s)
  }

  val manifestAggregateTaskDef = Def.task {
    Aggregate.Manifest(applicationId.value,
      versionName.value, versionCode.value,
      minSdkVersion.value, targetSdkVersion.value,
      manifestPlaceholders.value)
  }
  val dexAggregateTaskDef = Def.task {
    Aggregate.Dex(dexInputs.value, dexMaxHeap.value, dexMulti.value,
      dexMainFileClassesConfig.value, dexMinimizeMainFile.value,
      buildTools.value, dexAdditionalParams.value)
  }

  val dexTaskDef = ( builder
                   , dexAggregate
                   , predex
                   , proguard
                   , classesJar
                   , minSdkVersion
                   , libraryProject
                   , binPath
                   , apkbuildDebug
                   , streams) map {
    case (bldr, dexOpts, pd, pg, classes, minSdk, lib, bin, debug, s) =>
      Dex.dex(bldr, dexOpts, pd, pg, classes, minSdk, lib, bin, debug(), s)
  }

  val predexTaskDef = Def.task {
    val opts = dexAggregate.value
    val inputs = opts.inputs._2
    val multiDex = opts.multi
    val minSdk = minSdkVersion.value
    val classes = classesJar.value
    val pg = proguard.value
    val bldr = builder.value
    val s = streams.value
    val bin = binPath.value
    Dex.predex(opts, inputs, multiDex, minSdk, classes, pg, bldr, bin, s)
  }

  val proguardInputsTaskDef = ( useProguard
                              , proguardOptions
                              , proguardConfig
                              , proguardLibraries
                              , dependencyClasspath
                              , platformJars
                              , classesJar
                              , proguardScala
                              , proguardCache
                              , apkbuildDebug
                              , streams
                              ) map {
    case (u, pgOptions, pgConfig, l, d, (p, x), c, s, pc, debug, st) =>
      Proguard.proguardInputs(
        u, pgOptions, pgConfig, l, d, p, x, c, s, pc, debug(), st)
  }

  val resourceShrinkerTaskDef = Def.task {
    val jar = proguard.value
    val resApk = packageResources.value
    val doShrink = shrinkResources.value
    val layout = projectLayout.value
    val log = streams.value.log
    import com.android.build.gradle.tasks.ResourceUsageAnalyzer
    if (jar.isDefined && doShrink && !ResourceUsageAnalyzer.TWO_PASS_AAPT) {
      val shrunkResApk = resApk.getParentFile / ("shrunk-" + resApk.getName)
      val resTarget = layout.bin / "resources" / "res"
      val analyzer = new ResourceUsageAnalyzer(
        layout.gen, jar.get, processManifest.value, null, resTarget)
      analyzer.analyze()
      analyzer.rewriteResourceZip(resApk, shrunkResApk)
      val unused = analyzer.getUnusedResourceCount
      if (unused > 0) {
        val before = resApk.length
        val after = shrunkResApk.length
        val pct = (before - after) * 100 / before
        log.info(s"Resource Shrinker: $unused unused resources")
        log.info(s"Resource Shrinker: data reduced from ${sizeString(before)} to ${sizeString(after)}, removed $pct%")
      }
      shrunkResApk
    } else {
      resApk
    }
  }

  val proguardAggregateTaskDef = Def.task {
    Aggregate.Proguard(useProguard.value, useProguardInDebug.value,
      proguardScala.value,
      proguardConfig.value, proguardOptions.value, proguardCache.value)
  }

  val proguardTaskDef: Def.Initialize[Task[Option[File]]] =
      ( proguardAggregate
      , builder
      , libraryProject
      , proguardInputs
      , apkbuildDebug
      , binPath
      , retrolambdaAggregate
      , streams
      ) map { case (a, bldr, l, inputs, debug, b, ra, s) =>
        Proguard.proguard(a, bldr, l, inputs, debug(), b, ra, s)
  }

  case class TestListener(log: Logger) extends ITestRunListener {
    import com.android.ddmlib.testrunner.TestIdentifier
    private var _failures: Seq[TestIdentifier] = Seq.empty
    def failures = _failures

    type TestMetrics = java.util.Map[String,String]
    override def testRunStarted(name: String, count: Int) {
      log.info("testing %s (tests: %d)" format (name, count))
    }

    override def testStarted(id: TestIdentifier) {
      log.info(" - " + id.getTestName)
    }

    override def testEnded(id: TestIdentifier, metrics: TestMetrics) {
      log.debug("finished: %s (%s)" format (id.getTestName, metrics))
    }

    override def testFailed(id: TestIdentifier, m: String) {
      log.error("failed: %s\n%s" format (id.getTestName, m))

      _failures = _failures :+ id
    }

    override def testRunFailed(msg: String) {
      log.error("Testing failed: " + msg)
    }

    override def testRunStopped(elapsed: Long) {
      log.info("test run stopped (%dms)" format elapsed)
    }

    override def testRunEnded(elapsed: Long, metrics: TestMetrics) {
      log.info("test run finished (%dms)" format elapsed)
      log.debug("run end metrics: " + metrics)
    }

    override def testAssumptionFailure(id: TestIdentifier, m: String) {
      log.error("assumption failed: %s\n%s" format (id.getTestName, m))

      _failures = _failures :+ id
    }

    override def testIgnored(test: TestIdentifier) {
      log.warn("ignored: %s" format test.getTestName)
    }
  }

  val testAggregateTaskDef = Def.task {
    Aggregate.AndroidTest(debugIncludesTests.value, instrumentTestRunner.value,
      instrumentTestTimeout.value, apkbuildDebug.value(),
      (externalDependencyClasspath in Test).value map (_.data),
      (externalDependencyClasspath in Compile).value map (_.data),
      packagingOptions.value, libraryProject.value)
  }
  val testTaskDef = ( projectLayout
                    , builder
                    , classDirectory
                    , sdkPath
                    , allDevices
                    , dexMaxHeap
                    , testAggregate
                    , manifestAggregate
                    , retrolambdaAggregate
                    , libraryProjects
                    , streams) map {
    (layout, bldr, classes, sdk, all, xmx, ta, ma, ra, libs, s) =>
    if (ta.libraryProject)
      Plugin.fail("This project cannot `android:test`, it has set 'libraryProject in Android := true")
    val pkg = ma.applicationId
    val minSdk = ma.minSdkVersion
    val targetSdk = ma.targetSdkVersion
    val placeholders = ma.placeholders
    val timeo = ta.instrumentTestTimeout
    val noTestApk = ta.debugIncludesTests
    val runner = ta.instrumentTestRunner
    val clib = ta.externalDependencyClasspathInCompile
    val tlib = ta.externalDependencyClassPathInTest
    val cache = s.cacheDirectory
    val re = ra.enable
    val debug = ta.apkbuildDebug

    val testManifest = layout.testSources / "AndroidManifest.xml"
    val manifestFile = if (noTestApk || testManifest.exists) {
      testManifest
    } else {
      generateTestManifest(pkg, classes, runner)
    }

    if (!noTestApk) {
      classes.mkdirs()
      val manifest = XML.loadFile(manifestFile)
      val testPackage = manifest.attribute("package") get 0 text
      val instr = manifest \\ "instrumentation"
      val instrData = (instr map { i =>
        (i.attribute(ANDROID_NS, "name") map (_(0).text),
        i.attribute(ANDROID_NS, "targetPackage") map (_(0).text))
      }).headOption
      val trunner = instrData flatMap (
        _._1) getOrElse runner
      val tpkg = instrData flatMap (_._2) getOrElse pkg
      val processedManifest = classes / "AndroidManifest.xml"
      // profiling and functional test? false for now
      bldr.processTestManifest(testPackage, minSdk.toString, targetSdk.toString,
        tpkg, trunner, false, false, manifestFile, libs.asJava,
        (placeholders: Map[String,Object]).asJava, processedManifest.getAbsoluteFile,
        cache / "processTestManifest")
      val options = new DexOptions {
        override def getIncremental = true
        override def getJumboMode = false
        override def getPreDexLibraries = false
        override def getJavaMaxHeapSize = xmx
        override def getThreadCount = java.lang.Runtime.getRuntime.availableProcessors()
      }
      val rTxt = classes / "R.txt"
      val dex = layout.bin / "dex-test"
      dex.mkdirs()
      val res = layout.bin / "resources-test.ap_"
      val apk = layout.bin / "instrumentation-test.ap_"

      if (!rTxt.exists) rTxt.createNewFile()
      Resources.aapt(bldr, processedManifest, testPackage, libs, false, debug,
        layout.testRes, layout.testAssets,
        res.getAbsolutePath, classes, null, s.log)

      val deps = tlib filterNot (clib contains)
      val tmp = cache / "test-dex"
      tmp.mkdirs()
      val inputs = if (re && RetrolambdaSupport.isAvailable) {
        RetrolambdaSupport(classes, deps, ra.classpath, bldr, s)
      } else {
        Seq(classes) ++ deps
      }
      bldr.convertByteCode(inputs.asJava, List.empty.asJava,
        dex, false, null, options, List.empty.asJava, tmp, false, !debug)

      val debugConfig = new DefaultSigningConfig("debug")
      debugConfig.initDebug()

      val opts = ta.packagingOptions
      bldr.packageApk(res.getAbsolutePath, dex,
        List.empty.asJava, List.empty.asJava, null, null, s.cacheDirectory / "test-apkbuild-merge", null,
        debug, debugConfig, opts.asAndroid, apk.getAbsolutePath)
      s.log.debug("Installing test apk: " + apk)

      def install(device: IDevice) {
        installPackage(apk, sdk, device, s.log)
      }

      if (all)
        Commands.deviceList(sdk, s.log).par foreach install
      else
        Commands.targetDevice(sdk, s.log) foreach install

      try {
        runTests(sdk, testPackage, s, trunner, timeo, all)
      } finally {
        def uninstall(device: IDevice) {
          uninstallPackage(None, testPackage, sdk, device, s.log)
        }

        if (all)
          Commands.deviceList(sdk, s.log).par foreach uninstall
        else
          Commands.targetDevice(sdk, s.log) foreach uninstall
      }
    } else {
      runTests(sdk, pkg, s, runner, timeo, all)
    }
    ()
  }

  val testOnlyTaskDef: Def.Initialize[InputTask[Unit]] = Def.inputTask {
    val layout = projectLayout.value
    val noTestApk = debugIncludesTests.value
    val pkg = applicationId.value
    val classes = (classDirectory in Test).value
    val all = allDevices.value
    val s = streams.value
    val timeo = instrumentTestTimeout.value
    val sdk = sdkPath.value
    val runner = instrumentTestRunner.value
    val testManifest = layout.testSources / "AndroidManifest.xml"
    val manifestFile = if (noTestApk || testManifest.exists) {
      testManifest
    } else {
      generateTestManifest(pkg, classes, runner)
    }
    val manifest = XML.loadFile(manifestFile)
    val testPackage = manifest.attribute("package") get 0 text
    val testSelection = Def.spaceDelimited().parsed.mkString(" ")
    val trunner = if(noTestApk) runner else {
      val instr = manifest \\ "instrumentation"
      (instr map { i =>
        (i.attribute(ANDROID_NS, "name") map (_(0).text),
          i.attribute(ANDROID_NS, "targetPackage") map (_(0).text))
      }).headOption flatMap ( _._1) getOrElse runner
    }
    runTests(sdk, testPackage, s, trunner, timeo, all, Some(testSelection))
  }

  private def generateTestManifest(pkg: String, classes: File,
    runner: String) = {
    val TOOLS_PREFIX = "tools"
    val tns = NamespaceBinding(TOOLS_PREFIX, TOOLS_NS, TopScope)
    val vn = new PrefixedAttribute(ANDROID_PREFIX, "versionName", "1.0", Null)
    val vc = new PrefixedAttribute(ANDROID_PREFIX, "versionCode", "1", vn)
    val pkgAttr = new UnprefixedAttribute("package",
      pkg + ".instrumentTest", vc)
    val ns = NamespaceBinding(ANDROID_PREFIX, ANDROID_NS, tns)

    val minSdk = new PrefixedAttribute(
      ANDROID_PREFIX, "minSdkVersion", "3", Null)
    val usesSdk = new Elem(null, "uses-sdk", minSdk, TopScope, minimizeEmpty = true)
    val runnerlib = new PrefixedAttribute(
      ANDROID_PREFIX, "name", TEST_RUNNER_LIB, Null)
    val usesLib = new Elem(null, USES_LIBRARY_TAG, runnerlib, TopScope, minimizeEmpty = true)
    val app = new Elem(null,
      APPLICATION_TAG, Null, TopScope, minimizeEmpty = false, usesLib)
    val name = new PrefixedAttribute(
      ANDROID_PREFIX, "name", runner, Null)
    val instrumentation = new Elem(null, INSTRUMENTATION_TAG, name, TopScope, minimizeEmpty = true)
    val manifest = new Elem(null,
      "manifest", pkgAttr, ns, minimizeEmpty = false, usesSdk, app, instrumentation)

    val manifestFile = classes / "GeneratedTestAndroidManifest.xml"
    XML.save(manifestFile.getAbsolutePath, manifest, "utf-8", true, null)
    manifestFile
  }

  private def runTests(sdk: String, testPackage: String,
      s: TaskStreams, runner: String, timeo: Int, all: Boolean, testSelection: Option[String] = None) {
    import com.android.ddmlib.testrunner.InstrumentationResultParser
    val intent = testPackage + "/" + runner
    def execute(d: IDevice): Unit = {
      val listener = TestListener(s.log)
      val p = new InstrumentationResultParser(testPackage, listener)
      val receiver = new Commands.ShellLogging(l => p.processNewLines(Array(l)))
      val selection = testSelection map { "-e " + _ } getOrElse ""
      val command = "am instrument -r -w %s %s" format(selection, intent)
      s.log.info(s"Testing on ${d.getProperty(IDevice.PROP_DEVICE_MODEL)} (${d.getSerialNumber})...")
      s.log.debug("Executing [%s]" format command)
      val timeout = DdmPreferences.getTimeOut
      DdmPreferences.setTimeOut(timeo)
      d.executeShellCommand(command, receiver)
      DdmPreferences.setTimeOut(timeout)

      s.log.debug("instrument command executed")

      if (listener.failures.nonEmpty) {
        Plugin.fail("Tests failed: " + listener.failures.size + "\n" +
          (listener.failures map (" - " + _)).mkString("\n"))
      }
    }
    if (all)
      Commands.deviceList(sdk, s.log).par foreach execute
    else
      Commands.targetDevice(sdk, s.log) foreach execute

  }

  val cleanTaskDef = Def.task {
    val s = streams.value
    def execute(d: IDevice): Unit = {
      val receiver = new Commands.ShellLogging(l => s.log.info(l))
      val pkg = applicationId.value
      val command = "pm clear %s" format pkg
      s.log.info(s"Clearing data for $pkg on ${d.getProperty(IDevice.PROP_DEVICE_MODEL)} (${d.getSerialNumber})...")
      s.log.debug("Executing [%s]" format command)
      d.executeShellCommand(command, receiver)
    }
    val all = allDevices.value
    val k = sdkPath.value
    if (all)
      Commands.deviceList(k, s.log).par foreach execute
    else
      Commands.targetDevice(k, s.log) foreach execute
  }

  val runTaskDef: Def.Initialize[InputTask[Unit]] = Def.inputTask {
    val k = sdkPath.value
    val l = projectLayout.value
    val p = applicationId.value
    val s = streams.value
    val all = allDevices.value
    val isLib = libraryProject.value
    if (isLib)
      Plugin.fail("This project is not runnable, it has set 'libraryProject in Android := true")

    val r = Def.spaceDelimited().parsed
    val manifestXml = l.bin / "AndroidManifest.xml"
    val m = XML.loadFile(manifestXml)
    // if an arg is specified, try to launch that
    (if (r.isEmpty) None else Some(r mkString " ")) orElse ((m \\ "activity") find {
      // runs the first-found activity
      a => (a \ "intent-filter") exists { filter =>
        val attrpath = "@{%s}name" format ANDROID_NS
        (filter \\ attrpath) exists (_.text == "android.intent.action.MAIN")
      }
    } map { activity =>
      val name = activity.attribute(ANDROID_NS, "name") get 0 text

      "%s/%s" format (p, if (name.indexOf(".") == -1) "." + name else name)
    }) match {
      case Some(intent) =>
        val receiver = new Commands.ShellLogging(l => s.log.info(l))
        def execute(d: IDevice): Unit = {
          val command = "am start -n %s" format intent
          s.log.info(s"Running on ${d.getProperty(IDevice.PROP_DEVICE_MODEL)} (${d.getSerialNumber})...")
          s.log.debug("Executing [%s]" format command)
          d.executeShellCommand(command, receiver)
          s.log.debug("run command executed")
        }
        if (all)
          Commands.deviceList(k, s.log).par foreach execute
        else
          Commands.targetDevice(k, s.log) foreach execute
      case None =>
        Plugin.fail(
          "No activity found with action 'android.intent.action.MAIN'")
    }

    ()
  }

  val KB = 1024 * 1.0
  val MB = KB * KB
  val installTaskDef = ( packageT
                       , libraryProject
                       , sdkPath
                       , allDevices
                       , streams) map {
    (p, l, k, all, s) =>

    if (!l) {
      def execute(d: IDevice): Unit = {
        val cacheName = "install-" + URLEncoder.encode(
          d.getSerialNumber, "utf-8")
        FileFunction.cached(s.cacheDirectory / cacheName, FilesInfo.hash) { in =>
          s.log.info(s"Installing to ${d.getProperty(IDevice.PROP_DEVICE_MODEL)} (${d.getSerialNumber})...")
          installPackage(p, k, d, s.log)
          in
        }(Set(p))
      }
      if (all)
        Commands.deviceList(k, s.log).par foreach execute
      else
        Commands.targetDevice(k, s.log) foreach execute
    }
  }

  def installPackage(apk: File, sdkPath: String, device: IDevice, log: Logger) {
    val start = System.currentTimeMillis
    logRate(log, "[%s] Install finished:" format apk.getName, apk.length) {
      Option(device.installPackage(apk.getAbsolutePath, true)) map { err =>
        Plugin.fail("Install failed: " + err)
      }
    }
  }

  def logRate[A](log: Logger, msg: String, size: Long)(f: => A): A = {
    val start = System.currentTimeMillis
    val a = f
    val end = System.currentTimeMillis
    val secs = (end - start) / 1000d
    val rate = size/KB/secs
    val mrate = if (rate > MB) rate / MB else rate
    log.info("%s %s in %.2fs. %.2f%s/s" format (msg, sizeString(size), secs, mrate,
      if (rate > MB) "MB" else "KB"))
    a
  }

  def uninstallPackage(cacheDir: Option[File], packageName: String, sdkPath: String, device: IDevice, log: Logger) {
    val cacheName = "install-" + URLEncoder.encode(
      device.getSerialNumber, "utf-8")
    cacheDir foreach { c =>
      FileFunction.cached(c / cacheName, FilesInfo.hash) { in =>
        Set.empty
      }(Set.empty)
    }
    log.info(s"Uninstalling from ${device.getProperty(IDevice.PROP_DEVICE_MODEL)} (${device.getSerialNumber})...")
    Option(device.uninstallPackage(packageName)) map { err =>
      Plugin.fail("[%s] Uninstall failed: %s" format (packageName, err))
    } getOrElse {
      log.info("[%s] Uninstall finished" format packageName)
    }
  }
  private def sizeString(len: Long) = {
    val KB = 1024 * 1.0
    val MB = KB * KB
    len match {
      case s if s < MB  => "%.2fKB" format (s/KB)
      case s if s >= MB => "%.2fMB" format (s/MB)
    }
  }
  val uninstallTaskDef = (sdkPath, applicationId, streams, allDevices) map { (k,p,s,all) =>
    def uninstall(device: IDevice) {
      uninstallPackage(Some(s.cacheDirectory), p, k, device, s.log)
    }

    if (all)
      Commands.deviceList(k, s.log).par foreach uninstall
    else
      Commands.targetDevice(k, s.log) foreach uninstall
  }

  def loadLibraryReferences(b: File, props: Properties, prefix: String = ""):
  Seq[AutoLibraryProject] = {
    val p = props.asScala
    (p.keys.collect {
        case k if k.startsWith("android.library.reference") => k
      }.toList.sortWith { (a,b) => a < b } flatMap { k =>
        AutoLibraryProject(b/p(k)) +:
          loadLibraryReferences(b/p(k), loadProperties(b/p(k)), k)
      }) distinct
  }

  def loadProperties(path: File): Properties = {
    val p = new Properties
    (path * "*.properties" get) foreach { f =>
      Using.fileInputStream(f) { p.load }
    }
    p
  }

  val unmanagedJarsTaskDef = ( unmanagedJars in Compile
                             , baseDirectory
                             , buildTools in Android
                             , rsSupportMode in Android
                             , libraryProjects in Android, streams) map {
    (u, b, t, rs, l, s) =>

    val rsJars =
      if (rs) (t.getLocation / "renderscript" / "lib" * "*.jar").get
        .map(f => Attributed.blank(f.getCanonicalFile))
      else Seq()

    // remove scala-library if present
    // add all dependent library projects' classes.jar files
    (u ++ rsJars ++ (l filterNot {
        case _: ApkLibrary         => true
//        case _: AarLibrary         => true
        case _: AutoLibraryProject => true
        case _ => false
      } map { p => Attributed.blank(p.getJarFile.getCanonicalFile) }) ++ (for {
        d <- l/* filterNot { // currently unworking
          case _: AarLibrary => true
          case _ => false
        }*/
        j <- d.getLocalJars.asScala
      } yield Attributed.blank(j.getCanonicalFile)) ++ (for {
        d <- Seq(b / "libs", b / "lib")
        j <- d * "*.jar" get
      } yield Attributed.blank(j.getCanonicalFile))
    ) filter { c =>
      !c.data.getName.startsWith("scala-library") && c.data.isFile
    }
  }
}


text:
/*
 * 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.
 */
package org.atteo.classindex.processor;

public class ImportantClassIndexProcessor extends ClassIndexProcessor {
	public ImportantClassIndexProcessor() {
		indexSubclasses(Plugin.class);
		indexPackages("org.atteo.classindex.second");
		indexAnnotations(Important.class);
	}
}

redpajama_set_name: RedPajamaGithub


text:
package org.apache.jackrabbit.oak.upgrade.version;

import static com.google.common.collect.ImmutableSet.of;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Sets.newHashSet;
import static java.util.Collections.singleton;
import static org.apache.jackrabbit.JcrConstants.JCR_BASEVERSION;
import static org.apache.jackrabbit.JcrConstants.JCR_CREATED;
import static org.apache.jackrabbit.JcrConstants.JCR_ISCHECKEDOUT;
import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES;
import static org.apache.jackrabbit.JcrConstants.JCR_PREDECESSORS;
import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
import static org.apache.jackrabbit.JcrConstants.JCR_SYSTEM;
import static org.apache.jackrabbit.JcrConstants.JCR_UUID;
import static org.apache.jackrabbit.JcrConstants.JCR_VERSIONHISTORY;
import static org.apache.jackrabbit.JcrConstants.JCR_VERSIONSTORAGE;
import static org.apache.jackrabbit.JcrConstants.MIX_REFERENCEABLE;
import static org.apache.jackrabbit.JcrConstants.MIX_VERSIONABLE;
import static org.apache.jackrabbit.oak.plugins.memory.MultiGenericPropertyState.nameProperty;
import static org.apache.jackrabbit.oak.spi.version.VersionConstants.REP_VERSIONSTORAGE;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Set;

import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.plugins.nodetype.TypePredicate;
import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;

import com.google.common.base.Joiner;
import org.apache.jackrabbit.util.ISO8601;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class VersionHistoryUtil {

    private static final Logger LOG = LoggerFactory.getLogger(VersionHistoryUtil.class);

    public static String getRelativeVersionHistoryPath(String versionableUuid) {
        return Joiner.on('/').join(concat(
                singleton(""),
                getRelativeVersionHistoryPathSegments(versionableUuid),
                singleton(versionableUuid)));
    }

    /**
     * Constructs the version history path based on the versionable's UUID.
     *
     * @param versionStorage below which to look for the version.
     * @param versionableUuid The String representation of the versionable's UUID.
     * @return The NodeState corresponding to the version history, or {@code null}
     *         if it does not exist.
     */
    static NodeState getVersionHistoryNodeState(NodeState versionStorage, String versionableUuid) {
        NodeState historyParent = versionStorage;
        for (String segment : getRelativeVersionHistoryPathSegments(versionableUuid)) {
            historyParent = historyParent.getChildNode(segment);
        }
        return historyParent.getChildNode(versionableUuid);
    }

    public static NodeBuilder getVersionHistoryBuilder(NodeBuilder versionStorage, String versionableUuid) {
        NodeBuilder history = versionStorage;
        for (String segment : getRelativeVersionHistoryPathSegments(versionableUuid)) {
            history = history.getChildNode(segment);
        }
        return history.getChildNode(versionableUuid);
    }

    private static List<String> getRelativeVersionHistoryPathSegments(String versionableUuid) {
        final List<String> segments = new ArrayList<String>();
        for (int i = 0; i < 3; i++) {
            segments.add(versionableUuid.substring(i * 2, i * 2 + 2));
        }
        return segments;
    }

    public static NodeState getVersionStorage(NodeState root) {
        return root.getChildNode(JCR_SYSTEM).getChildNode(JCR_VERSIONSTORAGE);
    }

    public static NodeBuilder getVersionStorage(NodeBuilder root) {
        return root.getChildNode(JCR_SYSTEM).getChildNode(JCR_VERSIONSTORAGE);
    }

    public static NodeBuilder createVersionStorage(NodeBuilder root) {
        NodeBuilder vs = root.child(JCR_SYSTEM).child(JCR_VERSIONSTORAGE);
        if (!vs.hasProperty(JCR_PRIMARYTYPE)) {
            vs.setProperty(JCR_PRIMARYTYPE, REP_VERSIONSTORAGE, Type.NAME);
        }
        return vs;
    }

    public static List<String> getVersionableNodes(NodeState root, TypePredicate isVersionable, Calendar olderThan) {
        List<String> paths = new ArrayList<>();
        NodeState versionStorage = getVersionStorage(root);
        getVersionableNodes(root, versionStorage, isVersionable, olderThan, PathUtils.ROOT_PATH, paths);
        return paths;
    }

    private static void getVersionableNodes(NodeState node, NodeState versionStorage, TypePredicate isVersionable, Calendar olderThan, String path, List<String> paths) {
        if (isVersionable.apply(node)) {
            if (olderThan == null) {
                paths.add(path);
            } else {
                NodeState versionHistory = getVersionHistoryNodeState(versionStorage, node.getString(JCR_UUID));
                Calendar lastModified = getVersionHistoryLastModified(versionHistory);
                if (lastModified.before(olderThan)) {
                    paths.add(path);
                }
            }
        }
        for (ChildNodeEntry c : node.getChildNodeEntries()) {
            getVersionableNodes(c.getNodeState(), versionStorage, isVersionable, olderThan, PathUtils.concat(path, c.getName()), paths);
        }
    }

    public static Calendar getVersionHistoryLastModified(NodeState versionHistory) {
        Calendar youngest = Calendar.getInstance();
        youngest.setTimeInMillis(0);
        for (final ChildNodeEntry entry : versionHistory.getChildNodeEntries()) {
            final NodeState version = entry.getNodeState();
            if (version.hasProperty(JCR_CREATED)) {
                final Calendar created = ISO8601.parse(version.getProperty(JCR_CREATED).getValue(Type.DATE));
                if (created.after(youngest)) {
                    youngest = created;
                }
            }
        }
        return youngest;
    }

    public static void removeVersionProperties(NodeBuilder versionableBuilder, TypePredicate isReferenceable) {
        assert versionableBuilder.exists();

        removeMixin(versionableBuilder, MIX_VERSIONABLE);

        // we don't know if the UUID is otherwise referenced,
        // so make sure the node remains referencable
        if (!isReferenceable.apply(versionableBuilder.getNodeState())) {
            addMixin(versionableBuilder, MIX_REFERENCEABLE);
        }

        versionableBuilder.removeProperty(JCR_VERSIONHISTORY);
        versionableBuilder.removeProperty(JCR_PREDECESSORS);
        versionableBuilder.removeProperty(JCR_BASEVERSION);
        versionableBuilder.removeProperty(JCR_ISCHECKEDOUT);
    }

    static void addMixin(NodeBuilder builder, String name) {
        if (builder.hasProperty(JCR_MIXINTYPES)) {
            final Set<String> mixins = newHashSet(builder.getProperty(JCR_MIXINTYPES).getValue(Type.NAMES));
            if (mixins.add(name)) {
                builder.setProperty(nameProperty(JCR_MIXINTYPES, mixins));
            }
        } else {
            builder.setProperty(nameProperty(JCR_MIXINTYPES, of(name)));
        }
    }

    private static void removeMixin(NodeBuilder builder, String name) {
        if (builder.hasProperty(JCR_MIXINTYPES)) {
            final Set<String> mixins = newHashSet(builder.getProperty(JCR_MIXINTYPES).getValue(Type.NAMES));
            if (mixins.remove(name)) {
                if (mixins.isEmpty()) {
                    builder.removeProperty(JCR_MIXINTYPES);
                } else {
                    builder.setProperty(nameProperty(JCR_MIXINTYPES, mixins));
                }
            }
        }
    }

    public static NodeBuilder removeVersions(NodeState root,
                               List<String> toRemove) {
        NodeBuilder rootBuilder = root.builder();
        TypePredicate isReferenceable = new TypePredicate(root, MIX_REFERENCEABLE);
        NodeBuilder versionStorage = getVersionStorage(rootBuilder);
        for (String p : toRemove) {
            LOG.info("Removing version history for {}", p);
            NodeBuilder b = getBuilder(rootBuilder, p);
            String uuid = b.getString(JCR_UUID);
            VersionHistoryUtil.removeVersionProperties(b, isReferenceable);
            getVersionHistoryBuilder(versionStorage, uuid).remove();
        }
        return rootBuilder;
    }

    private static NodeBuilder getBuilder(NodeBuilder root, String path) {
        NodeBuilder builder = root;
        for (String e : PathUtils.elements(path)) {
            builder = builder.child(e);
        }
        return builder;
    }

}


text:
""" Copy + Paste in Windows
"""

# found @ http://code.activestate.com/recipes/150115/

from .base import *

try:
    import clr
    clr.AddReference('PresentationCore')
    import System.Windows.Clipboard as clip
except ImportError as why:
    raise ClrNotFound

def copy(string, **kwargs):
    """Copy given string into system clipboard."""

    clip.SetText(string)
    return

def paste(**kwargs):
    """Returns system clipboard contents."""

    if clip.ContainsText():
        return clip.GetText()

    return None


text:
1. 安装
```sh
$ npm install --save-dev open-browser-webpack-plugin #
```
2. webpack 配置文件中使用
```javascript
var OpenBrowserPlugin = require('open-browser-webpack-plugin');

module.exports = {
  entry: path.resolve(__dirname, 'lib/entry.js'),
  output: {
    path: __dirname + "/bundle/",
    filename: "bundle.js"
  },
  plugins: [
    new OpenBrowserPlugin({ url: 'http://localhost:3000' })
  ]
};
```


text:
describe TreeNode do
  # Force load all the TreeNode:: subclasses
  Dir[ManageIQ::UI::Classic::Engine.root.join('app', 'presenters', 'tree_node', '*.rb')].each { |f| require f }

  # FIXME: rewrite this to FactoryBot
  let(:object) do
    # We need a Zone & Server for creating a MiqSchedule
    EvmSpecHelper.create_guid_miq_server_zone if klass == MiqSchedule
    klass.new
  end
  let(:parent_id) { dup }
  let(:tree) { double }
  subject { TreeNode.new(object, parent_id, tree) }

  describe '.new' do
    shared_examples 'instance variables' do
      it 'sets instance variables' do
        expect(subject.instance_variable_get(:@object)).to eq(object)
        expect(subject.instance_variable_get(:@parent_id)).to eq(parent_id)
        expect(subject.instance_variable_get(:@tree)).to eq(tree)
      end
    end

    TreeNode.constants.each do |type|
      # We never instantiate MiqAeNode and Node in our codebase
      next if %i[MiqAeNode Node Menu Root REXML].include?(type)

      describe(type) do
        let(:klass) { type.to_s.constantize }

        it 'initializes a new instance' do
          expect(subject).to be_a("TreeNode::#{klass}".constantize)
        end

        include_examples 'instance variables'

        # Skip tests for descendants of Hash
        next if type == :Hash

        type.to_s.constantize.descendants.each do |subtype|
          # Skip the subtypes that have been already tested above
          next if TreeNode.constants.include?(subtype.to_s.to_sym)

          describe(subtype) do
            let(:klass) { subtype }

            it 'initializes a new instance' do
              expect(subject).to be_a("TreeNode::#{klass.base_class}".constantize)
            end

            include_examples 'instance variables'
          end
        end
      end
    end
  end

  describe '.exists?' do
    subject { described_class.exists?(object) }

    context 'object has a direct subclass' do
      let(:object) { User.new }
      it { is_expected.to be_truthy }
    end

    context 'object has an indirect subclass' do
      let(:object) { VmOrTemplate.new }
      it { is_expected.to be_truthy }
    end

    context 'object is a hash' do
      let(:object) { {} }
      it { is_expected.to be_truthy }
    end

    context 'object is an array' do
      let(:object) { [] }
      it { is_expected.to be_falsey }
    end

    context 'object is nil' do
      let(:object) { nil }
      it { is_expected.to be_falsey }
    end
  end
end


text:
package com.bitmonlab.osiris.test.acceptancetest.map.metadata;

import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;

import javax.inject.Inject;
import javax.inject.Named;

import org.junit.Assert;
import org.springframework.data.mongodb.core.MongoTemplate;

import com.bitmonlab.osiris.test.acceptancetest.map.commons.HttpResponse;
import com.bitmonlab.osiris.test.acceptancetest.map.commons.SecurityCredentials;
import com.bitmonlab.osiris.commons.map.model.geojson.MetaData;
import com.bitmonlab.osiris.api.core.map.transferobject.MetaDataDTO;
import com.bitmonlab.osiris.restsender.ClientResponse;
import com.bitmonlab.osiris.restsender.Headers;
import com.bitmonlab.osiris.restsender.RestMethod;
import com.bitmonlab.osiris.restsender.RestRequestSender;
import com.sun.jersey.api.client.GenericType;

import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;

public class GetMetaData {

	@Inject
	@Named("osirisMapRequestSender")
	private RestRequestSender sender;

	@Inject
	@Named("osirisGeolocationMongoTemplate")
	private MongoTemplate mongoTemplate;

	@Inject
	private SecurityCredentials securityCredentials;

	private ClientResponse<MetaDataDTO> response;

	@Inject
	private HttpResponse httpResponse;

	private final static String collectionMetaData="Metadata";

	@Given("^I have a map with an APPLICATIONID \"([^\"]*)\" and metadata osmChecksum \"([^\"]*)\", routingChecksum \"([^\"]*)\", minLat \"([^\"]*)\", minLon \"([^\"]*)\", maxLat \"([^\"]*)\" and maxLon \"([^\"]*)\"$")
	public void I_have_a_map_with_an_APPLICATIONID_and_metadata_osmChecksum_routingChecksum_minLat_minLon_maxLat_and_maxLon(String appId, String osmChecksum, String routingChecksum, String minLat, String minLon, String maxLat, String maxLon){
	    // Express the Regexp above with the code you wish you had
		MetaData metadata=createMetaData(appId, osmChecksum, routingChecksum, minLat, minLon, maxLat, maxLon);
		mongoTemplate.save(metadata, collectionMetaData);
	}

	@When("^I invoke a GET metadata to \"([^\"]*)\" and applicationIdentifier \"([^\"]*)\"$")
	public void I_invoke_a_GET_metadata_to_and_applicationIdentifier(String url, String appId) throws NoSuchAlgorithmException, UnsupportedEncodingException{
	    // Express the Regexp above with the code you wish you had

		securityCredentials.createCredential(appId, "root", "1234");

		response= sender.invoke(RestMethod.GET, url , new GenericType<MetaDataDTO>(){}, new Headers("api_key", appId), new Headers("Authorization", "Basic cm9vdDoxMjM0"));
		httpResponse.setResponse(response);
	}

	@Then("^I verify metadata has same fields osmChecksum \"([^\"]*)\", routingChecksum \"([^\"]*)\", minLat \"([^\"]*)\", minLon \"([^\"]*)\", maxLat \"([^\"]*)\" and maxLon \"([^\"]*)\"$")
	public void I_verify_metadata_has_same_fields_osmChecksum_routingChecksum_minLat_minLon_maxLat_and_maxLon(String osmChecksum, String routingChecksum, String minLat, String minLon, String maxLat, String maxLon){
	    // Express the Regexp above with the code you wish you had
		String chkSumResponse = response.getEntity().getOSMChecksum();
		String minLatResponse = response.getEntity().getMinLatitude();
		String minLonResponse = response.getEntity().getMinLongitude();
		String maxLatResponse = response.getEntity().getMaxLatitude();
		String maxLonResponse = response.getEntity().getMaxLongitude();
		String checksumRouting = response.getEntity().getRoutingChecksum();

		Assert.assertEquals("Checksum must be the same", osmChecksum, chkSumResponse);
		Assert.assertEquals("minLat must be the same", minLat, minLatResponse);
		Assert.assertEquals("minLon must be the same", minLon, minLonResponse);
		Assert.assertEquals("maxLat must be the same", maxLat, maxLatResponse);
		Assert.assertEquals("maxLon must be the same", maxLon, maxLonResponse);
		Assert.assertEquals("RoutingChecksum must be the same",routingChecksum, checksumRouting);
	}

	private MetaData createMetaData(String appId, String osmChecksum, String routingChecksum, String minLat, String minLon, String maxLat, String maxLon){
		MetaData metaData=new MetaData();
		metaData.setAppId(appId);
		metaData.setMaxlat(Double.parseDouble(maxLat));
		metaData.setMaxlon(Double.parseDouble(maxLon));
		metaData.setMinlat(Double.parseDouble(minLat));
		metaData.setMinlon(Double.parseDouble(minLon));
		metaData.setOSMChecksum(osmChecksum);
		metaData.setRoutingChecksum(routingChecksum);
		return metaData;
	}

}


text:
class Vec {
    public x: number;
    public y: number;

    constructor(x: number, y:number) {
        this.x = x
        this.y = y
    }
}

class Map {
    size: number;
    walls: Uint8Array;
    constructor(size: number) {
        this.size = size;
        this.walls = new Uint8Array(size * size);
    }
    get(x: number, y: number) {
        x = Math.floor(x);
        y = Math.floor(y);

        if (x < 0 || x > this.size - 1 || y < 0 || y > this.size - 1) return -1;
        return this.walls[y * this.size + x]
    }

    cast(point: Vec, angle: number, range: number) {

    }

}

class Player {
    x: number;
    y: number;

    direction: number;

    constructor(x: number, y: number, direction: number) {
        this.x = x;
        this.y = y;
        this.direction = direction;
    }
    rotate(angle: number) : Player {
        this.direction = (this.direction + angle + (Math.PI * 2)) % (Math.PI * 2);
        return this
    }

    walk(distance: number, map: Map) : Player {
        var dx = Math.cos(this.direction) * distance;
        var dy = Math.sin(this.direction) * distance;
        if (map.get(this.x + dx, this.y) <= 0) this.x += dx;
        if (map.get(this.x, this.y + dy) <= 0) this.y += dy;
        return this
    }
}
class Engine {
    id: string;
    canvas: any;
    ctx: CanvasRenderingContext2D;
    player: Player;
    map: Map;
    constructor(id: string) {
        this.id = id
    }
    setup() {
        this.canvas = document.getElementById(this.id);
        this.ctx = this.canvas.getContext('2d')
    }

    start() {

    }
    update() {

    }
}

window.onload = function() {
    var engine = new Engine('canvas')
    engine.start()
}


text:
"""
Cli tool for odin
"""

import os
import argparse
import queue
import logging
import uuid
import json
from pprint import pprint
import odin
from odin.static import __version__
from odin.utils import (run_scan, assembler, get_filter)
from odin.store import OpenDnsModel
from odin import utils

# Default logging capabilities (logging nowhere)
log = odin.get_logger()

def get_args():
    """Parse input parameters

    :returns: an Namespace object with inputted arguments
    :rtype: argparse.Namespace
    """

    parser = argparse.ArgumentParser()
    parser_exclusive = parser.add_mutually_exclusive_group(required=False)
    parser_exclusive.add_argument('-v', '--verbose',
                                  action='count', default=None)
    parser_exclusive.add_argument('-q', '--quiet',
                                  action='store_const', const=0, default=None)

    hold_parser = argparse.ArgumentParser(
        description='{0}{1}{2}{3}{4}{5}{6}'.format(
            'Odin is a command line tool to scan an host or a ',
            'CIDR formatted network and find Open Resolvers. ',
            'As you would probably run the script over some 1000~ hosts at ',
            'a time, the chuck switch is provided in order to select the ',
            'thread pool number to spawn to process the requests. (bare in ',
            'mind your ISP could easely throttle you out if you burst to much',
            'traffic in a single run!)'))
    hold_parser.add_argument("--version", action="version",
                             version="%(prog)s " + __version__)
    subparsers = hold_parser.add_subparsers(dest="subparser")

    # Scan sub parser
    scan = subparsers.add_parser('scan', parents=[parser],
                                 conflict_handler='resolve',
                                 description="{}{}{}".format(
                                     "Perform a scan and return the ",
                                     "result, optionally save the ",
                                     "scan into the DB"))
    scan.add_argument("-t", "--target", dest="target",
                      action="store", type=str, default=None,
                      help="Set target: IP or CIDR range.", required=True)
    scan.add_argument("-c", "--chunk", dest="chunk", action="store",
                      default=50, type=int,
                      help="Set Ip Range chunk size; 1024 max.")
    scan.add_argument("-f", "--filter", dest="filter", action="store",
                      help='{} {} {}'.format(
                          "show only if target is (or has):",
                          "is_dns, is_resolver, version, all.",
                          "It defaults to 'is_dns'."),
                      required=False, default='is_resolver', type=str)
    scan.add_argument("--store", action="store_true",
                      help="if specified store the result in Dynamo")
    scan.add_argument("--dump", action="store_true",
                      help="{}{}".format(
                          "if specified dump the result ",
                          "into randomly generated file in CWD"))

    # Query sub parser
    query = subparsers.add_parser('query', parents=[parser],
                                  conflict_handler='resolve',
                                  )
    query.add_argument("-t", "--type", dest="type",
                       action="store", type=str,
                       required=True, help="{}{}".format(
                           "Specify the type of record to query for: ",
                           "is_dns | is_resolver"))
    query.add_argument("-r", "--range", dest="range",
                       action="store", type=str, default=None,
                       help="{}{}".format(
                           "Set target range in the form like: ",
                           "192 | 192.168 | 192.168.0"))
    query.add_argument("-V", "--version", dest="version", nargs='?',
                       const=None, type=str,
                       help='{} {} {}'.format(
                           "query only for target with ",
                           "or without a particular dns version in the form:",
                           "'dnsmasq' or '!dnsmasq'"))
    query.add_argument("--reversed", action="store_false",
                       help="{}{}".format(
                           "if specified, the resultset ",
                           "is sorted from older to newer"),
                       default=True)
    query.add_argument("-l", "--limit", dest="limit", action="store",
                       default=None, type=int,
                       help="Set a limit for results")
    query.add_argument("-e", "--extended", action="store_true", default=None,
                       help="if specified show all from returned object")

    # Db sun parser
    db = subparsers.add_parser('db', parents=[parser],
                               conflict_handler='resolve',
                               )
    exclusive = db.add_mutually_exclusive_group(required=True)
    exclusive.add_argument("--dump", dest="dump", action="store",
                           help="Output file")
    exclusive.add_argument("--load", dest="load", action="store",
                           help="Input file")
    exclusive.add_argument("--create", dest="create",
                           nargs=2, metavar=('read', 'write'),
                           help="{}{}".format(
                               "Create the DB, if not exists already,",
                               " giving read and write capacity"))
    exclusive.add_argument("--delete", action="store_true",
                           help="delete the DB table")
    exclusive.add_argument("--describe", action="store_true",
                           help="describe the DB tables")

    # Delete sub parser
    delete = subparsers.add_parser('delete', parents=[parser],
                                   conflict_handler='resolve'
                                   )
    delete.add_argument("-t", "--target", dest="target",
                        action="store", type=str, default=None,
                        help="Set target for deletion: IP or CIDR range.",
                        required=True)

    return (hold_parser.parse_args(), hold_parser)

def do_query(subject, index=None,
             nets=[], scan_index_forward=None, limit=None,
             version_string=None, negate_version=None):
    """Run a query against the DB"""

    if negate_version:
        version_name = 'version__not_contains'
    elif version_string is True:
        version_name = 'version__not_null'
    else:
        version_name = 'version__contains'

    query = {'scan_index_forward': scan_index_forward}
    if limit is not None:
        query.update({'limit': limit})
    if version_string:
        query.update({version_name: version_string})

    if subject == 'is_resolver':
        query_over = getattr(OpenDnsModel, 'openresolvers_index')
    elif subject == 'is_dns':
        query_over = getattr(OpenDnsModel, 'dns_index')
        query.update({'is_resolver__eq': False,
                      'is_dns__eq': True})  # FIXME

    if len(nets) is 0:
        log.info('performing a single query for %s type', subject)
        for ip in query_over.query(1, **query):
            log.debug('returned ip: %s', ip.ip)
            yield ip
    else:
        log.info('performing a batch of queries for %s type', subject)
        for net in nets:
            log.debug('query for net: %s', net)
            query.update({index + '__eq': str(net)})
            for ip in query_over.query(1, **query):
                log.debug('returned ip: %s', ip.ip)
                yield ip

def main():
    """ the main script."""

    args, parser = get_args()
    if args.subparser is None:
        parser.print_help()
        return

    # setup logging
    levels = [logging.ERROR, logging.WARNING, logging.INFO, logging.DEBUG]
    # taking care to check either verbosity or quiet flag
    if args.verbose is not None:
        arg = args.verbose + 1
    elif args.quiet is not None:
        arg = args.quiet
    else:
        arg = 1
    level = levels[min(len(levels)-1, arg)]
    log = odin.get_logger(level)

    # SCAN case
    if args.subparser == "scan":
        log.info('Preparing for scanning..')

        targets = utils.findip(args.target)
        log.debug('list of ip to be scanned: %s', targets)

        assert args.chunk > 1 and args.chunk <= 2048, (
            'You have to specify a chunk between 1 and 2048.')
        targets = utils.chunker(targets, args.chunk)

        assert args.filter in ['is_dns',
                               'is_resolver',
                               'version',
                               'all'], ('{}{}'.format(
                                   'You have to specify a filter in:',
                                   ' is_dns, is_resolver, version, all.'))

        my_queue = queue.Queue()
        result = []
        printing = {}

        for obj in run_scan(my_queue, targets):
            log.debug('adding %s to the resultset', obj.ip)
            printing[obj.ip] = obj.serialize
            result.append(obj)

        if args.dump:
            log.info('dump flag passed: saving results to file..')
            filename = str(uuid.uuid4())
            with open(filename, 'w') as f:
                json.dump(
                    [r.serialize for r in result if r.serialize['is_dns']], f)

        if args.store:
            log.info('store flag passed: saving results into the DB..')
            try:
                with OpenDnsModel.batch_write() as batch:
                    for ip in result:
                        log.debug('storing ip: %s', ip)
                        batch.save(ip)
            except Exception as err:
                log.error('batch failed to save to db: %s', err, exc_info=True)
                pass

        pprint(printing)

    # QUERY case
    elif args.subparser == "query":
        log.info('Preparing for querying..')
        # query needs:
        # * show all openresolvers
        # * show all openresolvers with version X
        # * show all dns
        # * show all dns with version X
        # * show all
        # - all above with given range 192, 192.168, 192.168.55
        # - all above with timerange first to last or viceversa
        # - all above with filter option to show only certain info
        # * show last X [anythig, dns, resolver], with possible cass filter
        # * count number per: all, dns, resolver, with  possible class fliter
        if args.range:
            cidr, class_range = assembler(args.range)
            nets = [args.range]
        else:
            class_range = None
            nets = []

        if args.version == 1:
            version_string, negate_version = True, None
        elif args.version:
            version_string, negate_version = get_filter(args.version)
        else:
            version_string, negate_version = None, None
        log.debug(
            'cheking version params: version_string %s, negate_version %s',
            version_string, negate_version)

        for result in do_query(args.type, index=class_range,
                               nets=nets, scan_index_forward=args.reversed,
                               version_string=version_string, limit=args.limit,
                               negate_version=negate_version):
            log.debug('perform serialization of obj: %s', result.ip)
            if args.extended:
                pprint(result.serialize)
            else:
                pprint({'ip': result.ip, 'version': result.version})

    # DELETE CASE
    elif args.subparser == "delete":
        log.info('starting deletion of IP addresses')
        targets = utils.findip(args.target)
        # FIXME BUG in pynamo: single delete is ok, but batching complain about
        # key that cannnot be null
        objects = []
        for target in targets:
            log.debug('preparing to delete item: %s', target)
            try:
                objects.append(OpenDnsModel.get(target))
            # obj does not exist
            except Exception as err:
                log.info('ip: %s does not exist in DB: %s', target,
                         err, exc_info=True)
        try:
            with OpenDnsModel.batch_write() as batch:
                for ip in objects:
                    batch.delete(ip)
        except Exception as err:
            log.error("unable to delete the specified ips",
                      exc_info=True)
            return
        log.info('delete operation finished successfully')

    # DB manipulation case
    elif args.subparser == "db":
        if args.describe:
            log.info('describe table %s', OpenDnsModel.Meta.table_name)
            return pprint(OpenDnsModel.describe_table())

        if args.load:
            log.info('preparing to load dataset from file..')
            try:
                OpenDnsModel.load(args.load)
            except IOError as err:
                log.error('%s%s%s',
                          '\nUnable to load data from ',
                          args.load,
                          '. are you sure the file exisits?\n', exc_info=True)
                return
            log.info('data succefully loaded from %s', args.load)

        elif args.dump:
            log.info('dumping the DB in %s', args.dump)
            if os.path.exists(args.dump):
                answer = input(
                    'file {} exist: overwrite? '.format(args.dump))
                if answer in ['yes', 'y']:
                    OpenDnsModel.dump(args.dump)
                else:
                    log.warn('user choice exception, exiting..')
            else:
                OpenDnsModel.dump(args.dump)
            log.info('DB dumped correctly')

        elif args.create:
            log.info("creating database... ")
            try:
                read, write = (int(param) for param in args.create)
            except Exception as err:
                log.error(
                    'wrong read or write parameter specified: %s',
                    args.create, exc_info=True)
                return

            result = OpenDnsModel.create_table(wait=True,
                                               read_capacity_units=read,
                                               write_capacity_units=write)
            if result is None:
                log.debug('DB already exist')
                return pprint(OpenDnsModel.describe_table())
            else:
                return pprint(result)

        elif args.delete:
            log.info("deleting database.. ")
            result = OpenDnsModel.delete_table()
            log.info("delete successful")
            return pprint(result)

        elif args.modify:
            # TODO make a function I saved output because no documentation is
            # there
            # q=TableConnection(table_name='OpenDns',
            #         host='http://127.0.0.1:8000')
            # q.update_table(
            #         read_capacity_units=50,
            #         write_capacity_units=50,
            #         global_secondary_index_updates=[
            #             {'read_capacity_units': 50,
            #              'write_capacity_units': 50,
            #              'index_name': 'ClassA'}])
            pass

    else:
        parser.print_help()

if __name__ == "__main__":
    main()


text:
<?php

class Sorted extends Schema {
    function __construct(array $config){
        if(isset($config['default'])){
            $default = $config['default'];
        }
        else{
            $default = $config['types'][0];
        }
        $this->_schema = array(
            "type"=> "object",
            "description"=> "Specify the sort type and direction.",
            "additionalProperties"=>false,
            "properties"=> array(
                "fields"=> array(
                    "enum"=>$config['types'],
                    "description"=> "The field(s) to sort on.",
                    "default"=> $default,
                    "minimum"=> 1,
                    "maximum"=> 100
                ),
                "order"=> array(
                    "enum"=>array(
                        "asc",
                        "desc"
                    ),
                    "description"=>"Choose a direction to sort",
                    "default"=>"asc"
                )
            )
        );
    }
}


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace KanColleLib.TransmissionData.api_get_member
{
    public class Ship3
    {
        public Ship2 ship_data;
        public Deck deck_data;
        public Unsetslot slot_data;

        public static Ship3 fromDynamic(dynamic json)
        {
            Ship3 ship3 = new Ship3();

            ship3.ship_data = Ship2.fromDynamic(json.api_ship_data);
            ship3.deck_data = Deck.fromDynamic(json.api_deck_data);
            ship3.slot_data = Unsetslot.fromDynamic(json.api_slot_data);

            return ship3;
        }
    }
}


text:
#include "TextBuilder.h"

namespace Twofold {
namespace intern {

Text TextBuilder::build() const
{
    return m_buffer;
}

const QString &TextBuilder::indentation() const
{
    return m_indentation;
}

int TextBuilder::line() const
{
    return m_line;
}

int TextBuilder::column() const
{
    if (0 == m_column) return 1 + m_indentation.length();
    return m_column;
}

bool TextBuilder::isBlankLine() const
{
    return 0 == m_column;
}

void TextBuilder::setIndentation(const QString &indent)
{
    m_indentation = indent;
}

TextBuilder &TextBuilder::operator<<(const TextSpan &textSpan)
{
    auto it = textSpan.begin;
    const auto end = textSpan.end;
    if (it == end)
        return *this; // empty text does not trigger indentation
    auto column = m_column;
    if (0 == column) m_buffer.append( m_indentation );
    while (true) {
        auto line_end = std::find(it, end, '\n');
        if (line_end != end) {
            ++m_line;
            column = 0;
            ++line_end;
        }
        else {
            if (0 == column) column = 1 + m_indentation.length();
            column += std::distance(it, end);
        }
        m_buffer.append(it, std::distance(it, line_end));
        if (line_end == end)
            break; // end of text reached
        it = line_end;
        m_buffer.append( m_indentation );
    }
    m_column = column;
    return *this;
}

TextBuilder &TextBuilder::operator<<(NewLine)
{
    ++m_line;
    m_column = 0;
    m_buffer.append('\n');
    return *this;
}

} // namespace intern
} // namespace Twofold