Quest: Logika, entropia, modele i abstrakcja

Cel projektu

Zrozumienie czterech podstawowych pojęć z teorii informatyki.
Celem nie jest referat teoretyczny.
Celem jest pokazanie, że te pojęcia realnie wpływają na rozumienie, ocenę i projektowanie systemów i ich funkcji.

Etap I – praca indywidualna (2 lekcje)

Każdy losuje jedno pojęcie z listy. Tematem pracy grupy jest jednak związana z pojęciem zasada podana na drugiej stronie

  • Logika
  • Entropia
  • Model
  • Abstrakcja

Zadania indywidualne

  1. Zrozumieć pojęcie
  2. Wybrać jedno realne case study z informatyki lub życia:
    • błąd systemu,
    • nieudane wdrożenie,
    • paradoks logiczny,
    • problem z danymi.
  3. Opisać:
    • Na czym polega problem?
    • Gdzie w nim widać dane pojęcie?
    • Jakie są konsekwencje jego niezrozumienia?
  4. Przygotować założenia, szkic strony HTML/CSS:
    • Struktura sekcji
    • Nagłówki
    • Miejsce na diagram lub przykład

Strona ma być prosta. Kluczowa jest tu treść. Należy ja wygenerować. Ma być jednak poprawna (nie okropna).

Etap II – grupy eksperckie (3 lekcje)

Osoby z tym samym pojęciem tworzą grupę ekspercką.

Zadania grupy

  1. Wybrać najlepsze case study.
  2. Ujednolicić teorię.
  3. Wyeliminować błędy i uproszczenia.
  4. Połączyć pomysły w jedną spójną stronę prezentacyjną.

Strona powinna zawierać:

  • definicję pojęcia,
  • jeden wyraźny problem praktyczny,
  • analizę,
  • prosty przykład,
  • wnioski.

Ważne:
Nie tworzymy „encyklopedii”.
Tworzymy przekonującą narrację problemową.

Etap III – prezentacje (2 lekcje)

Każda grupa ma:

  • 10–15 minut prezentacji,
  • 5 minut na pytania.

Ocena obejmuje:

  • Zrozumienie pojęcia
  • Jakość case study
  • Trafność przykładów
  • Strona WWW
  • Jasność przekazu

Wymagania formalne strony

  • Czytelna struktura
  • Maksymalnie 3 kolory
  • Jedna strona (single-page)

Strona ma wspierać myślenie, nie odwracać uwagi.

Projekt: Mapa Dorobku Ludzkości

1. Cel projektu

Celem projektu jest stworzenie aplikacji w React (JSX), prezentującej interaktywne infografiki ukazujące rozwój kultury, literatury i technologii jako złożony, wielowymiarowy proces.

Efektem końcowym będzie wspólna aplikacja rozwijana w jednym repozytorium GitHub. Build produkcyjny należy raz w tygodniu umieścić na serwerze pozwalającym na wygodne przeglądanie treści. Back-end nie jest wymagany.

2. Struktura zespołów i role

Każdy zespół jest trzyosobowy. W każdej grupie występują trzy wyspecjalizowane role:

RolaGłówna odpowiedzialność (oprócz regularnego developmentu)
Koordynator Standardów Technologicznychspójność struktury komponentów, standardy kodu, integracja z częścią wspólną
Koordynator Analizy Danych i Logikipoprawność struktury danych, relacji, walidacji i transformacji danych w aplikacji
Koordynator Poprawności Merytorycznejpoprawność merytoryczna treści oraz ich właściwe odwzorowanie w modelu danych i interfejsie

Kluczowe zasady współpracy

  • Każdy koduje i dodaje nowe funkcjonalności.
  • Role określają główny wymiar odpowiedzialności w zespole.
  • Decyzje są podejmowane wspólnie, ale każdy lider pilnuje jakości w swoim obszarze.

Mechanizm tworzenia zespołów

  1. Wszyscy uczestnicy samodzielnie dzielą się na 3 równe grupy specjalistyczne:
    • technologiczne,
    • analityczne,
    • merytoryczne.
  2. Następnie losowo tworzone są zespoły projektowe tak, aby w każdym znalazł się jeden lider z każdej grupy.

3. Modele infografik i poziom trudności

Każdy zespół wybiera jeden model wizualizacji:

ModelPoziom trudności
Oś przejść – Zmiany postrzegania świataEasy
Równoległe osie – Asynchroniczność modernizmówNormal
Sieć wpływów – Kultura bez epokNormal
Cywilizacja warstwowa – Struktury procesów i fale wydarzeńHard
Drzewo rozwoju – Ewolucja formHard

Dokładne opisy poszczególnych modeli znajdują się na stronie 2. żaden model wizualny nie może powtórzyć się więcej niż 2 razy. Każdy zespół może wybrać dla siebie dowolny okres lub dowolna tematykę, które na ich infografice będę prezentowane domyślnie za pomocą filtrów, ale powinna istnieć możliwość prezentowania wszystkich danych. Poziomy trudności wynikają z:

  • złożoności logiki wizualizacji,
  • liczby zależności między elementami,
  • potrzeby zaawansowanego modelowania danych.

4. Organizacja repozytorium

Wszystkie zespoły pracują w jednym repozytorium GitHub.

Struktura

/src
/core → część wspólna (layout, routing, komponenty bazowe)
/data → wspólna baza danych
/axis-model
/parallel-model
/network-model
/layers-model
/tree-model

Zasady

  • Każdy model jako osobny folder.
  • Plik CODEOWNERS przypisuje folder do konkretnego zespołu.
  • Zmiany w folderze zespołu wymagają jego akceptacji.
  • Folder /core współtworzony wyłącznie przez Koordynatorów Technologicznych.
  • Folder /data współtworzony przez Koordynatorów Merytorycznych.
  • Koordynatorzy Analizy odpowiadają za funkcje transformujące dane.

5. Zakres odpowiedzialności osób w zespołach

Koordynator Standardów Technologicznych

  • ustala strukturę folderów i komponentów,
  • dba o wygląd i spójność UI,
  • pomaga przy integracji elementów zespołu z częścią wspólną.

Koordynator Poprawności Merytorycznej

  • spójność kategorii, tagów i relacji.
  • wybór wydarzeń i dzieł do bazy,
  • odpowiada za komunikatywność infografiki i wizualne przedstawienie treści w UI.

Koordynator Analizy Danych i Logiki

  • tworzy i sprawdza bazę danych (historyData),
  • pilnuje poprawności relacji między elementami,
  • odpowiada za filtrowanie i sortowanie danych w aplikacji.

6. Zwinna metodyka pracy – uproszczony Scrum

Czas realizacji: ok. 1 miesiąca. Dokładny termin oddania zostanie doprecyzowany po trzech tygodniach.

Struktura pracy: 4 sprinty

  1. ustalenie zakresu danych, projekt struktury technicznej, makiety wizualne
  2. implementacja podstaw wizualizacji, pierwsza integracja z danymi
  3. rozwój interaktywności, poprawa estetyki, testy spójności
  4. optymalizacja, refaktoryzacja, finalna integracja

Cotygodniowe rytuały

  1. Daily Stand-up (5 min)
    Każda osoba odpowiada: Co zrobiłem? Co robię dziś? Co mnie blokuje?
  2. Podsumowanie Sprintu
    • prezentacja postępów,
    • informacja zwrotna.
    • co działa,
    • co poprawić,
    • jakie problemy organizacyjne wystąpiły.

quasiQuest: useContext

Porozmawiaj z LLM na temat hooka useContext i przetestuj przykłady. Zacznij od prompta:


Stwórz przykładową aplikację w React używającą Vite. Chodzi o pokazanie, kiedy warto użyć hooka useContext zamiast przekazywania propsów. 

Wymagania:
1. Pokaż co najmniej jeden przypadek użycia useContext (np. dane użytkownika, motyw, język aplikacji, ustawienia globalne).
2. Pokaż prosty przykład "przed" użyciem useContext, gdzie dane są przekazywane przez propsy w kilku poziomach komponentów.
3. Pokaż "po" użyciu useContext – te same dane są dostępne w głębokich komponentach bez props drilling.
4. Kod powinien być czytelny, działający w projekcie Vite + React.
5. Dodaj komentarze wyjaśniające, dlaczego w danym miejscu użycie useContext jest przydatne.

Quest: Częsty błąd z useState

Licznik z błędem

Przeanalizuj poniższy przykład, a następnie go uruchom. Czy działa zgodnie z oczekiwaniem?

import React, { useState } from "react";

function App() {
  const [count, setCount] = useState(0);

  const handleIncrement = () => {
    // Błąd: oba wywołania używają starej wartości count
    setCount(count + 1);
    setCount(count + 1);
  };

  return (
    <div style={{ padding: "20px" }}>
      <h1>Błędne zwiększanie licznika</h1>
      <p>Licznik: {count}</p>
      <button onClick={handleIncrement}>Zwiększ dwa razy</button>
    </div>
  );
}

export default App;

React grupuje wiele zmian stanu lub propsów w jednym renderze, zamiast renderować komponent osobno po każdej zmianie. Jeśli w jednej funkcji wywołasz setState kilka razy, React nie wykona tyle renderów, ile wywołań tylko zrobi tylko jeden render na koniec.
Poprawna wersja:

const handleIncrement = () => {
    // Poprawnie: każda aktualizacja korzysta z aktualnej wartości
    setCount(prev => prev + 1);
    setCount(prev => prev + 1);
  };

Przykład z tablicą

import React, { useState } from "react";

function App() {
  const [items, setItems] = useState([]);

  const addItems = () => {
    // Błąd: oba wywołania używają starej wartości items
    setItems([...items, "A"]);
    setItems([...items, "B"]);
  };

  return (
    <div style={{ padding: "20px" }}>
      <h1>Błędne dodawanie elementów</h1>
      <button onClick={addItems}>Dodaj A i B</button>
      <ul>
        {items.map((item, index) => (
          <li key={index}>{item}</li>
        ))}
      </ul>
    </div>
  );
}

export default App;

Napisz poprawną wersję addItems wykorzystującą prev

Zasada: Używaj setState(prev => …) gdy:

  • nowa wartość zależy od poprzedniej
  • aktualizujesz licznik
  • aktualizujesz tablicę
  • aktualizujesz obiekt

Quest: Bootstrap z CSSem w parze

Przykład poniżej pokazuje, że wygląd Bootstrapa 5 można zmieniać (bez SCSS), korzystając z kaskady CSS oraz zmiennych CSS wbudowanych w framework.

Nadpisanie zmiennych globalnych (:root) zmienia cały motyw aplikacji, natomiast nadpisanie zmiennych w kontenerze działa tylko lokalnie, w obrębie danej sekcji. Nadpisywanie zmiennych komponentu (np. przycisków) jest bezpieczniejsze i bardziej przewidywalne niż klasyczne nadpisywanie właściwości typu background-color.
Spróbuj zmieniać wartości zmiennych i poprzenosić między style sekcjami, żeby zobaczyć, jak kaskada i dziedziczenie CSS wpływają na wygląd.

<!doctype html>
<html lang="pl">
<head>
  <meta charset="utf-8">
  <title>Bootstrap 5 – nadpisywanie stylów</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <!-- Bootstrap -->
  <link
    href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css"
    rel="stylesheet"
  >

  <!-- Custom overrides -->
  <style>
    /* ===============================
       1. Globalne nadpisanie zmiennych
       =============================== */
    :root {
      --bs-primary: #6f42c1;
      --bs-body-bg: #f5f3ff;
      --bs-body-color: #2d2a32;
      --bs-border-radius: 1rem;
    }

    /* ===============================
       2. Nadpisanie komponentu (btn)
       =============================== */
    .btn-primary {
      --bs-btn-bg: #6f42c1;
      --bs-btn-border-color: #6f42c1;
      --bs-btn-hover-bg: #59339d;
      --bs-btn-hover-border-color: #59339d;
    }

    /* ===============================
       3. Klasyczne nadpisanie CSS
       =============================== */
    .card {
      border-width: 2px;
    }

    /* ===============================
       4. Lokalny kontekst (sekcja dark)
       =============================== */
    .dark-section {
      --bs-body-bg: #1e1b29;
      --bs-body-color: #f1f1f1;
      --bs-card-bg: #2a2638;
      --bs-primary: #f72585;
    }

    /* ===============================
       5. Custom component
       =============================== */
    .custom-alert {
      border-left: 6px solid var(--bs-primary);
      background-color: #fff;
    }
  </style>
</head>

<body class="py-4">

<div class="container">
  <h1 class="mb-4">Bootstrap 5 – nadpisywanie stylów (bez SCSS)</h1>

  <!-- ===============================
       PRZYCISKI
       =============================== -->
  <section class="mb-5">
    <h2>Przyciski (zmienne komponentu)</h2>
    <button class="btn btn-primary me-2">Primary</button>
    <button class="btn btn-outline-primary">Outline</button>
  </section>

  <!-- ===============================
       KARTY
       =============================== -->
  <section class="mb-5">
    <h2>Karty (globalne zmienne + CSS)</h2>
    <div class="row g-3">
      <div class="col-md-4">
        <div class="card p-3">
          <h5 class="card-title">Card domyślna</h5>
          <p class="card-text">Zmodyfikowany radius i border.</p>
        </div>
      </div>
      <div class="col-md-4">
        <div class="card p-3 border-primary">
          <h5 class="card-title">Card z utility</h5>
          <p class="card-text">Kolor przez klasy pomocnicze.</p>
        </div>
      </div>
    </div>
  </section>

  <!-- ===============================
       ALERTY
       =============================== -->
  <section class="mb-5">
    <h2>Alerty (różne podejścia)</h2>

    <div class="alert alert-primary">
      Standardowy alert Bootstrap
    </div>

    <div class="alert custom-alert">
      Alert z własnym komponentem
    </div>
  </section>

  <!-- ===============================
       FORMULARZ
       =============================== -->
  <section class="mb-5">
    <h2>Formularz</h2>
    <form class="card p-4">
      <div class="mb-3">
        <label class="form-label">Email</label>
        <input type="email" class="form-control">
      </div>
      <div class="mb-3">
        <label class="form-label">Hasło</label>
        <input type="password" class="form-control">
      </div>
      <button class="btn btn-primary">Zaloguj</button>
    </form>
  </section>
</div>

<!-- ===============================
     SEKCJA LOKALNA (dark mode)
     =============================== -->
<section class="dark-section py-5 mt-5">
  <div class="container">
    <h2>Sekcja z lokalnie nadpisanymi zmiennymi</h2>
    <p>
      Ten sam Bootstrap, inne zmienne CSS – bez duplikowania stylów.
    </p>
    <button class="btn btn-primary">Primary w dark mode</button>

    <div class="card p-3 mt-3">
      <h5 class="card-title">Card w dark section</h5>
      <p class="card-text">Zmienne działają kontekstowo.</p>
    </div>
  </div>
</section>

</body>
</html>