blob: 2fcfb91b14683b402b14c09222ca68c8b5d8ba1c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nlpcraft.examples.alarm;
import org.apache.nlpcraft.model.*;
import java.time.*;
import java.time.format.*;
import java.util.*;
import static java.time.temporal.ChronoUnit.*;
/**
* Alarm example data model.
* <p>
* This example provides a simple "alarm clock" interface where you can ask to set the timer
* for a specific duration from now expressed in hours, minutes and/or seconds. You can say "ping me in 3 minutes",
* "buzz me in an hour and 15 minutes", or "set my alarm for 30 secs". When the timers is up it will
* simply print out "BEEP BEEP BEEP" in the probe console.
* <p>
* See 'README.md' file in the same folder for running and testing instructions.
*/
public class AlarmModel extends NCModelFileAdapter {
private static final DateTimeFormatter FMT =
DateTimeFormatter.ofPattern("HH'h' mm'm' ss's'").withZone(ZoneId.systemDefault());
private final Timer timer = new Timer();
public AlarmModel() {
// Loading the model from the file in the classpath.
super("org/apache/nlpcraft/examples/alarm/alarm_model.json");
}
/**
* Callback on intent match.
*
* @param ctx Intent solver context.
* @return Query result.
*/
@NCIntentRef("alarm")
@NCIntentSample({
"Ping me in 3 minutes",
"Buzz me in an hour and 15mins",
"Set my alarm for 30s"
})
NCResult onMatch(
NCIntentMatch ctx,
@NCIntentTerm("nums") List<NCToken> numToks
) {
// As an example - we check against an ambiguous match.
if (ctx.isAmbiguous())
throw new NCRejection("Not exact match.");
long unitsCnt = numToks.stream().map(tok -> (String)tok.meta("num:unit")).distinct().count();
if (unitsCnt != numToks.size())
throw new NCRejection("Ambiguous time units.");
LocalDateTime now = LocalDateTime.now();
LocalDateTime dt = now;
for (NCToken num : numToks) {
String unit = num.meta("nlpcraft:num:unit");
// Skip possible fractional to simplify.
long v = ((Double)num.meta("nlpcraft:num:from")).longValue();
if (v <= 0)
throw new NCRejection("Value must be positive: " + unit);
switch (unit) {
case "second": { dt = dt.plusSeconds(v); break; }
case "minute": { dt = dt.plusMinutes(v); break; }
case "hour": { dt = dt.plusHours(v); break; }
case "day": { dt = dt.plusDays(v); break; }
case "week": { dt = dt.plusWeeks(v); break; }
case "month": { dt = dt.plusMonths(v); break; }
case "year": { dt = dt.plusYears(v); break; }
default:
// It shouldn't be assert, because 'datetime' unit can be extended.
throw new NCRejection("Unsupported time unit: " + unit);
}
}
long ms = now.until(dt, MILLIS);
assert ms >= 0;
timer.schedule(
new TimerTask() {
@Override
public void run() {
System.out.println(
"BEEP BEEP BEEP for: " + ctx.getContext().getRequest().getNormalizedText() + ""
);
}
},
ms
);
return NCResult.text("Timer set for: " + FMT.format(dt));
}
@Override
public void onDiscard() {
// Clean up when model gets discarded (e.g. during testing).
timer.cancel();
}
}