Schemat danych

Ten format przyjmuje upload JSON i zwraca parser PDF. Upload zastępuje wszystkie zajęcia planu w zakresie dat. Dzień w zakresie bez zajęć to dzień wolny.

PoleWymaganeOpis
wersjatakZawsze 1.
plan.kierunek, plan.roktakKody ze źródła, np. FIZ i I. Muszą zgadzać się z planem.
zrodlo.typtakpdf, wydruk albo inne; opcjonalnie url i opis.
zakres.od, zakres.dotakDaty RRRR-MM-DD.
zajecia[].datatakRRRR-MM-DD.
zajecia[].od, .dotakGG:MM z zerem, np. 08:00.
zajecia[].czas, .hniePomijane. Czasu i H z planu uczelni nie przepisujemy – aplikacja liczy je z od i do (H = czas / 45 min). Jeśli są w pliku, nie przeszkadzają.
zajecia[].przedmiottakTekst.
zajecia[].prowadzacy, .rz, .gr, .salatakTekst albo null, gdy w źródle pusto. Grupa: a–h, A–H, I–VIII, 1–8.
zajecia[].kolejnoscnieNumer wiersza w źródle.
zajecia[].kolornie#rrggbb, tylko z PDF.

Schemat JSON

Otwórz plik
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://nieoficjalneplanyzajecupsl.kozakstrona.pl/schemat-planu.json",
  "title": "Plan zajęć – upload",
  "description": "Format danych planu zajęć dla Nieoficjalnego kalendarza zajęć UPSL. Ten sam format zwraca parser PDF i przyjmuje upload JSON. Upload zastępuje wszystkie zajęcia planu w zakresie dat.",
  "type": "object",
  "additionalProperties": false,
  "required": ["wersja", "plan", "zrodlo", "zakres", "zajecia"],
  "properties": {
    "wersja": {
      "description": "Wersja formatu.",
      "const": 1
    },
    "plan": {
      "description": "Kody kierunku i roku tak, jak stoją w źródle. Muszą zgadzać się z planem, do którego wgrywamy dane.",
      "type": "object",
      "additionalProperties": false,
      "required": ["kierunek", "rok"],
      "properties": {
        "kierunek": { "type": "string", "minLength": 1, "examples": ["FIZ"] },
        "rok": { "type": "string", "pattern": "^(I|II|III|IV|V|VI)$", "examples": ["I"] }
      }
    },
    "zrodlo": {
      "description": "Skąd pochodzą dane.",
      "type": "object",
      "additionalProperties": false,
      "required": ["typ"],
      "properties": {
        "typ": { "enum": ["pdf", "wydruk", "inne"] },
        "url": { "type": "string", "format": "uri", "description": "Link do PDF na stronie uczelni." },
        "opis": { "type": "string", "description": "Np. 'wydruk z tablicy, tydzień 12-18.10'." }
      }
    },
    "zakres": {
      "description": "Dni, które upload zastępuje w całości. Dzień w zakresie bez zajęć oznacza dzień wolny. Warunek od <= do sprawdza aplikacja.",
      "type": "object",
      "additionalProperties": false,
      "required": ["od", "do"],
      "properties": {
        "od": { "$ref": "#/$defs/data" },
        "do": { "$ref": "#/$defs/data" }
      }
    },
    "zajecia": {
      "type": "array",
      "items": { "$ref": "#/$defs/zajecia" }
    }
  },
  "$defs": {
    "data": {
      "type": "string",
      "format": "date",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      "examples": ["2026-10-15"]
    },
    "godzina": {
      "type": "string",
      "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
      "examples": ["08:00"]
    },
    "zajecia": {
      "description": "Jeden wiersz planu. Pola jak kolumny PDF; dzień tygodnia, kierunek i rok wynikają z daty i z pola plan. Warunki od < do oraz data w zakresie sprawdza aplikacja.",
      "type": "object",
      "additionalProperties": false,
      "required": ["data", "od", "do", "przedmiot", "prowadzacy", "rz", "gr", "sala"],
      "properties": {
        "data": { "$ref": "#/$defs/data" },
        "od": { "$ref": "#/$defs/godzina" },
        "do": { "$ref": "#/$defs/godzina" },
        "czas": {
          "description": "Pomijane: aplikacja liczy czas z od i do. Dopuszczone, żeby pliki w starym formacie dalej działały."
        },
        "h": {
          "description": "Pomijane: aplikacja liczy godziny dydaktyczne (po 45 min) z od i do. Dopuszczone, żeby pliki w starym formacie dalej działały."
        },
        "przedmiot": { "type": "string", "minLength": 1 },
        "prowadzacy": {
          "description": "null, gdy w źródle pusto.",
          "type": ["string", "null"],
          "minLength": 1
        },
        "rz": {
          "description": "Rodzaj zajęć, np. W, CS, CL, CR, CUP. null, gdy w źródle pusto.",
          "type": ["string", "null"],
          "pattern": "^[A-ZĄĆĘŁŃÓŚŹŻ]{1,6}$"
        },
        "gr": {
          "description": "Grupa. Zapis wyznacza podział: a–h, A–H, I–VIII, 1–8. null = zajęcia dla wszystkich.",
          "type": ["string", "null"],
          "pattern": "^([a-h]|[A-H]|I|II|III|IV|V|VI|VII|VIII|[1-8])$"
        },
        "sala": {
          "description": "Tekst kolumny S tak, jak w źródle (np. 'zdalne', 's. 218 (Westerplatte 64)'). null, gdy pusto.",
          "type": ["string", "null"],
          "minLength": 1
        },
        "kolejnosc": {
          "description": "Numer wiersza w źródle, od 1. Potrzebny w widoku 'Jak w PDF'.",
          "type": "integer",
          "minimum": 1
        },
        "kolor": {
          "description": "Kolor tła przedmiotu z PDF. Opcjonalny – brak przy wydruku.",
          "type": "string",
          "pattern": "^#[0-9a-f]{6}$"
        }
      }
    }
  }
}