text:
package org.jetbrains.plugins.scala
package lang
package psi
package implicits

import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.util.Key
import com.intellij.psi._
import com.intellij.psi.util.{CachedValue, PsiModificationTracker, PsiTreeUtil}
import org.jetbrains.plugins.scala.caches.CachesUtil
import org.jetbrains.plugins.scala.extensions._
import org.jetbrains.plugins.scala.lang.psi.api.InferUtil
import org.jetbrains.plugins.scala.lang.psi.api.base.patterns.ScBindingPattern
import org.jetbrains.plugins.scala.lang.psi.api.expr.{ScExpression, ScMethodCall}
import org.jetbrains.plugins.scala.lang.psi.api.statements._
import org.jetbrains.plugins.scala.lang.psi.api.statements.params.{ScClassParameter, ScParameter}
import org.jetbrains.plugins.scala.lang.psi.api.toplevel.imports.usages.ImportUsed
import org.jetbrains.plugins.scala.lang.psi.api.toplevel.templates.{ScExtendsBlock, ScTemplateBody}
import org.jetbrains.plugins.scala.lang.psi.api.toplevel.typedef._
import org.jetbrains.plugins.scala.lang.psi.api.toplevel.{ScModifierListOwner, ScTypedDefinition}
import org.jetbrains.plugins.scala.lang.psi.impl.ScalaPsiManager
import org.jetbrains.plugins.scala.lang.psi.types.Compatibility.Expression
import org.jetbrains.plugins.scala.lang.psi.types._
import org.jetbrains.plugins.scala.lang.psi.types.nonvalue.Parameter
import org.jetbrains.plugins.scala.lang.psi.types.result.TypingContext
import org.jetbrains.plugins.scala.lang.resolve.processor.{BaseProcessor, ImplicitProcessor}
import org.jetbrains.plugins.scala.lang.resolve.{ResolveUtils, ScalaResolveResult, StdKinds}
import org.jetbrains.plugins.scala.project._
import org.jetbrains.plugins.scala.project.ScalaLanguageLevel.Scala_2_10

import scala.collection.mutable.ArrayBuffer
import scala.collection.{Set, mutable}

/**
 * Utility class for implicit conversions.
 * @author alefas, ilyas
 */
//todo: refactor this terrible code
class ScImplicitlyConvertible(place: PsiElement, placeType: Boolean => Option[ScType]) {
  def this(expr: ScExpression) {
    this(expr, fromUnder => {
      //this code is required, because compiler works in the same way
      //otherwise we will see strange error messages like:
      // def foo(x: Map[String, Int]) {}
      // def foo(x: String) {}
      // foo(Map(y -> 1)) //Error is here
      expr.getTypeWithoutImplicits(TypingContext.empty, fromUnderscore = fromUnder).toOption.map {
        case tp =>
          ScType.extractDesignatorSingletonType(tp) match {
            case Some(res) => res
            case _ => tp
          }
      }
    })
  }

  import org.jetbrains.plugins.scala.lang.psi.implicits.ScImplicitlyConvertible._

  def implicitMap(exp: Option[ScType] = None,
                  fromUnder: Boolean = false,
                  args: Seq[ScType] = Seq.empty,
                  exprType: Option[ScType] = None): Seq[ImplicitResolveResult] = {
    val buffer = new ArrayBuffer[ImplicitResolveResult]
    val seen = new mutable.HashSet[PsiNamedElement]
    for (elem <- implicitMapFirstPart(exp, fromUnder, exprType)) {
      if (!seen.contains(elem.element)) {
        seen += elem.element
        buffer += elem
      }
    }
    for (elem <- implicitMapSecondPart(exp, fromUnder, args = args)) {
      if (!seen.contains(elem.element)) {
        seen += elem.element
        buffer += elem
      }
    }
    buffer.toSeq
  }

  def implicitMapFirstPart(exp: Option[ScType] = None,
                  fromUnder: Boolean = false,
                  exprType: Option[ScType] = None): Seq[ImplicitResolveResult] = {
    type Data = (Option[ScType], Boolean, Option[ScType])
    val data = (exp, fromUnder, exprType)

    CachesUtil.getMappedWithRecursionPreventingWithRollback(place, data, CachesUtil.IMPLICIT_MAP1_KEY,
      (expr: PsiElement, data: Data) => buildImplicitMap(data._1, data._2, isFromCompanion = false, Seq.empty, data._3), Seq.empty,
      PsiModificationTracker.MODIFICATION_COUNT)
  }

  def implicitMapSecondPart(exp: Option[ScType] = None,
                            fromUnder: Boolean = false,
                            args: Seq[ScType] = Seq.empty,
                            exprType: Option[ScType] = None): Seq[ImplicitResolveResult] = {
    type Data = (Option[ScType], Boolean, Seq[ScType], Option[ScType])
    val data = (exp, fromUnder, args, exprType)

    CachesUtil.getMappedWithRecursionPreventingWithRollback(place, data, CachesUtil.IMPLICIT_MAP2_KEY,
      (expr: PsiElement, data: Data) => buildImplicitMap(data._1, data._2, isFromCompanion = true, data._3, data._4), Seq.empty,
      PsiModificationTracker.MODIFICATION_COUNT)
  }

  private def buildImplicitMap(exp: Option[ScType],
                               fromUnder: Boolean = false,
                               isFromCompanion: Boolean,
                               args: Seq[ScType] = Seq.empty,
                               exprType: Option[ScType] = None): Seq[ImplicitResolveResult] = {
    ScalaPsiUtil.debug(s"Implicit map: $exprType, from companion: $isFromCompanion, expected: $exp", LOG)

    val typez: ScType = exprType.getOrElse(placeType(fromUnder).getOrElse(return Seq.empty))

    val buffer = new ArrayBuffer[ImplicitMapResult]
    if (!isFromCompanion) {
      buffer ++= buildSimpleImplicitMap(fromUnder, exprType)
    }
    if (isFromCompanion) {
      val processor = new CollectImplicitsProcessor(true)
      val expandedType: ScType = exp match {
        case Some(expected) =>
          ScFunctionType(expected, Seq(typez) ++ args)(place.getProject, place.getResolveScope)
        case None if args.nonEmpty => ScTupleType(Seq(typez) ++ args)(place.getProject, place.getResolveScope)
        case None => typez
      }
      for (obj <- ScalaPsiUtil.collectImplicitObjects(expandedType, place.getProject, place.getResolveScope)) {
        processor.processType(obj, place, ResolveState.initial())
      }
      for (res <- processor.candidatesS.map(forMap(_, typez)) if res.condition) {
        buffer += res
      }
    }

    val result = new ArrayBuffer[ImplicitResolveResult]

    buffer.foreach{case ImplicitMapResult(_, r, tp, retTp, newSubst, uSubst, implicitDepSusbt) =>
      r.element match {
        case f: ScFunction if f.hasTypeParameters =>
          uSubst.getSubstitutor match {
            case Some(substitutor) =>
              exp match {
                case Some(expected) =>
                  val additionalUSubst = Conformance.undefinedSubst(expected, newSubst.subst(retTp))
                  (uSubst + additionalUSubst).getSubstitutor match {
                    case Some(innerSubst) =>
                      result += ImplicitResolveResult(innerSubst.subst(retTp), r.element, r.importsUsed, r.substitutor,
                        implicitDepSusbt, isFromCompanion)
                    case None =>
                      result += ImplicitResolveResult(substitutor.subst(retTp), r.element, r.importsUsed, r.substitutor,
                        implicitDepSusbt, isFromCompanion)
                  }
                case None =>
                  result += ImplicitResolveResult(substitutor.subst(retTp), r.element, r.importsUsed, r.substitutor,
                    implicitDepSusbt, isFromCompanion)
              }
            case _ =>
          }
        case _ =>
          result += ImplicitResolveResult(retTp, r.element, r.importsUsed, r.substitutor, implicitDepSusbt, isFromCompanion)
      }
    }

    result.toSeq
  }

  private def buildSimpleImplicitMap(fromUnder: Boolean, exprType: Option[ScType] = None): ArrayBuffer[ImplicitMapResult] = {
    type Data = (Boolean, Option[ScType])
    val data = (fromUnder, exprType)
    import org.jetbrains.plugins.scala.caches.CachesUtil._

    getMappedWithRecursionPreventingWithRollback[PsiElement, Data, ArrayBuffer[ImplicitMapResult]](place,
      data, IMPLICIT_SIMPLE_MAP_KEY, (expr: PsiElement, data: Data) => buildSimpleImplicitMapInner(data._1, data._2),
      ArrayBuffer.empty, PsiModificationTracker.MODIFICATION_COUNT)
  }

  private def buildSimpleImplicitMapInner(fromUnder: Boolean, exprType: Option[ScType] = None): ArrayBuffer[ImplicitMapResult] = {
    ScalaPsiUtil.debug(s"Simple implicit map: $exprType", LOG)

    val typez: ScType = exprType.getOrElse(placeType(fromUnder).getOrElse(return ArrayBuffer.empty))

    val processor = new CollectImplicitsProcessor(false)

    // Collect implicit conversions from bottom to up
    def treeWalkUp(p: PsiElement, lastParent: PsiElement) {
      if (p == null) return
      if (!p.processDeclarations(processor,
        ResolveState.initial,
        lastParent, place)) return
      p match {
        case (_: ScTemplateBody | _: ScExtendsBlock) => //template body and inherited members are at the same level
        case _ => if (!processor.changedLevel) return
      }
      treeWalkUp(p.getContext, p)
    }
    treeWalkUp(place, null)

    val result = new ArrayBuffer[ImplicitMapResult]
    if (typez == types.Nothing) return result
    if (typez.isInstanceOf[ScUndefinedType]) return result

    val sigsFound = processor.candidatesS.map(forMap(_, typez))

    for (res <- sigsFound if res.condition) {
      result += res
    }

    result
  }

  def forMap(r: ScalaResolveResult, typez: ScType): ImplicitMapResult = {
    ScalaPsiUtil.debug(s"Check implicit: $r for type: $typez", LOG)

    val default = ImplicitMapResult(condition = false, r, null, null, null, null, null)
    if (!PsiTreeUtil.isContextAncestor(ScalaPsiUtil.nameContext(r.element), place, false)) { //to prevent infinite recursion
      ProgressManager.checkCanceled()

      lazy val funType = Option(
        ScalaPsiManager.instance(place.getProject).getCachedClass(
          "scala.Function1", place.getResolveScope, ScalaPsiManager.ClassCategory.TYPE
        )
      ) collect {
        case cl: ScTrait => ScParameterizedType(ScType.designator(cl), cl.typeParameters.map(tp =>
          new ScUndefinedType(new ScTypeParameterType(tp, ScSubstitutor.empty), 1)))
      } flatMap {
        case p: ScParameterizedType => Some(p)
        case _ => None
      }

      def firstArgType = funType.map(_.typeArgs.head)

      def secondArgType = funType.map(_.typeArgs.apply(1))

      val subst = r.substitutor
      val (tp: ScType, retTp: ScType) = r.element match {
        case f: ScFunction if f.paramClauses.clauses.nonEmpty =>
          val params = f.paramClauses.clauses.head.parameters
          (subst.subst(params.head.getType(TypingContext.empty).getOrNothing),
           subst.subst(f.returnType.getOrNothing))
        case f: ScFunction =>
          Conformance.undefinedSubst(funType.getOrElse(return default), subst.subst(f.returnType.getOrElse(return default))).getSubstitutor match {
            case Some(innerSubst) => (innerSubst.subst(firstArgType.getOrElse(return default)), innerSubst.subst(secondArgType.getOrElse(return default)))
            case _ => (types.Nothing, types.Nothing)
          }
        case b: ScBindingPattern =>
          Conformance.undefinedSubst(funType.getOrElse(return default), subst.subst(b.getType(TypingContext.empty).getOrElse(return default))).getSubstitutor match {
            case Some(innerSubst) => (innerSubst.subst(firstArgType.getOrElse(return default)), innerSubst.subst(secondArgType.getOrElse(return default)))
            case _ => (types.Nothing, types.Nothing)
          }
        case param: ScParameter =>
          // View Bounds and Context Bounds are processed as parameters.
          Conformance.undefinedSubst(funType.getOrElse(return default), subst.subst(param.getType(TypingContext.empty).getOrElse(return default))).
                  getSubstitutor match {
            case Some(innerSubst) => (innerSubst.subst(firstArgType.getOrElse(return default)), innerSubst.subst(secondArgType.getOrElse(return default)))
            case _ => (types.Nothing, types.Nothing)
          }
        case obj: ScObject =>
          Conformance.undefinedSubst(funType.getOrElse(return default), subst.subst(obj.getType(TypingContext.empty).getOrElse(return default))).
                  getSubstitutor match {
            case Some(innerSubst) => (innerSubst.subst(firstArgType.getOrElse(return default)), innerSubst.subst(secondArgType.getOrElse(return default)))
            case _ => (types.Nothing, types.Nothing)
          }
      }
      val newSubst = r.element match {
        case f: ScFunction => ScalaPsiUtil.inferMethodTypesArgs(f, r.substitutor)
        case _ => ScSubstitutor.empty
      }
      if (!typez.weakConforms(newSubst.subst(tp))) {
        ScalaPsiUtil.debug(s"Implicit $r doesn't conform to $typez", LOG)

        ImplicitMapResult(condition = false, r, tp, retTp, null, null, null)
      } else {
        r.element match {
          case f: ScFunction if f.hasTypeParameters =>
            var uSubst = Conformance.undefinedSubst(newSubst.subst(tp), typez)
            uSubst.getSubstitutor(notNonable = false) match {
              case Some(unSubst) =>
                def hasRecursiveTypeParameters(typez: ScType): Boolean = {

                  var hasRecursiveTypeParameters = false
                  typez.recursiveUpdate {
                    case tpt: ScTypeParameterType =>
                      f.typeParameters.find(tp => (tp.name, ScalaPsiUtil.getPsiElementId(tp)) == (tpt.name, tpt.getId)) match {
                        case None => (true, tpt)
                        case _ =>
                          hasRecursiveTypeParameters = true
                          (true, tpt)
                      }
                    case tp: ScType => (hasRecursiveTypeParameters, tp)
                  }
                  hasRecursiveTypeParameters
                }
                for (tParam <- f.typeParameters) {
                  val lowerType: ScType = tParam.lowerBound.getOrNothing
                  if (lowerType != types.Nothing) {
                    val substedLower = unSubst.subst(subst.subst(lowerType))
                    if (!hasRecursiveTypeParameters(substedLower)) {
                      uSubst = uSubst.addLower((tParam.name, ScalaPsiUtil.getPsiElementId(tParam)), substedLower, additional = true)
                    }
                  }
                  val upperType: ScType = tParam.upperBound.getOrAny
                  if (upperType != types.Any) {
                    val substedUpper = unSubst.subst(subst.subst(upperType))
                    if (!hasRecursiveTypeParameters(substedUpper)) {
                      uSubst = uSubst.addUpper((tParam.name, ScalaPsiUtil.getPsiElementId(tParam)), substedUpper, additional = true)
                    }
                  }
                }

                uSubst.getSubstitutor(notNonable = false) match {
                  case Some(unSubst) =>
                    //let's update dependent method types
                    //todo: currently it looks like a hack in the right place, probably whole this class should be
                    //todo: rewritten in more clean and clear way.
                    val dependentSubst = new ScSubstitutor(() => {
                      val level = place.languageLevel
                      if (level >= Scala_2_10) {
                        f.paramClauses.clauses.headOption.map(_.parameters).toSeq.flatten.map {
                          case (param: ScParameter) => (new Parameter(param), typez)
                        }.toMap
                      } else Map.empty
                    })

                    def probablyHasDepententMethodTypes: Boolean = {
                      if (f.paramClauses.clauses.length != 2 || !f.paramClauses.clauses.last.isImplicit) return false
                      val implicitClauseParameters = f.paramClauses.clauses.last.parameters
                      var res = false
                      f.returnType.foreach(_.recursiveUpdate {
                        case rtTp if res => (true, rtTp)
                        case ScDesignatorType(p: ScParameter) if implicitClauseParameters.contains(p) =>
                          res = true
                          (true, tp)
                        case tp: ScType => (false, tp)
                      })
                      res
                    }

                    val implicitDependentSubst = new ScSubstitutor(() => {
                      val level = place.languageLevel
                      if (level >= Scala_2_10) {
                        if (probablyHasDepententMethodTypes) {
                          val params: Seq[Parameter] = f.paramClauses.clauses.last.effectiveParameters.map(
                            param => new Parameter(param))
                          val (inferredParams, expr, _) = InferUtil.findImplicits(params, None,
                            place, check = false, abstractSubstitutor = subst followed dependentSubst followed unSubst)
                          inferredParams.zip(expr).map {
                            case (param: Parameter, expr: Expression) =>
                              (param, expr.getTypeAfterImplicitConversion(checkImplicits = true, isShape = false, None)._1.get)
                          }.toMap
                        } else Map.empty
                      } else Map.empty
                    })

                    //todo: pass implicit parameters
                    ScalaPsiUtil.debug(s"Implicit $r is ok for type $typez", LOG)
                    ImplicitMapResult(condition = true, r, tp, dependentSubst.subst(retTp), newSubst, uSubst, implicitDependentSubst)
                  case _ =>
                    ScalaPsiUtil.debug(s"Implicit $r has problems with type parameters bounds for type $typez", LOG)
                    ImplicitMapResult(condition = false, r, tp, retTp, null, null, null)
                }
              case _ =>
                ScalaPsiUtil.debug(s"Implicit $r has problems with type parameters bounds for type $typez", LOG)
                ImplicitMapResult(condition = false, r, tp, retTp, null, null, null)
            }
          case _ =>
            ScalaPsiUtil.debug(s"Implicit $r is ok for type $typez", LOG)
            ImplicitMapResult(condition = true, r, tp, retTp, newSubst, null: ScUndefinedSubstitutor, ScSubstitutor.empty)
        }
      } //possible true
    } else default
  }

  class CollectImplicitsProcessor(withoutPrecedence: Boolean) extends ImplicitProcessor(StdKinds.refExprLastRef, withoutPrecedence) {
    //can be null (in Unit tests or without library)
    private val funType: ScType = {
      val funClass: PsiClass = ScalaPsiManager.instance(place.getProject).getCachedClass(place.getResolveScope, "scala.Function1")
      funClass match {
        case cl: ScTrait => ScParameterizedType(ScType.designator(funClass), cl.typeParameters.map(tp =>
          new ScUndefinedType(new ScTypeParameterType(tp, ScSubstitutor.empty))))
        case _ => null
      }
    }

    protected def getPlace: PsiElement = place

    def execute(element: PsiElement, state: ResolveState): Boolean = {
      def fromType: Option[ScType] = state.get(BaseProcessor.FROM_TYPE_KEY).toOption
      lazy val subst: ScSubstitutor = fromType match {
        case Some(tp) => getSubst(state).addUpdateThisType(tp)
        case _ => getSubst(state)
      }

      element match {
        case named: PsiNamedElement if kindMatches(element) => named match {
          //there is special case for Predef.conforms method
          case f: ScFunction if f.hasModifierProperty("implicit") && !isConformsMethod(f) =>
            if (!ScImplicitlyConvertible.checkFucntionIsEligible(f, place) ||
              !ResolveUtils.isAccessible(f, getPlace)) return true
            val clauses = f.paramClauses.clauses
            //filtered cases
            if (clauses.length > 2) return true
            if (clauses.length == 2) {
              if (!clauses(1).isImplicit) {
                return true
              }
              if (f.hasTypeParameters) {
                val typeParameters = f.typeParameters
                for {
                  param <- clauses(1).parameters
                  paramType <- param.getType(TypingContext.empty)
                } {
                  var hasTypeParametersInType = false
                  paramType.recursiveUpdate {
                    case tp@ScTypeParameterType(name, _, _, _, _) if typeParameters.contains(name) =>
                      hasTypeParametersInType = true
                      (true, tp)
                    case tp: ScType if hasTypeParametersInType => (true, tp)
                    case tp: ScType => (false, tp)
                  }
                  if (hasTypeParametersInType) return true //looks like it's not working in compiler 2.10, so it's faster to avoid it
                }
              }
            }
            if (clauses.isEmpty) {
              val rt = subst.subst(f.returnType.getOrElse(return true))
              if (funType == null || !rt.conforms(funType)) return true
            } else if (clauses.head.parameters.length != 1 || clauses.head.isImplicit) return true
            addResult(new ScalaResolveResult(f, subst, getImports(state)))
          case b: ScBindingPattern =>
            ScalaPsiUtil.nameContext(b) match {
              case d: ScDeclaredElementsHolder if (d.isInstanceOf[ScValue] || d.isInstanceOf[ScVariable]) &&
                      d.asInstanceOf[ScModifierListOwner].hasModifierProperty("implicit") =>
                if (!ResolveUtils.isAccessible(d.asInstanceOf[ScMember], getPlace)) return true
                val tp = subst.subst(b.getType(TypingContext.empty).getOrElse(return true))
                if (funType == null || !tp.conforms(funType)) return true
                addResult(new ScalaResolveResult(b, subst, getImports(state)))
              case _ => return true
            }
          case param: ScParameter if param.isImplicitParameter =>
            param match {
              case c: ScClassParameter =>
                if (!ResolveUtils.isAccessible(c, getPlace)) return true
              case _ =>
            }
            val tp = subst.subst(param.getType(TypingContext.empty).getOrElse(return true))
            if (funType == null || !tp.conforms(funType)) return true
            addResult(new ScalaResolveResult(param, subst, getImports(state)))
          case obj: ScObject if obj.hasModifierProperty("implicit") =>
            if (!ResolveUtils.isAccessible(obj, getPlace)) return true
            val tp = subst.subst(obj.getType(TypingContext.empty).getOrElse(return true))
            if (funType == null || !tp.conforms(funType)) return true
            addResult(new ScalaResolveResult(obj, subst, getImports(state)))
          case _ =>
        }
        case _ =>
      }
      true
    }
  }

  private def isConformsMethod(f: ScFunction): Boolean = {
    (f.name == "conforms" || f.name == "$conforms") &&
            Option(f.containingClass).flatMap(cls => Option(cls.qualifiedName)).contains("scala.Predef")
  }
}

object ScImplicitlyConvertible {
  private implicit val LOG = Logger.getInstance("#org.jetbrains.plugins.scala.lang.psi.implicits.ScImplicitlyConvertible")

  val IMPLICIT_RESOLUTION_KEY: Key[PsiClass] = Key.create("implicit.resolution.key")
  val IMPLICIT_CONVERSIONS_KEY: Key[CachedValue[collection.Map[ScType, Set[(ScFunctionDefinition, Set[ImportUsed])]]]] = Key.create("implicit.conversions.key")

  case class Implicit(tp: ScType, fun: ScTypedDefinition, importsUsed: Set[ImportUsed])

  val IMPLICIT_REFERENCE_NAME = "implicitReferenceName"
  val IMPLICIT_EXPRESSION_NAME = "implicitExpressionName"
  val IMPLICIT_CALL_TEXT = IMPLICIT_REFERENCE_NAME + "(" + IMPLICIT_EXPRESSION_NAME + ")"

  val FAKE_RESOLVE_RESULT_KEY: Key[ScalaResolveResult] = Key.create("fake.resolve.result.key")
  val FAKE_EXPRESSION_TYPE_KEY: Key[ScType] = Key.create("fake.expr.type.key")
  val FAKE_EXPECTED_TYPE_KEY: Key[Option[ScType]] = Key.create("fake.expected.type.key")

  def setupFakeCall(expr: ScMethodCall, rr: ScalaResolveResult, tp: ScType, expected: Option[ScType]) {
    expr.getInvokedExpr.putUserData(FAKE_RESOLVE_RESULT_KEY, rr)
    expr.args.exprs.head.putUserData(FAKE_EXPRESSION_TYPE_KEY, tp)
    expr.putUserData(FAKE_EXPECTED_TYPE_KEY, expected)
  }

  def checkFucntionIsEligible(function: ScFunction, place: PsiElement): Boolean = {
    if (!function.hasExplicitType) {
      if (PsiTreeUtil.isContextAncestor(function.getContainingFile, place, false)) {
        val commonContext = PsiTreeUtil.findCommonContext(function, place)
        if (place == commonContext) return true //weird case, it covers situation, when function comes from object, not treeWalkUp
        if (function == commonContext) return false
        else {
          var functionContext: PsiElement = function
          while (functionContext.getContext != commonContext) functionContext = functionContext.getContext
          var placeContext: PsiElement = place
          while (placeContext.getContext != commonContext) placeContext = placeContext.getContext
          (functionContext, placeContext) match {
            case (functionContext: ScalaPsiElement, placeContext: ScalaPsiElement) =>
              val funElem = functionContext.getDeepSameElementInContext
              val conElem = placeContext.getDeepSameElementInContext
              val children = commonContext match {
                case stubPsi: StubBasedPsiElement[_] =>
                  val stub = stubPsi.getStub
                  import scala.collection.JavaConverters._
                  if (stub != null) stub.getChildrenStubs.asScala.map(_.getPsi).toArray
                  else stubPsi.getChildren
                case _ => commonContext.getChildren
              }
              children.find(elem => elem == funElem || elem == conElem) match {
                case Some(elem) if elem == conElem => return false
                case _ =>
              }
            case _ =>
          }
        }
      }
    }
    true
  }

  case class ImplicitMapResult(condition: Boolean, resolveResult: ScalaResolveResult, tp: ScType, rt: ScType,
                               newSubst: ScSubstitutor, subst: ScUndefinedSubstitutor,
                               implicitDependentSubst: ScSubstitutor)

  case class ImplicitResolveResult(tp: ScType, element: PsiNamedElement, importUsed: Set[ImportUsed],
                                   subst: ScSubstitutor, implicitDependentSubst: ScSubstitutor, isFromCompanion: Boolean) {
    def getClazz: Option[PsiClass] = {
      element.getParent match {
        case tb: ScTemplateBody => Some(PsiTreeUtil.getParentOfType(tb, classOf[PsiClass]))
        case _ => None
      }
    }

    def getTypeWithDependentSubstitutor: ScType = implicitDependentSubst.subst(tp)
  }

}


text:
class Rejoin
  include Cinch::Plugin

  set :help, 'If the bot is kicked, it will attempt to rejoin after 10 seconds by default.'

  listen_to :kick
  def listen(m)
    return unless User(m.params[1]) == @bot
    sleep config[:delay] || 10
    m.channel.join(m.channel.key)
  end
end

redpajama_set_name: RedPajamaGithub


text:
//  CovarianceMatrixAdaptationEvolutionStrategy.java
//
//  Author:
//       Esteban López-Camacho <esteban@lcc.uma.es>
//
//  Copyright (c) 2014 Antonio J. Nebro
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.

package org.uma.jmetal.algorithm.singleobjective.evolutionstrategy;

import org.uma.jmetal.algorithm.impl.AbstractEvolutionStrategy;
import org.uma.jmetal.algorithm.singleobjective.evolutionstrategy.util.CMAESUtils;
import org.uma.jmetal.problem.DoubleProblem;
import org.uma.jmetal.solution.DoubleSolution;
import org.uma.jmetal.util.JMetalLogger;
import org.uma.jmetal.util.comparator.ObjectiveComparator;

import java.util.*;

/**
 * Class implementing the CMA-ES algorithm
 */
@SuppressWarnings("serial")
public class CovarianceMatrixAdaptationEvolutionStrategy
    extends AbstractEvolutionStrategy<DoubleSolution, DoubleSolution> {
  private Comparator<DoubleSolution> comparator ;
  private int lambda ;
  private int evaluations ;
  private int maxEvaluations ;
  private double[] typicalX;

  /**
   * CMA-ES state variables
   */

  // Distribution mean and current favorite solution to the optimization problem
  private double[] distributionMean;

  // coordinate wise standard deviation (step size)
  private double sigma;

  // Symmetric and positive definitive covariance matrix
  private double[][] c;

  // Evolution paths for c and sigma
  private double[] pathsC;
  private double[] pathsSigma;

  /*
   * Strategy parameter setting: Selection
   */

  // number of parents/points for recombination
  private int mu;

  private double[] weights;
  private double muEff;

  /*
   * Strategy parameter setting: Adaptation
   */

  // time constant for cumulation for c
  private double cumulationC;

  // t-const for cumulation for sigma control
  private double cumulationSigma;

  // learning rate for rank-one update of c
  private double c1;

  // learning rate for rank-mu update
  private double cmu;

  // damping for sigma
  private double dampingSigma;

  /*
   * Dynamic (internal) strategy parameters and constants
   */

  // coordinate system
  private double[][] b;

  // diagonal D defines the scaling
  private double[] diagD;

  // c^1/2
  private double[][] invSqrtC;

  // track update of b and c
  private int eigenEval;

  private double chiN;

  private DoubleSolution bestSolutionEver = null;

  private Random rand;

  /** Constructor */
  private CovarianceMatrixAdaptationEvolutionStrategy (Builder builder) {
    super(builder.problem) ;
    this.lambda = builder.lambda ;
    this.maxEvaluations = builder.maxEvaluations ;
    this.typicalX = builder.typicalX;
    this.sigma = builder.sigma;

    long seed = System.currentTimeMillis();
    rand = new Random(seed);
    comparator = new ObjectiveComparator<DoubleSolution>(0);

    initializeInternalParameters();

  }

  /* Getters */
  public int getLambda() {
    return lambda;
  }

  public int getMaxEvaluations() {
    return maxEvaluations;
  }

  /**
   * Buider class
   */
  public static class Builder {
    private static final int DEFAULT_LAMBDA = 10 ;
    private static final int DEFAULT_MAX_EVALUATIONS = 1000000 ;
    private static final double DEFAULT_SIGMA = 0.3;

    private DoubleProblem problem ;
    private int lambda ;
    private int maxEvaluations ;
    private double [] typicalX;
    private double sigma;

    public Builder(DoubleProblem problem) {
      this.problem = problem;
      lambda = DEFAULT_LAMBDA;
      maxEvaluations = DEFAULT_MAX_EVALUATIONS;
      sigma = DEFAULT_SIGMA;
    }

    public Builder setLambda(int lambda) {
      this.lambda = lambda;
      return this;
    }

    public Builder setMaxEvaluations(int maxEvaluations) {
      this.maxEvaluations = maxEvaluations;
      return this;
    }

    public Builder setTypicalX (double [] typicalX) {
      this.typicalX = typicalX;
      return this;
    }

    public Builder setSigma (double sigma) {
      this.sigma = sigma;
      return this;
    }

    public CovarianceMatrixAdaptationEvolutionStrategy build() {
      return new CovarianceMatrixAdaptationEvolutionStrategy(this);
    }
  }

  @Override protected void initProgress() {
    evaluations = 0;
  }

  @Override protected void updateProgress() {
    evaluations += lambda;
    updateInternalParameters();
  }

  @Override protected boolean isStoppingConditionReached() {
    return evaluations >= maxEvaluations;
  }

  @Override protected List<DoubleSolution> createInitialPopulation() {
    List<DoubleSolution> population = new ArrayList<>(lambda);
    for (int i = 0; i < lambda; i++) {
      DoubleSolution newIndividual = getProblem().createSolution();
      population.add(newIndividual);
    }
    return population;
  }

  @Override protected List<DoubleSolution> evaluatePopulation(List<DoubleSolution> population) {
    for (DoubleSolution solution : population) {
      getProblem().evaluate(solution);
    }
    return population;
  }

  @Override protected List<DoubleSolution> selection(List<DoubleSolution> population) {
    return population;
  }

  @Override protected List<DoubleSolution> reproduction(List<DoubleSolution> population) {

    List<DoubleSolution> offspringPopulation = new ArrayList<>(lambda);

    for (int iNk = 0; iNk < lambda; iNk++) {
      offspringPopulation.add(sampleSolution());
    }

    return offspringPopulation;
  }

  @Override protected List<DoubleSolution> replacement(List<DoubleSolution> population,
      List<DoubleSolution> offspringPopulation) {
    return offspringPopulation;
  }

  @Override public DoubleSolution getResult() {
    return bestSolutionEver;
  }

  private void initializeInternalParameters() {

    // number of objective variables/problem dimension
    int numberOfVariables = getProblem().getNumberOfVariables();

    // objective variables initial point
    // TODO: Initialize the mean in a better way

    if (typicalX != null) {
      distributionMean = typicalX;
    } else {
      distributionMean = new double[numberOfVariables];
      for (int i = 0; i < numberOfVariables; i++) {
        distributionMean[i] = rand.nextDouble();
      }
    }

    /* Strategy parameter setting: Selection */

    // number of parents/points for recombination
    mu = (int) Math.floor(lambda / 2);

    // muXone array for weighted recombination
    weights = new double[mu];
    double sum = 0;
    for (int i = 0; i < mu; i++) {
      weights[i] = (Math.log(mu + 1 / 2) - Math.log(i + 1));
      sum += weights[i];
    }
    // normalize recombination weights array
    for (int i = 0; i < mu; i++) {
      weights[i] = weights[i] / sum;
    }

    // variance-effectiveness of sum w_i x_i
    double sum1 = 0;
    double sum2 = 0;
    for (int i = 0; i < mu; i++) {
      sum1 += weights[i];
      sum2 += weights[i] * weights[i];
    }
    muEff = sum1 * sum1 / sum2;

    /* Strategy parameter setting: Adaptation */

    // time constant for cumulation for C
    cumulationC =
        (4 + muEff / numberOfVariables) / (numberOfVariables + 4 + 2 * muEff / numberOfVariables);

    // t-const for cumulation for sigma control
    cumulationSigma = (muEff + 2) / (numberOfVariables + muEff + 5);

    // learning rate for rank-one update of C
    c1 = 2 / ((numberOfVariables + 1.3) * (numberOfVariables + 1.3) + muEff);

    // learning rate for rank-mu update
    cmu = Math.min(1 - c1,
        2 * (muEff - 2 + 1 / muEff) / ((numberOfVariables + 2) * (numberOfVariables + 2) + muEff));

    // damping for sigma, usually close to 1
    dampingSigma = 1 +
        2 * Math.max(0, Math.sqrt((muEff - 1) / (numberOfVariables + 1)) - 1) + cumulationSigma;

    /* Initialize dynamic (internal) strategy parameters and constants */

    // diagonal D defines the scaling
    diagD = new double[numberOfVariables];

    // evolution paths for C and sigma
    pathsC = new double[numberOfVariables];
    pathsSigma = new double[numberOfVariables];

    // b defines the coordinate system
    b = new double[numberOfVariables][numberOfVariables];
    // covariance matrix C
    c = new double[numberOfVariables][numberOfVariables];

    // C^-1/2
    invSqrtC = new double[numberOfVariables][numberOfVariables];

    for (int i = 0; i < numberOfVariables; i++) {
      pathsC[i] = 0;
      pathsSigma[i] = 0;
      diagD[i] = 1;
      for (int j = 0; j < numberOfVariables; j++) {
        b[i][j] = 0;
        invSqrtC[i][j] = 0;
      }
      for (int j = 0; j < i; j++) {
        c[i][j] = 0;
      }
      b[i][i] = 1;
      c[i][i] = diagD[i] * diagD[i];
      invSqrtC[i][i] = 1;
    }

    // track update of b and D
    eigenEval = 0;

    chiN = Math.sqrt(numberOfVariables) * (1 - 1 / (4 * numberOfVariables) + 1 / (21
        * numberOfVariables * numberOfVariables));

  }

  private void updateInternalParameters() {

    int numberOfVariables = getProblem().getNumberOfVariables();

    double[] oldDistributionMean = new double[numberOfVariables];
    System.arraycopy( distributionMean, 0, oldDistributionMean, 0, numberOfVariables );

    // Sort by fitness and compute weighted mean into distributionMean
    // minimization
    Collections.sort(getPopulation(), comparator);
    storeBest();

    // calculate new distribution mean and BDz~N(0,C)
    updateDistributionMean();

    // Cumulation: Update evolution paths
    int hsig = updateEvolutionPaths(oldDistributionMean);

    // Adapt covariance matrix C
    adaptCovarianceMatrix(oldDistributionMean, hsig);

    // Adapt step size sigma
    double psxps = CMAESUtils.norm(pathsSigma);
    sigma *= Math.exp((cumulationSigma / dampingSigma) * (Math.sqrt(psxps) / chiN - 1));

    // Decomposition of C into b*diag(D.^2)*b' (diagonalization)
    decomposeCovarianceMatrix();

  }

  private void updateDistributionMean() {

    int numberOfVariables = getProblem().getNumberOfVariables();

    for (int i = 0; i < numberOfVariables; i++) {
      distributionMean[i] = 0.;
      for (int iNk = 0; iNk < mu; iNk++) {
        double variableValue = (double) getPopulation().get(iNk).getVariableValue(i);
        distributionMean[i] += weights[iNk] * variableValue;
      }
    }

  }

  private int updateEvolutionPaths(double[] oldDistributionMean) {

    int numberOfVariables = getProblem().getNumberOfVariables();

    double[] artmp = new double[numberOfVariables];
    for (int i = 0; i < numberOfVariables; i++) {
      artmp[i] = 0;
      for (int j = 0; j < numberOfVariables; j++) {
        artmp[i] += invSqrtC[i][j] * (distributionMean[j] - oldDistributionMean[j]) / sigma;
      }
    }
    // cumulation for sigma (pathsSigma)
    for (int i = 0; i < numberOfVariables; i++) {
      pathsSigma[i] = (1. - cumulationSigma) * pathsSigma[i]
          + Math.sqrt(cumulationSigma * (2. - cumulationSigma) * muEff) * artmp[i];
    }

    // calculate norm(pathsSigma)^2
    double psxps = CMAESUtils.norm(pathsSigma);

    // cumulation for covariance matrix (pathsC)
    int hsig = 0;
    if ((Math.sqrt(psxps) / Math
        .sqrt(1. - Math.pow(1. - cumulationSigma, 2. * evaluations / lambda)) / chiN) < (1.4
        + 2. / (numberOfVariables + 1.))) {
      hsig = 1;
    }
    for (int i = 0; i < numberOfVariables; i++) {
      pathsC[i] = (1. - cumulationC) * pathsC[i]
            + hsig * Math.sqrt(cumulationC * (2. - cumulationC) * muEff)
            * (distributionMean[i] - oldDistributionMean[i])
            / sigma;
    }

    return hsig;

  }

  private void adaptCovarianceMatrix(double[] oldDistributionMean, int hsig) {

    int numberOfVariables = getProblem().getNumberOfVariables();

    for (int i = 0; i < numberOfVariables; i++) {
      for (int j = 0; j <= i; j++) {
        c[i][j] = (1 - c1 - cmu) * c[i][j]
              + c1
              * (pathsC[i] * pathsC[j] + (1 - hsig) * cumulationC
              * (2. - cumulationC) * c[i][j]);
        for (int k = 0; k < mu; k++) {
          /*
           * additional rank mu
           * update
           */
          double valueI = getPopulation().get(k).getVariableValue(i);
          double valueJ = getPopulation().get(k).getVariableValue(j);
          c[i][j] += cmu
                * weights[k]
                * (valueI - oldDistributionMean[i])
                * (valueJ - oldDistributionMean[j]) /sigma
                / sigma;
        }
      }
    }

  }

  private void decomposeCovarianceMatrix() {
    int numberOfVariables = getProblem().getNumberOfVariables();

    if (evaluations - eigenEval > lambda / (c1 + cmu) / numberOfVariables / 10) {

      eigenEval = evaluations;

      // enforce symmetry
      for (int i = 0; i < numberOfVariables; i++) {
        for (int j = 0; j <= i; j++) {
          b[i][j] = b[j][i] = c[i][j];
        }
      }

      // eigen decomposition, b==normalized eigenvectors
      double[] offdiag = new double[numberOfVariables];
      CMAESUtils.tred2(numberOfVariables, b, diagD, offdiag);
      CMAESUtils.tql2(numberOfVariables, diagD, offdiag, b);

      checkEigenCorrectness();

      double[][] artmp2 = new double[numberOfVariables][numberOfVariables];
      for (int i = 0; i < numberOfVariables; i++) {
        if (diagD[i] > 0) {
          diagD[i] = Math.sqrt(diagD[i]);
        }
        for (int j = 0; j < numberOfVariables; j++) {
          artmp2[i][j] = b[i][j] * (1 / diagD[j]);
        }
      }
      for (int i = 0; i < numberOfVariables; i++) {
        for (int j = 0; j < numberOfVariables; j++) {
          invSqrtC[i][j] = 0.0;
          for (int k = 0; k < numberOfVariables; k++) {
            invSqrtC[i][j] += artmp2[i][k] * b[j][k];
          }
        }
      }

    }

  }

  private void checkEigenCorrectness() {
    int numberOfVariables = getProblem().getNumberOfVariables();

    if (CMAESUtils.checkEigenSystem(numberOfVariables, c, diagD, b) > 0) {
      evaluations = maxEvaluations;
    }

    for (int i = 0; i < numberOfVariables; i++) {
      // Numerical problem?
      if (diagD[i] < 0) {
        JMetalLogger.logger.severe(
              "CovarianceMatrixAdaptationEvolutionStrategy.updateDistribution:" +
                    " WARNING - an eigenvalue has become negative.");
        evaluations = maxEvaluations;
      }
    }

  }

  private DoubleSolution sampleSolution() {

    DoubleSolution solution = getProblem().createSolution();

    int numberOfVariables = getProblem().getNumberOfVariables();
    double[] artmp = new double[numberOfVariables];
    double sum;

    for (int i = 0; i < numberOfVariables; i++) {
      //TODO: Check the correctness of this random (http://en.wikipedia.org/wiki/CMA-ES)
      artmp[i] = diagD[i] * rand.nextGaussian();
    }
    for (int i = 0; i < numberOfVariables; i++) {
      sum = 0.0;
      for (int j = 0; j < numberOfVariables; j++) {
        sum += b[i][j] * artmp[j];
      }

      double value = distributionMean[i] + sigma * sum;
      if (value > ((DoubleProblem)getProblem()).getUpperBound(i)) {
        value = ((DoubleProblem)getProblem()).getUpperBound(i);
      } else if (value < ((DoubleProblem)getProblem()).getLowerBound(i)) {
        value = ((DoubleProblem)getProblem()).getLowerBound(i);
      }

      solution.setVariableValue(i, value);
    }

    return solution;
  }

  private void storeBest() {
    if ((bestSolutionEver == null) || (bestSolutionEver.getObjective(0) > getPopulation().get(0)
        .getObjective(0))) {
      bestSolutionEver = getPopulation().get(0);
    }
  }

  @Override public String getName() {
    return "CMAES" ;
  }

  @Override public String getDescription() {
    return "Covariance Matrix Adaptation Evolution Strategy" ;
  }

}


text:
layout: post
date: '2015-08-04'
title: "Bonny Bliss Bonny Love 6519 Modest Lace Ball Gown Wedding Dress"
category: Bonny Bliss
tags: [Bonny Bliss]
---
### Bonny Bliss Bonny Love 6519 Modest Lace Ball Gown Wedding Dress
Just **$300.99**
###

This princess gown is covered with delicate lace appliques. The natural waist is adorned with a beaded band. The full skirt wraps around to complete the train and zipper closure.Fabrics: Tulle

Colors available: Ivory, White

Buy it: [https://www.eudances.com/en/bonny-bliss/3869-bonny-love-6519-modest-lace-ball-gown-wedding-dress.html](https://www.eudances.com/en/bonny-bliss/3869-bonny-love-6519-modest-lace-ball-gown-wedding-dress.html)


text:
<!doctype html>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="/stylesheets/styles.css">
    <title>Obachuka</title>

First alpha

      by Obachuka

Here's my first version of the game! It's only been tested on Chrome and Firefox. Any other browser is on their own. Input doesn't work on mobile phones either.

There's still a bunch of bugs in this release, and I couldn't get text rendering working either, so I'm printing it to the console output. As I've said before, I want to replace my font code anyways.

I want to give a shoutout to John Sharp's blog. Emscripten has a lot of documentation, but for some reason, I could not find the basic usage instructions. And this guy has it all neatly compiled together on his blog.


text:
package com.lightcrafts.image.metadata;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.io.File;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.HashSet;
import java.util.Set;

import com.lightcrafts.image.BadImageFileException;
import com.lightcrafts.image.metadata.values.*;
import com.lightcrafts.utils.bytebuffer.LCByteBuffer;
import com.lightcrafts.utils.Rational;

import static com.lightcrafts.image.metadata.EXIFConstants.*;
import static com.lightcrafts.image.metadata.EXIFTags.*;
import static com.lightcrafts.image.metadata.ImageMetadataConstants.*;
import static com.lightcrafts.image.types.TIFFConstants.*;

/**
 * An EXIFParser is used to parse raw EXIF metadata from an image.
 *
 * @author Paul J. Lucas [paul@lightcrafts.com]
 */
public final class EXIFParser {

    ////////// public /////////////////////////////////////////////////////////

    /**
     * Construct an EXIFParser.
     *
     * @param imageFile The image to read the metadata from.
     * @param exifSegBuf The {@link ByteBuffer} containing the raw binary EXIF
     * metadata from the image file.  Note that this is a subset of the
     * {@link ByteBuffer} of the entire image file.
     * @param isSubdirectory This is true only if we're reading a
     * subdirectory.
     */
    public EXIFParser( EXIFParserEventHandler handler, File imageFile,
                       LCByteBuffer exifSegBuf, boolean isSubdirectory ) {
        m_buf = exifSegBuf;
        m_handler = handler;
        m_imageFile = imageFile;
        m_isSubdirectory = isSubdirectory;
    }

    /**
     * Parse the metadata from all directories.
     */
    public void parseAllDirectories() throws IOException {
        int ifdOffset = EXIF_HEADER_START_SIZE + m_buf.getInt();
        final Set<Integer> ifdOffsetSet = new HashSet<Integer>();
        while ( true ) {
            if ( ifdOffset == 0 )
                break;
            if ( ifdOffset < 0 ) {
                m_handler.gotBadMetadata( "IFD offset < 0" );
                break;
            }
            if ( !ifdOffsetSet.add( ifdOffset ) ) {
                //
                // There are some bad images in the wild where the next IFD
                // offset refers to a previous offset: catch this case to
                // prevent an infinite loop.
                //
                break;
            }
            final ImageMetadataDirectory dir = m_handler.gotDirectory();
            parseDirectory( ifdOffset, 0, dir );
            if ( m_stop )
                break;
            ifdOffset = m_buf.getInt();
            if ( ifdOffset > 0 ) {
                ifdOffset += EXIF_HEADER_START_SIZE;
                if ( ifdOffset >= m_buf.limit() )
                    m_handler.gotBadMetadata( "IFD offset >= EXIF limit" );
            }
        }
    }

    /**
     * Parse the metadata from a single directory.
     *
     * @param offset The offset from the beginning of the file of the
     * directory.
     * @param valueOffsetAdjustment The larger-than-4-byte-value offset
     * adjustment.
     * @param dir The {@link ImageMetadataDirectory}to parse metadata for.
     */
    public void parseDirectory( int offset, int valueOffsetAdjustment,
                                ImageMetadataDirectory dir ) throws IOException {
        int entryCount = m_buf.getUnsignedShort( offset );
        if ( entryCount > DIRECTORY_ENTRY_MAX_SANE_COUNT )
            entryCount = DIRECTORY_ENTRY_MAX_SANE_COUNT;
        for ( int entry = 0; entry < entryCount; ++entry ) {
            try {
                final int pos = calcIFDEntryPosition( offset, entry );
                parseDirectoryEntry( pos, valueOffsetAdjustment, dir );
            }
            catch ( IOException e ) {
                throw e;
            }
            catch ( Exception e ) {
                m_handler.gotBadMetadata( e );
            }
            if ( m_stop )
                return;
        }
        //
        // Position the buffer immediately after the last entry so
        // readAllDirectories() can read the following offset to the next
        // directory, if any.
        //
        m_buf.position( calcIFDEntryPosition( offset, entryCount ) );
    }

    /**
     * Parse the EXIF header.
     *
     * @throws BadImageFileException if the header isn't as it's expected to be.
     */
    public void parseHeader() throws BadImageFileException, IOException {
        m_buf.position( 0 );
        if ( m_buf.remaining() < EXIF_HEADER_SIZE )
            throw new BadImageFileException( m_imageFile );
        if ( !m_buf.getEquals( "Exif", "ASCII" ) )
            throw new BadImageFileException( m_imageFile );
        m_buf.skipBytes( 2 );

        final int byteOrder = m_buf.getShort();
        if ( byteOrder == TIFF_LITTLE_ENDIAN )
            m_buf.order( ByteOrder.LITTLE_ENDIAN );
        else if ( byteOrder == TIFF_BIG_ENDIAN )
            m_buf.order( ByteOrder.BIG_ENDIAN );
        else
            throw new BadImageFileException( m_imageFile );

        if ( m_buf.getUnsignedShort() != TIFF_MAGIC_NUMBER )
            throw new BadImageFileException( m_imageFile );
    }

    /**
     * Parse a value (or values) for a given EXIF tag.
     *
     * @param tagID The ID of the tag that "owns" this value.
     * @param fieldType The type of value.
     * @param offset The offset of the first byte of the value.
     * @param numValues The number of values.
     * @return Returns a new {@link ImageMetaValue}.
     */
    public ImageMetaValue parseValue( int tagID, int fieldType, int offset,
                                      int numValues ) throws IOException {
        switch ( fieldType ) {

            case EXIF_FIELD_TYPE_STRING: {
                final String s = parseString( offset, numValues );
                if ( s == null )
                    return null;
                switch ( tagID ) {
                    case EXIF_DATE_TIME:
                    case EXIF_DATE_TIME_DIGITIZED:
                    case EXIF_DATE_TIME_ORIGINAL:
                        //
                        // We elevate dates from mere Strings into Date types
                        // in their own right.
                        //
                        return new DateMetaValue( s );
                    default:
                        return new StringMetaValue( s );
                }
            }

            case EXIF_FIELD_TYPE_SBYTE: {
                final long[] values = new long[ numValues ];
                for ( int i = 0; i < numValues; ++i )
                    values[i] = m_buf.get( offset + i );
                return new ByteMetaValue( values );
            }

            case EXIF_FIELD_TYPE_UBYTE: {
                final long[] values = new long[ numValues ];
                for ( int i = 0; i < numValues; ++i )
                    values[i] = m_buf.getUnsignedByte( offset + i );
                return new UnsignedByteMetaValue( values );
            }

            case EXIF_FIELD_TYPE_SLONG: {
                final long[] values = new long[ numValues ];
                final int valueSize = EXIF_FIELD_SIZE[ EXIF_FIELD_TYPE_SLONG ];
                for ( int i = 0; i < numValues; ++i )
                    values[i] = m_buf.getInt( offset + i * valueSize );
                return new LongMetaValue( values );
            }

            case EXIF_FIELD_TYPE_ULONG: {
                final long[] values = new long[ numValues ];
                final int valueSize = EXIF_FIELD_SIZE[ EXIF_FIELD_TYPE_ULONG ];
                for ( int i = 0; i < numValues; ++i )
                    values[i] = m_buf.getInt( offset + i * valueSize );
                return new UnsignedLongMetaValue( values );
            }

            case EXIF_FIELD_TYPE_SRATIONAL: {
                final Rational[] values = new Rational[ numValues ];
                final int valueSize =
                    EXIF_FIELD_SIZE[ EXIF_FIELD_TYPE_SRATIONAL ];
                final int longSize = EXIF_FIELD_SIZE[ EXIF_FIELD_TYPE_SLONG ];
                for ( int i = 0; i < numValues; ++i )
                    try {
                        final int pos = offset + i * valueSize;
                        values[i] = new Rational(
                            m_buf.getInt( pos ), m_buf.getInt( pos + longSize )
                        );
                    }
                    catch ( IllegalArgumentException e ) {
                        m_handler.gotBadMetadata( e );
                        return null;
                    }
                return new RationalMetaValue( values );
            }

            case EXIF_FIELD_TYPE_URATIONAL: {
                final Rational[] values = new Rational[ numValues ];
                final int valueSize =
                    EXIF_FIELD_SIZE[ EXIF_FIELD_TYPE_URATIONAL ];
                final int longSize = EXIF_FIELD_SIZE[ EXIF_FIELD_TYPE_ULONG ];
                for ( int i = 0; i < numValues; ++i )
                    try {
                        final int pos = offset + i * valueSize;
                        values[i] = new Rational(
                            m_buf.getInt( pos ), m_buf.getInt( pos + longSize )
                        );
                    }
                    catch ( IllegalArgumentException e ) {
                        m_handler.gotBadMetadata( e );
                        return null;
                    }
                return new UnsignedRationalMetaValue( values );
            }

            case EXIF_FIELD_TYPE_SSHORT: {
                final long[] values = new long[ numValues ];
                final int valueSize = EXIF_FIELD_SIZE[ EXIF_FIELD_TYPE_SSHORT ];
                for ( int i = 0; i < numValues; ++i )
                    values[i] = m_buf.getShort( offset + i * valueSize );
                return new ShortMetaValue( values );
            }

            case EXIF_FIELD_TYPE_USHORT: {
                final long[] values = new long[ numValues ];
                final int valueSize = EXIF_FIELD_SIZE[ EXIF_FIELD_TYPE_USHORT ];
                for ( int i = 0; i < numValues; ++i )
                    values[i] = m_buf.getUnsignedShort( offset + i * valueSize );
                return new UnsignedShortMetaValue( values );
            }

            case EXIF_FIELD_TYPE_FLOAT: {
                final float[] values = new float[ numValues ];
                final int valueSize = EXIF_FIELD_SIZE[ TIFF_FIELD_TYPE_FLOAT ];
                for ( int i = 0; i < numValues; ++i )
                    values[i] = m_buf.getFloat( offset + i * valueSize );
                return new FloatMetaValue( values );
            }

            case EXIF_FIELD_TYPE_DOUBLE: {
                final double[] values = new double[ numValues ];
                final int valueSize = EXIF_FIELD_SIZE[ TIFF_FIELD_TYPE_DOUBLE ];
                for ( int i = 0; i < numValues; ++i )
                    values[i] = m_buf.getDouble( offset + i * valueSize );
                return new DoubleMetaValue( values );
            }

            case EXIF_FIELD_TYPE_UNDEFINED:
                return new UndefinedMetaValue(
                    m_buf.getBytes( offset, numValues )
                );

            default:
                throw new IllegalStateException(
                    String.format( "unknown field type (0x%0) for tag ID 0x%0",
                                   fieldType, tagID )
                );
        }
    }

    /**
     * Stop parsing immediately.
     */
    public void stopParsing() {
        m_stop = true;
    }

    ////////// private ////////////////////////////////////////////////////////

    /**
     * Calculate an IFD's entry position.
     *
     * @param ifdOffset The offset of the start of the IFD.
     * @param entry The entry number within the currenf IFD to calculate the
     * position of.
     * @return Returns said position.
     */
    private static int calcIFDEntryPosition( int ifdOffset, int entry ) {
        return ifdOffset + EXIF_SHORT_SIZE + entry * EXIF_IFD_ENTRY_SIZE;
    }

    /**
     * Calculate the offset of a metadata value.
     *
     * @param byteCount The number of bytes comprising the value.
     * @param valueOffsetAdjustment The larger-than-4-byte-value offset
     * adjustment.
     * @return Returns the offset of the value.
     */
    private int calcValueOffset( int byteCount, int valueOffsetAdjustment )
        throws IOException
    {
        if ( byteCount <= TIFF_INLINE_VALUE_MAX_SIZE ) {
            //
            // The value in the directory entry itself.
            //
            return m_buf.position();
        }
        final int offset = m_buf.getInt()
            + (m_isSubdirectory ? 0 : EXIF_HEADER_START_SIZE)
            + valueOffsetAdjustment;
        if ( offset + byteCount > m_buf.limit() ) {
            //
            // Bogus offset and/or byteCount.
            //
            return -1;
        }
        return offset;
    }

    /**
     * Parse the metadata from a single directory entry.
     *
     * @param offset The offset from the beginning of the file of the
     * directory entry.
     * @param valueOffsetAdjustment The larger-than-4-byte-value offset
     * adjustment.
     * @param dir The {@link ImageMetadataDirectory}to parse metadata for.
     */
    private void parseDirectoryEntry( int offset, int valueOffsetAdjustment,
                                      ImageMetadataDirectory dir )
        throws IOException
    {
        m_buf.position( offset );
        final int tagID = m_buf.getUnsignedShort();
        if ( tagID < 0 )
            return;
        final int fieldType = m_buf.getUnsignedShort();
        if ( fieldType <= 0 || fieldType >= EXIF_FIELD_SIZE.length ) {
            m_handler.gotBadMetadata(
                String.format( "unknown field type (0x%0) for tag ID 0x%0",
                               fieldType, tagID )
            );
            return;
        }

        final int numValues = m_buf.getInt();
        if ( numValues < 0 ) {
            m_handler.gotBadMetadata(
                String.format( "numValues (0x%x) < 0 for tag ID 0x%x",
                               numValues, tagID )
            );
            return;
        }
        final int byteCount = numValues * EXIF_FIELD_SIZE[ fieldType ];
        if ( byteCount <= 0 )
            return;
        final int valueOffset =
            calcValueOffset( byteCount, valueOffsetAdjustment );
        if ( valueOffset < 0 ) {
            m_handler.gotBadMetadata(
                String.format( "valueOffset < 0 for tag ID 0x%x", tagID )
            );
            return;
        }

        final int subdirOffset =
            (m_isSubdirectory ? 0 : EXIF_HEADER_START_SIZE)
                + m_buf.getInt( valueOffset )
                + valueOffsetAdjustment;

        m_handler.gotTag(
            tagID, fieldType, numValues, byteCount, valueOffset,
            valueOffsetAdjustment, subdirOffset, m_imageFile, m_buf, dir
        );
    }

    /**
     * Parse a String out of EXIF metadata by scanning for an
     * embedded null byte and stopping there if found.
     *
     * @param offset The offset of the first character.
     * @param maxLength The maximum length of the string.
     * @return Returns the parsed string.
     */
    private String parseString( int offset, int maxLength ) throws IOException {
        int length = 0;
        while ( length < maxLength && m_buf.get( offset + length ) != '\0' )
            ++length;
        return m_buf.getString( offset, length, "UTF-8" );
    }

    /**
     * This is a special case of {@link #parseString(int,int)} that handles
     * EXIF UserComment reading.  The UserComment starts with 8 bytes that
     * specify the character set.  Currently, only ASCII and Unicode are
     * supported.
     *
     * @param offset The offset of the first character.
     * @param count The number of characters.
     * @param fieldType The field type.
     * @return Returns the UserComment string or null if it can't
     * be read.
     */
    private String parseUserComment( int offset, int count, int fieldType )
        throws IOException
    {
        count *= EXIF_FIELD_SIZE[ fieldType ];
        //
        // At least Olympus cameras pad the comment with trailing spaces --
        // remove these first.
        //
        final byte[] bytes = m_buf.getBytes( offset, count );
        while ( count > 0 )
            if ( bytes[ count - 1 ] == ' ' )
                --count;
            else
                break;

        if ( count > 8 ) {
            count -= 8;
            final String charsetCode = new String( bytes, 0, 8 ).toUpperCase();
            if ( "ASCII\0\0\0".equals( charsetCode ) )
                return new String( bytes, 8, count );
            if ( "UNICODE\0".equals( charsetCode  ) )
                try {
                    return new String(
                        bytes, 8, count,
                        m_buf.order() == ByteOrder.LITTLE_ENDIAN ?
                            "UTF-16LE" : "UTF-16BE"
                    );
                }
                catch ( UnsupportedEncodingException e ) {
                    // should never happen, but just in case ....
                }
            // TODO: handle JIS encoding
        }
        return null;
    }

    /**
     * The {@link LCByteBuffer} containing the raw EXIF metadata to be parsed.
     */
    private final LCByteBuffer m_buf;

    /**
     * The {@link EXIFParserEventHandler} in use.
     */
    private final EXIFParserEventHandler m_handler;

    /**
     * The image {@link File} the EXIF metadata was read from.
     */
    private final File m_imageFile;

    /**
     * This is true only if we're reading an EXIF subdirectory.
     */
    private final boolean m_isSubdirectory;

    /**
     * Set to true to stop the parser immediately.
     */
    private boolean m_stop;
}
/* vim:set et sw=4 ts=4: */


text:
layout: post
title: "My Personal Journey to the Open Source Community"
---

For five years now, GitHub has been a part of the month-long celebration of open
source software, known as Hacktoberfest. Hacktoberfest is an opportunity for new and
veteran contributors to open pull requests on various projects across GitHub. During
this "trick-or-treat for hackers", maintainers of projects are extremely welcoming and love
to see new contributors to open source visit their projects. This was not only my
first time contributing during Hacktoberfest, but my first time contributing to an
open source project other than my own. However, it was my own project, [neighbor](https://github.com/mccurdyc/neighbor)
that inspired me to contribute to the project of choice, namely [source{d}'s](https://sourced.tech/)
[go-git](https://github.com/src-d/go-git).

## My personal open-source project

My personal project, [neighbor](https://github.com/mccurdyc/neighbor), is a
"neighborhood watch" for projects in the GitHub community. Users
create and run arbitrary shell commands or scripts on each project in the list
of cloned projects returned from a [GitHub search query](https://developer.github.com/v3/search/#search-repositories).
neighbor is an extensible means to enforce code quality on GitHub.

Due to the implementation of neighbor --- primarily the language choice, Go --- and
neighbor's tight coupling to GitHub via the API, discovering tools such as [Google's go-github](https://github.com/google/go-github)
and [source{d}'s go-git](https://github.com/src-d/go-git) was inevitable. While
querying GitHub's API certainly would have been possible without go-github, it
did add nice abstractions such as token authentication via OAuth2. On the other
hand, cloning projects would have consisted of numerous `git clone` shell commands via the
[`os/exec` package](https://golang.org/pkg/os/exec/); a much nastier problem to deal with. Not only this, but each
clone most-likely would have been its own [`Command`](https://golang.org/pkg/os/exec/#Command)
with the project under inspection as an argument.

## A quick shout-out to source{d}

If you are unfamiliar with source{d}, you should check out what they are doing
on [their website](https://sourced.tech) and [GitHub profile](https://github.com/src-d).
At a high-level, source{d} is doing machine learning *on* code. To support this
mission, source{d} as an organization has created numerous tools, all of which are open source
under [source{d} proper](https://github.com/src-d) and the [Bablefish](https://github.com/bblfsh) organizations.

Not only do these tools help them achieve their goal of machine learning on code,
but most are built in such as way that they can be useful to those outside of
the source{d} organization, working on their own projects or research, such as myself.
Just to list a few of the projects: [engine](https://github.com/src-d/engine),
[gitbase](https://github.com/src-d/gitbase), and [lookout](https://github.com/src-d/lookout).
Admittedly, I have not had the opportunity to use all of these tools or investigate too deeply.

Next, something that I greatly appreciate about source{d} is the example they
set as an open and transparent organization, by including their [organizational documentation as
a public repository on GitHub](https://github.com/src-d/guide), something that [I mentioned
on Twitter](https://twitter.com/McCurdyColton/status/1041665070651125760) that we
started doing at StockX, except only internally.

Finally, everyone that I interacted with from source{d} was patient as I tossed
around ideas and helpful in pointing me in the right direction when I needed the
guidance, both on the [source{d} Slack](https://sourced-community.slack.com) and
in GitHub reviews. I honestly felt like part of the team.

## What is go-git?

[go-git](https://github.com/src-d/go-git) is a "highly extensible Git implementation
in pure Go". In other words, go-git aims to be a feature-complete [git](https://git-scm.com/) implementation,
written entirely in Go. This is a huge contribution to the Go community! Having a
well-written and maintained package such as go-git available in any language would
be amazing, let alone my favorite language, Go!

## Why did I choose to contribute to go-git?

As a matter of fact, it was more like the issues chose me. While working on my
project, neighbor, specifically around authenticating with GitHub, I encountered
a few challenges. After using go-github, which supported OAuth2 for authentication,
I had the expectation that I would do something similar in go-git, namely use token
authentication, but this was not the case. It wasn't until I opened an [issue on
go-git](https://github.com/src-d/go-git/issues/999) and had a conversation with
one of the core maintainers of the project, Santiago M. Mola ([GitHub: @smola](https://github.com/smola), [Twitter: @mola_io](https://twitter.com/mola_io?lang=en)),
that I realized and accepted that [GitHub advises using basic authentication](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/)
(i.e., username, "password") for token authentication via personal access tokens.

To help others ([Issue#618](https://github.com/src-d/go-git/issues/61), [Issue#730](https://github.com/src-d/go-git/issues/73))
in the future who encounter the same confusion that I faced, [I created a few examples](https://github.com/src-d/go-git/pull/990)
for basic authentication with a password and personal access token.

After that, I was pumped and ready for more. I wanted to solve an issue that had
been open for a while on one of source{d}'s projects. I felt most comfortable
in and knowledgable of go-git, so that is where I started the search. In the issue
tracker on go-git, I came across [Issue#969](https://github.com/src-d/go-git/issues/969)
which had been open for almost 30 days, had no activity and was on a topic that
I had just recently been formally introduced to. I knew this issue was for me!
Only a few weeks prior, I was formally introduced to "flaky" tests by a colleague of mine who sent
me a [paper by Jonathan Bell of Carnegie Mellon University, et al.](https://www.jonbell.net/icse18-deflaker.pdf).
Bell et al. formally discuss flaky tests and propose a tool, DeFlaker, for automatically
detecting flaky tests.

Flaky tests often lead to untrusted or misleading tests and are arguably worse
than no test. Was that most recent change honestly the reason that the test failed?
Or, was it because the flakiness of the test was triggered? While discussing
flaky tests in detail is not in the scope of this post, one final key point made in the Bell
et al. paper is important to my story. "The typical way to detect flaky tests is to rerun
failing tests repeatedly", which was exactly what I did to solve [Issue#969](https://github.com/src-d/go-git/issues/969).

I found the cause of the flaky test using the exact method discussed in the paper
by Bell et al., a [simple script](https://gist.github.com/mccurdyc/5b39f971a122544e02e1e21c639a1e67)
that ran `go test` continuously, for a max of 5000 iterations with the same flags
as the CI of the go-git project enabled, looking for a failing test case. As simple
as this script may be, it ultimately helped me identify the root of the flakiness,
which ended up being a race condition where a resource was being closed prior to
writing to the resource being completed.

If you are wondering why I didn't use the [Go race detector](https://blog.golang.org/race-detector),
you are asking a great question! Ultimately, the reason was because I didn't want
to pull the necessary code out into an isolated demo project. Looking back, I probably
should have done this. Or at least ran the tests with the `-race` flag enabled.

## Conclusion

This year's Hacktoberfest marked the first time that I contributed to an open
source project other than my own. However, it was my own project that provided me
with the challenges personally to then want to help others. The project that I
contributed to was just one of many great projects from the creating organization,
namely source{d}. The issues that I solved were either related to a problem that
I personally encountered or had recently read a research paper about and was excited
to learn more. Everyone that I worked with or spoke to from source{d} was welcoming
of new ideas and patient with me as a new contributor to open source.

While I do plan to take a month break from contributing to other open source projects,
to continue making progress on my own personal projects, write more and spend time
with family during the upcoming holiday, I will certainly be contributing again
in the near future and go-git will be the first project that I visit.

If you are new to open source or are looking to solve your first issue on a project
other than your own, I'd love to talk! You can find my contact information on
the [Contact page](http://coltonmccurdy.com/contact). If you are interested in
formal research that I have done, check out the [Papers page](http://coltonmccurdy.com/papers).

Colton J. McCurdy

Twitter: [@McCurdyColton](https://twitter.com/mccurdycolton)

GitHub: [mccurdyc](https://twitter.com/mccurdycolton)


text:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project basedir="." default="build" name="gatekeeper">
    <fail message="Please build using Ant 1.7.0 or higher.">
        <condition><not><antversion atleast="1.7.0"/></not></condition>
    </fail>
    <property name="build.dir" value="${user.dir}/build"/>
    <target name="clean">
        <delete dir="${build.dir}"/>
        <delete dir="${dest.dir}"/>
    </target>
    <target name="libs">
        <copy todir="${dest.dir}/" file="/usr/share/varbj/jars/gson-2.2.2.jar"/>
    </target>
    <target name="compile" depends="libs">
        <mkdir dir="${build.dir}"/>
        <javac debug="true" debuglevel="source,lines,vars" destdir="${build.dir}" source="1.6" target="1.6" includeantruntime="false">
            <src path="src"/>
            <classpath>
                <pathelement location="${dest.dir}/gson-2.2.2.jar"/>
            </classpath>
        </javac>
    </target>
    <target name="build" depends="compile">
        <jar destfile="${dest.dir}/jguibio.jar" basedir="${build.dir}"/>
    </target>
</project>


text:
"""
Test module for the Fedex ShipService WSDL.
"""

import unittest
import logging
import sys

sys.path.insert(0, '..')
from fedex.services.ship_service import FedexProcessShipmentRequest
from fedex.services.ship_service import FedexDeleteShipmentRequest

# Common global config object for testing.
from tests.common import get_fedex_config

CONFIG_OBJ = get_fedex_config()

logging.getLogger('suds').setLevel(logging.ERROR)
logging.getLogger('fedex').setLevel(logging.INFO)

@unittest.skipIf(not CONFIG_OBJ.account_number, "No credentials provided.")
class ShipServiceTests(unittest.TestCase):
    """
    These tests verify that the ship service WSDL is in good shape.
    """

    def test_create_delete_shipment(self):
        shipment = FedexProcessShipmentRequest(CONFIG_OBJ)

        shipment.RequestedShipment.DropoffType = 'REGULAR_PICKUP'
        shipment.RequestedShipment.ServiceType = 'FEDEX_GROUND'
        shipment.RequestedShipment.PackagingType = 'YOUR_PACKAGING'

        shipment.RequestedShipment.Shipper.Contact.PersonName = 'Sender Name'
        shipment.RequestedShipment.Shipper.Contact.PhoneNumber = '9012638716'

        shipment.RequestedShipment.Shipper.Address.StreetLines = ['Address Line 1']
        shipment.RequestedShipment.Shipper.Address.City = 'Herndon'
        shipment.RequestedShipment.Shipper.Address.StateOrProvinceCode = 'VA'
        shipment.RequestedShipment.Shipper.Address.PostalCode = '20171'
        shipment.RequestedShipment.Shipper.Address.CountryCode = 'US'

        shipment.RequestedShipment.Recipient.Contact.PersonName = 'Recipient Name'
        shipment.RequestedShipment.Recipient.Contact.PhoneNumber = '9012637906'

        shipment.RequestedShipment.Recipient.Address.StreetLines = ['Address Line 1']
        shipment.RequestedShipment.Recipient.Address.City = 'Herndon'
        shipment.RequestedShipment.Recipient.Address.StateOrProvinceCode = 'VA'
        shipment.RequestedShipment.Recipient.Address.PostalCode = '20171'
        shipment.RequestedShipment.Recipient.Address.CountryCode = 'US'
        shipment.RequestedShipment.EdtRequestType = 'NONE'

        shipment.RequestedShipment.ShippingChargesPayment.Payor.ResponsibleParty.AccountNumber \
            = CONFIG_OBJ.account_number

        shipment.RequestedShipment.ShippingChargesPayment.PaymentType = 'SENDER'

        shipment.RequestedShipment.LabelSpecification.LabelFormatType = 'COMMON2D'
        shipment.RequestedShipment.LabelSpecification.ImageType = 'PNG'
        shipment.RequestedShipment.LabelSpecification.LabelStockType = 'PAPER_7X4.75'
        shipment.RequestedShipment.LabelSpecification.LabelPrintingOrientation = 'BOTTOM_EDGE_OF_TEXT_FIRST'

        # Use order if setting multiple labels or delete
        del shipment.RequestedShipment.LabelSpecification.LabelOrder

        package1_weight = shipment.create_wsdl_object_of_type('Weight')
        package1_weight.Value = 2.0
        package1_weight.Units = "LB"
        package1 = shipment.create_wsdl_object_of_type('RequestedPackageLineItem')
        package1.PhysicalPackaging = 'ENVELOPE'
        package1.Weight = package1_weight
        shipment.add_package(package1)

        shipment.send_validation_request()
        shipment.send_request()

        assert shipment.response
        assert shipment.response.HighestSeverity in ['SUCCESS', 'WARNING']
        track_id = shipment.response.CompletedShipmentDetail.CompletedPackageDetails[0].TrackingIds[0].TrackingNumber
        assert track_id

        del_shipment = FedexDeleteShipmentRequest(CONFIG_OBJ)
        del_shipment.DeletionControlType = "DELETE_ALL_PACKAGES"
        del_shipment.TrackingId.TrackingNumber = track_id
        del_shipment.TrackingId.TrackingIdType = 'EXPRESS'

        del_shipment.send_request()

        assert del_shipment.response

if __name__ == "__main__":
    logging.basicConfig(stream=sys.stdout, level=logging.INFO)
    unittest.main()


text:
import { createAction } from "redux-actions";
import keyMirror from "keymirror";
import { createUrl, metaGenerator } from "utils";
import { GET, PATCH, POST } from "utils/api";
import { notify } from "utils/actions";

const actions = keyMirror({
  REQUEST_OWN_PLAYER: null,
  RECEIVE_OWN_PLAYER: null,
  REQUEST_SUBMIT_PROFILE: null,
  RECEIVE_SUBMIT_PROFILE: null,
  DISMISS_CHANGES_SAVED: null,
  CONFIRM_APPLY_TO_TEAM: null,
  CANCEL_APPLY_TO_TEAM: null,
  REQUEST_SUBMIT_APPLICATION: null,
  RECEIVE_SUBMIT_APPLICATION: null,
  REQUEST_NEW_PLAYER_ITEMS: null,
  RECEIVE_NEW_PLAYER_ITEMS: null,
  REQUEST_EMAIL_PREFERENCES: null,
  RECEIVE_EMAIL_PREFERENCES: null,
  REQUEST_SUBMIT_EMAIL_PREFERENCES: null,
  RECEIVE_SUBMIT_EMAIL_PREFERENCES: null
});
export default actions;

export const requestNewItems = () => (dispatch, getState) => {
  dispatch(createAction(actions.REQUEST_NEW_PLAYER_ITEMS)());
  const {
    auth: { authToken },
    player: {
      player: { id }
    }
  } = getState();
  if (id && authToken) {
    return GET(createUrl("/api/players/me/new_items/"), authToken).then(
      response =>
        response.json().then(json => {
          const payload = response.ok
            ? json
            : new Error("Error retrieving new items.");
          return dispatch(
            createAction(actions.RECEIVE_NEW_PLAYER_ITEMS)(payload)
          );
        })
    );
  }
};

export const requestEmailPreferences = () => (dispatch, getState) => {
  dispatch(createAction(actions.REQUEST_EMAIL_PREFERENCES)());
  const {
    auth: { authToken },
    player: {
      player: { id }
    }
  } = getState();
  if (id && authToken) {
    return GET(createUrl("/api/user_email_preferences/self/"), authToken).then(
      response =>
        response.json().then(json => {
          const payload = response.ok
            ? json
            : new Error("Error retrieving email preferences.");
          return dispatch(
            createAction(actions.RECEIVE_EMAIL_PREFERENCES)(payload)
          );
        })
    );
  }
};

export const submitEmailPreferences = data => (dispatch, getState) => {
  dispatch(createAction(actions.REQUEST_SUBMIT_EMAIL_PREFERENCES)());
  const {
    auth: { authToken },
    player: {
      userEmailPreferences: { id }
    }
  } = getState();
  if (id && authToken) {
    return PATCH(
      createUrl(`/api/user_email_preferences/${id}/`),
      authToken,
      data
    ).then(response =>
      response.json().then(json => {
        const payload = response.ok
          ? json
          : new Error("Error submitting email preferences.");
        dispatch(
          createAction(
            actions.RECEIVE_SUBMIT_EMAIL_PREFERENCES,
            null,
            metaGenerator
          )(payload)
        );
        notify(response);
        return { response, json };
      })
    );
  }
};

export const requestOwnPlayer = () => (dispatch, getState) => {
  dispatch(createAction(actions.REQUEST_OWN_PLAYER)());
  return GET(createUrl("/api/players/me/"), getState().auth.authToken).then(
    response =>
      response.json().then(json => {
        const payload = response.ok
          ? json
          : new Error("Error retrieving own player.");
        dispatch(
          createAction(actions.RECEIVE_OWN_PLAYER, null, metaGenerator)(payload)
        );
        if (response.ok) {
          dispatch(requestNewItems());
          dispatch(requestEmailPreferences());
        }
      })
  );
};

export const requestOwnPlayerIfNeeded = () => (dispatch, getState) => {
  const { isLoading, lastUpdated } = getState().player;
  if (!isLoading && !lastUpdated) {
    return dispatch(requestOwnPlayer());
  }
};

export const submitProfile = data => (dispatch, getState) => {
  dispatch(createAction(actions.REQUEST_SUBMIT_PROFILE)());
  const {
    auth: { authToken },
    player: {
      player: { id }
    }
  } = getState();
  if (id && authToken) {
    return PATCH(createUrl(`/api/players/${id}/`), authToken, data).then(
      response =>
        response.json().then(json => {
          const payload = response.ok
            ? json
            : new Error("Error submitting profile.");
          if (response.ok) {
            dispatch(requestOwnPlayer());
          }
          dispatch(
            createAction(actions.RECEIVE_SUBMIT_PROFILE, null, metaGenerator)(
              payload
            )
          );
          notify(response);
          return { response, json };
        })
    );
  }
};

export const dismissChangesSaved = createAction(actions.DISMISS_CHANGES_SAVED);

export const tryApplyToTeam = createAction(actions.CONFIRM_APPLY_TO_TEAM);
export const cancelApplyToTeam = createAction(actions.CANCEL_APPLY_TO_TEAM);

export const submitApplication = data => (dispatch, getState) => {
  dispatch(createAction(actions.REQUEST_SUBMIT_APPLICATION)());
  const {
    auth: { authToken },
    player: {
      player: { id }
    }
  } = getState();
  if (id && authToken) {
    return POST(createUrl("/api/applications/"), authToken, {
      ...data,
      player: id
    }).then(response =>
      response.json().then(json => {
        const payload = response.ok
          ? json
          : new Error("Error creating application.");
        dispatch(
          createAction(actions.RECEIVE_SUBMIT_APPLICATION, null, metaGenerator)(
            payload
          )
        );
        notify(response, "Application submitted!");
        return { response, json };
      })
    );
  }
};


text:
import {
  IExerciseRecord,
  IExercise,
} from './exercise.types';
import { makeTypedFactory } from 'typed-immutable-record';

export const ExerciseFactory = makeTypedFactory<IExercise, IExerciseRecord>({
  id: null,
  name: null,
  bodypart: null
});

export const INITIAL_STATE = ExerciseFactory();


text:
import { spawner, SpawnResult } from '@integration/testing-tools';
import * as path from 'path';

const wdioExecutable = path.resolve(
    require.resolve('@wdio/cli/package.json'),
    '..',
    'bin',
    'wdio',
);

const wdioSpawner = spawner(
    wdioExecutable,
    { cwd: path.resolve(__dirname, '..') },
);

export function wdio(...params: string[]): Promise<SpawnResult> {
    return wdioSpawner(
        ...params,
    );
}


text:
package org.drools.compiler.kie.builder.impl;

import org.drools.compiler.kproject.xml.PomModel;
import org.kie.api.builder.KieModule;
import org.kie.api.builder.KieScanner;
import org.kie.api.builder.ReleaseId;
import org.kie.api.runtime.KieContainer;

import java.io.InputStream;

public interface InternalKieScanner extends KieScanner {

    enum Status {
        STARTING, SCANNING, UPDATING, RUNNING, STOPPED, SHUTDOWN
    }

    void setKieContainer(KieContainer kieContainer);

    KieModule loadArtifact(ReleaseId releaseId);

    KieModule loadArtifact(ReleaseId releaseId, InputStream pomXML);

    KieModule loadArtifact(ReleaseId releaseId, PomModel pomModel);

    String getArtifactVersion(ReleaseId releaseId);

    ReleaseId getScannerReleaseId();

    ReleaseId getCurrentReleaseId();

    Status getStatus();

    long getPollingInterval();
}


text:
@interface PasswordKnownView : PasswordViewController;
@end