WIP.
diff --git a/examples/pizzeria.html b/examples/pizzeria.html
index 0a0ecd7..52fbd0f 100644
--- a/examples/pizzeria.html
+++ b/examples/pizzeria.html
@@ -175,6 +175,100 @@
</section>
<section id="code">
<h2 class="section-title">Model Class <a href="#"><i class="top-link fas fa-fw fa-angle-double-up"></i></a></h2>
+
+ <p>
+ Open <code>src/main/scala/demo/<b>PizzeriaOrder.scala</b></code> file and replace its content with the following code:
+ </p>
+ <pre class="brush: scala, highlight: [6, 17, 20, 25]">
+ package demo
+
+ import scala.collection.mutable
+ import org.apache.nlpcraft.*
+
+ enum PizzeriaOrderState:
+ case DIALOG_EMPTY, DIALOG_IS_READY, DIALOG_SHOULD_CANCEL, DIALOG_SPECIFY, DIALOG_CONFIRM
+
+ private object OrderPosition:
+ val DFLT_QTY = 1
+
+ private trait OrderPosition:
+ val name: String
+ var qty: Option[Int]
+ require(name != null && name.nonEmpty)
+
+ case class Pizza(name: String, var size: Option[String], var qty: Option[Int]) extends OrderPosition:
+ override def toString = s"$name '${size.getOrElse("undefined size")}' ${qty.getOrElse(OrderPosition.DFLT_QTY)} pcs"
+
+ case class Drink(name: String, var qty: Option[Int]) extends OrderPosition:
+ override def toString = s"$name ${qty.getOrElse(OrderPosition.DFLT_QTY)} pcs"
+
+ import PizzeriaOrderState.*
+
+ class PizzeriaOrder:
+ private var state = DIALOG_EMPTY
+ private val pizzas = mutable.ArrayBuffer.empty[Pizza]
+ private val drinks = mutable.ArrayBuffer.empty[Drink]
+
+ def isEmpty: Boolean = pizzas.isEmpty && drinks.isEmpty
+
+ def isValid: Boolean = !isEmpty && findPizzaWithoutSize.isEmpty
+
+ def add(ps: Seq[Pizza], ds: Seq[Drink]): Unit =
+ def setByName[T <: OrderPosition](buf: mutable.ArrayBuffer[T], t: T): Unit =
+ buf.find(_.name == t.name) match
+ case Some(foundT) => if t.qty.nonEmpty then foundT.qty = t.qty
+ case None => buf += t
+
+ for (p <- ps)
+ def setPizza(pred: Pizza => Boolean, notFound: => () => Unit): Unit =
+ pizzas.find(pred) match
+ case Some(foundPizza) =>
+ if p.size.nonEmpty then foundPizza.size = p.size
+ if p.qty.nonEmpty then foundPizza.qty = p.qty
+ case None => notFound()
+
+ if p.size.nonEmpty then setPizza(
+ x => x.name == p.name && x.size == p.size,
+ () => setPizza(x => x.name == p.name && x.size.isEmpty, () => pizzas += p)
+ )
+ else setByName(pizzas, p)
+
+ for (d <- ds) setByName(drinks, d)
+
+ def findPizzaWithoutSize: Option[Pizza] = pizzas.find(_.size.isEmpty)
+
+ def fixPizzaWithoutSize(size: String): Boolean =
+ findPizzaWithoutSize match
+ case Some(p) =>
+ p.size = size.?
+ true
+ case None => false
+
+ def getState: PizzeriaOrderState = state
+
+ def setState(state: PizzeriaOrderState): Unit = this.state = state
+
+ override def toString: String =
+ if !isEmpty then
+ val ps = if pizzas.nonEmpty then s"pizza: ${pizzas.mkString(", ")}" else ""
+ val ds = if drinks.nonEmpty then s"drinks: ${drinks.mkString(", ")}" else ""
+
+ if ds.isEmpty then ps else if ps.isEmpty then ds else s"$ps, $ds"
+ else "nothing ordered"
+ </pre>
+
+ <ul>
+ <li>
+ <code>Line 6</code> defines order states enumeration.
+ </li>
+ <li>
+ <code>Lines 17 and 20</code> define order parts classes definition.
+ </li>
+ <li>
+ <code>Line 25</code> defines pizza order state representation.
+ </li>
+ </ul>
+
<p>
Open <code>src/main/scala/demo/<b>PizzeriaModel.scala</b></code> file and replace its content with the following code:
</p>
@@ -290,14 +384,14 @@
private def askStopOrDoStop(o: Order)(using ctx: NCContext, im: NCIntentMatch): Result =
if o.isValid then askShouldStop() else doStop(o)
- import org.apache.nlpcraft.examples.pizzeria.PizzeriaModel.*
+ import PizzeriaModel.*
class PizzeriaModel extends NCModelAdapter(
NCModelConfig("nlpcraft.pizzeria.ex", "Pizzeria Example Model", "1.0"),
PizzeriaModelPipeline.PIPELINE
) with LazyLogging:
// This method is defined in class scope and has package access level for tests reasons.
- private[pizzeria] def doExecute(o: Order)(using ctx: NCContext, im: NCIntentMatch): Result =
+ private[demo] def doExecute(o: Order)(using ctx: NCContext, im: NCIntentMatch): Result =
require(o.isValid)
doResultWithClear(s"Executed: $o.")
@@ -416,7 +510,7 @@
In its callback current order state is changed.
If processed order is in valid state user receives order confirmation request like "<i>Is order ready?</i>",
otherwise user receives request which asks him to specify the order.
- Both responses have <code>ASK_DIALOG</code> type.
+ Both responses have <a href="../apis/latest/org/apache/nlpcraft/NCResultType.html#ASK_DIALOG-0">ASK_DIALOG</a> type.
</li>
<li>
@@ -477,7 +571,7 @@
Open <code>src/main/scala/demo/components/<b>PizzeriaOrderMapper.scala</b></code> file and replace its content with the following code:
</p>
<pre class="brush: scala, highlight: [11, 25, 30, 61]">
- package demo
+ package demo.components
import org.apache.nlpcraft.*
import com.typesafe.scalalogging.LazyLogging
@@ -554,7 +648,9 @@
<code>Line 25</code> defines <code>PizzeriaOrderMapper</code> model which implements <a href="../apis/latest/org/apache/nlpcraft/NCEntityMapper.html">NCEntityMapper</a>.
</li>
<li>
- <code>Line 30</code> defines helper method <code>map()</code> which clones <code>destEn</code> entity,
+ <code>Line 30</code> defines helper method
+ <a href="../apis/latest/org/apache/nlpcraft/NCEntityMapper.html#map-fffff77c">map()</a> w
+ hich clones <code>destEn</code> entity,
extends it by <code>extraEnt</code> tokens and <code>destProp</code> property and, as result,
returns new entities instances instead of passed into the method.
</li>
@@ -625,7 +721,7 @@
which is based on YAM model definition <code>pizzeria_model.yaml</code>.
</li>
<li>
- <code>Lines 31 and 37</code> define entity mappers <code>PizzeriaOrderMapper</code> which
+ <code>Lines 31 and 37</code> define entity mappers <code>PizzeriaOrderMapper</code> instances which
map <code>ord:pizza</code> elements with theirs sizes from <code>ord:pizza:size</code> and
quantities from <code>stanford:number</code>.
</li>
@@ -639,7 +735,7 @@
<section id="testing">
<h2 class="section-title">Testing <a href="#"><i class="top-link fas fa-fw fa-angle-double-up"></i></a></h2>
<p>
- The test defined in <code>CalculatorModelSpec</code> allows to check that all input test sentences are
+ The test defined in <code>PizzeriaModelSpec</code> allows to check that all input test sentences are
processed correctly and trigger the expected intents:
</p>
<pre class="brush: scala, highlight: [14, 48, 61, 96]">
@@ -853,7 +949,9 @@
</li>
<li>
<code>Line 61</code> defines test helper method <code>dialog()</code>.
- It sends request to model via <code>ask()</code> method and accumulates execution results.
+ It sends request to model via client's method
+ <a href="../apis/latest/org/apache/nlpcraft/NCModelClient.html#ask-fffff9ce">ask()</a>
+ and accumulates execution results.
</li>
<li>
<code>Line 96</code> defines main test block.