def +=()

in nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/matcher/NCIntentSolverManager.scala [116:285]


        def +=(that: Weight): Weight =
            val tmp = mutable.ArrayBuffer[Int]()
            for (i <- 0 until Math.max(buf.size, that.buf.size))
                tmp.append(norm(i, buf) + norm(i, that.buf))
            buf.clear()
            buf ++= tmp
            this

        /**
          * Appends new weight.
          *
          * @param w New weight to append.
          */
        def append(w: Int): Weight =
            buf.append(w)
            this

        /**
          * Prepends new weight.
          *
          * @param w New weight to prepend.
          */
        def prepend(w: Int): Weight =
            buf.prepend(w)
            this

        /**
          * Sets specific weight at a given index.
          *
          * @param idx
          * @param w
          */
        def setWeight(idx: Int, w: Int): Unit =
            buf(idx) = w

        /**
          * Gets element at given index or zero if index is out of bounds.
          *
          * @param i Index in collection.
          * @param c Collection.
          */
        private def norm(i: Int, c: mutable.ArrayBuffer[Int]): Int = if i < c.size then c(i) else 0

        /**
          *
          * @param that
          */
        override def compare(that: Weight): Int =
            def compareWeight(idx: Int): Option[Int] =
                val res = Integer.compare(norm(idx, buf), norm(idx, that.buf))
                Option.when(res != 0)(res)

            (0 until Math.max(buf.size, that.buf.size)).flatMap(compareWeight).to(LazyList).headOption.getOrElse(0)

        def toSeq: Seq[Int] = buf.toSeq

        override def toString: String = buf.mkString("[", ", ", "]")

    /**
      *
      * @param used
      * @param entity
      */
    private case class IntentEntity(var used: Boolean, var conv: Boolean, entity: NCEntity)

    type ResultData = Either[NCResult, NCMatchedCallback]

    /**
      *
      * @param result
      * @param intentMatch
      */
    private case class IterationResult(result: ResultData, intentMatch: NCIntentMatch)

    /**
      * @param termId
      * @param usedEntities
      * @param weight
      */
    private case class TermMatch(termId: Option[String], usedEntities: List[IntentEntity], weight: Weight):
        private lazy val maxIndex: Int = usedEntities.map(_.entity.getTokens.map(_.getIndex).max).max

        def after(tm: TermMatch): Boolean = maxIndex > tm.maxIndex

    /**
      *
      * @param entities
      */
    private case class PredicateMatch(entities: List[IntentEntity], weight: Weight)

    /**
      *
      * @param term
      * @param usedEntities
      */
    private case class TermEntitiesGroup(
        term: NCIDLTerm,
        usedEntities: List[IntentEntity]
    )

    /**
      *
      * @param entityGroups
      * @param weight
      * @param intent
      */
    private case class IntentMatchHolder(
        entityGroups: List[TermEntitiesGroup],
        weight: Weight,
        intent: NCIDLIntent
    )

    /**
      *
      * @param intentMatch
      * @param callback
      * @param variant
      * @param variantIdx
      */
    private case class MatchHolder(
        intentMatch: IntentMatchHolder, // Match.
        callback: NCCallbackInput => NCResult, // Callback function.
        variant: IntentSolverVariant, // Variant used for the match.
        variantIdx: Int // Variant index.
    )

    /**
      *
      * @param userId
      * @param mldId
      */
    private case class UserModelKey(userId: String, mldId: String)

import org.apache.nlpcraft.internal.intent.matcher.NCIntentSolverManager.*

/**
 * Intent solver that finds the best matching intent given user sentence.
 */
class NCIntentSolverManager(
    dialog: NCDialogFlowManager,
    conv: NCConversationManager,
    intents: Map[NCIDLIntent, NCCallbackInput => NCResult]
) extends LazyLogging:
    private final val reqIds = mutable.HashMap.empty[UserModelKey, String]

    /**
     * Main entry point for intent engine.
     *
      * @param mdl Model.
     * @param ctx Query context.
     * @param intents Intents to match for.
     */
    private def solveIntents(mdl: NCModel, ctx: NCContext, intents: Map[NCIDLIntent, NCCallbackInput => NCResult]): List[IntentSolverResult] =
        dialog.ack(ctx.getRequest.getUserId)

        val matches = mutable.ArrayBuffer.empty[MatchHolder]

        // Find all matches across all intents and sentence variants.
        for (
            (vrn, vrnIdx) <- ctx.getVariants.zipWithIndex;
            ents = vrn.getEntities;
            varEntsGroups = ents.filter(t => t.getGroups != null && t.getGroups.nonEmpty).map(_.getGroups);
            (intent, callback) <- intents
        )
            val convEnts: Seq[IntentEntity] =
                if intent.terms.exists(_.conv) then
                    // We do not mix tokens with same group from the conversation and given sentence.
                    ctx.getConversation.getStm.
                        map(ent => ent -> (if ent.getGroups == null then Set.empty else ent.getGroups)).
                        filter { (_, entGroups)  => !varEntsGroups.exists(_.subsetOf(entGroups)) }.