Individualization

Learn how Divekit creates individualized programming assignments using variation.json and individualization.json configurations.

Overview

Divekit individualizes each student’s (or group’s) repository during distribution using two configuration files: variation.json and individualization.json. They define object/relationship variants, logic options, and per-member assignments — including structural changes, file selection by logic, and Lua-based customizations. Each distributed repository is unique while the core task stays consistent.

Configuration Files

Configs live in .divekit/distributions/<distribution-name>/:

  • variation.json: Declares available variations for objects, relations, and logic.
  • individualization.json: Assigns these variations to members (fixed or random) and sets per-member options.

They are created/copied during divekit init and can be edited directly or via divekit config.

variation.json Structure

The file lists arrays of objects, relations, and logic definitions:

{
  "objects": [{
    "ids": "Vehicle",
    "objectVariations": [
      {"name": "Car", "fields": [{"name": "speed", "type": "int", "values": ["100", "150"]}]},
      {"name": "Truck", "fields": [{"name": "weight", "type": "int", "values": ["2000", "3000"]}]}
    ]
  }],
  "relations": [{
    "id": "relation1", "type": "association", "source": "entity1", "target": "entity2",
    "options": ["one-to-one", "one-to-many"]
  }],
  "logic": [{
    "id": "logic1", "type": "businessLogic", "location": "src/logic",
    "options": ["simple", "complex"]
  }]
}
  • objects: Entity variations (e.g., class alternatives with fields).
  • relations: Relationship variants (e.g., multiplicities or types).
  • logic: Logic variants that select files or scripts (e.g., ShoppingCart_simple.java).

Variables may use placeholders like {{...}} or Lua for dynamic values.

individualization.json Structure

This file assigns variations to members and controls application:

{
  "version": "1.0",
  "logicId": "logic1",
  "objectAssignments": [
    {"memberId": "student1", "objectVariations": {"entity1": "Car"}, "relationOptions": {"relation1": "one-to-many"}},
    {"memberId": "student2", "objectVariations": {"entity1": "Truck"}, "randomLogic": true}
  ],
  "globalSettings": {"delimiter": "$", "warnUnresolved": true}
}
  • logicId: Global or per-member logic variant.
  • objectAssignments: Per-member object and relation choices (fixed or random).
  • globalSettings: Placeholder delimiter and unresolved-token warnings.

Without per-member overrides, values are chosen randomly from variation.json.

Individualization Process

Individualization runs during divekit distribute:

  1. Load variation.json and individualization.json.
  2. Resolve each member’s variation set (fixed or random).
  3. Generate content:
    • Replace placeholders (e.g., $EntityName$ → “Car”).
    • Include/rename files by logic selection (e.g., _logic1).
    • Apply relation-driven code changes.
    • Run Lua for custom generation.
  4. Validate unresolved placeholders (warn if enabled).
  5. Create the new repo with the individualized content.

Using Placeholders

Placeholders in origin files are replaced during individualization:

public class $EntityName$ {
    private String name = "$DefaultName$";
    private int $AttributeName$ = $RandomNumber$;
    // Relation example
    public $RelatedEntity$ getRelated() {
        return related;
    }
}
  • $EntityName$: Selected object name (e.g., “Car”).
  • $DefaultName$: From object-variation fields.
  • Relations may generate extra code or files.

For logic variants, files like ShoppingCart_$LogicId$.java are renamed or included based on the selected logic.

Creating the Configuration Files

During divekit init

  • variation.json: Empty skeleton with default sections.
  • individualization.json: Copied from user config or created with defaults (optionally copied from another distribution).

Manual Editing

Edit both JSON files in .divekit/distributions/<name>/. Validate with divekit doctor.

individuals.json (optional)

Created during distribution to record assigned variations per member for reuse (e.g., patches). Not created at init.

Examples

Simple Object Variation

  • Define object “Person” with variations “Student” (age 18–25) and “Teacher” (30–50). Assign “Student” randomly to half the members. Result: corresponding class and fields per repo.

Logic Variant with Lua

  • Logic options “simple” vs “complex” with Algorithm_simple.java / Algorithm_complex.java. Lua generates data based on selected complexity.

Relation Individualization

  • Relation “hasFriend”: choose “one-to-one” or “one-to-many”. Fixed “one-to-many” yields list-based code.

Quality Assurance and Troubleshooting

  • Unresolved tokens: Use --warn-unresolved-tokens true to log warnings.
  • Validation: Run divekit doctor to check configs.
  • Dry runs: Use simulated provider (--provider simulated).
  • Reproducibility: Assigned variations persist in individuals.json (e.g., for late joiners).

Best Practices

  • Start simple; grow complexity gradually.
  • Use Lua for advanced generation.
  • Test with a small member list first.
  • Document variation IDs and logic options.
  • Provide fallbacks to avoid unresolved tokens.

For advanced setups, see the full schema in code or the RE docs under docs/re.