Add support for date/time conditions, closes #18
This commit is contained in:
parent
ac4d8efe3e
commit
44f40fd259
|
@ -26,3 +26,19 @@ Respackopts also allows checking mod (or minecraft) versions against predicates
|
|||
Fabric API provides a system called resource conditions, which is similar to respackopts own system.
|
||||
Respackopts previously allowed accessing fabric resource conditions and respackopts conditions from one another,
|
||||
however, this feature was removed in favor of enforcing the new muscript syntax.
|
||||
|
||||
## Dates
|
||||
Respackopts supports expressing conditions on the date of resource loading (not necessarily the date the resource is used)
|
||||
|
||||
You can get the current date via `date.today` and compare it (`==`, `>`, `<`, ...) with a date object created
|
||||
via the date constructor, for example: `date(2022, 5, 4)` stands for the fourth of may 2022.
|
||||
|
||||
You can also access the year, month or day using `.year`, `.month` or `.day` respectively (for example, `date.today.year == 2022`)
|
||||
|
||||
## Times
|
||||
Respackopts supports expressing conditions on the time of resource loading (not necessarily the time the resource is used)
|
||||
|
||||
You can get the current time via `time.now` and compare it (`==`, `>`, `<`, ...) with a time object created
|
||||
via the time constructor, for example: `date(23, 30, 1)` stands for half past 11 PM and one second
|
||||
|
||||
You can also access the hour, minute or second using `.hour`, `.minute` or `.second` respectively (for example, `time.now.hour >= 21`)
|
||||
|
|
|
@ -132,28 +132,12 @@ public class MetaCache {
|
|||
}
|
||||
|
||||
public static ExpressionParameter getParameter(@Nullable CacheKey key) {
|
||||
return hydrateParameter(key == null ? new ExpressionParameter() : MetaCache.getState(key).expressionParameter());
|
||||
}
|
||||
|
||||
public static ExpressionParameter hydrateParameter(ExpressionParameter parameter) {
|
||||
ExpressionParameter parameter = key == null ? new ExpressionParameter() : MetaCache.getState(key).expressionParameter();
|
||||
MetaCache.forEach((id, state) -> {
|
||||
String key = Respackopts.sanitizeString(state.packId());
|
||||
if (!parameter.has(key))
|
||||
parameter.set(key, state.configBranch().getDynamic());
|
||||
String packId = Respackopts.sanitizeString(state.packId());
|
||||
if (!parameter.has(packId))
|
||||
parameter.set(packId, state.configBranch().getDynamic());
|
||||
});
|
||||
StandardLib.addTo(parameter);
|
||||
parameter.set("version", DFinal.of(args -> {
|
||||
if (args.size() != 2) throw new IllegalArgumentException("Expected 2 arguments on version but got " + args.size());
|
||||
VersionPredicate predicate;
|
||||
try {
|
||||
predicate = VersionPredicate.parse(args.get(1).asString().getValue());
|
||||
} catch (VersionParsingException e) {
|
||||
throw new RuntimeException("Could not parse version predicate", e);
|
||||
}
|
||||
return DFinal.of(FabricLoader.getInstance().getModContainer(args.get(0).asString().getValue())
|
||||
.map(c -> predicate.test(c.getMetadata().getVersion()))
|
||||
.orElse(false));
|
||||
}));
|
||||
return parameter;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
package io.gitlab.jfronny.respackopts.util;
|
||||
|
||||
import io.gitlab.jfronny.muscript.*;
|
||||
import io.gitlab.jfronny.muscript.dynamic.*;
|
||||
import net.fabricmc.loader.api.*;
|
||||
import net.fabricmc.loader.api.metadata.version.*;
|
||||
|
||||
import java.time.*;
|
||||
import java.util.*;
|
||||
import java.util.function.*;
|
||||
|
||||
public class MuUtils {
|
||||
public static ExpressionParameter addDefault(ExpressionParameter parameter) {
|
||||
StandardLib.addTo(parameter);
|
||||
parameter.set("version", DFinal.of(args -> {
|
||||
if (args.size() != 2) throw new IllegalArgumentException("Expected 2 arguments on version but got " + args.size());
|
||||
VersionPredicate predicate;
|
||||
try {
|
||||
predicate = VersionPredicate.parse(args.get(1).asString().getValue());
|
||||
} catch (VersionParsingException e) {
|
||||
throw new RuntimeException("Could not parse version predicate", e);
|
||||
}
|
||||
return DFinal.of(FabricLoader.getInstance().getModContainer(args.get(0).asString().getValue())
|
||||
.map(c -> predicate.test(c.getMetadata().getVersion()))
|
||||
.orElse(false));
|
||||
}));
|
||||
parameter.set("date", new DCallableObject(Map.of(
|
||||
"today", new DDate(LocalDate::now)
|
||||
), DFinal.of(args -> {
|
||||
// Constructor
|
||||
if (args.size() == 1) return new DDate(() -> LocalDate.ofEpochDay(args.get(0).asNumber().getValue().longValue()));
|
||||
if (args.size() != 3) throw new IllegalArgumentException("Expected 3 arguments for full date constructor");
|
||||
int a0 = args.get(0).asNumber().getValue().intValue();
|
||||
int a1 = args.get(1).asNumber().getValue().intValue();
|
||||
int a2 = args.get(2).asNumber().getValue().intValue();
|
||||
return new DDate(() -> LocalDate.of(a0, a1, a2));
|
||||
})));
|
||||
parameter.set("time", new DCallableObject(Map.of(
|
||||
"now", new DTime(LocalTime::now)
|
||||
), DFinal.of(args -> {
|
||||
// Constructor
|
||||
if (args.size() == 1) return new DTime(() -> LocalTime.ofSecondOfDay(args.get(0).asNumber().getValue().intValue()));
|
||||
if (args.size() != 3) throw new IllegalArgumentException("Expected 3 arguments for full time constructor");
|
||||
int a0 = args.get(0).asNumber().getValue().intValue();
|
||||
int a1 = args.get(1).asNumber().getValue().intValue();
|
||||
int a2 = args.get(2).asNumber().getValue().intValue();
|
||||
return new DTime(() -> LocalTime.of(a0, a1, a2));
|
||||
})));
|
||||
return parameter;
|
||||
}
|
||||
|
||||
private record DCallableObject(Map<String, Dynamic<?>> value, DCallable callable) implements DObject {
|
||||
@Override
|
||||
public Map<String, Dynamic<?>> getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DCallable asCallable() {
|
||||
return callable;
|
||||
}
|
||||
}
|
||||
|
||||
private record DDate(Supplier<LocalDate> date) implements DObject {
|
||||
@Override
|
||||
public Map<String, Dynamic<?>> getValue() {
|
||||
return Map.of(
|
||||
"year", DFinal.of(date.get().getYear()),
|
||||
"month", DFinal.of(date.get().getMonthValue()),
|
||||
"day", DFinal.of(date.get().getDayOfMonth())
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DString asString() {
|
||||
return DFinal.of(date.get().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public DNumber asNumber() {
|
||||
return DFinal.of(date.get().toEpochDay());
|
||||
}
|
||||
}
|
||||
|
||||
private record DTime(Supplier<LocalTime> time) implements DObject {
|
||||
@Override
|
||||
public Map<String, Dynamic<?>> getValue() {
|
||||
return Map.of(
|
||||
"hour", DFinal.of(time.get().getHour()),
|
||||
"minute", DFinal.of(time.get().getMinute()),
|
||||
"second", DFinal.of(time.get().getSecond())
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DString asString() {
|
||||
return DFinal.of(time.get().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public DNumber asNumber() {
|
||||
return DFinal.of(time.get().toSecondOfDay());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -104,6 +104,6 @@ class ConditionJsonSerializationTest {
|
|||
|
||||
private boolean evaluateCondition(String json) {
|
||||
BoolExpr condition = AttachmentHolder.attach(7, () -> GSON.fromJson(json, BoolExpr.class));
|
||||
return condition.get(MetaCache.hydrateParameter(new ExpressionParameter()));
|
||||
return condition.get(MuUtils.addDefault(new ExpressionParameter()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
package io.gitlab.jfronny.respackopts;
|
||||
|
||||
import io.gitlab.jfronny.muscript.*;
|
||||
import io.gitlab.jfronny.muscript.compiler.*;
|
||||
import io.gitlab.jfronny.respackopts.util.*;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class TemporalExpressionTest {
|
||||
@Test
|
||||
void componentTest() {
|
||||
ExpressionParameter param = MuUtils.addDefault(new ExpressionParameter());
|
||||
|
||||
assertEquals(10, Parser.parse("date(2020, 5, 10).day").asNumberExpr().get(param));
|
||||
assertEquals(5, Parser.parse("date(2020, 5, 10).month").asNumberExpr().get(param));
|
||||
assertEquals(2020, Parser.parse("date(2020, 5, 10).year").asNumberExpr().get(param));
|
||||
|
||||
assertEquals(59, Parser.parse("time(13, 45, 59).second").asNumberExpr().get(param));
|
||||
assertEquals(45, Parser.parse("time(13, 45, 59).minute").asNumberExpr().get(param));
|
||||
assertEquals(13, Parser.parse("time(13, 45, 59).hour").asNumberExpr().get(param));
|
||||
}
|
||||
|
||||
@Test
|
||||
void compareTest() {
|
||||
ExpressionParameter param = MuUtils.addDefault(new ExpressionParameter());
|
||||
|
||||
assertTrue(Parser.parse("date(2020, 5, 10) > date(2020, 5, 9)").asBoolExpr().get(param));
|
||||
assertTrue(Parser.parse("date(2020, 5, 10) > date(2020, 4, 10)").asBoolExpr().get(param));
|
||||
assertTrue(Parser.parse("date(2020, 5, 10) > date(2019, 5, 10)").asBoolExpr().get(param));
|
||||
|
||||
assertTrue(Parser.parse("time(13, 45, 59) > time(13, 45, 58)").asBoolExpr().get(param));
|
||||
assertTrue(Parser.parse("time(13, 45, 59) > time(13, 44, 59)").asBoolExpr().get(param));
|
||||
assertTrue(Parser.parse("time(13, 45, 59) > time(12, 45, 59)").asBoolExpr().get(param));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue