diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1d4c835
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,12 @@
+build/
+.gradle/
+out/
+
+.idea/
+*.iml
+*.iws
+*.ipr
+
+.gradle/
+.intellijPlatform/
+.kotlin/
diff --git a/.idea/.gitignore b/.idea/.gitignore
deleted file mode 100644
index 6129c37..0000000
--- a/.idea/.gitignore
+++ /dev/null
@@ -1,15 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
-# Editor-based HTTP Client requests
-/httpRequests/
-# Datasource local storage ignored files
-/dataSources/
-/dataSources.local.xml
-/pl-java2026.iml
-/vcs.xml
-/modules.xml
-/misc.xml
-/copilot.data.migration.edit.xml
-/copilot.data.migration.ask.xml
-/copilot.data.migration.agent.xml
diff --git a/README.md b/README.md
index 6114919..1d7bd5d 100644
--- a/README.md
+++ b/README.md
@@ -1,88 +1,12 @@
-# PŁ: Zaawansowane Zagadnienia Programowania w Javie - Edycja 2026
+Dzień dobry, z tej strony Zespół 2 IAS. Chcemy przedstawić nasz plugin inspirowany grą PacMan.
-## Zaliczenie
+Żeby zobaczyć nasze arcydzieło trzeba sklonować repozytorium, w cli zbudować projekt za pomocą polecenia: ./gradlew build (może to potrwać nawet 10 minut).
-- Projekt grupowy: od 3 do 6 osób (brak odstępstw)
-- Tematyka realizowanego projektu: dowolna
-- Elementy, które powinny znaleźć się końcowym projekcie i podlegają ocenie:
- - Współpraca z repozytorium Git (dowolnie wybrany darmowy hosting według upodobań, na przykład: Github, Gitlab lub
- Bitbucket)
- - Aktywność w realizacji projektu:
- - *pull requesty* wraz z *code review* wewnątrz zespołu
- - *githubowy pulse* lub inne narzędzie pokazujące ciągłość pracy podczas semestru
- - podział zadań przy implementacji funkcjonalności projektu poprzez *board projektowy* (Jira, Trello,...)
+Jak się powiedzie build wpisujemy polcenie: ./gradlew runIde . Wyświetli nam się okienko gdzie stwórzmy nowy projekt i z lewej strony będzie zakładka Pacman_Game.
- - Praktyczna implementacja i wdrożenie rozwiązań, tematów, narzędzi prezentowanych podczas zajęć (nie muszą być
- wszystkie, 60-80% jest ok)
- - [ ] Aplikacja oparta o **Spring (Boot) Framework**
- - [ ] Integracja z zewnętrznym zasobem po **REST** z wykorzystaniem publicznego API (
- np.: https://github.com/public-apis/public-apis) wraz z wykorzystaniem (przetworzeniem) otrzymanych danych
- - [ ] Zaprojektowanie własnego API z wykorzystaniem biblioteki **OpenAPI** wraz z drugą aplikacją, która
- konsumuje udostępnione API. Klient będzie wykonywał zapytania HTTP do serwisu i analizował otrzymane dane.
- - [ ] Architektura mikroserwisowa z wykorzystaniem **Spring Cloud Eureka**, umożliwiająca rejestrację i
- wykrywanie usług. Aplikacja będzie składała się z minimum dwóch mikroserwisów, które będą się wzajemnie
- komunikowały przy użyciu Spring Eureka jako serwera rejestracji usług.
- - [ ] Wykorzystanie **Spring Cloud Config Server**, który centralizuje zarządzanie konfiguracją dla wielu
- mikroserwisów. Dzięki temu wszystkie serwisy w systemie mogą korzystać z jednej wspólnej konfiguracji,
- przechowywanej w centralnym miejscu (np. w plikach YAML na oddzielnym repozytorium Git), a zmiany w
- konfiguracji są natychmiastowo propagowane do aplikacji.
- - [ ] Wykorzystanie **Keycloak** lub **Spring Authorization Server** (lub inny nieprezentowany podczas zajęć)
- jako systemu zarządzającego autoryzacją i autentykacją użytkowników oraz/i serwisów.
- - [ ] Aplikacja powinna być zaprojektowana w taki sposób, aby jej komponenty zostały odpowiednio przetestowane
- przy użyciu różnych typów testów, np. **jednostkowych (unit tests)**, **integracyjnych (integration tests)**
- oraz **testów BDD (Behavior Driven Development)**. Celem jest zapewnienie wysokiej jakości kodu, wykrywanie
- błędów na wczesnym etapie oraz zapewnienie, że aplikacja działa zgodnie z oczekiwaniami użytkowników
- końcowych. Użycie **Cucumber** – napisanie kilku testów z wykorzystaniem różnych konstrukcji **Gherkina** i
- dodanie testów realizowanych przez **AssertJ**
- - [ ] Statyczna analiza kodu – lokalne postawienie SonarQube, utworzenie projektu, dodanie skanera, analiza
- wyników, dbanie o utrzymanie długu technicznego na akceptowalnym poziomie
- - [ ] Aplikacja wykorzystująca ostatnie nowości w **JDK** (np. Local-Variable Type Inference, Text Blocks,
- Sealed Classes, Pattern Matching dla instanceof, Virtual Threads, Records)
- - [ ] Obsługa **LLM / AI w Javie** – skorzystanie z API do zadania przetwarzania tekstu lub np.
- predykcja/klasyfikacja własnym modelem
- - UI oraz UX nie mają znaczenia, podczas prezentacji można użyć narzędzi typu Swagger albo Postman
- - Unikanie typowych aplikacji Create-Read-Update-Delete (CRUD)
+Gra polega na tym, żeby unikać niebieskiego i różowego ducha swoją zółtą postacią. Dla zwycięstwa musimy zebrać wszystkie różowe punkciki, jeżeli jakikolwiek duch złapie nas
+do tego mementu to przegraliśmy i wyświetla się "Game Over!", żeby ponownie zagrać wystarczy kliknąć Restart Game u góry. Jak wygramy wyświetli się "You Win!".
-## Realizowane zagadnienia
+Nasz plugin w działaniu możemy zobaczyć tutaj:
-| Prowadzący | Temat |
-|------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| ŁCh | - Cucumber (BDD) + AssertJ
- Spring: Podstawowe zagadnienia, MVC, RestController, HttpClient, JPA
- LLM |
-| MD | - Wprowadzenie + IntelliJ
- Testy Mutacyjne
- From Java to Go |
-| MK | - Logi + Observability (JMX+Spring Atuators/Endpoints)
- Spring AOP
- Refleksja, Classloader, Annotation Processing |
-| ZN | - JDK Updates (od wersji 9 do wersji 25)
- Mikroserwisy 101: praktyczne podstawy budowy systemu z wykorzystaniem REST i Spring Cloud Eureka
- Mikroserwisy 102 (+ Spring Security): zaawansowane tematy związane z wykorzystaniem narzędzi do zarządzania autoryzacją i autentykacją |
-
-## Ramowy plan zajęć
-
-| Lp | Data | Temat | Uwagi |
-|----|-------|------------------------------------------------|--------------------------------------------------------------------------------------|
-| 1 | 2.03 | Wprowadzenie + IntelliJ | [Materiały na zajęcia](https://github.com/zzpj/pl-java2026/tree/main/intro-intellij) |
-| 2 | 9.03 | | |
-| 3 | 16.03 | | |
-| 4 | 23.03 | Przedstawienie pomysłu na projekt | |
-| 5 | 30.03 | | |
-| 6 | 13.04 | | |
-| 7 | 20.04 | | |
-| 8 | 4.05 | | |
-| 9 | 11.05 | | |
-| 10 | 18.05 | | |
-| 11 | 25.05 | Sprawdzanie postępu realizacji projektu | |
-| 12 | 1.06 | | |
-| 13 | 8.06 | | |
-| 14 | 15.06 | | |
-| 15 | 22.06 | Finalne przedstawienie zrealizowanego projektu | |
-
-## Ankiety
-
-- [Ankieta Wejściowa: Oczekiwania](https://forms.gle/3VvpUs9ntmiUmmBB7 ) - wypełnij teraz, abyśmy mogli lepiej
- dostosować zajęcia do Twoich potrzeb i oczekiwań!
-- [Ankieta Wyjściowa: Ocena zajęć i wnioski](https://to-be-defined-abc) - wypełnij po zakończeniu zajęć, aby podzielić
- się swoimi doświadczeniami i pomóc nam w przyszłości!
-
-## Youtube
-- [Nagrania z zajęć 2026](https://to-be-defined-xyz)
-- [Nagrania z zajęć 2025](https://www.youtube.com/playlist?list=PLIPonSYREXmIEPZtRujsooBwAPBSsxROs)
-- [Nagrania z zajęć 2024](https://www.youtube.com/playlist?list=PLIPonSYREXmIQN-S_9i0mrTyAK5u0gA8t)
-- [Nagrania z zajęć 2023](https://www.youtube.com/playlist?list=PLIPonSYREXmKVCktLuj_Duve4tQNEA3p1)
-- [Nagrania z zajęć 2022](https://www.youtube.com/playlist?list=PLIPonSYREXmLkAgnHHFsoRL3bRZwOwrMi)
-- [Nagrania z zajęć 2021](https://www.youtube.com/playlist?list=PLIPonSYREXmICvsCV_osPqDlTg3MDPDPg)
+
diff --git a/build.gradle.kts b/build.gradle.kts
new file mode 100644
index 0000000..f59ee8a
--- /dev/null
+++ b/build.gradle.kts
@@ -0,0 +1,55 @@
+plugins {
+ id("java")
+ id("org.jetbrains.kotlin.jvm") version "2.1.20"
+ id("org.jetbrains.intellij.platform") version "2.10.2"
+}
+
+group = "com.example"
+version = "1.0-SNAPSHOT"
+
+repositories {
+ mavenCentral()
+ intellijPlatform {
+ defaultRepositories()
+ }
+}
+
+// Read more: https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin.html
+dependencies {
+ intellijPlatform {
+ intellijIdea("2025.2.4")
+ testFramework(org.jetbrains.intellij.platform.gradle.TestFrameworkType.Platform)
+
+
+ // Add plugin dependencies for compilation here, example:
+ // bundledPlugin("com.intellij.java")
+ }
+}
+
+intellijPlatform {
+ pluginConfiguration {
+ ideaVersion {
+ sinceBuild = "252.25557"
+ }
+
+ changeNotes = """
+ Initial version
+ """.trimIndent()
+ }
+}
+
+tasks {
+ // Set the JVM compatibility versions
+ withType {
+ sourceCompatibility = "21"
+ targetCompatibility = "21"
+ }
+}
+
+kotlin {
+ compilerOptions {
+ jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_21)
+ }
+}
+
+
diff --git a/gameplay.gif b/gameplay.gif
new file mode 100644
index 0000000..f047456
Binary files /dev/null and b/gameplay.gif differ
diff --git a/gameplay.mp4 b/gameplay.mp4
new file mode 100644
index 0000000..e0067e4
Binary files /dev/null and b/gameplay.mp4 differ
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..fdfb2ce
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,4 @@
+# Enable Gradle Configuration Cache -> https://docs.gradle.org/current/userguide/configuration_cache.html
+org.gradle.configuration-cache=false
+# Enable Gradle Build Cache -> https://docs.gradle.org/current/userguide/build_cache.html
+org.gradle.caching=false
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..249e583
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..d30212c
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000..1b6c787
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,234 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+
+APP_NAME="Gradle"
+APP_BASE_NAME=${0##*/}
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..ac1b06f
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/intro-intellij/grupy/README.md b/intro-intellij/grupy/README.md
index e69de29..cdcd4cd 100644
--- a/intro-intellij/grupy/README.md
+++ b/intro-intellij/grupy/README.md
@@ -0,0 +1,9 @@
+Grupa nr IAS:
+GitHub: MacWalcz (GitLab: @McWalcz)
+GitHub: vladyslavsigma (GitLab: @vshpyhariev )
+GitHub: ApeFiction (GitLab: @ApeFiction)
+GitHub: MikitaKarabeika (GitLab: @Niktoninn )
+GitHub: Krakengard (GitLab: @Krakengard )
+
+
+
diff --git a/pacmanPlugin.iml b/pacmanPlugin.iml
new file mode 100644
index 0000000..482334b
--- /dev/null
+++ b/pacmanPlugin.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/settings.gradle.kts b/settings.gradle.kts
new file mode 100644
index 0000000..1408a73
--- /dev/null
+++ b/settings.gradle.kts
@@ -0,0 +1 @@
+rootProject.name = "pacmanPlugin"
\ No newline at end of file
diff --git a/src/main/java/MyMessageBundle.kt b/src/main/java/MyMessageBundle.kt
new file mode 100644
index 0000000..71ee8ce
--- /dev/null
+++ b/src/main/java/MyMessageBundle.kt
@@ -0,0 +1,20 @@
+import com.intellij.DynamicBundle
+import org.jetbrains.annotations.Nls
+import org.jetbrains.annotations.PropertyKey
+import java.util.function.Supplier
+
+private const val BUNDLE = "messages.MyMessageBundle"
+
+internal object MyMessageBundle {
+ private val instance = DynamicBundle(MyMessageBundle::class.java, BUNDLE)
+
+ @JvmStatic
+ fun message(key: @PropertyKey(resourceBundle = BUNDLE) String, vararg params: Any?): @Nls String {
+ return instance.getMessage(key, *params)
+ }
+
+ @JvmStatic
+ fun lazyMessage(@PropertyKey(resourceBundle = BUNDLE) key: String, vararg params: Any?): Supplier<@Nls String> {
+ return instance.getLazyMessage(key, *params)
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/MyToolWindow.kt b/src/main/java/MyToolWindow.kt
new file mode 100644
index 0000000..1973ef4
--- /dev/null
+++ b/src/main/java/MyToolWindow.kt
@@ -0,0 +1,33 @@
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.wm.ToolWindow
+import com.intellij.openapi.wm.ToolWindowFactory
+import com.intellij.ui.components.JBLabel
+import com.intellij.ui.components.JBPanel
+import com.intellij.ui.content.ContentFactory
+import javax.swing.JButton
+import kotlin.random.Random
+
+class MyToolWindowFactory : ToolWindowFactory {
+ override fun shouldBeAvailable(project: Project) = true
+
+ override fun createToolWindowContent(project: Project, toolWindow: ToolWindow) {
+ val myToolWindow = MyToolWindow()
+ val content = ContentFactory.getInstance().createContent(myToolWindow.getContent(), null, false)
+ toolWindow.contentManager.addContent(content)
+ }
+
+ class MyToolWindow {
+ private val content = JBPanel>().apply {
+ val label = JBLabel("The random number is: ?")
+
+ add(label)
+ add(JButton("Shuffle").apply {
+ addActionListener {
+ label.text = "The random number is: " + Random(System.currentTimeMillis()).nextInt(1000)
+ }
+ })
+ }
+
+ fun getContent(): JBPanel> = content
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/example/pacmanPlugin/Icons.java b/src/main/java/com/example/pacmanPlugin/Icons.java
new file mode 100644
index 0000000..f024696
--- /dev/null
+++ b/src/main/java/com/example/pacmanPlugin/Icons.java
@@ -0,0 +1,30 @@
+package com.example.pacmanPlugin;
+
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+
+public class Icons {
+
+ private static final int ICON_SIZE = 16;
+
+ private static Icon loadGif(String path) {
+ ImageIcon originalIcon = new ImageIcon(Icons.class.getResource(path));
+ int width = originalIcon.getIconWidth();
+ int height = originalIcon.getIconHeight();
+
+ if (width <= ICON_SIZE && height <= ICON_SIZE) {
+ return originalIcon;
+ }
+
+ java.awt.Image scaledImage = originalIcon.getImage().getScaledInstance(ICON_SIZE, ICON_SIZE, java.awt.Image.SCALE_DEFAULT);
+ return new ImageIcon(scaledImage);
+ }
+
+ //public static final Icon PacMan = loadGif("/icons/PacMan.gif");
+ public static final ImageIcon PacRight = new ImageIcon(Icons.class.getResource("/icons/PacManRight.gif"));
+ public static final ImageIcon PacLeft = new ImageIcon(Icons.class.getResource("/icons/PacManLeft.gif"));
+ public static final ImageIcon PacUp = new ImageIcon(Icons.class.getResource("/icons/PacManUp.gif"));
+ public static final ImageIcon PacDown = new ImageIcon(Icons.class.getResource("/icons/PacManDown.gif"));
+ public static final ImageIcon PinkGhost = new ImageIcon(Icons.class.getResource("/icons/pinkghostright.gif"));
+ public static final ImageIcon BlueGhost = new ImageIcon(Icons.class.getResource("/icons/blueghostright.gif"));
+}
\ No newline at end of file
diff --git a/src/main/java/com/example/pacmanPlugin/Map.java b/src/main/java/com/example/pacmanPlugin/Map.java
new file mode 100644
index 0000000..90d9305
--- /dev/null
+++ b/src/main/java/com/example/pacmanPlugin/Map.java
@@ -0,0 +1,23 @@
+package com.example.pacmanPlugin;
+
+public class Map {
+ public static final int CellSize=20;
+ public static final int[][] MaP={
+ {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
+ {1,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,1},
+ {1,0,1,1,0,1,0,1,1,1,1,1,1,0,1,0,1,1,0,1},
+ {1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1},
+ {1,0,1,0,1,1,0,1,1,0,0,1,1,0,1,1,0,1,0,1},
+ {1,0,0,0,0,0,0,1,0,3,4,0,1,0,0,0,0,0,0,1},
+ {1,0,1,0,1,1,0,1,1,1,1,1,1,0,1,1,0,1,0,1},
+ {1,0,1,0,0,0,0,0,0,0,0,0,0,2,0,0,0,1,0,1},
+ {1,0,1,1,0,1,0,1,1,1,1,1,1,0,1,0,1,1,0,1},
+ {1,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,1},
+ {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
+
+ };
+}
+//1-wall
+//2-pacman startpoint
+//3 ghosts startpoint
+//0-food
\ No newline at end of file
diff --git a/src/main/java/com/example/pacmanPlugin/PanelLogic.java b/src/main/java/com/example/pacmanPlugin/PanelLogic.java
new file mode 100644
index 0000000..797c51b
--- /dev/null
+++ b/src/main/java/com/example/pacmanPlugin/PanelLogic.java
@@ -0,0 +1,286 @@
+package com.example.pacmanPlugin;
+
+import com.intellij.ui.components.JBPanel;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+
+import java.awt.event.KeyListener;
+
+public class PanelLogic extends JBPanel {
+ private static final int RIGHT = 1;
+ private static final int LEFT = 2;
+ private static final int UP = 3;
+ private static final int DOWN = 4;
+
+ private boolean winSoundPlayed = false;
+ private boolean loseSoundPlayed = false;
+
+ private int pacX = 13;
+ private int pacY = 7;
+
+ private int dx = 0;
+ private int dy = 0;
+
+ private int ghost1X = 9;
+ private int ghost1Y = 5;
+
+ private int ghost2X = 10;
+ private int ghost2Y = 5;
+
+ private boolean isGameOver = false;
+
+ private ImageIcon currentPacman = Icons.PacRight;
+ private ImageIcon PinkGhost = Icons.PinkGhost;
+ private ImageIcon BlueGhost = Icons.BlueGhost;
+
+ private final int[][] gameMap;
+ private boolean isWon = false;
+ private int dotsLeft = 0;//?????????????
+
+ public PanelLogic() {
+ this.gameMap = new int[Map.MaP.length][Map.MaP[0].length];
+ for (int i = 0; i < Map.MaP.length; i++) {
+ for (int j = 0; j < Map.MaP[i].length; j++) {
+ gameMap[i][j] = Map.MaP[i][j];
+ if (gameMap[i][j] == 0) dotsLeft++;
+ }
+ }
+
+
+ setFocusable(true);//??? get keybord focus
+
+ addKeyListener(new KeyAdapter() {
+ @Override
+ public void keyPressed(KeyEvent e) {
+ if (isWon) return;
+
+ int key = e.getKeyCode();
+ if (key == KeyEvent.VK_UP && camMove(pacX, pacY, 0, -1)) {
+ dx = 0; dy = -1;
+ currentPacman = Icons.PacUp;
+ } else if (key == KeyEvent.VK_DOWN && camMove(pacX, pacY, 0, 1)) {
+ dx = 0; dy = 1;
+ currentPacman = Icons.PacDown;
+ } else if (key == KeyEvent.VK_LEFT && camMove(pacX, pacY, -1, 0)) {
+ dx = -1; dy = 0;
+ currentPacman = Icons.PacLeft;
+ } else if (key == KeyEvent.VK_RIGHT && camMove(pacX, pacY, 1, 0)) {
+ dx = 1; dy = 0;
+ currentPacman = Icons.PacRight;
+ }
+ }
+ });
+
+
+ Timer timer = new Timer(150, e -> {
+ if (!isWon && !isGameOver) {
+
+ movePAcMAn();
+ moveGhosts();
+ checkCollision();
+ repaint();
+
+ }
+ });
+ timer.start();
+ }
+
+ private void movePAcMAn(){
+ if(isGameOver) return;
+
+ if(camMove(pacX, pacY, dx, dy)) {
+ pacX += dx;
+ pacY += dy;
+
+ if(gameMap[pacY][pacX]==0){
+ gameMap[pacY][pacX]=2;
+ dotsLeft--;
+ Sounds.playCoin();
+ if(dotsLeft<=0)isWon=true;
+ }
+
+ }
+ }
+
+ private void moveGhostRandomly(int ghost) {
+
+ int[] dxs = {1,-1,0,0};
+ int[] dys = {0,0,1,-1};
+
+ int r = (int)(Math.random()*4);
+
+ int dx = dxs[r];
+ int dy = dys[r];
+
+ if (ghost == 1) {
+ int nx = ghost1X + dx;
+ int ny = ghost1Y + dy;
+
+ if (camMove(pacX, pacY, dx, dy)) {
+ ghost1X = nx;
+ ghost1Y = ny;
+ }
+
+ } else {
+
+ int nx = ghost2X + dx;
+ int ny = ghost2Y + dy;
+
+ if (camMove(pacX, pacY, dx, dy)) {
+ ghost2X = nx;
+ ghost2Y = ny;
+ }
+
+ }
+ }
+
+ private void checkCollision(){
+
+ if(pacX == ghost1X && pacY == ghost1Y){
+ isGameOver = true;
+
+ }
+
+ if(pacX == ghost2X && pacY == ghost2Y){
+ isGameOver = true;
+
+ }
+
+ }
+ private boolean camMove(int x, int y, int dx, int dy) {
+
+ int nextX = x + dx;
+ int nextY = y + dy;
+
+ return nextY >= 0 &&
+ nextY < gameMap.length &&
+ nextX >= 0 &&
+ nextX < gameMap[0].length &&
+ gameMap[nextY][nextX] != 1;
+ }
+
+ private void movePinkGhost() {
+
+ int[] dxs = {1,-1,0,0};
+ int[] dys = {0,0,1,-1};
+
+ while(true) {
+ int r = (int) (Math.random() * 4);
+
+ int dx = dxs[r];
+ int dy = dys[r];
+
+ if (camMove(ghost1X, ghost1Y, dx, dy)) {
+ ghost1X += dx;
+ ghost1Y += dy;
+ break;
+ }
+ }
+ }
+ private void moveBlueGhost() {
+
+ int[] dxs = {1,-1,0,0};
+ int[] dys = {0,0,1,-1};
+
+ while(true) {
+ int r = (int)(Math.random()*4);
+
+ int dx = dxs[r];
+ int dy = dys[r];
+
+ if (camMove(ghost2X, ghost2Y, dx, dy)) {
+ ghost2X += dx;
+ ghost2Y += dy;
+ break;
+ }
+ }
+ }
+
+ private void moveGhosts() {
+
+ movePinkGhost();
+ moveBlueGhost();
+
+ }
+
+ @Override
+ protected void paintComponent(Graphics G){
+ super.paintComponent(G);
+ Graphics2D G2=(Graphics2D) G;
+ for (int i = 0; i < Map.MaP.length; i++) {
+ for (int j = 0; j < Map.MaP[i].length; j++) {
+ int X=j*Map.CellSize;
+ int Y=i*Map.CellSize;
+
+ if(gameMap[i][j]==1){
+ G2.setColor(new Color(13, 13, 130));
+ G2.fillRect(X+2,Y+2,Map.CellSize-4,Map.CellSize-4);
+ } else if (gameMap[i][j]==0){
+ G2.setColor(new Color(241, 186, 235));
+ G2.fillOval(X+8,Y+8,4,4);
+ }
+ }
+ }
+ //Icons.PacMan.paintIcon(this,G2,pacX*Map.CellSize,pacY*Map.CellSize);
+ //G2.drawImage(((ImageIcon)Icons.PacMan).getImage(),pacX*Map.CellSize,pacY*Map.CellSize, Map.CellSize,Map.CellSize,this);
+ G2.drawImage(currentPacman.getImage(), pacX * Map.CellSize, pacY * Map.CellSize, Map.CellSize, Map.CellSize, this);
+ G2.drawImage(PinkGhost.getImage(), ghost1X*Map.CellSize,ghost1Y*Map.CellSize, Map.CellSize, Map.CellSize, this);
+ G2.drawImage(BlueGhost.getImage(), ghost2X*Map.CellSize,ghost2Y*Map.CellSize, Map.CellSize, Map.CellSize, this);
+
+ if(isWon){
+ if(!winSoundPlayed){
+ Sounds.playWin();
+ winSoundPlayed = true;
+ }
+
+ G2.setColor(Color.YELLOW);
+ G2.setFont(new Font("Monospaced",Font.BOLD,40));
+ G2.drawString("You Win!",100,110);
+ }
+
+ if(isGameOver){
+ if(!loseSoundPlayed){
+ Sounds.playLose();
+ loseSoundPlayed = true;
+ }
+ G2.setColor(Color.RED);
+ G2.setFont(new Font("Monospaced",Font.BOLD,40));
+ G2.drawString("Game Over",85,110);
+ }
+
+ }
+
+ public void restartGame() {
+ pacX = 13;
+ pacY = 7;
+ dx = 0;
+ dy = 0;
+
+ ghost1X = 9;
+ ghost1Y = 5;
+ ghost2X = 10;
+ ghost2Y = 5;
+
+ winSoundPlayed = false;
+ loseSoundPlayed = false;
+
+ isGameOver = false;
+ isWon = false;
+ currentPacman = Icons.PacRight;
+
+ dotsLeft = 0;
+ for (int i = 0; i < Map.MaP.length; i++) {
+ for (int j = 0; j < Map.MaP[i].length; j++) {
+ gameMap[i][j] = Map.MaP[i][j];
+ if (gameMap[i][j] == 0) dotsLeft++;
+ }
+ }
+
+ repaint();
+ requestFocusInWindow();
+ }
+
+ }
\ No newline at end of file
diff --git a/src/main/java/com/example/pacmanPlugin/Sounds.java b/src/main/java/com/example/pacmanPlugin/Sounds.java
new file mode 100644
index 0000000..d71a9b3
--- /dev/null
+++ b/src/main/java/com/example/pacmanPlugin/Sounds.java
@@ -0,0 +1,76 @@
+package com.example.pacmanPlugin;
+
+import javax.sound.sampled.*;
+import java.io.File;
+
+public class Sounds {
+
+ public static void playWin() {
+ try {
+ AudioInputStream audioStream =
+ AudioSystem.getAudioInputStream(
+ Sounds.class.getResource("/sounds/win.wav"));
+
+ Clip clip = AudioSystem.getClip();
+ clip.open(audioStream);
+ FloatControl volume = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
+
+
+ clip.start();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static void playMusic() {
+ try {
+ AudioInputStream audioStream =
+ AudioSystem.getAudioInputStream(
+ Sounds.class.getResource("/sounds/music.wav"));
+ Clip clip = AudioSystem.getClip();
+ clip.open(audioStream);
+ FloatControl volume = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
+ clip.loop(Clip.LOOP_CONTINUOUSLY);
+ volume.setValue(-25.0f);
+ clip.start();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static void playLose() {
+ try {
+ AudioInputStream audioStream =
+ AudioSystem.getAudioInputStream(
+ Sounds.class.getResource("/sounds/lose.wav"));
+ Clip clip = AudioSystem.getClip();
+ clip.open(audioStream);
+ FloatControl volume = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
+
+
+ clip.start();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static void playCoin() {
+ try {
+ AudioInputStream audioStream =
+ AudioSystem.getAudioInputStream(
+ Sounds.class.getResource("/sounds/coin.wav"));
+ Clip clip = AudioSystem.getClip();
+ clip.open(audioStream);
+ FloatControl volume = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
+
+
+ clip.start();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/main/java/com/example/pacmanPlugin/WindowFAc.java b/src/main/java/com/example/pacmanPlugin/WindowFAc.java
new file mode 100644
index 0000000..986139d
--- /dev/null
+++ b/src/main/java/com/example/pacmanPlugin/WindowFAc.java
@@ -0,0 +1,38 @@
+package com.example.pacmanPlugin;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.wm.ToolWindow;
+import com.intellij.openapi.wm.ToolWindowFactory;
+import com.intellij.ui.content.Content;
+import com.intellij.ui.content.ContentFactory;
+import javax.swing.*;
+import java.awt.*;
+
+public class WindowFAc implements ToolWindowFactory {
+
+ @Override
+ public void createToolWindowContent(Project project, ToolWindow toolWindow) {
+ JPanel mainWrapper = new JPanel(new BorderLayout());
+
+ PanelLogic gamePanel = new PanelLogic();
+ Sounds.playMusic();
+ JButton restartButton = new JButton("Restart Game");
+
+ restartButton.setFocusable(false);
+
+ restartButton.addActionListener(e -> {
+ gamePanel.restartGame();
+ gamePanel.requestFocusInWindow();
+ });
+
+ mainWrapper.add(restartButton, BorderLayout.NORTH);
+ mainWrapper.add(gamePanel, BorderLayout.CENTER);
+
+ Content content = ContentFactory.getInstance()
+ .createContent(mainWrapper, "", false);
+
+ toolWindow.getContentManager().addContent(content);
+
+ gamePanel.requestFocusInWindow();
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml
new file mode 100644
index 0000000..c96c934
--- /dev/null
+++ b/src/main/resources/META-INF/plugin.xml
@@ -0,0 +1,31 @@
+
+
+
+ com.example.pacmanPlugin
+
+
+ PacmanPlugin
+
+
+ Krakengard
+
+
+
+
+
+ com.intellij.modules.platform
+
+ messages.MyMessageBundle
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/META-INF/pluginIcon.svg b/src/main/resources/META-INF/pluginIcon.svg
new file mode 100644
index 0000000..dcf6b99
--- /dev/null
+++ b/src/main/resources/META-INF/pluginIcon.svg
@@ -0,0 +1,12 @@
+
\ No newline at end of file
diff --git a/src/main/resources/icons/PacManDown.gif b/src/main/resources/icons/PacManDown.gif
new file mode 100644
index 0000000..c36428a
Binary files /dev/null and b/src/main/resources/icons/PacManDown.gif differ
diff --git a/src/main/resources/icons/PacManLeft.gif b/src/main/resources/icons/PacManLeft.gif
new file mode 100644
index 0000000..49fa37e
Binary files /dev/null and b/src/main/resources/icons/PacManLeft.gif differ
diff --git a/src/main/resources/icons/PacManRight.gif b/src/main/resources/icons/PacManRight.gif
new file mode 100644
index 0000000..6a07e0b
Binary files /dev/null and b/src/main/resources/icons/PacManRight.gif differ
diff --git a/src/main/resources/icons/PacManUp.gif b/src/main/resources/icons/PacManUp.gif
new file mode 100644
index 0000000..d5535f5
Binary files /dev/null and b/src/main/resources/icons/PacManUp.gif differ
diff --git a/src/main/resources/icons/blueghostleft.gif b/src/main/resources/icons/blueghostleft.gif
new file mode 100644
index 0000000..1e55367
Binary files /dev/null and b/src/main/resources/icons/blueghostleft.gif differ
diff --git a/src/main/resources/icons/blueghostright.gif b/src/main/resources/icons/blueghostright.gif
new file mode 100644
index 0000000..16d17ee
Binary files /dev/null and b/src/main/resources/icons/blueghostright.gif differ
diff --git a/src/main/resources/icons/pinkghostleft.gif b/src/main/resources/icons/pinkghostleft.gif
new file mode 100644
index 0000000..04489a3
Binary files /dev/null and b/src/main/resources/icons/pinkghostleft.gif differ
diff --git a/src/main/resources/icons/pinkghostright.gif b/src/main/resources/icons/pinkghostright.gif
new file mode 100644
index 0000000..a4195da
Binary files /dev/null and b/src/main/resources/icons/pinkghostright.gif differ
diff --git a/src/main/resources/messages/MyMessageBundle.properties b/src/main/resources/messages/MyMessageBundle.properties
new file mode 100644
index 0000000..f62fbeb
--- /dev/null
+++ b/src/main/resources/messages/MyMessageBundle.properties
@@ -0,0 +1 @@
+toolwindow.stripe.MyToolWindow=My Tool Window
\ No newline at end of file
diff --git a/src/main/resources/sounds/coin.wav b/src/main/resources/sounds/coin.wav
new file mode 100644
index 0000000..d8941f5
Binary files /dev/null and b/src/main/resources/sounds/coin.wav differ
diff --git a/src/main/resources/sounds/lose.wav b/src/main/resources/sounds/lose.wav
new file mode 100644
index 0000000..f324b3f
Binary files /dev/null and b/src/main/resources/sounds/lose.wav differ
diff --git a/src/main/resources/sounds/music.wav b/src/main/resources/sounds/music.wav
new file mode 100644
index 0000000..6513a20
Binary files /dev/null and b/src/main/resources/sounds/music.wav differ
diff --git a/src/main/resources/sounds/win.wav b/src/main/resources/sounds/win.wav
new file mode 100644
index 0000000..d4dc5ac
Binary files /dev/null and b/src/main/resources/sounds/win.wav differ