text:
package com.facebook.buck.rules.keys;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThat;

import com.facebook.buck.core.build.action.BuildEngineAction;
import com.facebook.buck.core.model.BuildTarget;
import com.facebook.buck.core.model.BuildTargetFactory;
import com.facebook.buck.core.model.RuleType;
import com.facebook.buck.core.rulekey.AddToRuleKey;
import com.facebook.buck.core.rulekey.AddsToRuleKey;
import com.facebook.buck.core.rulekey.RuleKey;
import com.facebook.buck.core.rules.BuildRule;
import com.facebook.buck.core.rules.SourcePathRuleFinder;
import com.facebook.buck.core.rules.TestBuildRuleParams;
import com.facebook.buck.core.rules.actions.ActionRegistryForTests;
import com.facebook.buck.core.rules.impl.NoopBuildRuleWithDeclaredAndExtraDeps;
import com.facebook.buck.core.rules.resolver.impl.TestActionGraphBuilder;
import com.facebook.buck.core.sourcepath.FakeSourcePath;
import com.facebook.buck.core.sourcepath.PathSourcePath;
import com.facebook.buck.core.sourcepath.SourcePath;
import com.facebook.buck.io.filesystem.ProjectFilesystem;
import com.facebook.buck.io.filesystem.impl.FakeProjectFilesystem;
import com.facebook.buck.rules.keys.RuleKeyDiagnostics.Result;
import com.facebook.buck.rules.keys.config.TestRuleKeyConfigurationFactory;
import com.facebook.buck.rules.keys.hasher.StringRuleKeyHasher;
import com.facebook.buck.testutil.DummyFileHashCache;
import com.facebook.buck.util.cache.FileHashCacheMode;
import com.facebook.buck.util.cache.impl.DefaultFileHashCache;
import com.facebook.buck.util.cache.impl.StackedFileHashCache;
import com.facebook.buck.util.hashing.FileHashLoader;
import com.facebook.buck.util.sha1.Sha1HashCode;
import com.facebook.buck.util.types.Either;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.MapMaker;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import org.hamcrest.Matchers;
import org.junit.Test;

// There are tons of unused fields in this class.
public class DefaultRuleKeyFactoryTest {

  @Test
  public void shouldNotAddUnannotatedFieldsToRuleKey() {
    BuildTarget target = BuildTargetFactory.newInstance("//cheese:peas");
    SourcePathRuleFinder ruleFinder = new TestActionGraphBuilder();

    DefaultRuleKeyFactory factory =
        new TestDefaultRuleKeyFactory(new DummyFileHashCache(), ruleFinder);

    @SuppressWarnings("unused")
    class UndecoratedFields extends EmptyFakeBuildRule {
      private String field = "cake-walk";

      public UndecoratedFields() {
        super(target);
      }
    }

    Result<RuleKey, String> result =
        factory.buildForDiagnostics(new UndecoratedFields(), new StringRuleKeyHasher());
    assertThat(result.diagKey, Matchers.not(Matchers.containsString("cake-walk")));
  }

  @Test
  public void shouldAddASingleAnnotatedFieldToRuleKey() {
    BuildTarget target = BuildTargetFactory.newInstance("//cheese:peas");
    SourcePathRuleFinder ruleFinder = new TestActionGraphBuilder();

    DefaultRuleKeyFactory factory =
        new TestDefaultRuleKeyFactory(new DummyFileHashCache(), ruleFinder);

    @SuppressWarnings("unused")
    class DecoratedFields extends EmptyFakeBuildRule {

      @AddToRuleKey private String field = "cake-walk";

      public DecoratedFields() {
        super(target);
      }
    }

    Result<RuleKey, String> result =
        factory.buildForDiagnostics(new DecoratedFields(), new StringRuleKeyHasher());
    assertThat(result.diagKey, Matchers.containsString("cake-walk"));
  }

  @Test
  public void shouldAllowAFieldToBeStringified() {
    BuildTarget target = BuildTargetFactory.newInstance("//cheese:peas");
    SourcePathRuleFinder ruleFinder = new TestActionGraphBuilder();

    DefaultRuleKeyFactory factory =
        new TestDefaultRuleKeyFactory(new DummyFileHashCache(), ruleFinder);

    class Stringifiable {
      @Override
      public String toString() {
        return "sausages";
      }
    }

    @SuppressWarnings("unused")
    class StringifiedField extends EmptyFakeBuildRule {
      @AddToRuleKey(stringify = true)
      private Stringifiable field = new Stringifiable();

      public StringifiedField() {
        super(target);
      }
    }

    Result<RuleKey, String> result =
        factory.buildForDiagnostics(new StringifiedField(), new StringRuleKeyHasher());
    assertThat(result.diagKey, Matchers.containsString("string(\"sausages\"):key(field)"));
  }

  @Test
  public void shouldAllowAddsToRuleKeysToAppendToRuleKey() {
    BuildTarget target = BuildTargetFactory.newInstance("//cheese:peas");
    SourcePathRuleFinder ruleFinder = new TestActionGraphBuilder();

    FileHashLoader fileHashLoader = new DummyFileHashCache();
    DefaultRuleKeyFactory factory = new TestDefaultRuleKeyFactory(fileHashLoader, ruleFinder);

    class AppendingField extends EmptyFakeBuildRule {
      @AddToRuleKey private Adder field = new Adder();

      public AppendingField() {
        super(target);
      }
    }

    AppendingField buildRule = new AppendingField();
    Result<RuleKey, String> fieldResult =
        factory.buildForDiagnostics(buildRule.field, new StringRuleKeyHasher());
    Result<RuleKey, String> result =
        factory.buildForDiagnostics(buildRule, new StringRuleKeyHasher());
    assertThat(
        result.diagKey,
        Matchers.containsString(
            String.format("(sha1=%s):wrapper(APPENDABLE):key(field)", fieldResult.ruleKey)));
  }

  @Test
  public void shouldAllowRuleKeyAppendablesToAppendToRuleKey() {
    BuildTarget target = BuildTargetFactory.newInstance("//cheese:peas");
    SourcePathRuleFinder ruleFinder = new TestActionGraphBuilder();

    FileHashLoader fileHashLoader = new DummyFileHashCache();
    DefaultRuleKeyFactory factory = new TestDefaultRuleKeyFactory(fileHashLoader, ruleFinder);

    class AppendingField extends EmptyFakeBuildRule {
      @AddToRuleKey private Appender field = new Appender();

      public AppendingField() {
        super(target);
      }
    }
    AppendingField buildRule = new AppendingField();
    Result<RuleKey, String> fieldResult =
        factory.buildForDiagnostics(buildRule.field, new StringRuleKeyHasher());
    Result<RuleKey, String> result =
        factory.buildForDiagnostics(buildRule, new StringRuleKeyHasher());
    assertThat(
        result.diagKey,
        Matchers.containsString(
            String.format("(sha1=%s):wrapper(APPENDABLE):key(field)", fieldResult.ruleKey)));
  }

  @Test
  public void stringifiedAddsToRuleKeysGetAddedToRuleKeyAsStrings() {
    BuildTarget target = BuildTargetFactory.newInstance("//cheese:peas");
    SourcePathRuleFinder ruleFinder = new TestActionGraphBuilder();

    DefaultRuleKeyFactory factory =
        new TestDefaultRuleKeyFactory(new DummyFileHashCache(), ruleFinder);

    class AppendingField extends EmptyFakeBuildRule {
      @AddToRuleKey(stringify = true)
      private Adder field = new Adder();

      public AppendingField() {
        super(target);
      }
    }

    AppendingField buildRule = new AppendingField();
    Result<RuleKey, String> fieldResult =
        factory.buildForDiagnostics(buildRule.field, new StringRuleKeyHasher());
    Result<RuleKey, String> result =
        factory.buildForDiagnostics(buildRule, new StringRuleKeyHasher());
    assertThat(
        result.diagKey, Matchers.not(Matchers.containsString(fieldResult.ruleKey.toString())));
    assertThat(result.diagKey, Matchers.not(Matchers.containsString("APPENDABLE")));
    assertThat(result.diagKey, Matchers.containsString("string(\"cheddar\"):key(field)"));
  }

  @Test
  public void stringifiedRuleKeyAppendablesGetAddedToRuleKeyAsStrings() {
    BuildTarget target = BuildTargetFactory.newInstance("//cheese:peas");
    SourcePathRuleFinder ruleFinder = new TestActionGraphBuilder();

    DefaultRuleKeyFactory factory =
        new TestDefaultRuleKeyFactory(new DummyFileHashCache(), ruleFinder);

    class AppendingField extends EmptyFakeBuildRule {
      @AddToRuleKey(stringify = true)
      private Appender field = new Appender();

      public AppendingField() {
        super(target);
      }
    }

    AppendingField buildRule = new AppendingField();
    Result<RuleKey, String> fieldResult =
        factory.buildForDiagnostics(buildRule.field, new StringRuleKeyHasher());
    Result<RuleKey, String> result =
        factory.buildForDiagnostics(buildRule, new StringRuleKeyHasher());
    assertThat(
        result.diagKey, Matchers.not(Matchers.containsString(fieldResult.ruleKey.toString())));
    assertThat(result.diagKey, Matchers.not(Matchers.containsString("APPENDABLE")));
    assertThat(result.diagKey, Matchers.containsString("string(\"cheddar\"):key(field)"));
  }

  @Test
  public void fieldsAreAddedInAlphabeticalOrder() {
    BuildTarget target = BuildTargetFactory.newInstance("//cheese:peas");
    SourcePathRuleFinder ruleFinder = new TestActionGraphBuilder();

    DefaultRuleKeyFactory factory =
        new TestDefaultRuleKeyFactory(new DummyFileHashCache(), ruleFinder);

    @SuppressWarnings("unused")
    class UnsortedFields extends EmptyFakeBuildRule {
      @AddToRuleKey private String gamma = "stinking bishop";
      @AddToRuleKey private int beta = 1;
      @AddToRuleKey private String alpha = "stilton";

      public UnsortedFields() {
        super(target);
      }
    }

    Result<RuleKey, String> result =
        factory.buildForDiagnostics(new UnsortedFields(), new StringRuleKeyHasher());
    assertThat(
        result.diagKey,
        Matchers.containsString(
            "string(\"stilton\"):key(alpha):number(1):key(beta):string(\"stinking bishop\"):key(gamma):"));
  }

  @Test
  public void actionsFieldsAreAddedToRuleKeysInOrder() {
    BuildTarget target = BuildTargetFactory.newInstance("//cheese:peas");
    SourcePathRuleFinder ruleFinder = new TestActionGraphBuilder();

    DefaultRuleKeyFactory factory =
        new TestDefaultRuleKeyFactory(new DummyFileHashCache(), ruleFinder);

    Result<RuleKey, String> result =
        factory.buildForDiagnostics(
            new SomeAction(new ActionRegistryForTests(target), 2, "C"), new StringRuleKeyHasher());
    assertThat(result.diagKey, Matchers.containsString("string(\"C\"):key(a):number(2):key(i):"));
  }

  @Test
  public void fieldsFromParentClassesShouldBeAddedAndFieldsRetainOverallAlphabeticalOrdering() {
    BuildTarget topLevelTarget = BuildTargetFactory.newInstance("//cheese:peas");
    SourcePathRuleFinder ruleFinder = new TestActionGraphBuilder();

    DefaultRuleKeyFactory factory =
        new TestDefaultRuleKeyFactory(new DummyFileHashCache(), ruleFinder);

    @SuppressWarnings("unused")
    class Parent extends EmptyFakeBuildRule {
      @AddToRuleKey private BuildTarget target;

      public Parent(BuildTarget target) {
        super(target);
        this.target = target;
      }
    }

    @SuppressWarnings("unused")
    class Child extends Parent {
      @AddToRuleKey private String exoticCheese = "bavarian smoked";

      public Child(BuildTarget target) {
        super(target);
      }
    }

    Result<RuleKey, String> result =
        factory.buildForDiagnostics(new Child(topLevelTarget), new StringRuleKeyHasher());
    assertThat(
        result.diagKey,
        Matchers.containsString(
            "string(\"bavarian smoked\"):key(exoticCheese):target(//cheese:peas):key(target):"));
  }

  @Test
  public void fieldsFromParentClassesAreAlsoAdded() {
    BuildTarget target = BuildTargetFactory.newInstance("//cheese:peas");
    SourcePathRuleFinder ruleFinder = new TestActionGraphBuilder();

    DefaultRuleKeyFactory factory =
        new TestDefaultRuleKeyFactory(new DummyFileHashCache(), ruleFinder);

    @SuppressWarnings("unused")
    class Parent extends EmptyFakeBuildRule {
      @AddToRuleKey private String key = "parent";

      public Parent() {
        super(target);
      }
    }

    @SuppressWarnings("unused")
    class Child extends Parent {
      @AddToRuleKey private String key = "child";

      public Child() {}
    }

    Result<RuleKey, String> result =
        factory.buildForDiagnostics(new Child(), new StringRuleKeyHasher());
    assertThat(
        result.diagKey,
        Matchers.containsString(":string(\"child\"):key(key):string(\"parent\"):key(key):"));
  }

  @Test
  public void testBothKeysAndValuesGetHashed() {
    assertKeysGetHashed(null);
    assertBothKeysAndValuesGetHashed(true, false);
    assertBothKeysAndValuesGetHashed((double) 123, (double) 42);
    assertBothKeysAndValuesGetHashed((float) 123, (float) 42);
    assertBothKeysAndValuesGetHashed(123, 42); // (int)
    assertBothKeysAndValuesGetHashed((long) 123, (long) 42);
    assertBothKeysAndValuesGetHashed((short) 123, (short) 42);
    assertBothKeysAndValuesGetHashed((byte) 123, (byte) 42);
    assertBothKeysAndValuesGetHashed((char) 0, (char) 42);
    assertBothKeysAndValuesGetHashed(new byte[] {1, 2, 3}, new byte[] {4, 2});
    assertBothKeysAndValuesGetHashed(DummyEnum.BLACK, DummyEnum.WHITE);
    assertBothKeysAndValuesGetHashed("abc", "def");
    assertBothKeysAndValuesGetHashed(Pattern.compile("regex1"), Pattern.compile("regex2"));
    assertBothKeysAndValuesGetHashed(
        Sha1HashCode.of("a002b39af204cdfaa5fdb67816b13867c32ac52c"),
        Sha1HashCode.of("b67816b13867c32ac52ca002b39af204cdfaa5fd"));
    assertBothKeysAndValuesGetHashed(
        new RuleKey("a002b39af204cdfaa5fdb67816b13867c32ac52c"),
        new RuleKey("b67816b13867c32ac52ca002b39af204cdfaa5fd"));
    assertBothKeysAndValuesGetHashed(
        RuleType.of("rule_type", RuleType.Kind.BUILD), RuleType.of("type2", RuleType.Kind.BUILD));
    assertBothKeysAndValuesGetHashed(
        BuildTargetFactory.newInstance("//example/base:one"),
        BuildTargetFactory.newInstance("//example/base:two"));

    // wrapper types
    assertBothKeysAndValuesGetHashed(Optional.of("abc"), Optional.of("def"));
    assertBothKeysAndValuesGetHashed(Either.ofLeft("abc"), Either.ofLeft("def"));
    assertBothKeysAndValuesGetHashed(Either.ofRight("def"), Either.ofRight("ghi"));
    assertBothKeysAndValuesGetHashed(Suppliers.ofInstance("abc"), Suppliers.ofInstance("def"));

    // iterables & maps
    assertBothKeysAndValuesGetHashed(Arrays.asList(1, 2, 3), Arrays.asList(4, 2));
    assertBothKeysAndValuesGetHashed(ImmutableList.of("abc", "xy"), ImmutableList.of("xy", "abc"));
    assertBothKeysAndValuesGetHashed(ImmutableMap.of("key", "v1"), ImmutableMap.of("key", "v2"));

    // nested
    assertBothKeysAndValuesGetHashed(
        ImmutableMap.of("key", Optional.of(ImmutableList.of(1, 2, 3))),
        ImmutableMap.of("key", Optional.of(ImmutableList.of(1, 2, 4))));
  }

  @Test
  public void testFactoryReportsInputsAndDependenciesToCacheForBuildRule() throws IOException {
    SourcePathRuleFinder ruleFinder = new TestActionGraphBuilder();
    NoopRuleKeyCache<RuleKey> noopRuleKeyCache = new NoopRuleKeyCache<>();
    ProjectFilesystem filesystem = new FakeProjectFilesystem();
    DefaultRuleKeyFactory factory =
        new DefaultRuleKeyFactory(
            new RuleKeyFieldLoader(TestRuleKeyConfigurationFactory.create()),
            new StackedFileHashCache(
                ImmutableList.of(
                    DefaultFileHashCache.createDefaultFileHashCache(
                        filesystem, FileHashCacheMode.DEFAULT))),
            ruleFinder,
            noopRuleKeyCache,
            Optional.empty());

    // Create a sample input.
    PathSourcePath input = FakeSourcePath.of(filesystem, "input");
    filesystem.touch(input.getRelativePath());

    // Create a sample dep rule.
    BuildRule dep = new EmptyFakeBuildRule(BuildTargetFactory.newInstance("//:dep"));

    // Create a sample rule key appendable.
    RuleKeyAppendable appendable = sink -> {};

    // Create a dummy build rule that uses the input.
    BuildTarget buildTarget = BuildTargetFactory.newInstance("//:target");
    BuildRule rule =
        new NoopBuildRuleWithDeclaredAndExtraDeps(
            buildTarget,
            filesystem,
            TestBuildRuleParams.create().withDeclaredDeps(ImmutableSortedSet.of(dep))) {

          @AddToRuleKey private final SourcePath inputField = input;

          @AddToRuleKey private final RuleKeyAppendable appendableField = appendable;
        };

    // Build the rule key.
    factory.build(rule);

    // Verify the input was properly reported to the rule key cache.
    RuleKeyResult<RuleKey> result = noopRuleKeyCache.results.get(rule);
    assertThat(result, Matchers.notNullValue());
    assertThat(
        result.inputs,
        Matchers.containsInAnyOrder(ImmutableRuleKeyInput.of(filesystem, input.getRelativePath())));
    assertThat(result.deps, Matchers.containsInAnyOrder(dep, appendable));
  }

  @Test
  public void testFactoryReportsInputsAndDependenciesToCacheForRuleKeyAppendable()
      throws IOException {
    SourcePathRuleFinder ruleFinder = new TestActionGraphBuilder();
    NoopRuleKeyCache<RuleKey> noopRuleKeyCache = new NoopRuleKeyCache<>();
    ProjectFilesystem filesystem = new FakeProjectFilesystem();
    DefaultRuleKeyFactory factory =
        new DefaultRuleKeyFactory(
            new RuleKeyFieldLoader(TestRuleKeyConfigurationFactory.create()),
            new StackedFileHashCache(
                ImmutableList.of(
                    DefaultFileHashCache.createDefaultFileHashCache(
                        filesystem, FileHashCacheMode.DEFAULT))),
            ruleFinder,
            noopRuleKeyCache,
            Optional.empty());

    // Create a sample input.
    PathSourcePath input = FakeSourcePath.of(filesystem, "input");
    filesystem.touch(input.getRelativePath());

    // Create a sample rule key appendable.
    RuleKeyAppendable appendable = sink -> sink.addValue(Paths.get("cheese"), input);

    // Create a dummy build rule that uses the input.
    BuildTarget buildTarget = BuildTargetFactory.newInstance("//:target");
    BuildRule rule =
        new NoopBuildRuleWithDeclaredAndExtraDeps(
            buildTarget, filesystem, TestBuildRuleParams.create()) {

          @SuppressWarnings("unused")
          @AddToRuleKey
          private final RuleKeyAppendable appendableField = appendable;
        };

    // Build the rule key.
    factory.build(rule);

    // Verify the input was properly reported to the rule key cache.
    RuleKeyResult<RuleKey> result = noopRuleKeyCache.results.get(appendable);
    assertThat(result, Matchers.notNullValue());
    assertThat(
        result.inputs,
        Matchers.containsInAnyOrder(ImmutableRuleKeyInput.of(filesystem, input.getRelativePath())));
    assertThat(result.deps, Matchers.emptyIterable());
  }

  private void assertBothKeysAndValuesGetHashed(@Nullable Object val1, @Nullable Object val2) {
    assertKeysGetHashed(val1);
    assertValuesGetHashed(val1, val2);
  }

  private void assertKeysGetHashed(@Nullable Object val) {
    BuildTarget target = BuildTargetFactory.newInstance("//cheese:peas");
    SourcePathRuleFinder ruleFinder = new TestActionGraphBuilder();
    BuildRule rule = new EmptyFakeBuildRule(target);

    DefaultRuleKeyFactory factory =
        new TestDefaultRuleKeyFactory(new DummyFileHashCache(), ruleFinder);

    RuleKey key1 =
        factory.newBuilderForTesting(rule).setReflectively("key1", val).build(RuleKey::new);
    RuleKey key1again =
        factory.newBuilderForTesting(rule).setReflectively("key1", val).build(RuleKey::new);
    RuleKey key2 =
        factory.newBuilderForTesting(rule).setReflectively("key2", val).build(RuleKey::new);
    assertEquals("Rule keys should be same! " + val, key1, key1again);
    assertNotEquals("Rule keys should be different! " + val, key1, key2);
  }

  private void assertValuesGetHashed(@Nullable Object val1, @Nullable Object val2) {
    Preconditions.checkArgument(!Objects.equal(val1, val2), "Values should be different!");
    BuildTarget target = BuildTargetFactory.newInstance("//cheese:peas");
    SourcePathRuleFinder ruleFinder = new TestActionGraphBuilder();
    BuildRule rule = new EmptyFakeBuildRule(target);

    DefaultRuleKeyFactory factory =
        new TestDefaultRuleKeyFactory(new DummyFileHashCache(), ruleFinder);

    RuleKey key1 =
        factory.newBuilderForTesting(rule).setReflectively("key", val1).build(RuleKey::new);
    RuleKey key1again =
        factory.newBuilderForTesting(rule).setReflectively("key", val1).build(RuleKey::new);
    RuleKey key2 =
        factory.newBuilderForTesting(rule).setReflectively("key", val2).build(RuleKey::new);
    assertEquals("Rule keys should be same! " + val1, key1, key1again);
    assertNotEquals("Rule keys should be different! " + val1 + " != " + val2, key1, key2);
  }

  @SuppressWarnings("unused")
  private static class Adder implements AddsToRuleKey {
    @AddToRuleKey private String cheese = "brie";
    @AddToRuleKey private String wine = "cabernet";

    @Override
    public String toString() {
      return "cheddar";
    }
  }

  @SuppressWarnings("unused")
  private static class Appender implements RuleKeyAppendable {
    @AddToRuleKey private String wine = "cabernet";

    @Override
    public void appendToRuleKey(RuleKeyAppendableSink sink) {
      sink.addValue(Paths.get("cheese"), null);
    }

    @Override
    public String toString() {
      return "cheddar";
    }
  }

  private enum DummyEnum {
    BLACK,
    WHITE,
  }

  private static class NoopRuleKeyCache<V> implements RuleKeyCache<V> {

    private final Map<Object, RuleKeyResult<V>> results = new MapMaker().weakKeys().makeMap();

    @Nullable
    @Override
    public V get(BuildEngineAction action) {
      RuleKeyResult<V> result = results.get(action);
      if (result != null) {
        return result.result;
      }
      return null;
    }

    @Override
    public V get(
        BuildEngineAction action, Function<? super BuildEngineAction, RuleKeyResult<V>> create) {
      RuleKeyResult<V> result = create.apply(action);
      results.put(action, result);
      return result.result;
    }

    @Override
    public V get(
        AddsToRuleKey appendable, Function<? super AddsToRuleKey, RuleKeyResult<V>> create) {
      RuleKeyResult<V> result = create.apply(appendable);
      results.put(appendable, result);
      return result.result;
    }

    @Override
    public void invalidateInputs(Iterable<RuleKeyInput> inputs) {
      throw new UnsupportedOperationException();
    }

    @Override
    public void invalidateAllExceptFilesystems(ImmutableSet<ProjectFilesystem> filesystems) {
      throw new UnsupportedOperationException();
    }

    @Override
    public void invalidateFilesystem(ProjectFilesystem filesystem) {
      throw new UnsupportedOperationException();
    }

    @Override
    public void invalidateAll() {
      throw new UnsupportedOperationException();
    }
  }
}


text:
Planet Four
=======

Will *only* run on Node 0.10.x - use [NVM](https://github.com/creationix/nvm) to install older versions of Node.

## Commands

### Run a local development server

`npm run start`

or

`docker-compose run --service-ports p4 npm run start`

### Build and deploy the frontend to staging

`npm run deploy-to-staging`

or

`docker-compose run --service-ports p4 npm run deploy-to-staging`

Staging URL is [https://www.planetfour.org/beta](https://www.planetfour.org/beta)

### Build and deploy the frontend to production

`npm run deploy`

or

`docker-compose run --service-ports p4 npm run deploy`

### Deploy the translations

`npm run deploy-locale`

or

`docker-compose run --service-ports p4 npm run deploy-locale`

Requires the `OUROBOROS_AUTH` environment variable to be set as `login:apiKey`, for example: `OUROBOROS_AUTH=mylogin:abcd1234`

redpajama_set_name: RedPajamaGithub


text:
package com.google.cloud.dataflow.sdk.coders;

import com.google.cloud.dataflow.sdk.testing.CoderProperties;
import com.google.cloud.dataflow.sdk.util.common.CounterTestUtils;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
 * Unit tests for {@link ByteArrayCoder}.
 */
@RunWith(JUnit4.class)
public class ByteArrayCoderTest {

  private static final byte[][] TEST_VALUES = {
    {0xa, 0xb, 0xc}, {}, {}, {0xd, 0xe}, {0xd, 0xe}, {}};

  @Test
  public void testDecodeEncodeEquals() throws Exception {
    ByteArrayCoder coder = ByteArrayCoder.of();
    for (byte[] value : TEST_VALUES) {
      CoderProperties.coderDecodeEncodeEqual(coder, value);
    }
  }

  @Test
  public void testRegisterByteSizeObserver() throws Exception {
    CounterTestUtils.testByteCount(ByteArrayCoder.of(), Coder.Context.OUTER,
                                   new byte[][]{{ 0xa, 0xb, 0xc }});

    CounterTestUtils.testByteCount(ByteArrayCoder.of(), Coder.Context.NESTED,
                                   new byte[][]{{ 0xa, 0xb, 0xc }, {}, {}, { 0xd, 0xe }, {}});
  }

  @Test
  public void testStructuralValueConsistentWithEquals() throws Exception {
    ByteArrayCoder coder = ByteArrayCoder.of();
    // We know that byte array coders are NOT compatible with equals
    // (aka injective w.r.t. Object.equals)
    for (byte[] value1 : TEST_VALUES) {
      for (byte[] value2 : TEST_VALUES) {
        CoderProperties.structuralValueConsistentWithEquals(coder, value1, value2);
      }
    }
  }
}


text:
package iht.controllers.application.assets.trusts

import iht.config.AppConfig
import iht.connector.{CachingConnector, IhtConnector}
import iht.controllers.application.EstateController
import iht.models.application.ApplicationDetails
import iht.models.application.assets.HeldInTrust
import iht.utils.{ApplicationKickOutHelper, CommonHelper}
import javax.inject.Inject
import play.api.mvc.MessagesControllerComponents
import uk.gov.hmrc.auth.core.AuthConnector
import uk.gov.hmrc.auth.core.retrieve.v2.Retrievals.{nino => ninoRetrieval}
import uk.gov.hmrc.play.bootstrap.frontend.controller.FrontendController
import iht.views.html.application.asset.trusts.trusts_overview

class TrustsOverviewControllerImpl @Inject()(val ihtConnector: IhtConnector,
                                             val cachingConnector: CachingConnector,
                                             val authConnector: AuthConnector,
                                             val trustsOverviewView: trusts_overview,
                                             implicit val appConfig: AppConfig,
val cc: MessagesControllerComponents) extends FrontendController(cc) with TrustsOverviewController {

}

trait TrustsOverviewController extends EstateController {
  override val applicationSection = Some(ApplicationKickOutHelper.ApplicationSectionAssetsInTrust)

  val trustsOverviewView: trusts_overview
  def onPageLoad = authorisedForIhtWithRetrievals(ninoRetrieval) { userNino =>

    implicit request => {
      withRegistrationDetails { registrationDetails =>
        for {
          applicationDetails: Option[ApplicationDetails] <- ihtConnector.getApplication(
            getNino(userNino),
            CommonHelper.getOrExceptionNoIHTRef(registrationDetails.ihtReference),
            registrationDetails.acknowledgmentReference
          )
          trusts: Option[HeldInTrust] = applicationDetails.flatMap(_.allAssets.flatMap(_.heldInTrust))
        } yield {
          Ok(trustsOverviewView(trusts, registrationDetails))
        }
      }
    }
  }
}


text:
def extractVesperlxd(item):
	"""
	Parser for 'VesperLxD'
	"""
	vol, chp, frag, postfix = extractVolChapterFragmentPostfix(item['title'])
	if not (chp or vol) or 'preview' in item['title'].lower():
		return None

	tagmap = [
		('Invincible Level Up',                                   'Invincible Level Up',                                'translated'),
		('Rebirth of an Abandoned Woman',                         'Rebirth of an Abandoned Woman',                      'translated'),
		("Great Han's Female General Wei Qiqi",                   "Great Han's Female General Wei Qiqi",                'translated'),
		('The Woman Who Accepts Her Fate',                        'The Woman Who Accepts Her Fate',                     'translated'),
		('Miracle Doctor, Wild Empress: Genius Summoner',         'Miracle Doctor, Wild Empress: Genius Summoner',      'translated'),
		('The General's Little Peasant Wife',                     'The General's Little Peasant Wife',                  'translated'),
		('Midnight Offering: Hades\'s Little Pet',                'Midnight Offering: Hades\'s Little Pet',             'translated'),
		('The Man Who Met God',                                   'The Man Who Met God',                                'translated'),
	]

	for tagname, name, tl_type in tagmap:
		if tagname in item['tags']:
			return buildReleaseMessageWithType(item, name, vol, chp, frag=frag, postfix=postfix, tl_type=tl_type)

	return False


text:
<?php
define('lang_Select','Сонгох');
define('lang_Erase','Устгах');
define('lang_Open','Нээх');
define('lang_Confirm_del','Та энэ файлыг устгахдаа итгэлтэй байна уу?');
define('lang_All','Бүгд');
define('lang_Files','Файлууд');
define('lang_Images','Зурагнууд');
define('lang_Archives','Архивлагдсан файлууд');
define('lang_Error_Upload','Хуулсан файл зөвшөөрөгдөх хэмжээнээс их байна.');
define('lang_Error_extension','Файлын өргөтгөх зөвшөөрөгдөөгүй.');
define('lang_Upload_file','Хуулах');
define('lang_Filters','Шүүлтүүрүүд');
define('lang_Videos','Бичлэгнүүд');
define('lang_Music','Дуунууд');
define('lang_New_Folder','Шинэ хавтас');
define('lang_Folder_Created','Хавтас амжилттай үүслээ');
define('lang_Existing_Folder','Давхардсан хавтас');
define('lang_Confirm_Folder_del','Хавтас болон доторх бүх файлуудыг устгахдаа итгэлтэй байна уу?');
define('lang_Return_Files_List','Файлын жагсаалт руу буцах');
define('lang_Preview','Урьдчилан харах');
define('lang_Download','Татаж авах');
define('lang_Insert_Folder_Name','Хавтасны нэрийг оруулна уу:');
define('lang_Root','root');
define('lang_Rename','Нэрлэх');
define('lang_Back','буцах');
define('lang_View','Үзэх');
define('lang_View_list','Жагсаалтаар харах');
define('lang_View_columns_list','Баганаар харах');
define('lang_View_boxes','Хайрцгаар харах');
define('lang_Toolbar','Товчилсон товчнууд');
define('lang_Actions','Үйлдэл');
define('lang_Rename_existing_file','Файл аль хэдийнэ үүссэн байна');
define('lang_Rename_existing_folder','Хавтас аль хэдийнэ үүсэн байна');
define('lang_Empty_name','Нэр хоосон байна');
define('lang_Text_filter','текстэн шүүлтүүр');
define('lang_Swipe_help','Файл/Хавтасны нэрийг товшоод тохиргоог харна уу');
define('lang_Upload_base','Энгийнээр хуулах');
define('lang_Upload_java','JAVA-гаар хуулах (их хэмжээтэй файл)');
define('lang_Upload_java_help',"Хэрэв Java Applet уншихгүй бол 1. Java суусан эсэхийг шалгана уу, үгүй бол [эндээс татаж авна уу]   2. Галт хана дээр хаалт хийсэн эсэхийг шалгана уу");
define('lang_Upload_base_help',"Хуулах хэсэг дээр файлыг зөөж тавих болон дээр нь дарж хуулж болно (орчин үеийн хөтөч дээр). Хуулж дууссан бол 'Файлын жагсаалт руу буцах' товчин дээр дарна уу.");
define('lang_Type_dir','dir');
define('lang_Type','Төрөл');
define('lang_Dimension','Харьцаа');
define('lang_Size','Хэмжээ');
define('lang_Date','Огноо');
define('lang_Filename','Файлын нэр');
define('lang_Operations','Үйлдэлүүд');
define('lang_Date_type','y-m-d');
define('lang_OK','ОК');
define('lang_Cancel','Буцах');
define('lang_Sorting','эрэмбэлэх');
define('lang_Show_url','URL-г харах');
define('lang_Extract','энд задла');
define('lang_File_info','файлын мэдээлэл');
define('lang_Edit_image','зураг засварлах');
define('lang_Duplicate','Давхардуулах');
define('lang_Folders', 'Folders');
define('lang_Copy','Copy');
define('lang_Cut','Cut');
define('lang_Paste','Paste');
define('lang_CB', 'CB'); // clipboard
define('lang_Paste_Here','Paste to this directory');
define('lang_Paste_Confirm','Are you sure you want to paste to this directory? This will overwrite existing files/folders if encountered any.');
define('lang_Paste_Failed','Failed to paste file(s)');
define('lang_Clear_Clipboard','Clear clipboard');
define('lang_Clear_Clipboard_Confirm','Are you sure you want to clear the clipboard?');
define('lang_Files_ON_Clipboard','There are files on the clipboard.');
define('lang_Copy_Cut_Size_Limit','The selected files/folders are too big to %s. Limit: %d MB/operation'); // %s = cut or copy
define('lang_Copy_Cut_Count_Limit','You selected too many files/folders to %s. Limit: %d files/operation'); // %s = cut or copy
define('lang_Copy_Cut_Not_Allowed','You are not allowed to %s files.'); // %s(1) = cut or copy, %s(2) = files or folders
define('lang_Aviary_No_Save', 'Could not save image');
define('lang_Zip_No_Extract', 'Could not extract. File might be corrupt.');
define('lang_Zip_Invalid', 'This extension is not supported. Valid: zip, gz, tar.');
define('lang_Dir_No_Write', 'The directory you selected is not writable.');
define('lang_Function_Disabled', 'The %s function has been disabled by the server.'); // %s = cut or copy
?>


text:
from django.conf.urls import url
from . import views

app_name = 'research'

urlpatterns = [
    url(r'^$', views.IndexView.as_view(), name='index'),
    url(r'^domain/(?P<pk>[0-9]+)/$', views.DomainView.as_view(), name='domain'),
    url(r'^detail/(?P<pk>[0-9]+)/$', views.ProjectView.as_view(), name='project')
]


text:
"""
CSV file module.
"""

from pyyaul.base.file._base import File
import csv

class CsvFile(File):
	"""
	Class for representing a JSON file.
	"""

	data = None  #`list` of `list`s representing the internal data of the file.

	def __init__(self, path=None):
		self.data = []
		super().__init__(path)

	def _load(self, path):
		try:
			with path.open('r') as fd:
				reader = csv.reader(fd, 'excel')
				self.data = list(r for r in reader)
		except FileNotFoundError:
			self.data = []

	def _save(self, path):
		with path.open('w', newline='') as fd:
			writer = csv.writer(fd, 'excel')
			for r in self.data:
				writer.writerow(r)


text:
/*----------------- MAIN CONTAINER DEFINITIONS ------------------*/
@import url('https://fonts.googleapis.com/css?family=Special+Elite|Italianno&display=swap');

.sheet-main-container {
  min-width: 600px;
	max-width: 1000px;
	background-color: #f0f2f1;
	padding: 30px 30px 0px 30px;
	display: flex;
	flex-direction: column;
}

.sheet-main-container input {
	height: 28px;
	border: 0px;
	border-bottom: 1px solid black;
	border-radius: 0px;
	padding: 0px;
	height: auto;
}

.sheet-main-container select {
	width: auto;
	height: 25px;
	margin: 0px;
	background: none;
}

.sheet-main-container input[type=text] {
	width: 10px;
	flex-grow: 1;
	background: none;
}

.sheet-main-container input[type=number] {
	width: 40px;
	text-align: center;
	background: none;
}

.sheet-main-container textarea {
	box-sizing: border-box;
	margin: 0px;
	height: auto;
	flex-grow: 1;
	background: none;
}

.sheet-main-container button {
	margin: 0px !important;
}

/*----------------- GENERAL CSS ------------------*/

.sheet-main-font {
	font-family: 'Special Elite';
}

.sheet-secondary-font {
	font-family: 'Italianno';
}

.sheet-title1 {
	font-size: 20px;
}

.sheet-title2 {
	font-size: 30px;
}

.sheet-flex-row {
	display: flex;
	flex-direction: row;
}

.sheet-flex-column {
	display: flex;
  flex-direction: column;
}

.sheet-grow {
	flex-grow: 1;
}

.sheet-label {
	font-size: 0.5fr;
	margin-right: 5px;
	line-height: 1;
}

.sheet-row-item-margin {
	margin-right: 5px !important;
}

/*----------------- SHEET PARTS ------------------*/

.sheet-header {
	display: flex;
	flex-direction: column;
	margin-bottom: 10px;
}

.sheet-header-row {
	margin-bottom: 10px;
	display: flex;
	flex-direction: row;
	align-items: center;
}

.sheet-header-row span {
	font-size: 13px !important;
}

.sheet-header-right-margin {
	margin-right: 10px !important;
}

.sheet-logo {
	background-image: url('https://raw.githubusercontent.com/Roll20/roll20-character-sheets/master/GoddessSaveTheQueen/img/goddess-logo.png');
	background-repeat: no-repeat;
	background-size: 195px 172px;
	width: 195px;
	height: 172px;
	margin-top: 20px;
}

.sheet-help {
	border: 1px dotted black;
	width: 20px;
	height: 20px;
	text-align: center;
}

.sheet-buttons-section {
	display: flex;
	flex-direction: row;
	justify-content: flex-end;
	align-items: center;
}

.sheet-buttons-section button {
	margin-right: 5px !important;
}

.sheet-tab-panel {
	/*display: flex;*/
	display: none;
	flex-direction: row;
}

.sheet-dice-row {
	display: flex;
	flex-direction: row;
	align-items: center;
	margin-bottom: 5px;
}

.sheet-actions {
	display: flex;
	flex-direction: column;
	justify-content: space-between;
}

.sheet-dice-row-margin {
	margin-right: 3px;
}

.sheet-middle {
	display: grid;
	grid-template-columns: 1fr 1fr 1fr;
	grid-template-rows: auto auto;
	column-gap: 10px;
}

.sheet-middle textarea {
	min-height: 6em;
}

.sheet-middle-column {
	display: flex;
	flex-direction: column;
	flex-grow: 1;
}

.sheet-karma-row {
	display: flex;
	flex-direction: row;
	margin-bottom: 20px;
}

.sheet-independence {
	display: flex;
	flex-direction: column;
	align-items: center;
}

.sheet-notes-box {
	flex-grow: 1;
}

.sheet-footer {
	text-align: right;
	font-style: italic;
}

.sheet-box {
	margin-bottom: 10px;
	padding: 10px;
}

.sheet-box-title {
	margin-bottom: 10px;
}

.sheet-repeatable-item {
	display: flex;
	flex-direction: column;
	margin-bottom: 10px;
}

.sheet-repeatable-row {
	display: flex;
	flex-direction: row;
	align-items: flex-end;
	margin-bottom: 5px;
}

.sheet-repeatable-row-box {
	display: flex;
	flex-direction: column;
	align-items: center;
}

.sheet-repeatable-dice-row {
	align-items: center;
	display: flex;
	flex-direction: row;
}

.sheet-dice-roller-row {
	display: grid;
	grid-auto-flow: column;
	justify-items: center;
	align-items: center;
	margin: 20px 0px 20px 0px;
	line-height: 1;
}

.sheet-dice-roller-row input {
	border: none;
	background: none;
	margin-left: 12px;
}

.sheet-dice-roller-row span {
	font-size: 23px;
}

.sheet-dice-roller-row .sheet-plus, .sheet-dice-roller-row button {
	margin-top: 20px !important;
}

.sheet-dice-row-circle {
	background-image: url('https://raw.githubusercontent.com/Roll20/roll20-character-sheets/master/GoddessSaveTheQueen/img/goddes-circle.png');
	background-repeat: no-repeat;
	background-size: 40px 40px;
	width: 40px;
	height: 40px;
	display: flex;
	align-items: center;
	justify-content: center;
}

.sheet-plus {
	font-size: 20px;
}

.sheet-dice-roller-box {
	display: flex;
	flex-direction: column;
	align-items: center;
}

.sheet-traumas {
	flex-grow: 1;
	display: flex;
	flex-direction: column;
}

.sheet-traumas-box {
	display: grid;
	gap: 5px;
	grid-template-columns: 1fr 1fr;
	grid-template-rows: 1fr 1fr;
	flex-grow: 1;
}

.sheet-traumas-box textarea {
	margin-right: 10px;
}

.sheet-die-icon {
	background-image: url('https://raw.githubusercontent.com/Roll20/roll20-character-sheets/master/GoddessSaveTheQueen/img/goddes-die.png');
	background-repeat: no-repeat;
	background-size: 20px 22px;
	width: 20px;
	min-width: 20px;
	height: 22px;
	min-height: 22px;
}

/*----------------- SPECIALTY SELECTION ------------------*/

.sheet-specialty-selected:not([value="custom"]) ~ .sheet-custom-specialty {
	display:none;
}

/*----------------- TAB CONTROL ------------------*/

/*Configure the tab buttons*/
.sheet-profiletab,
.sheet-configurationtab,
.sheet-journaltab {
	display: none;
}

/* show the selected tab */
.sheet-tabcontrol[value="profile"] ~ div.sheet-profiletab,
.sheet-tabcontrol[value="configuration"] ~ div.sheet-configurationtab,
.sheet-tabcontrol[value="journal"] ~ div.sheet-journaltab {
	display: block;
}

/*----------------- ROLL BUTTON ------------------*/

.sheet-main-container button[type=roll] {
	border: 0px;
	font-size: 35px;
	width: 25px;
	height: 25px;
	background: transparent !important;
	text-shadow: none !important;
	box-shadow: none !important;
	padding: 0px;
}

.sheet-main-container button[type=roll]::before {
	content: 'f';
	font-family: 'dicefontd6' !important;
}

.sheet-main-container button[type=roll]:hover {
	opacity: 0.5;
}

/*------------- REPEATABLE SECTIONS BUTTONS -------------*/

.repcontrol>.btn {
  background-color: transparent;
  font-size: 2px;
  background-image: none;
  text-shadow: none;
  box-shadow: none;
  display: inline-block;
	position: relative;
	border: 0px;
}

.repcontrol>.btn:hover {
	opacity: 0.5;
}

.repcontrol>.btn.repcontrol_add::before {
  content: "&";
  color: #616280;
  font-size: 20px;
  font-family: 'Pictos' !important;
	position: absolute;
	left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}

.repcontrol>.btn.repcontrol_edit::before {
	content: "(";
  color: #616280;
  font-size: 20px;
  font-family: 'Pictos' !important;
	position: absolute;
	left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}

/* change the 'Done' text after clicking 'Modify' */
.editmode ~ .repcontrol>.repcontrol_edit::before {
	content: ')';
}

/*------------- REPEATABLE SECTIONS TOGGLE SHOW/HIDE -------------*/

.sheet-showhidebutton {
	display: flex;
	align-items: center;
	justify-content: center;
}

.sheet-showhidebutton input[type=checkbox] {
	width: 20px;
	position: absolute;
	opacity: 0;
}

.sheet-showhidebutton:hover {
	opacity: 0.5;
}

.sheet-showhidebutton input[type=checkbox]:checked ~ span::before {
	content: '▲';
}

.sheet-showhidebutton span {
	color: black;
  font-size: 20px;
}

.sheet-showhidebutton span::before {
	content: '▼';
}

.sheet-toggle-checkbox {
	display: none;
}

.sheet-showhide {
	display: none;
}

.sheet-toggle-checkbox:checked ~ .sheet-showhide {
	display: block;
}

/*------------- SHEET ROLL TEMPLATE -------------*/

.sheet-rolltemplate-main .sheet-template-container {
	display: flex;
	flex-direction: column;
	border: 2px solid black;
	font-family: Paytone One;
	text-align: center;
}

.sheet-rolltemplate-main p {
    font-family: Paytone One;
    text-align: left;
}

.sheet-rolltemplate-main .sheet-template-row {
	display: flex;
	flex-direction: column;
	border-bottom: 1px solid black;
	padding: 5px;
	justify-content: center;
	align-items: center;
}

.sheet-rolltemplate-main .sheet-template-header {
	flex-direction: row !important;
	background-color: black;
	color: white;
}

.sheet-rolltemplate-main .sheet-template-label {
	font-weight: bold;
	text-transform: uppercase;
	margin-bottom: 5px;
}

.sheet-rolltemplate-main .sheet-template-success {
	color: green;
}

.sheet-rolltemplate-main .sheet-template-fail {
	color: red;
}

/*------------- KARMA CLOCK -------------*/

.sheet-karma-clock {
  margin: 5px;
	min-width: 44px;
	min-height: 44px;
	max-width: 44px;
	max-height: 44px;
	position: relative;
}

.sheet-karma-clock .sheet-clock-div {
	background-color: black;
	height: 45px;
	width: 2px;
	position: absolute;
	z-index: 2;
}

.sheet-karma-clock .sheet-clock-0deg{
	background-color: black;
	transform: translateX(22px);
}

.sheet-karma-clock .sheet-clock-90deg {
	background-color: black;
	transform: translateX(22px) rotate(90deg);
}

.sheet-karma-clock .sheet-clock-input {
	position: absolute;
	width: 20px !important;
	height: 20px !important;
	z-index: 2;
	opacity: 0;
}

.sheet-karma-clock input[value="1"] {
	right: 0px;
	top: 2px;
	bottom: 0px;
}

.sheet-karma-clock input[value="2"] {
	right: 0px;
	bottom: 0px;
}

.sheet-karma-clock input[value="3"] {
	bottom: 0px;
	left: 2px;
}

.sheet-karma-clock input[value="4"] {
	top: 2px;
	left: 2px;
}

/* Clock Zero Button */
.sheet-karma-clock input[value="0"] {
	width: 15px !important;
	height: 15px !important;
	bottom: -11px;
	left: -11px;
}

.sheet-karma-clock span {
	position: absolute;
	min-width: 15px !important;
	min-height: 15px !important;
	max-width: 15px !important;
	max-height: 15px !important;
	bottom: -11px;
	left: -11px;
	border: 1px solid black;
	border-radius: 50%;
}

.sheet-karma-clock > span::before {
	position: absolute;
	content: "";
	background: black;
	width: 1px;
	height: 15px;
	transform: translateX(7px) rotate(45deg);
}

.sheet-karma-clock span::after {
	position: absolute;
	content: "";
	background: black;
	width: 1px;
	height: 15px;
	transform: translateX(7px) rotate(135deg);
}

/* Clock painting programming */

.sheet-karma-clock .sheet-clock-paint {
	position: absolute;
	min-width: 44px;
	min-height: 44px;
	max-width: 44px;
	max-height: 44px;
	border: 1px solid black;
	border-radius: 50%;
	z-index: 0;
}

.sheet-karma-clock input[value="0"]:checked ~ span {
	display: none;
}

.sheet-karma-clock input[value="1"]:checked ~ .sheet-clock-paint {
	background-image: linear-gradient(90deg, #f0f2f1 50%, transparent 50%), linear-gradient(180deg, red 50%, #f0f2f1 50%);
}

.sheet-karma-clock input[value="2"]:checked ~ .sheet-clock-paint {
	background-image: linear-gradient(90deg, #f0f2f1 50%, red 50%);
}

.sheet-karma-clock input[value="3"]:checked ~ .sheet-clock-paint {
	background-image: linear-gradient(180deg, transparent 50%, red 50%), linear-gradient(90deg, #f0f2f1 50%, red 50%);
}

.sheet-karma-clock input[value="4"]:checked ~ .sheet-clock-paint {
	background: red;
}

/*------------- IMPETUS CLOCK -------------*/
.sheet-impetus-clock-container {
	position: relative;
	margin: 0px 25px 50px 50px;
}

.sheet-impetus-clock {
  margin: 5px;
	min-width: 100px;
	min-height: 100px;
	max-width: 100px;
	max-height: 100px;
	position: relative;
}

.sheet-impetus-clock .sheet-clock-div {
	background-color: black;
	width: 2px;
	position: absolute;
	z-index: 1;
}

.sheet-impetus-clock .sheet-clock-45deg{
	height: 115px;
	background-color: black;
	transform: translateX(40px) translateY(-3px) rotate(65.5deg)
}

.sheet-impetus-clock .sheet-clock-90deg {
	height: 115px;
	background-color: black;
	transform: translateX(40px) translateY(-12px) rotate(112.5deg);
}

.sheet-impetus-clock .sheet-clock-135deg {
	height: 140px;
	background-color: black;
	transform: translateX(50px) translateY(-20px) rotate(157.5deg);
}

.sheet-impetus-clock .sheet-clock-180deg {
	height: 140px;
	background-color: black;
	transform: translateX(50px) translateY(-20px) rotate(202.5deg);
}

.sheet-impetus-clock .sheet-clock-input {
	position: absolute;
	width: 25px !important;
	height: 25px !important;
	z-index: 2;
	opacity: 0;
}

.sheet-impetus-clock input[value="1"] {
	right: 15px;
	top: 15px;
}

.sheet-impetus-clock input[value="2"] {
	right: 5px;
	top: 38px;
}

.sheet-impetus-clock input[value="3"] {
	bottom: 15px;
	right: 15px;
}

.sheet-impetus-clock input[value="4"] {
	bottom: 5px;
	right: 37px;
}

.sheet-impetus-clock input[value="5"] {
	bottom: 14px;
	left: 15px;
}

.sheet-impetus-clock input[value="6"] {
	bottom: 37px;
	left: 5px;
}

.sheet-impetus-clock input[value="7"] {
	top: 13px;
	left: 15px;
}

/* Clock Zero Button */
.sheet-impetus-clock input[value="0"] {
	width: 15px !important;
	height: 15px !important;
	top: 10px;
	left: 42px;
	z-index: 3;
}

.sheet-impetus-clock span {
	position: absolute;
	min-width: 15px !important;
	min-height: 15px !important;
	max-width: 15px !important;
	max-height: 15px !important;
	top: 10px;
	left: 42px;
	border: 1px solid black;
	border-radius: 50%;
	z-index: 2;
}

.sheet-impetus-clock > span::before {
	position: absolute;
	content: "";
	background: black;
	width: 1px;
	height: 15px;
	transform: translateX(7px) rotate(45deg);
}

.sheet-impetus-clock span::after {
	position: absolute;
	content: "";
	background: black;
	width: 1px;
	height: 15px;
	transform: translateX(7px) rotate(135deg);
}

/* Clock painting programming */

.sheet-impetus-clock .sheet-clock-paint {
	position: absolute;
	min-width: 100px;
	min-height: 100px;
	max-width: 100px;
	max-height: 100px;
	border: 1px solid black;
	border-radius: 50%;
	z-index: 0;
}

.sheet-impetus-clock .sheet-clock-paint::before {
	content: "";
	position: absolute;
	min-width: 90px;
	min-height: 90px;
	max-width: 90px;
	max-height: 90px;
	border: 2px solid black;
	border-radius: 50%;
	z-index: 0;
	left: 3px;
	top: 3px;
}

.sheet-impetus-clock .sheet-clock-paint::after {
	content: "";
	position: absolute;
	min-width: 96px;
	min-height: 96px;
	max-width: 96px;
	max-height: 96px;
	border: 2px solid #f0f2f1;
	border-radius: 50%;
	z-index: 2;
}

.sheet-impetus-clock input[value="0"]:checked ~ span {
	display: none;
}

.sheet-impetus-clock input[value="1"]:checked ~ .sheet-clock-paint::before {
	background-image: linear-gradient(112.5deg, #f0f2f1 50%, transparent 50%), linear-gradient(157.5deg, red 50%, #f0f2f1 50%);
}

.sheet-impetus-clock input[value="2"]:checked ~ .sheet-clock-paint::before {
	background-image: linear-gradient(112.5deg, #f0f2f1 50%, transparent 50%), linear-gradient(202.5deg, red 50%, #f0f2f1 50%);
}

.sheet-impetus-clock input[value="3"]:checked ~ .sheet-clock-paint::before {
	background-image: linear-gradient(112.5deg, #f0f2f1 50%, transparent 50%), linear-gradient(247.5deg, red 50%, #f0f2f1 50%);
}

.sheet-impetus-clock input[value="4"]:checked ~ .sheet-clock-paint::before {
	background: linear-gradient(112.5deg, #f0f2f1 50%, transparent 50%), linear-gradient(292.5deg, red 50%, #f0f2f1 50%);
}

.sheet-impetus-clock input[value="5"]:checked ~ .sheet-clock-paint::before {
	background: linear-gradient(337.5deg, red 50%, transparent 50%), linear-gradient(112.5deg, #f0f2f1 50%, red 50%);
}

.sheet-impetus-clock input[value="6"]:checked ~ .sheet-clock-paint::before {
	background: linear-gradient(382.5deg, red 50%, transparent 50%), linear-gradient(112.5deg, #f0f2f1 50%, red 50%);
}

.sheet-impetus-clock input[value="7"]:checked ~ .sheet-clock-paint::before {
	background-image: linear-gradient(-112.5deg, transparent 50%, red 50%), linear-gradient(112.5deg, #f0f2f1 50%, red 50%);
}

/* Clock labels */

.sheet-impetus-label {
	font-size: 10px;
}

.sheet-impetus-die-number {
	font-size: 15px;
}

.sheet-impetus-die-box {
	display: flex;
	flex-direction: row;
	align-items: stretch;
}

.sheet-impetus-die-icon {
	background-image: url('https://raw.githubusercontent.com/Roll20/roll20-character-sheets/master/GoddessSaveTheQueen/img/goddes-die.png');
	background-repeat: no-repeat;
	background-size: 16px 18px;
	width: 16px;
	min-width: 16px;
	height: 18px;
	min-height: 18px;
}

.sheet-determined {
	position: absolute;
	top: -50px;
	transform: translateX(85px) translateY(100px) rotate(270deg);
}

.sheet-tired {
	position: absolute;
	top: -50px;
	transform: translateX(35px) translateY(170px);
}

.sheet-weak {
	position: absolute;
	top: -50px;
	transform: translateX(-15px) translateY(145px) rotate(45deg);
}

.sheet-shaken {
	position: absolute;
	top: -50px;
	transform: translateX(-50px) translateY(100px) rotate(0deg);
}

.sheet-shaken span {
	transform: translateX(-9px) rotate(270deg);
}

.sheet-trauma {
	position: absolute;
	top: -50px;
	transform: translateX(-5px) translateY(55px) rotate(-45deg);
}

/*------------- INDEPENDENCE CHECKBOXES -------------*/
.sheet-circle-box {
	margin: 0px 5px 0px 5px;
}

.sheet-independence-circle-size {
	width: 15px;
	height: 15px;
}

.sheet-independence-checkbox {
	opacity: 0;
	z-index: 1;
	position: absolute;
	margin: 0px !important;
	width: 15px !important;
	height: 15px !important;
}
.sheet-circle {
	border: 2px solid black;
	border-radius: 50%;
	width: 100%;
	height: 100%;
}

.sheet-black-circle {
	display: none;
	background-color: black;
}

.sheet-independence-checkbox:checked ~ div.sheet-black-circle {
	display: inline-block;
}

.sheet-independence-checkbox:checked ~ div.sheet-blank-circle {
	display: none;
}