All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.oliviercailloux.javagrade.graders.GraderDiceRoller Maven / Gradle / Ivy

The newest version!
package io.github.oliviercailloux.javagrade.graders;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.util.concurrent.SimpleTimeLimiter;
import io.github.oliviercailloux.g421.CyclicDiceRoller;
import io.github.oliviercailloux.grade.BatchGitHistoryGrader;
import io.github.oliviercailloux.grade.CodeGrader;
import io.github.oliviercailloux.grade.Criterion;
import io.github.oliviercailloux.grade.GitFileSystemWithHistoryFetcher;
import io.github.oliviercailloux.grade.GitFileSystemWithHistoryFetcherByPrefix;
import io.github.oliviercailloux.grade.GitFsGraderUsingLast;
import io.github.oliviercailloux.grade.GradeAggregator;
import io.github.oliviercailloux.grade.Mark;
import io.github.oliviercailloux.grade.MarksTree;
import io.github.oliviercailloux.grade.MavenCodeGrader;
import io.github.oliviercailloux.jaris.exceptions.TryCatchAll;
import io.github.oliviercailloux.javagrade.bytecode.Instanciator;
import java.io.UncheckedIOException;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Path;
import java.time.Duration;
import java.time.Instant;
import java.time.ZonedDateTime;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class GraderDiceRoller implements CodeGrader {
  @SuppressWarnings("unused")
  private static final Logger LOGGER = LoggerFactory.getLogger(GraderDiceRoller.class);

  public static final String PREFIX = "dice-roller";

  public static final ZonedDateTime DEADLINE =
      ZonedDateTime.parse("2022-05-13T14:25:00+02:00[Europe/Paris]");

  public static final double USER_WEIGHT = 0.025d;

  static record Pair (int first, int second) {

  }

  static record Triple (int first, int second, int third) {
    public Triple cycle() {
      return new Triple(third, first, second);
    }
  }

  public static void main(String[] args) throws Exception {
    final GitFileSystemWithHistoryFetcher fetcher =
        GitFileSystemWithHistoryFetcherByPrefix.getRetrievingByPrefix(PREFIX);
    final BatchGitHistoryGrader batchGrader =
        BatchGitHistoryGrader.given(() -> fetcher);

    final GraderDiceRoller grader421 = new GraderDiceRoller();
    final MavenCodeGrader m =
        MavenCodeGrader.basic(grader421, UncheckedIOException::new);

    batchGrader.getAndWriteGrades(DEADLINE, Duration.ofMinutes(5), GitFsGraderUsingLast.using(m),
        USER_WEIGHT, Path.of("grades " + PREFIX),
        PREFIX + Instant.now().atZone(DEADLINE.getZone()));
    grader421.close();
    LOGGER.info("Done, closed.");
  }

  private static final Criterion C_STATE_0 = Criterion.given("Illegal state (not rolled)");

  private static final Criterion C_STATE_1 = Criterion.given("Illegal state (set; not rolled)");

  private static final Criterion C_ARG = Criterion.given("Illegal argument (set)");
  private static final Criterion C_JUST_ROLL = Criterion.given("Just roll");

  private static final Criterion C_SET_ROLL_ONCE = Criterion.given("Set then roll once");

  private static final Criterion C_SET_ROLL = Criterion.given("Set then roll");

  private final ExecutorService executors;

  public GraderDiceRoller() {
    executors = Executors.newCachedThreadPool();
  }

  private TryCatchAll newInstance(Instanciator instanciator) {
    final TryCatchAll tryTarget =
        TryCatchAll.get(() -> instanciator.getInstanceOrThrow(CyclicDiceRoller.class));
    final TryCatchAll instance = tryTarget.andApply(target -> SimpleTimeLimiter
        .create(executors).newProxy(target, CyclicDiceRoller.class, Duration.ofSeconds(5)));
    return instance;
  }

  @Override
  public MarksTree gradeCode(Instanciator instanciator) {
    final ImmutableMap.Builder builder = ImmutableMap.builder();

    final TryCatchAll roller0 = newInstance(instanciator);
    final boolean invocationFailed =
        roller0.map(r -> false, c -> c instanceof InvocationTargetException);
    if (invocationFailed) {
      return Mark.zero("Invocation failed: " + roller0.toString());
    }

    {
      final TryCatchAll roller = newInstance(instanciator);
      final TryCatchAll got = roller.andApply(CyclicDiceRoller::first);
      final boolean pass = got.map(r -> false, c -> c instanceof IllegalStateException);

      builder.put(C_STATE_0, Mark.binary(pass, "", got.toString()));
    }

    {
      final TryCatchAll roller = newInstance(instanciator);
      final TryCatchAll rollerSet = roller.andConsume(r -> r.setResult(1, 2, 3));
      final TryCatchAll got = rollerSet.andApply(CyclicDiceRoller::first);
      final boolean pass = got.map(r -> false, c -> c instanceof IllegalStateException);

      builder.put(C_STATE_1, Mark.binary(pass, "", got.toString()));
    }

    {
      final TryCatchAll roller = newInstance(instanciator);
      final TryCatchAll got = roller.andConsume(r -> r.setResult(1, -2, 3));
      final boolean pass = got.map(r -> false, c -> c instanceof IllegalArgumentException);

      builder.put(C_ARG, Mark.binary(pass, "", got.toString()));
    }

    {
      final TryCatchAll roller = newInstance(instanciator);
      final ImmutableList> triples =
          IntStream.range(0, 4).boxed().map(i -> current(roller.andConsume(CyclicDiceRoller::roll)))
              .collect(ImmutableList.toImmutableList());
      final ImmutableList> expected = Stream.generate(() -> new Triple(1, 1, 1))
          .map(TryCatchAll::success).limit(4).collect(ImmutableList.toImmutableList());
      final boolean pass = triples.equals(expected);

      builder.put(C_JUST_ROLL, Mark.binary(pass, "", triples.toString()));
    }

    {
      final TryCatchAll roller = newInstance(instanciator);
      final TryCatchAll rollerSet = roller.andConsume(r -> r.setResult(2, 4, 6));
      final TryCatchAll triple = current(rollerSet.andConsume(CyclicDiceRoller::roll));
      final TryCatchAll expected = TryCatchAll.success(new Triple(2, 4, 6));
      final boolean pass = triple.equals(expected);

      builder.put(C_SET_ROLL_ONCE, Mark.binary(pass, "", triple.toString()));
    }

    {
      final TryCatchAll roller = newInstance(instanciator);
      final TryCatchAll rollerSet = roller.andConsume(r -> r.setResult(2, 4, 6));
      final ImmutableList> triples = IntStream.range(0, 4).boxed()
          .map(i -> current(rollerSet.andConsume(CyclicDiceRoller::roll)))
          .collect(ImmutableList.toImmutableList());
      final Triple t246 = new Triple(2, 4, 6);
      final ImmutableList> expected = Stream.iterate(t246, Triple::cycle)
          .map(TryCatchAll::success).limit(4).collect(ImmutableList.toImmutableList());
      final boolean pass = triples.equals(expected);

      builder.put(C_SET_ROLL, Mark.binary(pass, "", triples.toString()));
    }

    return MarksTree.composite(builder.build());
  }

  private TryCatchAll current(final TryCatchAll rolled) {
    /* TODO simplify. */
    final TryCatchAll first = rolled.andApply(CyclicDiceRoller::first);
    final TryCatchAll second = rolled.andApply(CyclicDiceRoller::second);
    final TryCatchAll dbl = first.and(second, Pair::new);
    final TryCatchAll third = rolled.andApply(CyclicDiceRoller::third);
    final TryCatchAll triple = dbl.and(third, (d, t) -> new Triple(d.first, d.second, t));
    // final Optional failure =
    // first.getCause().or(second::getCause).or(third::getCause);
    // final TryCatchAll triple = failure.map(f -> TryCatchAll.failure(f))
    // .orElse(TryCatchAll.get(() -> new Triple(first.orThrow(VerifyException::new),
    // second.orThrow(VerifyException::new), third.orThrow(VerifyException::new))));
    return triple;
  }

  @Override
  public GradeAggregator getCodeAggregator() {
    final ImmutableMap.Builder builder = ImmutableMap.builder();
    builder.put(C_STATE_0, 2d);
    builder.put(C_STATE_1, 2d);
    builder.put(C_ARG, 2.5d);
    builder.put(C_JUST_ROLL, 6.5d);
    builder.put(C_SET_ROLL_ONCE, 3.0d);
    builder.put(C_SET_ROLL, 3.5d);
    return GradeAggregator.staticAggregator(builder.build(), ImmutableMap.of());
  }

  public void close() {
    executors.shutdownNow();
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy