Skip to content

ReadingBat Core

ReadingBat Core is a Kotlin-based web application framework for creating interactive programming challenges, powering the ReadingBat platform. It provides a powerful DSL for defining challenges in Java, Python, and Kotlin, a Ktor-based web server, and real-time feedback via WebSockets.

Key Features

  • Content DSL -- Define programming challenges using an expressive Kotlin DSL
  • Multi-language support -- Java, Python, and Kotlin challenges in a single application
  • Local and remote content -- Load challenges from the local filesystem or GitHub repositories
  • Real-time feedback -- WebSocket-powered answer checking and progress tracking
  • Class management -- Teachers can create classes and monitor student progress
  • Flexible configuration -- HOCON properties with environment variable overrides

Quick Start

Define your content using the readingBatContent builder:

val basicContent =
  readingBatContent {
    repo = FileSystemSource("./")

    java {
      group("Warmup-1") {
        packageName = "warmup1"
        description = "Simple warmup problems to get started"
        includeFiles = "*.java"
      }
    }
  }

This creates a content definition that:

  1. Loads Java source files from the local filesystem
  2. Organizes them into a group called "Warmup-1"
  3. Auto-discovers all .java files in the warmup1 package

DSL Hierarchy

The content DSL follows a hierarchical structure:

graph TD
    A[ReadingBatContent] --> B[LanguageGroup - Java]
    A --> C[LanguageGroup - Python]
    A --> D[LanguageGroup - Kotlin]
    B --> E[ChallengeGroup]
    B --> F[ChallengeGroup]
    C --> G[ChallengeGroup]
    E --> H[Challenge]
    E --> I[Challenge]
    F --> J[Challenge]
    G --> K[Challenge]

ReadingBatContent LanguageGroup ChallengeGroup Challenge

Multi-Language Example

ReadingBat supports challenges in all three languages within a single content definition:

val multiLanguageContent =
  readingBatContent {
    repo = FileSystemSource("./")

    java {
      srcPath = "src/main/java"
      group("Warmup-1") {
        packageName = "warmup1"
        description = "Simple Java warmup problems"
        includeFiles = "*.java"
      }
      group("String-1") {
        packageName = "string1"
        description = "Basic string problems"
        includeFiles = "*.java"
      }
    }

    python {
      srcPath = "python"
      group("Warmup-1") {
        packageName = "warmup1"
        description = "Simple Python warmup problems"
        includeFilesWithType = "*.py" returns BooleanType
      }
    }

    kotlin {
      srcPath = "src/main/kotlin"
      group("Warmup-1") {
        packageName = "warmup1"
        description = "Simple Kotlin warmup problems"
        includeFilesWithType = "*.kt" returns StringType
      }
    }
  }

Java vs. Python/Kotlin

Java challenges use includeFiles because return types are inferred from source code. Python and Kotlin challenges require includeFilesWithType with an explicit return type.

Architecture Overview

Component Description
Content DSL Defines challenges via readingBatContent { } blocks
Ktor Server Serves HTML pages and handles API requests
Script Engines JSR-223 engines evaluate Java, Kotlin, and Python code
PostgreSQL Stores user accounts, progress, and class data
WebSockets Provides real-time answer checking and dashboard updates
Prometheus Exports metrics for monitoring

API Reference

Full API documentation (KDocs) is available at KDocs.

Next Steps

  • Content DSL


    Learn how to define challenges using the Kotlin DSL

    Content DSL

  • Configuration


    Configure the application with HOCON and environment variables

    Configuration

  • Server


    Understand the Ktor server setup and routing

    Server

  • Testing


    Write tests using the Kotest test support utilities

    Testing