diff --git a/.drone.yml b/.drone.yml
new file mode 100644
index 0000000..069d557
--- /dev/null
+++ b/.drone.yml
@@ -0,0 +1,71 @@
+kind: pipeline
+type: docker
+name: CI
+
+trigger:
+ when:
+ branch:
+ - master
+ - dev
+ - CI/CD
+ event:
+ - push
+
+steps:
+ - name: build-Models
+ image: mcr.microsoft.com/dotnet/sdk:8.0
+ commands:
+ - cd source/Trek-12/Models
+ - dotnet restore
+ - dotnet build -c Release --no-restore
+ - dotnet publish -c Release --no-restore -o $CI_PROJECT_DIR/build/release
+
+ - name: build-ConsoleApp
+ image: mcr.microsoft.com/dotnet/sdk:8.0
+ commands:
+ - cd source/Trek-12/ConsoleApp
+ - dotnet restore
+ - dotnet build -c Release --no-restore
+ - dotnet publish -c Release --no-restore -o $CI_PROJECT_DIR/build/release
+ depends_on: [build-Models]
+
+ - name: tests
+ image: mcr.microsoft.com/dotnet/sdk:8.0
+ commands:
+ - cd source/Trek-12
+ - dotnet restore CI-Trek-12.sln
+ - dotnet test CI-Trek-12.sln --no-restore
+ depends_on: [build-Models]
+
+ - name: code-analysis
+ image: hub.codefirst.iut.uca.fr/marc.chevaldonne/codefirst-dronesonarplugin-dotnet8
+ secrets: [ SECRET_SONAR_LOGIN ]
+ settings:
+ # accessible en ligne de commande par ${PLUGIN_SONAR_HOST}
+ sonar_host: https://codefirst.iut.uca.fr/sonar/
+ # accessible en ligne de commande par ${PLUGIN_SONAR_TOKEN}
+ sonar_token:
+ from_secret: SECRET_SONAR_LOGIN
+ commands:
+ - cd source/Trek-12
+ - dotnet restore CI-Trek-12.sln
+ - dotnet sonarscanner begin /k:"Trek-12" /d:sonar.host.url=$${PLUGIN_SONAR_HOST} /d:sonar.coverageReportPaths="coveragereport/SonarQube.xml" /d:sonar.coverage.exclusions="Tests/**" /d:sonar.login=$${PLUGIN_SONAR_TOKEN}
+ - dotnet build CI-Trek-12.sln -c Release --no-restore
+ - dotnet test CI-Trek-12.sln --logger trx --no-restore /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura --collect "XPlat Code Coverage"
+ - reportgenerator -reports:"**/coverage.cobertura.xml" -reporttypes:SonarQube -targetdir:"coveragereport"
+ - dotnet publish CI-Trek-12.sln -c Release --no-restore -o $CI_PROJECT_DIR/build/release
+ - dotnet sonarscanner end /d:sonar.login=$${PLUGIN_SONAR_TOKEN}
+ depends_on: [tests]
+
+ - name: generate-and-deploy-docs
+ image: hub.codefirst.iut.uca.fr/maxime.batista/codefirst-docdeployer:latest
+ failure: ignore
+ commands:
+ - /entrypoint.sh -l documentation/doxygen -t doxygen
+ when:
+ branch:
+ - master
+ - dev
+ event:
+ - push
+ depends_on: [ tests ]
diff --git a/README.md b/README.md
index 7779a13..8aad201 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,21 @@

+
+ Sonarcube Ratings
+
+ [](https://codefirst.iut.uca.fr/sonar/dashboard?id=Trek-12)
+[](https://codefirst.iut.uca.fr/sonar/dashboard?id=Trek-12)
+[](https://codefirst.iut.uca.fr/sonar/dashboard?id=Trek-12)
+
+
+[](https://codefirst.iut.uca.fr/remi.lavergne/Trek-12)
+[](https://codefirst.iut.uca.fr/sonar/dashboard?id=Trek-12)
+[](https://codefirst.iut.uca.fr/sonar/dashboard?id=Trek-12)
+[](https://codefirst.iut.uca.fr/sonar/dashboard?id=Trek-12)
+[](https://codefirst.iut.uca.fr/sonar/dashboard?id=Trek-12)
+
+
+
diff --git a/documentation/doxygen/Doxyfile b/documentation/doxygen/Doxyfile
new file mode 100644
index 0000000..d3d4895
--- /dev/null
+++ b/documentation/doxygen/Doxyfile
@@ -0,0 +1,428 @@
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+DOXYFILE_ENCODING = UTF-8
+PROJECT_NAME = "Trek 12"
+PROJECT_NUMBER = 1.0.0
+PROJECT_BRIEF = "Application de jeu plateau en roll & write sur le framework .NET MAUI avec XAML et C#"
+PROJECT_LOGO = /trek12.png
+OUTPUT_DIRECTORY = /documentation/doxygen
+CREATE_SUBDIRS = NO
+ALLOW_UNICODE_NAMES = NO
+OUTPUT_LANGUAGE = French
+BRIEF_MEMBER_DESC = YES
+REPEAT_BRIEF = YES
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+ALWAYS_DETAILED_SEC = NO
+INLINE_INHERITED_MEMB = NO
+FULL_PATH_NAMES = YES
+STRIP_FROM_PATH =
+STRIP_FROM_INC_PATH =
+SHORT_NAMES = NO
+JAVADOC_AUTOBRIEF = NO
+JAVADOC_BANNER = NO
+QT_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = NO
+PYTHON_DOCSTRING = YES
+INHERIT_DOCS = YES
+SEPARATE_MEMBER_PAGES = NO
+TAB_SIZE = 4
+ALIASES =
+OPTIMIZE_OUTPUT_FOR_C = NO
+# Well... the one for Java looks so similar to the one for C#...
+OPTIMIZE_OUTPUT_JAVA = YES
+OPTIMIZE_FOR_FORTRAN = NO
+OPTIMIZE_OUTPUT_VHDL = NO
+OPTIMIZE_OUTPUT_SLICE = NO
+EXTENSION_MAPPING =
+MARKDOWN_SUPPORT = YES
+TOC_INCLUDE_HEADINGS = 5
+AUTOLINK_SUPPORT = YES
+BUILTIN_STL_SUPPORT = NO
+CPP_CLI_SUPPORT = NO
+SIP_SUPPORT = NO
+IDL_PROPERTY_SUPPORT = YES
+DISTRIBUTE_GROUP_DOC = NO
+GROUP_NESTED_COMPOUNDS = NO
+SUBGROUPING = YES
+INLINE_GROUPED_CLASSES = NO
+INLINE_SIMPLE_STRUCTS = NO
+TYPEDEF_HIDES_STRUCT = NO
+LOOKUP_CACHE_SIZE = 0
+NUM_PROC_THREADS = 1
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+EXTRACT_ALL = YES
+# I do not like other members to see my private members... but you can set it to YES if you prefer.
+EXTRACT_PRIVATE = NO
+EXTRACT_PRIV_VIRTUAL = NO
+EXTRACT_PACKAGE = NO
+EXTRACT_STATIC = YES
+EXTRACT_LOCAL_CLASSES = YES
+EXTRACT_LOCAL_METHODS = NO
+EXTRACT_ANON_NSPACES = NO
+RESOLVE_UNNAMED_PARAMS = YES
+HIDE_UNDOC_MEMBERS = NO
+HIDE_UNDOC_CLASSES = NO
+HIDE_FRIEND_COMPOUNDS = NO
+HIDE_IN_BODY_DOCS = NO
+INTERNAL_DOCS = NO
+CASE_SENSE_NAMES = NO
+HIDE_SCOPE_NAMES = NO
+HIDE_COMPOUND_REFERENCE= NO
+SHOW_HEADERFILE = YES
+SHOW_INCLUDE_FILES = YES
+SHOW_GROUPED_MEMB_INC = NO
+FORCE_LOCAL_INCLUDES = NO
+INLINE_INFO = YES
+SORT_MEMBER_DOCS = NO
+SORT_BRIEF_DOCS = NO
+SORT_MEMBERS_CTORS_1ST = NO
+SORT_GROUP_NAMES = NO
+SORT_BY_SCOPE_NAME = NO
+STRICT_PROTO_MATCHING = NO
+GENERATE_TODOLIST = YES
+GENERATE_TESTLIST = YES
+GENERATE_BUGLIST = YES
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+SHOW_USED_FILES = YES
+SHOW_FILES = YES
+SHOW_NAMESPACES = YES
+FILE_VERSION_FILTER =
+LAYOUT_FILE =
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+QUIET = NO
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_IF_DOC_ERROR = YES
+WARN_IF_INCOMPLETE_DOC = YES
+WARN_NO_PARAMDOC = NO
+WARN_AS_ERROR = NO
+WARN_FORMAT = "$file:$line: $text"
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+INPUT = source
+INPUT_ENCODING = UTF-8
+FILE_PATTERNS = *.c \
+ *.cc \
+ *.cxx \
+ *.cpp \
+ *.c++ \
+ *.java \
+ *.ii \
+ *.ixx \
+ *.ipp \
+ *.i++ \
+ *.inl \
+ *.idl \
+ *.ddl \
+ *.odl \
+ *.h \
+ *.hh \
+ *.hxx \
+ *.hpp \
+ *.h++ \
+ *.l \
+ *.cs \
+ *.d \
+ *.php \
+ *.php4 \
+ *.php5 \
+ *.phtml \
+ *.inc \
+ *.m \
+ *.markdown \
+ *.md \
+ *.mm \
+ *.dox \
+ *.py \
+ *.pyw \
+ *.f90 \
+ *.f95 \
+ *.f03 \
+ *.f08 \
+ *.f18 \
+ *.f \
+ *.for \
+ *.vhd \
+ *.vhdl \
+ *.ucf \
+ *.qsf \
+ *.ice
+RECURSIVE = YES
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS = */Tests/*
+EXCLUDE_PATTERNS += */bin/*
+EXCLUDE_PATTERNS += */obj/*
+EXCLUDE_SYMBOLS =
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS = *
+EXAMPLE_RECURSIVE = NO
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_PATTERNS =
+FILTER_SOURCE_FILES = NO
+FILTER_SOURCE_PATTERNS =
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+SOURCE_BROWSER = NO
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+REFERENCED_BY_RELATION = NO
+REFERENCES_RELATION = NO
+REFERENCES_LINK_SOURCE = YES
+SOURCE_TOOLTIPS = YES
+USE_HTAGS = NO
+VERBATIM_HEADERS = YES
+CLANG_ASSISTED_PARSING = NO
+CLANG_ADD_INC_PATHS = YES
+CLANG_OPTIONS =
+CLANG_DATABASE_PATH =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+ALPHABETICAL_INDEX = YES
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+GENERATE_HTML = YES
+HTML_OUTPUT = html
+HTML_FILE_EXTENSION = .html
+HTML_HEADER =
+HTML_STYLESHEET =
+HTML_EXTRA_STYLESHEET =
+HTML_EXTRA_FILES = images/CodeFirst.png images/clubinfo.png
+HTML_COLORSTYLE_HUE = 215
+HTML_COLORSTYLE_SAT = 45
+HTML_COLORSTYLE_GAMMA = 240
+HTML_TIMESTAMP = NO
+HTML_DYNAMIC_MENUS = YES
+HTML_DYNAMIC_SECTIONS = NO
+HTML_INDEX_NUM_ENTRIES = 100
+GENERATE_DOCSET = NO
+DOCSET_FEEDNAME = "Doxygen generated docs"
+DOCSET_FEEDURL =
+DOCSET_BUNDLE_ID = org.doxygen.Project
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+DOCSET_PUBLISHER_NAME = Publisher
+GENERATE_HTMLHELP = NO
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+CHM_INDEX_ENCODING =
+BINARY_TOC = NO
+TOC_EXPAND = NO
+GENERATE_QHP = NO
+QCH_FILE =
+QHP_NAMESPACE = org.doxygen.Project
+QHP_VIRTUAL_FOLDER = doc
+QHP_CUST_FILTER_NAME =
+QHP_CUST_FILTER_ATTRS =
+QHP_SECT_FILTER_ATTRS =
+QHG_LOCATION =
+GENERATE_ECLIPSEHELP = NO
+ECLIPSE_DOC_ID = org.doxygen.Project
+DISABLE_INDEX = NO
+GENERATE_TREEVIEW = NO
+FULL_SIDEBAR = NO
+ENUM_VALUES_PER_LINE = 4
+TREEVIEW_WIDTH = 250
+EXT_LINKS_IN_WINDOW = NO
+OBFUSCATE_EMAILS = YES
+HTML_FORMULA_FORMAT = png
+FORMULA_FONTSIZE = 10
+FORMULA_TRANSPARENT = YES
+FORMULA_MACROFILE =
+USE_MATHJAX = NO
+MATHJAX_VERSION = MathJax_2
+MATHJAX_FORMAT = HTML-CSS
+MATHJAX_RELPATH =
+MATHJAX_EXTENSIONS =
+MATHJAX_CODEFILE =
+SEARCHENGINE = YES
+SERVER_BASED_SEARCH = NO
+EXTERNAL_SEARCH = NO
+SEARCHENGINE_URL =
+SEARCHDATA_FILE = searchdata.xml
+EXTERNAL_SEARCH_ID =
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+GENERATE_LATEX = NO
+LATEX_OUTPUT = latex
+LATEX_CMD_NAME =
+MAKEINDEX_CMD_NAME = makeindex
+LATEX_MAKEINDEX_CMD = makeindex
+COMPACT_LATEX = NO
+PAPER_TYPE = a4
+EXTRA_PACKAGES =
+LATEX_HEADER =
+LATEX_FOOTER =
+LATEX_EXTRA_STYLESHEET =
+LATEX_EXTRA_FILES =
+PDF_HYPERLINKS = YES
+USE_PDFLATEX = YES
+LATEX_BATCHMODE = NO
+LATEX_HIDE_INDICES = NO
+LATEX_BIB_STYLE = plain
+LATEX_TIMESTAMP = NO
+LATEX_EMOJI_DIRECTORY =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+GENERATE_RTF = NO
+RTF_OUTPUT = rtf
+COMPACT_RTF = NO
+RTF_HYPERLINKS = NO
+RTF_STYLESHEET_FILE =
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+GENERATE_MAN = NO
+MAN_OUTPUT = man
+MAN_EXTENSION = .3
+MAN_SUBDIR =
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+GENERATE_XML = NO
+XML_OUTPUT = xml
+XML_PROGRAMLISTING = YES
+XML_NS_MEMB_FILE_SCOPE = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+GENERATE_DOCBOOK = NO
+DOCBOOK_OUTPUT = docbook
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to Sqlite3 output
+#---------------------------------------------------------------------------
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+GENERATE_PERLMOD = NO
+PERLMOD_LATEX = NO
+PERLMOD_PRETTY = YES
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = NO
+EXPAND_ONLY_PREDEF = NO
+SEARCH_INCLUDES = YES
+INCLUDE_PATH =
+INCLUDE_FILE_PATTERNS =
+PREDEFINED =
+EXPAND_AS_DEFINED =
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+TAGFILES =
+GENERATE_TAGFILE =
+ALLEXTERNALS = NO
+EXTERNAL_GROUPS = YES
+EXTERNAL_PAGES = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+DIA_PATH =
+HIDE_UNDOC_RELATIONS = YES
+HAVE_DOT = NO
+DOT_NUM_THREADS = 0
+DOT_FONTNAME = Helvetica
+DOT_FONTSIZE = 10
+DOT_FONTPATH =
+CLASS_GRAPH = YES
+COLLABORATION_GRAPH = YES
+GROUP_GRAPHS = YES
+UML_LOOK = NO
+UML_LIMIT_NUM_FIELDS = 10
+DOT_UML_DETAILS = NO
+DOT_WRAP_THRESHOLD = 17
+TEMPLATE_RELATIONS = NO
+INCLUDE_GRAPH = YES
+INCLUDED_BY_GRAPH = YES
+CALL_GRAPH = NO
+CALLER_GRAPH = NO
+GRAPHICAL_HIERARCHY = YES
+DIRECTORY_GRAPH = YES
+DIR_GRAPH_MAX_DEPTH = 1
+DOT_IMAGE_FORMAT = png
+INTERACTIVE_SVG = NO
+DOT_PATH =
+DOTFILE_DIRS =
+MSCFILE_DIRS =
+DIAFILE_DIRS =
+PLANTUML_JAR_PATH =
+PLANTUML_CFG_FILE =
+PLANTUML_INCLUDE_PATH =
+DOT_GRAPH_MAX_NODES = 50
+MAX_DOT_GRAPH_DEPTH = 0
+DOT_TRANSPARENT = NO
+DOT_MULTI_TARGETS = NO
+GENERATE_LEGEND = YES
+DOT_CLEANUP = YES
\ No newline at end of file
diff --git a/source/Trek-12/CI-Trek-12.sln b/source/Trek-12/CI-Trek-12.sln
new file mode 100644
index 0000000..cf5f81d
--- /dev/null
+++ b/source/Trek-12/CI-Trek-12.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.8.34408.163
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Models", "Models\Models.csproj", "{807AB723-7AD3-42DD-9DA6-7AA5B0A9AAB4}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{383C4215-C680-4C2E-BC7E-B62F0B164370}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {807AB723-7AD3-42DD-9DA6-7AA5B0A9AAB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {807AB723-7AD3-42DD-9DA6-7AA5B0A9AAB4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {807AB723-7AD3-42DD-9DA6-7AA5B0A9AAB4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {807AB723-7AD3-42DD-9DA6-7AA5B0A9AAB4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {383C4215-C680-4C2E-BC7E-B62F0B164370}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {383C4215-C680-4C2E-BC7E-B62F0B164370}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {383C4215-C680-4C2E-BC7E-B62F0B164370}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {383C4215-C680-4C2E-BC7E-B62F0B164370}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {50EAA59B-6857-44DC-86B9-E8D258C0DC86}
+ EndGlobalSection
+EndGlobal
diff --git a/source/Trek-12/ConsoleApp/ConsoleApp.csproj b/source/Trek-12/ConsoleApp/ConsoleApp.csproj
new file mode 100644
index 0000000..229387b
--- /dev/null
+++ b/source/Trek-12/ConsoleApp/ConsoleApp.csproj
@@ -0,0 +1,14 @@
+
+
+
+ Exe
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/source/Trek-12/ConsoleApp/Program.cs b/source/Trek-12/ConsoleApp/Program.cs
new file mode 100644
index 0000000..117e7cb
--- /dev/null
+++ b/source/Trek-12/ConsoleApp/Program.cs
@@ -0,0 +1,246 @@
+// See https://aka.ms/new-console-template for more information
+
+using Models;
+using Models.Events;
+using Models.Exceptions;
+using Models.Game;
+
+namespace ConsoleApp;
+
+class Program
+{
+ ///
+ /// Main function of the console app
+ ///
+ ///
+ static void Main(string[] args)
+ {
+ Console.WriteLine("Enter your pseudo:");
+ string? pseudo = Console.ReadLine();
+ if (pseudo != null)
+ {
+ Player player = new Player(pseudo);
+
+ Map map = new Map("background");
+ Game game = new Game(player, map);
+
+ // Abonnement aux événements
+ game.GameStarted += OnGameStarted!;
+ game.GameEnded += OnGameEnded!;
+ game.BoardUpdated += OnBoardUpdated!;
+ game.DiceRolled += OnDiceRolled!;
+ game.OperationChosen += OnOperationChosen!;
+ game.CellChosen += OnCellChosen!;
+
+ // Initialisation
+ game.InitializeGame();
+ }
+ }
+
+ ///
+ /// Handles the event when the game has started.
+ ///
+ ///
+ ///
+ static void OnGameStarted(object sender, GameStartedEventArgs e)
+ {
+ Console.WriteLine($"The game has started! Player: {e.CurrentPlayer.Pseudo}");
+ }
+
+ ///
+ /// Handles the event when the game has ended.
+ ///
+ ///
+ ///
+ static void OnGameEnded(object sender, GameEndedEventArgs e)
+ {
+ Console.WriteLine($"The game has ended! Player: {e.CurrentPlayer.Pseudo}");
+ }
+
+ ///
+ /// Handles the event when the board is updated.
+ ///
+ ///
+ ///
+ static void OnBoardUpdated(object sender, EventArgs e)
+ {
+ DisplayBoard(((Game)sender).UsedMap);
+ DisplayOperationTable(((Game)sender).UsedMap.OperationGrid);
+ }
+
+ ///
+ /// Handles the event when the dice are rolled.
+ ///
+ ///
+ ///
+ static void OnDiceRolled(object sender, DiceRolledEventArgs e)
+ {
+ Console.WriteLine($"Dice 1: {e.Dice1Value} | Dice 2: {e.Dice2Value}");
+ Operation playerOperation = GetPlayerOperation();
+ ((Game)sender).HandlePlayerOperation(playerOperation);
+ }
+
+ ///
+ /// Handles the event when an operation is chosen by the player.
+ ///
+ ///
+ ///
+ static void OnOperationChosen(object sender, OperationChosenEventArgs e)
+ {
+ Console.WriteLine($"Operation: {e.Operation}, Result: {e.Result}");
+ DisplayOperationTable(((Game)sender).UsedMap.OperationGrid);
+ Cell playerChoice = GetPlayerChoice();
+ try
+ {
+ ((Game)sender).HandlePlayerChoice(playerChoice, e.Result);
+ }
+ catch (InvalidCellCoordinatesException err)
+ {
+ Console.WriteLine(err.Message);
+ playerChoice = GetPlayerChoice();
+ ((Game)sender).HandlePlayerChoice(playerChoice, e.Result);
+ }
+ catch (InvalidCellException err)
+ {
+ Console.WriteLine(err.Message);
+ playerChoice = GetPlayerChoice();
+ ((Game)sender).HandlePlayerChoice(playerChoice, e.Result);
+ }
+ }
+
+ ///
+ /// Handles the event when a cell is chosen by the player.
+ ///
+ ///
+ ///
+ static void OnCellChosen(object sender, CellChosenEventArgs e)
+ {
+ Console.WriteLine($"Cell chosen: ({e.Cell.X}, {e.Cell.Y}) with result: {e.Result}");
+ DisplayBoard(((Game)sender).UsedMap);
+ }
+
+ ///
+ /// Displays the game board.
+ ///
+ /// Used map to display
+ static void DisplayBoard(Map map)
+ {
+ int cpt = 0;
+ for (int i = 0; i < map.Boards.Count; i++)
+ {
+ if (cpt % 6 == 0)
+ {
+ Console.Write("| ");
+ }
+
+ if (map.Boards[i].Value.HasValue)
+ {
+ Console.Write(map.Boards[i].Value?.ToString().PadLeft(2));
+ }
+ else
+ {
+ Console.Write(" O");
+ }
+
+ cpt++;
+ if (cpt % 6 == 0)
+ {
+ Console.Write(" |");
+ Console.WriteLine();
+ }
+ }
+ }
+
+ ///
+ /// Displays the operation table.
+ ///
+ /// The operation table to display.
+ static void DisplayOperationTable(List operationTable)
+ {
+ Console.WriteLine("Operation Table:");
+ string[] operations = { "Addition (+)", "Subtraction (-)", "Multiplication (*)", "Lower Dice (less)", "Higher Dice (high)" };
+
+ for (int i = 0; i < operations.Length; i++)
+ {
+ Console.Write(operations[i].PadRight(18));
+
+ for (int j = 0; j < 4; j++)
+ {
+ int index = i * 4 + j;
+ if (index < operationTable.Count)
+ {
+ string status = operationTable[index].IsChecked ? "X" : " ";
+ Console.Write($" | {status}");
+ }
+ }
+ Console.WriteLine();
+ }
+ }
+
+ ///
+ /// Gets the cell chosen by the player.
+ ///
+ /// The cell chosen by the player.
+ static Cell GetPlayerChoice()
+ {
+ int row, column;
+ while (true)
+ {
+ Console.WriteLine("Enter the position of the cell you want to play");
+ Console.WriteLine("Enter the row number (0-5)");
+ if (!int.TryParse(Console.ReadLine(), out row) || row < 0 || row >= 6)
+ {
+ Console.WriteLine("Invalid row number. Please enter a number between 0 and 5.");
+ continue;
+ }
+
+ Console.WriteLine("Enter the column number (0-5)");
+ if (!int.TryParse(Console.ReadLine(), out column) || column < 0 || column >= 6)
+ {
+ Console.WriteLine("Invalid column number. Please enter a number between 0 and 5.");
+ continue;
+ }
+
+ return new Cell(row, column);
+ }
+ }
+
+ ///
+ /// Gets the operation chosen by the player.
+ ///
+ ///
+ ///
+ static Operation GetPlayerOperation()
+ {
+ DisplayOperationOptions();
+ string? op = Console.ReadLine();
+ while (op != "1" && op != "2" && op != "3" && op != "4" && op != "5")
+ {
+ Console.WriteLine("Invalid operation. Please choose again.");
+ op = Console.ReadLine();
+ }
+
+ return op switch
+ {
+ "1" => Operation.ADDITION,
+ "2" => Operation.SUBTRACTION,
+ "3" => Operation.MULTIPLICATION,
+ "4" => Operation.LOWER,
+ "5" => Operation.HIGHER,
+ _ => throw new ArgumentOutOfRangeException()
+ };
+ }
+
+ ///
+ /// Displays the operation options for the player to choose from.
+ ///
+ static void DisplayOperationOptions()
+ {
+ Console.WriteLine("Choose an operation:");
+ Console.WriteLine("1: Addition (+)");
+ Console.WriteLine("2: Subtraction (-)");
+ Console.WriteLine("3: Multiplication (*)");
+ Console.WriteLine("4: Lower Dice (less)");
+ Console.WriteLine("5: Higher Dice (high)");
+ }
+}
\ No newline at end of file
diff --git a/source/Trek-12/Models/Events/CellChosenEventArgs.cs b/source/Trek-12/Models/Events/CellChosenEventArgs.cs
new file mode 100644
index 0000000..9c2040c
--- /dev/null
+++ b/source/Trek-12/Models/Events/CellChosenEventArgs.cs
@@ -0,0 +1,19 @@
+using Models.Game;
+
+namespace Models.Events
+{
+ ///
+ /// Event arguments for when a cell is chosen.
+ ///
+ public class CellChosenEventArgs : EventArgs
+ {
+ public Cell Cell { get; }
+ public int Result { get; }
+
+ public CellChosenEventArgs(Cell cell, int result)
+ {
+ Cell = cell;
+ Result = result;
+ }
+ }
+}
\ No newline at end of file
diff --git a/source/Trek-12/Models/Events/DiceRolledEventArgs.cs b/source/Trek-12/Models/Events/DiceRolledEventArgs.cs
new file mode 100644
index 0000000..fd77f54
--- /dev/null
+++ b/source/Trek-12/Models/Events/DiceRolledEventArgs.cs
@@ -0,0 +1,19 @@
+using Models.Game;
+
+namespace Models.Events
+{
+ ///
+ /// Event arguments for when the dice are rolled.
+ ///
+ public class DiceRolledEventArgs : EventArgs
+ {
+ public int Dice1Value { get; }
+ public int Dice2Value { get; }
+
+ public DiceRolledEventArgs(int dice1Value, int dice2Value)
+ {
+ Dice1Value = dice1Value;
+ Dice2Value = dice2Value;
+ }
+ }
+}
diff --git a/source/Trek-12/Models/Events/GameEndedEventArgs.cs b/source/Trek-12/Models/Events/GameEndedEventArgs.cs
new file mode 100644
index 0000000..7148eeb
--- /dev/null
+++ b/source/Trek-12/Models/Events/GameEndedEventArgs.cs
@@ -0,0 +1,17 @@
+using Models.Game;
+
+namespace Models.Events
+{
+ ///
+ /// Event arguments for when the game ends.
+ ///
+ public class GameEndedEventArgs : EventArgs
+ {
+ public Player CurrentPlayer { get; }
+
+ public GameEndedEventArgs(Player winner)
+ {
+ CurrentPlayer = winner;
+ }
+ }
+}
diff --git a/source/Trek-12/Models/Events/GameStartedEventArgs.cs b/source/Trek-12/Models/Events/GameStartedEventArgs.cs
new file mode 100644
index 0000000..1f1e157
--- /dev/null
+++ b/source/Trek-12/Models/Events/GameStartedEventArgs.cs
@@ -0,0 +1,18 @@
+using Models.Game;
+
+namespace Models.Events
+{
+ ///
+ /// Event arguments for when the game starts.
+ ///
+ public class GameStartedEventArgs : EventArgs
+ {
+ public Player CurrentPlayer { get; }
+
+ public GameStartedEventArgs(Player selectedPlayer)
+ {
+ CurrentPlayer = selectedPlayer;
+ }
+ }
+}
+
diff --git a/source/Trek-12/Models/Events/OperationChosenEventArgs.cs b/source/Trek-12/Models/Events/OperationChosenEventArgs.cs
new file mode 100644
index 0000000..af43c76
--- /dev/null
+++ b/source/Trek-12/Models/Events/OperationChosenEventArgs.cs
@@ -0,0 +1,19 @@
+using Models.Game;
+
+namespace Models.Events
+{
+ ///
+ /// Event arguments for when an operation is chosen.
+ ///
+ public class OperationChosenEventArgs : EventArgs
+ {
+ public Operation Operation { get; }
+ public int Result { get; }
+
+ public OperationChosenEventArgs(Operation operation, int result)
+ {
+ Operation = operation;
+ Result = result;
+ }
+ }
+}
\ No newline at end of file
diff --git a/source/Trek-12/Models/Exceptions/InvalidCellCoordinatesException.cs b/source/Trek-12/Models/Exceptions/InvalidCellCoordinatesException.cs
new file mode 100644
index 0000000..4f4e53d
--- /dev/null
+++ b/source/Trek-12/Models/Exceptions/InvalidCellCoordinatesException.cs
@@ -0,0 +1,11 @@
+namespace Models.Exceptions
+{
+ ///
+ /// Exception for when the cell coordinates are invalid.
+ ///
+ public class InvalidCellCoordinatesException : Exception
+ {
+ public InvalidCellCoordinatesException(string message) : base(message) { }
+ }
+}
+
diff --git a/source/Trek-12/Models/Exceptions/InvalidCellException.cs b/source/Trek-12/Models/Exceptions/InvalidCellException.cs
new file mode 100644
index 0000000..7556c26
--- /dev/null
+++ b/source/Trek-12/Models/Exceptions/InvalidCellException.cs
@@ -0,0 +1,11 @@
+namespace Models.Exceptions
+{
+ ///
+ /// Exception for when the cell is invalid.
+ ///
+ public class InvalidCellException : Exception
+ {
+ public InvalidCellException(string message) : base(message) { }
+ }
+}
+
diff --git a/source/Trek-12/Models/Game/BestScore.cs b/source/Trek-12/Models/Game/BestScore.cs
new file mode 100644
index 0000000..c2c5ca4
--- /dev/null
+++ b/source/Trek-12/Models/Game/BestScore.cs
@@ -0,0 +1,69 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Models.Game
+{
+ ///
+ /// This class represents the best score of a player.
+ ///
+ public class BestScore
+ {
+ ///
+ /// Initialize a new instance of the BestScore class.
+ ///
+ /// Number of games played by the new user
+ /// Best score
+ public BestScore(int gamesPlayed, int score)
+ {
+ GamesPlayed = gamesPlayed;
+ Score = score;
+ if (GamesPlayed < 0)
+ GamesPlayed = 0;
+ if (Score < 0)
+ Score = 0;
+ }
+
+ ///
+ /// Number of games played by the user.
+ ///
+ public int GamesPlayed { get; private set; }
+
+ ///
+ /// Best score of the player.
+ ///
+ private int _score;
+ public int Score
+ {
+ get
+ {
+ return _score;
+ }
+ private set
+ {
+ if (value > _score)
+ _score = value;
+ }
+ }
+
+ ///
+ /// Increment the number of games played by the user.
+ ///
+ public void IncrGamesPlayed()
+ {
+ GamesPlayed += 1;
+ }
+
+ ///
+ /// Update the best score of the player.
+ ///
+ /// New best score
+ public void UpdateScore(int newScore)
+ {
+ Score = newScore;
+ }
+ }
+}
diff --git a/source/Trek-12/Models/Game/Cell.cs b/source/Trek-12/Models/Game/Cell.cs
new file mode 100644
index 0000000..49fe4bb
--- /dev/null
+++ b/source/Trek-12/Models/Game/Cell.cs
@@ -0,0 +1,64 @@
+namespace Models.Game
+{
+ ///
+ /// The Cell class represents a cell in the application.
+ ///
+ public class Cell : Position, IEquatable
+ {
+ ///
+ /// The value of the cell.
+ ///
+ private int? _value;
+ public int? Value {
+ get => _value;
+ set
+ {
+ if (value < 0)
+ {
+ throw new Exception("La valeur doit être supérieure à 0");
+ }
+ this._value = value;
+ }
+ }
+
+ ///
+ /// The fact that the cell is dangerous or not.
+ ///
+ private bool IsDangerous { get; set; }
+
+ ///
+ /// Atribute to know if the cell is a penalty cell.
+ ///
+ private bool Penalty { get; set; }
+
+ ///
+ /// Constructor of the Cell class.
+ ///
+ /// the x position
+ /// the y position
+ /// if the cell is a dangerous cell or not
+ public Cell(int x, int y,bool isDangerous = false):base(x,y)
+ {
+ IsDangerous = isDangerous;
+ Penalty = false;
+ }
+
+ ///
+ /// Function in order to return the fact that the cell is dangerous or not.
+ ///
+ /// If the cell is dangerous or not
+ public bool GetCellType() => IsDangerous;
+
+ ///
+ /// Redefine the equal operation between cells.
+ ///
+ /// The object to compare with the current cell.
+ /// true if the specified object is equal to the current cell; otherwise, false.
+ public bool Equals(Cell? other)
+ {
+ if (other == null) return false;
+ if (this.X == other.X && this.Y == other.Y) return true;
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/source/Trek-12/Models/Game/Dice.cs b/source/Trek-12/Models/Game/Dice.cs
new file mode 100644
index 0000000..2d47fe3
--- /dev/null
+++ b/source/Trek-12/Models/Game/Dice.cs
@@ -0,0 +1,85 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Models.Game
+{
+ ///
+ /// The Dice class represents a dice in the application.
+ ///
+ public class Dice
+ {
+ ///
+ /// Lowest number on the dice.
+ ///
+ public int NbMin { get; private set; }
+
+ ///
+ /// Highest number on the dice.
+ ///
+ public int NbMax { get; private set; }
+
+ ///
+ /// Value of the dice.
+ ///
+ private int _value;
+ public int Value {
+ get => _value;
+ private set
+ {
+ if (value < NbMin || value > NbMax)
+ {
+ value = NbMin;
+ }
+ _value = value;
+ }
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The lowest number on the dice, on which the highest number is set
+ public Dice(int nbmin)
+ {
+ if (nbmin < 0) nbmin = 0;
+ if (nbmin > 1) nbmin = 1;
+ NbMin = nbmin;
+ NbMax = nbmin + 5;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public Dice()
+ {
+ NbMin = 0;
+ NbMax = 5;
+ }
+
+ public override string ToString()
+ {
+ return $"Ce dé a pour valeur {Value} et est entre {NbMin} et {NbMax}";
+ }
+
+ ///
+ /// Rolls the dice.
+ ///
+ public void Roll()
+ {
+ Value = new Random().Next(NbMin, NbMax + 1);
+ }
+
+ ///
+ /// Compare 2 dice values.
+ ///
+ /// Another dice
+ /// true if the dice2 is higher than the dice1; otherwise, false.
+ public bool IsLower(Dice dice2)
+ {
+ return dice2.Value > this.Value;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/source/Trek-12/Models/Game/Game.cs b/source/Trek-12/Models/Game/Game.cs
new file mode 100644
index 0000000..ca6ede7
--- /dev/null
+++ b/source/Trek-12/Models/Game/Game.cs
@@ -0,0 +1,252 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Threading.Tasks.Dataflow;
+using Models.Events;
+using Models.Exceptions;
+using Models.Rules;
+
+namespace Models.Game
+{
+ ///
+ /// The Game class represents a game session in the application.
+ /// It contains all the necessary properties and methods to manage a game, including the game loop, dice rolling, and use of the game rules.
+ ///
+ public class Game
+ {
+ private bool _isRunning;
+ public Player CurrentPlayer { get; private set; }
+
+ public Map UsedMap { get; private set; }
+
+ private Dice Dice1 { get; }
+ private Dice Dice2 { get; }
+
+ private int Turn { get; set; }
+
+ public Rules.Rules GameRules { get; }
+
+
+ // == Events ==
+ public event EventHandler GameStarted;
+ public event EventHandler GameEnded;
+ public event EventHandler BoardUpdated;
+ public event EventHandler DiceRolled;
+ public event EventHandler OperationChosen;
+ public event EventHandler CellChosen;
+
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The player who play the game.
+ /// The map to be used in the game.
+ public Game(Player player, Map map)
+ {
+ _isRunning = false;
+ UsedMap = map;
+ CurrentPlayer = player;
+ Dice1 = new Dice();
+ Dice2 = new Dice(1);
+ Turn = 1;
+ GameRules = new Rules.Rules();
+ }
+
+ ///
+ /// Rolls all the dice.
+ ///
+ private void RollAllDice()
+ {
+ Dice1.Roll();
+ Dice2.Roll();
+ DiceRolled?.Invoke(this, new DiceRolledEventArgs(Dice1.Value, Dice2.Value));
+ }
+
+ ///
+ /// Marks an operation as checked in the operation grid of the game.
+ ///
+ ///
+ private void MarkOperationAsChecked(Operation operation)
+ {
+ int operationIndex = (int)operation;
+ int operationsPerType = 4; // Chaque type d'opération peut être fait 4 fois
+
+ for (int i = operationIndex * operationsPerType; i < (operationIndex + 1) * operationsPerType; i++)
+ {
+ if (!UsedMap.OperationGrid[i].IsChecked)
+ {
+ UsedMap.OperationGrid[i].Check();
+ break;
+ }
+ }
+ }
+
+ ///
+ /// Performs an operation on the values of two dice based on the provided operation.
+ ///
+ /// The operation to perform. This can be LOWER, HIGHER, SUBTRACTION, ADDITION, or MULTIPLICATION.
+ ///
+ /// The result of the operation. If the operation is LOWER or HIGHER, it returns the lower or higher value of the two dice respectively.
+ /// If the operation is SUBTRACTION, it returns the difference between the higher and lower value of the two dice.
+ /// If the operation is ADDITION, it returns the sum of the values of the two dice.
+ /// If the operation is MULTIPLICATION, it returns the product of the values of the two dice.
+ /// If the operation is not one of the operations, it throws an ArgumentOutOfRangeException.
+ ///
+ private int ResultOperation(Operation o)
+ {
+ int result = o switch
+ {
+ Operation.LOWER => Dice1.IsLower(Dice2) ? Dice1.Value : Dice2.Value,
+ Operation.HIGHER => Dice1.IsLower(Dice2) ? Dice2.Value : Dice1.Value,
+ Operation.SUBTRACTION => Dice1.IsLower(Dice2) ? Dice2.Value - Dice1.Value : Dice1.Value - Dice2.Value,
+ Operation.ADDITION => Dice2.Value + Dice1.Value,
+ Operation.MULTIPLICATION => Dice2.Value * Dice1.Value,
+ _ => throw new ArgumentOutOfRangeException()
+ };
+
+ MarkOperationAsChecked(o);
+ return result;
+ }
+
+
+ ///
+ /// Places the result of a dice operation into a chosen cell on the game board.
+ /// The result can be placed in the chosen cell if it's the first turn or if the chosen cell is valid according to the game rules.
+ ///
+ /// The cell chosen by the player to place the result.
+ /// The result of the dice operation to be placed in the cell.
+ private void PlaceResult(Cell playerChoice, int result)
+ {
+ if (Turn == 1 || GameRules.NearCellIsValid(playerChoice, UsedMap.Boards))
+ {
+ playerChoice.Value = result;
+ BoardUpdated?.Invoke(this, EventArgs.Empty);
+ }
+ }
+
+ ///
+ /// Add the choosen cell to a rope path if it's possible.
+ ///
+ ///
+ ///
+ private void AddToRopePath(Cell playerChoice,List adjacentes)
+ {
+ int index =0;
+
+ foreach (var cells in adjacentes)
+ {
+ // La cellule choisi peut creer/s'ajouter a un chemin de corde
+ if (cells.Value - playerChoice.Value == 1 || cells.Value - playerChoice.Value == -1)
+ {
+ // Le cas si il n'existe aucun chemin de corde
+ if (UsedMap.RopePaths.Count == 0)
+ {
+ // Creer un nouveau chemin de corde avec la cellule choisi par le joueur et celle adjacente
+ UsedMap.RopePaths.Add(new List {playerChoice, cells});
+ }
+
+
+ // A modifier dans le cas ou il est possible de fusionner deux chemins de corde
+ if (GameRules.IsInRopePaths(playerChoice, UsedMap.RopePaths, index)) break;
+
+ // Le cas si il existe des chemins de corde
+
+ // Est-ce que la cellule adjacentes fait parti d'un chemin de corde
+ if (!GameRules.IsInRopePaths(cells,UsedMap.RopePaths,index))
+ {
+ UsedMap.RopePaths.Add(new List { playerChoice, cells });
+ continue;
+ }
+
+ if (!GameRules.AsValue(playerChoice,UsedMap.RopePaths,index))
+ {
+ UsedMap.RopePaths[index].Add(playerChoice);
+ }
+
+ // Si oui, est-ce que le chemin possede deja la valeur correspondante a la valeur de la cellule du joueur choisi
+ // {playerChoice.Value} n'est pas dans le chemin de corde
+ // Ajouter au chemin
+ // {playerChoice.Value} existe dans le chemin de corde pas possible
+
+ }
+ }
+
+ }
+
+ ///
+ /// Initializes the game.
+ ///
+ public void InitializeGame()
+ {
+ _isRunning = true;
+ GameStarted?.Invoke(this, new GameStartedEventArgs(CurrentPlayer));
+ GameLoop();
+ }
+
+ ///
+ /// Ends the game.
+ ///
+ private void EndGame()
+ {
+ _isRunning = false;
+ GameEnded?.Invoke(this, new GameEndedEventArgs(CurrentPlayer));
+ }
+
+ ///
+ /// The main game loop that runs while the game is active.
+ ///
+ private void GameLoop()
+ {
+ while (_isRunning)
+ {
+ if (Turn == 20)
+ {
+ EndGame();
+ break;
+ }
+
+ RollAllDice();
+
+ Turn++;
+ }
+ }
+
+ ///
+ /// Handles the player's choice of an operation based on the dice values.s
+ ///
+ /// The operation chosen by the player.
+ public void HandlePlayerOperation(Operation operation)
+ {
+ int result = ResultOperation(operation);
+ OperationChosen?.Invoke(this, new OperationChosenEventArgs(operation, result));
+ }
+
+ ///
+ /// Handles the player's choice of a cell on the game board.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void HandlePlayerChoice(Cell cell, int result)
+ {
+ if (cell.X < 0 || cell.X >= UsedMap.Boards.Count / 6 || cell.Y < 0 || cell.Y >= 6)
+ {
+ throw new InvalidCellCoordinatesException("Invalid cell coordinates. Please choose again.");
+ }
+
+ if (!GameRules.IsCellValid(cell, UsedMap.Boards))
+ {
+ throw new InvalidCellException("Cell is not valid. Please choose again.");
+ }
+
+ PlaceResult(cell, result);
+ GameRules.IsZoneValidAndAddToZones(cell, UsedMap);
+ AddToRopePath(cell, GameRules.EveryAdjacentCells(cell, UsedMap.Boards));
+ CellChosen?.Invoke(this, new CellChosenEventArgs(cell, result));
+ BoardUpdated?.Invoke(this, EventArgs.Empty);
+ }
+ }
+}
diff --git a/source/Trek-12/Models/Game/Map.cs b/source/Trek-12/Models/Game/Map.cs
new file mode 100644
index 0000000..56dbb69
--- /dev/null
+++ b/source/Trek-12/Models/Game/Map.cs
@@ -0,0 +1,78 @@
+namespace Models.Game
+{
+
+ ///
+ /// The Map class is the representation of the game map with the board and the operations table.
+ ///
+ public class Map
+ {
+ ///
+ /// It is the list of cells on the map.
+ ///
+ public List Boards { get; private set; }
+
+ ///
+ /// It is the backgrond image of the map
+ ///
+ public string Background { get; private set; }
+
+ ///
+ /// It is the grid of the possible operation in the game
+ ///
+ public List OperationGrid { get; private set; }
+
+ ///
+ /// It is a list of a list containing user's rope paths in the current game
+ ///
+ public List> RopePaths { get; private set; }
+
+ ///
+ /// It is a list of a list containing user's zones in the current game
+ ///
+ public List> Zones { get; private set; }
+
+ ///
+ /// Initializes a new instance of the Map class.
+ ///
+ /// The background of the map.
+ public Map(string background)
+ {
+ Boards = InitializeBoards();
+ Background = background;
+ OperationGrid = InitializeOperationGrid();
+ RopePaths = new List>();
+ Zones = new List>();
+ }
+
+ ///
+ /// Initializes the boards of the map.
+ ///
+ /// Return the boards
+ private List InitializeBoards()
+ {
+ var boards = new List();
+ for (int i = 0; i < 36; i++) // 6x6 board
+ {
+ boards.Add(new Cell(i / 6, i % 6));
+ }
+ return boards;
+ }
+
+ ///
+ /// Initializes the operation grid of the map.
+ ///
+ /// Return the operation grid
+ private List InitializeOperationGrid()
+ {
+ var operationGrid = new List();
+ for (int i = 0; i < 5; i++) // 5 operations
+ {
+ for (int j = 0; j < 4; j++) // 4 cells per operation
+ {
+ operationGrid.Add(new OperationCell(i, j));
+ }
+ }
+ return operationGrid;
+ }
+ }
+}
\ No newline at end of file
diff --git a/source/Trek-12/Models/Game/Operation.cs b/source/Trek-12/Models/Game/Operation.cs
new file mode 100644
index 0000000..2eca1fe
--- /dev/null
+++ b/source/Trek-12/Models/Game/Operation.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Models.Game
+{
+ ///
+ /// Represents the available operations in the game.
+ ///
+ public enum Operation
+ {
+ LOWER,
+ HIGHER,
+ SUBTRACTION,
+ ADDITION,
+ MULTIPLICATION
+ }
+}
diff --git a/source/Trek-12/Models/Game/OperationCell.cs b/source/Trek-12/Models/Game/OperationCell.cs
new file mode 100644
index 0000000..d8ac6da
--- /dev/null
+++ b/source/Trek-12/Models/Game/OperationCell.cs
@@ -0,0 +1,30 @@
+namespace Models.Game
+{
+ ///
+ /// Represents a cell in the operation grid of the game.
+ ///
+ public class OperationCell : Position
+ {
+ ///
+ /// It tells if the operation is checked or not in the operation grid of the game.
+ ///
+ public bool IsChecked { get; private set; }
+
+ ///
+ /// Constructor of the OperationCell class.
+ ///
+ ///
+ ///
+ public OperationCell(int x, int y) : base(x, y)
+ {
+ }
+
+ ///
+ /// Check the operation cell.
+ ///
+ public void Check()
+ {
+ IsChecked = true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/source/Trek-12/Models/Game/Player.cs b/source/Trek-12/Models/Game/Player.cs
new file mode 100644
index 0000000..f363eb4
--- /dev/null
+++ b/source/Trek-12/Models/Game/Player.cs
@@ -0,0 +1,82 @@
+namespace Models.Game
+{
+
+ ///
+ /// Represents a player in the game.
+ ///
+ public class Player
+ {
+ ///
+ /// It is he pseudo of the player.
+ ///
+ public string Pseudo { get; private set; }
+
+ ///
+ /// It is the profile picture of the player.
+ ///
+ public string ProfilePicture { get; private set; }
+
+ ///
+ /// It is the creation date of the player.
+ ///
+ public string? CreationDate { get; private set; }
+
+ ///
+ /// It tells when was the last time the player played.
+ ///
+ public string? LastPlayed { get; private set; }
+
+ ///
+ /// Constructor with default values.
+ ///
+ public Player()
+ {
+ Pseudo = "Player";
+ ProfilePicture = "DefaultProfilePicture";
+ }
+
+ ///
+ /// Construct a new instance of Player with specified pseudo and profile picture.
+ ///
+ /// The pseudo of the player.
+ /// The profile picture of the player.
+ public Player(string pseudo, string profilePicture = "DefaultProfilePicture")
+ {
+ Pseudo = pseudo;
+ ProfilePicture = profilePicture;
+ }
+
+ ///
+ /// Chooses the operation for the player.
+ ///
+ /// The chosen operation.
+ public Operation ChooseOperation()
+ {
+ return Operation.LOWER;
+ }
+
+ ///
+ /// Redefine the equal operation between player.
+ ///
+ /// The object to compare with the current player.
+ /// true if the specified object is equal to the current player; otherwise, false.
+ public override bool Equals(object? obj)
+ {
+ if (obj == null || GetType() != obj.GetType())
+ {
+ return false;
+ }
+ Player c = (Player)obj;
+ return (Pseudo == c.Pseudo);
+ }
+
+ ///
+ /// Returns the hash code for the current player, in order for the Equals operation to work
+ ///
+ /// The hash code for the current player.
+ public override int GetHashCode()
+ {
+ return Pseudo.GetHashCode();
+ }
+ }
+}
\ No newline at end of file
diff --git a/source/Trek-12/Models/Game/Position.cs b/source/Trek-12/Models/Game/Position.cs
new file mode 100644
index 0000000..c1b75da
--- /dev/null
+++ b/source/Trek-12/Models/Game/Position.cs
@@ -0,0 +1,30 @@
+namespace Models.Game
+{
+
+ ///
+ /// The Position (x,y) of a cell in the game.
+ ///
+ public class Position
+ {
+ ///
+ /// The X coordinate.
+ ///
+ public int X { get; set; }
+
+ ///
+ /// The Y coordinate.
+ ///
+ public int Y { get; set; }
+
+ ///
+ /// Constructor of the Position class.
+ ///
+ /// The X coordinate.
+ /// The Y coordinate.
+ public Position(int x, int y)
+ {
+ X = x;
+ Y = y;
+ }
+ }
+}
\ No newline at end of file
diff --git a/source/Trek-12/Models/Interfaces/IRules.cs b/source/Trek-12/Models/Interfaces/IRules.cs
new file mode 100644
index 0000000..1b9cb8d
--- /dev/null
+++ b/source/Trek-12/Models/Interfaces/IRules.cs
@@ -0,0 +1,128 @@
+using Models.Game;
+
+namespace Models.Interfaces
+{
+
+ ///
+ /// Interface for the rules of the game.
+ ///
+ public interface IRules
+ {
+ //public bool NearCellIsValid(Position playerChoicePosition, SortedDictionary cells);
+
+ ///
+ /// Return true if the cell is empty, otherwise false.
+ ///
+ /// The cell that the player chose
+ /// Return true if the cell is empty, otherwise false.
+ public bool IsCellEmpty(Cell playerChoice);
+
+ ///
+ /// Check if the cell is valid.
+ ///
+ /// The cell that the player chose
+ /// Boards of the actual game
+ /// true if the cell is valid; otherwise, false
+ public bool IsCellValid(Cell playerChoicePosition, List cells);
+
+ //public bool IsRopePath(Cell playerChoice, HashSet ropePaths);
+
+ //public bool IsAdjacent(Cell cell1, Cell cell2, List cells);
+
+ //public int HowMany(Cell playerChoice, List cells);
+
+ //public void SetValueAndPenalty(int valueChoice, Cell playerChoice, List cells);
+
+
+ ///
+ /// Check if the given cell is adjacent to the target cell.
+ ///
+ /// The chosen cell.
+ /// The target cell.
+ /// True if the given cell is adjacent to the target cell; otherwise false.
+ public bool IsCellAdjacent(Cell choosenCell, Cell targetCell);
+
+ ///
+ /// Check if the given cell can be played there.
+ /// If there isn't any adjacent cell with a value, or if the cell is null, it returns false.
+ ///
+ /// The chosen cell.
+ /// The list of cells.
+ /// True if the chosen cell can be played here; otherwise false.
+ public bool NearCellIsValid(Cell choosenCell, List cells);
+
+ ///
+ /// Check if the chosen cell is valid and add it to the matching zone.
+ /// If there is a nearby cell with matching value but no zone already created, it creates one
+ ///
+ /// The chosen cell.
+ /// The map.
+ ///
+ public void IsZoneValidAndAddToZones(Cell chosenCell, Map map);
+
+ ///
+ /// Check if the value of the chosen cell is in the zones of the player.
+ ///
+ /// The cell chosen by the player.
+ /// The list of the player's zones.
+ /// True if the value is in the zones; otherwise false.
+ public bool IsValueInZones(Cell chosenCell, List> zones);
+
+ ///
+ /// Check if the chosen cell is in any of the player's zones.
+ ///
+ /// The chosen cell.
+ /// The list of the player's zones.
+ /// True if the cell is in any of the zones; otherwise false.
+ public bool IsCellInZone(Cell chosenCell, List> zones);
+
+ ///
+ /// Add the chosen cell to the list of zones.
+ /// The zone must be created before.
+ ///
+ /// The chosen cell.
+ /// The list of zones.
+ public void AddToZone(Cell chosenCell, List> zones);
+
+ ///
+ /// Create a new zone with the two cells and add it to the map.
+ ///
+ /// The first cell.
+ /// The second cell.
+ /// The map.
+ public void NewZoneIsCreated(Cell firstCell, Cell secondCell, Map map);
+
+ ///
+ /// Get every adjacent cell of the chosen cell.
+ ///
+ /// The chosen cell.
+ /// The list of cells.
+ /// The list of adjacent cells.
+ public List EveryAdjacentCells(Cell choosenCell, List cells);
+
+ ///
+ /// Calculate the final score by summing up the values of all the zones.
+ ///
+ /// The list of zones.
+ /// The final score.
+ public int? FinalCalculusOfZones(List> zones);
+
+ ///
+ /// Check if the adjacent cell is in any of the rope paths.
+ ///
+ /// The adjacent cell.
+ /// The list of rope paths.
+ /// The index of the rope path.
+ /// True if the adjacent cell is in the rope path; otherwise false.
+ public bool IsInRopePaths(Cell adjacente, List> ropePaths, int index);
+
+ ///
+ /// Check if the chosen cell has the same value as the rope path at the given index.
+ ///
+ /// The chosen cell.
+ /// The list of rope paths.
+ /// The index of the rope path.
+ /// True if the chosen cell has the same value as the rope path; otherwise false.
+ public bool AsValue(Cell choosenCell, List> ropePaths, int index);
+ }
+}
\ No newline at end of file
diff --git a/source/Trek-12/Models/Models.csproj b/source/Trek-12/Models/Models.csproj
new file mode 100644
index 0000000..0119668
--- /dev/null
+++ b/source/Trek-12/Models/Models.csproj
@@ -0,0 +1,15 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
diff --git a/source/Trek-12/Models/Rules/Rules.cs b/source/Trek-12/Models/Rules/Rules.cs
new file mode 100644
index 0000000..8a7dc43
--- /dev/null
+++ b/source/Trek-12/Models/Rules/Rules.cs
@@ -0,0 +1,205 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Models.Game;
+using Models.Interfaces;
+
+namespace Models.Rules
+{
+ ///
+ /// The Rules class contains all the rules of the game. It is used to check if a move is valid or not.
+ ///
+ public class Rules : IRules
+ {
+
+ public bool IsCellEmpty(Cell playerChoice)
+ {
+ if (playerChoice == null || playerChoice.Value == null) return true;
+ return false;
+ }
+
+ public bool IsCellValid(Cell playerChoicePosition, List cells)
+ {
+ if (!IsCellEmpty(playerChoicePosition)) return false;
+
+ if (EveryAdjacentCells(playerChoicePosition, cells).Count == 1) return false;
+
+ return true;
+ }
+
+ public bool IsCellAdjacent(Cell choosenCell, Cell targetCell)
+ {
+ if (Math.Abs(choosenCell.X - targetCell.X) > 1 || Math.Abs(choosenCell.Y - targetCell.Y) > 1)
+ return false;
+ if (Math.Abs(choosenCell.X - targetCell.X) > 1 && Math.Abs(choosenCell.Y - targetCell.Y) > 1)
+ return false;
+ if (choosenCell.X == 0 && targetCell.X == 4)
+ return false;
+ if (choosenCell.Y == 0 && targetCell.Y == 4)
+ return false;
+ if (choosenCell.X == 4 && targetCell.X == 0)
+ return false;
+ if (choosenCell.Y == 4 && targetCell.Y == 0)
+ return false;
+ if (choosenCell.X == targetCell.X && choosenCell.Y == targetCell.Y)
+ return false;
+
+ return true;
+ }
+
+ public bool IsInRopePaths (Cell adjacente,List> ropePaths,int index)
+ {
+ foreach (List path in ropePaths)
+ {
+ if (path.Contains(adjacente))
+ {
+ index=ropePaths.IndexOf(path);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public bool AsValue (Cell choosenCell, List> ropePaths,int index)
+ {
+ foreach (var item in ropePaths[index])
+ {
+ if (choosenCell.Value == item.Value) return true;
+ }
+ return false;
+ }
+ public bool NearCellIsValid(Cell choosenCell, List cells)
+ {
+ if (choosenCell == null || cells == null) return false;
+
+ IEnumerable PlayedCellsQuery =
+ from cell in cells
+ where cell.Value != null
+ select cell;
+
+ foreach (var cell in PlayedCellsQuery)
+ {
+ if(!IsCellAdjacent(choosenCell, cell)) continue;
+
+ return true;
+ }
+
+ return false;
+ }
+
+ public void IsZoneValidAndAddToZones(Cell chosenCell, Map map)
+ {
+ if (chosenCell == null ||chosenCell.Value == null) return;
+
+ List adjacentCells = new List();
+
+ adjacentCells = EveryAdjacentCells(chosenCell, map.Boards);
+
+ foreach(var cells in adjacentCells)
+ {
+ if (cells.Value == chosenCell.Value)
+ {
+ if(IsValueInZones(cells, map.Zones))
+ {
+ AddToZone(chosenCell, map.Zones);
+ }
+ else
+ {
+ NewZoneIsCreated(chosenCell, cells, map);
+ }
+ //return true; // Il y a une cellule adjacente avec la même valeur donc une zone est créée si elle n'est pas déjà existante
+ // Si il return true, tout c'est bien passer
+ }
+ }
+
+ return;
+ }
+
+ public bool IsValueInZones(Cell chosenCell, List> zones)
+ {
+ if (chosenCell == null) return false;
+
+ for (int i = 0; i < zones.Count; i++)
+ {
+ if (zones[i][0].Value == chosenCell.Value)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public bool IsCellInZone(Cell chosenCell, List> zones)
+ {
+ if (chosenCell == null) return false;
+
+ for (int i = 0; i < zones.Count; i++)
+ {
+ if (zones[i].Contains(chosenCell))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void AddToZone(Cell chosenCell, List> zones)
+ {
+ if (chosenCell == null || chosenCell.Value == null) return;
+
+ if (IsCellInZone(chosenCell, zones)) return;
+
+ for (int i = 0; i < zones.Count; i++)
+ {
+ if (zones[i][0].Value == chosenCell.Value)
+ {
+ zones[i].Add(chosenCell);
+ return;
+ }
+ }
+ return;
+ }
+
+ public void NewZoneIsCreated(Cell firstCell, Cell secondCell, Map map)
+ {
+ if (firstCell == null || secondCell == null || firstCell.Value == null || secondCell.Value == null) return;
+ List newZone = new List();
+ newZone.Add(firstCell);
+ newZone.Add(secondCell);
+ map.Zones.Add(newZone);
+ }
+
+ public List EveryAdjacentCells(Cell choosenCell, List cells)
+ {
+ List adjacentCells = new List();
+
+ foreach (var cell in cells)
+ {
+ if (choosenCell == cell) continue;
+ if (IsCellAdjacent(choosenCell, cell))
+ {
+ adjacentCells.Add(cell);
+ }
+ }
+
+ return adjacentCells;
+ }
+
+ public int? FinalCalculusOfZones(List> zones)
+ {
+ int? calculus = 0;
+ for(int i = 0; i < zones.Count; i++)
+ {
+ calculus += zones[i].Count - 1 + zones[i][0].Value;
+ if (zones[i].Count > 9)
+ {
+ calculus += (zones[i].Count - 9) * 5;
+ }
+ }
+ return calculus;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/source/Trek-12/Tests/BestScoreTests.cs b/source/Trek-12/Tests/BestScoreTests.cs
new file mode 100644
index 0000000..951989c
--- /dev/null
+++ b/source/Trek-12/Tests/BestScoreTests.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Models.Game;
+
+namespace Tests
+{
+ public class BestScoreTests
+ {
+ [Fact]
+ public void Constructor_WithNegativeInputs_SetsPropertiesToZero()
+ {
+ var bestScore = new BestScore(-5, -10);
+ Assert.Equal(0, bestScore.GamesPlayed);
+ Assert.Equal(0, bestScore.Score);
+ }
+
+ [Fact]
+ public void Constructor_WithPositiveInputs_SetsPropertiesCorrectly()
+ {
+ var bestScore = new BestScore(5, 10);
+ Assert.Equal(5, bestScore.GamesPlayed);
+ Assert.Equal(10, bestScore.Score);
+ }
+
+ [Fact]
+ public void IncrGamesPlayed_IncrementsGamesPlayed()
+ {
+ var bestScore = new BestScore(0, 0);
+ bestScore.IncrGamesPlayed();
+ Assert.Equal(1, bestScore.GamesPlayed);
+ }
+
+ [Fact]
+ public void ScoreSetter_WithLowerValue_DoesNotChangeScore()
+ {
+ var bestScore = new BestScore(0, 10);
+ bestScore.UpdateScore(5);
+ Assert.Equal(10, bestScore.Score);
+ }
+
+ [Fact]
+ public void ScoreSetter_WithHigherValue_ChangesScore()
+ {
+ var bestScore = new BestScore(0, 5);
+ bestScore.UpdateScore(10);
+ Assert.Equal(10, bestScore.Score);
+ }
+ }
+}
diff --git a/source/Trek-12/Tests/CellTests.cs b/source/Trek-12/Tests/CellTests.cs
new file mode 100644
index 0000000..e967bf1
--- /dev/null
+++ b/source/Trek-12/Tests/CellTests.cs
@@ -0,0 +1,50 @@
+namespace Tests;
+using Models.Game;
+
+public class CellTests
+{
+ [Fact]
+ public void CellConstructor_SetsCorrectValues()
+ {
+ Cell cell = new Cell(1, 2, true);
+
+ Assert.Equal(1, cell.X);
+ Assert.Equal(2, cell.Y);
+ Assert.True(cell.GetCellType());
+ }
+
+ [Fact]
+ public void CellConstructor_SetsDefaultValues()
+ {
+ Cell cell = new Cell(1, 2);
+
+ Assert.Equal(1, cell.X);
+ Assert.Equal(2, cell.Y);
+ Assert.False(cell.GetCellType());
+ }
+
+ [Fact]
+ public void ValueSetter_ThrowsException_WhenValueIsNegative()
+ {
+ Cell cell = new Cell(1, 2);
+
+ Assert.Throws(() => cell.Value = -1);
+ }
+
+ [Fact]
+ public void ValueSetter_SetsValue_WhenValueIsPositive()
+ {
+ Cell cell = new Cell(1, 2);
+
+ cell.Value = 5;
+
+ Assert.Equal(5, cell.Value);
+ }
+
+ [Fact]
+ public void ValueSetter_SetsValue_WhenValueIsNull()
+ {
+ Cell cell = new Cell(1, 2);
+ Assert.Null(cell.Value);
+ }
+}
\ No newline at end of file
diff --git a/source/Trek-12/Tests/DiceTests.cs b/source/Trek-12/Tests/DiceTests.cs
new file mode 100644
index 0000000..7831db6
--- /dev/null
+++ b/source/Trek-12/Tests/DiceTests.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Models.Game;
+
+namespace Tests;
+
+public class DiceTests
+{
+ [Fact]
+ public void Constructor_WithNegativeNbMin_SetsNbMinToZero()
+ {
+ Dice dice = new Dice(-1);
+ Assert.Equal(0, dice.NbMin);
+ }
+
+ [Fact]
+ public void Constructor_WithNbMinGreaterThanOne_SetsNbMinToOne()
+ {
+ Dice dice = new Dice(2);
+ Assert.Equal(1, dice.NbMin);
+ }
+
+ [Fact]
+ public void Constructor_WithValidNbMin_SetsNbMinAndNbMaxCorrectly()
+ {
+ Dice dice = new Dice(1);
+ Assert.Equal(1, dice.NbMin);
+ Assert.Equal(6, dice.NbMax);
+ }
+
+ [Fact]
+ public void DefaultConstructor_SetsNbMinToZeroAndNbMaxToFive()
+ {
+ Dice dice = new Dice();
+ Assert.Equal(0, dice.NbMin);
+ Assert.Equal(5, dice.NbMax);
+ }
+
+ [Fact]
+ public void Roll_SetsValueBetweenNbMinAndNbMax()
+ {
+ Dice dice = new Dice();
+ dice.Roll();
+ Assert.True(dice.Value >= dice.NbMin && dice.Value <= dice.NbMax);
+ }
+}
diff --git a/source/Trek-12/Tests/GlobalUsings.cs b/source/Trek-12/Tests/GlobalUsings.cs
new file mode 100644
index 0000000..8c927eb
--- /dev/null
+++ b/source/Trek-12/Tests/GlobalUsings.cs
@@ -0,0 +1 @@
+global using Xunit;
\ No newline at end of file
diff --git a/source/Trek-12/Tests/MapTests.cs b/source/Trek-12/Tests/MapTests.cs
new file mode 100644
index 0000000..027ed94
--- /dev/null
+++ b/source/Trek-12/Tests/MapTests.cs
@@ -0,0 +1,44 @@
+using Models;
+using Models.Game;
+
+namespace Tests;
+
+public class MapTests
+{
+ [Fact]
+ public void Map_Initialization_SetsBackground()
+ {
+ string background = "test_background";
+
+ var map = new Map(background);
+
+ Assert.Equal(background, map.Background);
+ }
+
+ [Fact]
+ public void Map_Initialization_InitializesBoards()
+ {
+ string background = "test_background";
+
+ var map = new Map(background);
+
+ Assert.Equal(36, map.Boards.Count);
+ for (int i = 0; i < 36; i++)
+ {
+ Assert.Equal(new Cell(i / 6, i % 6), map.Boards[i]);
+ }
+ }
+
+ [Fact]
+ public void Map_Initialization_InitializesRopePathsAndZones()
+ {
+ string background = "test_background";
+
+ var map = new Map(background);
+
+ Assert.NotNull(map.RopePaths);
+ Assert.NotNull(map.Zones);
+ Assert.Empty(map.RopePaths);
+ Assert.Empty(map.Zones);
+ }
+}
diff --git a/source/Trek-12/Tests/OperationCellTests.cs b/source/Trek-12/Tests/OperationCellTests.cs
new file mode 100644
index 0000000..673200d
--- /dev/null
+++ b/source/Trek-12/Tests/OperationCellTests.cs
@@ -0,0 +1,27 @@
+using Models.Game;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tests
+{
+ public class OperationCellTests
+ {
+ [Fact]
+ public void Constructor_WithValidCoordinates_SetsCoordinatesCorrectly()
+ {
+ OperationCell operationCell = new OperationCell(1, 2);
+ Assert.Equal(1, operationCell.X);
+ Assert.Equal(2, operationCell.Y);
+ }
+
+ [Fact]
+ public void Constructor_WithValidCoordinates_SetsIsCheckedToFalse()
+ {
+ OperationCell operationCell = new OperationCell(1, 2);
+ Assert.False(operationCell.IsChecked);
+ }
+ }
+}
diff --git a/source/Trek-12/Tests/PlayerTests.cs b/source/Trek-12/Tests/PlayerTests.cs
new file mode 100644
index 0000000..194fa85
--- /dev/null
+++ b/source/Trek-12/Tests/PlayerTests.cs
@@ -0,0 +1,43 @@
+namespace Tests;
+using Models.Game;
+
+public class PlayerTests
+{
+ [Theory]
+ [InlineData("Player", "DefaultProfilePicture")]
+ [InlineData("John Doe", "N/A.png")]
+ public void Constructor_WithPseudoAndProfilePicture_SetsPseudoAndProfilePictureCorrectly(string pseudo, string profilePicture)
+ {
+ var player = new Player(pseudo, profilePicture);
+ Assert.Equal(pseudo, player.Pseudo);
+ Assert.Equal(profilePicture, player.ProfilePicture);
+ }
+
+ [Fact]
+ public void Constructor_WithPseudoAndWithoutProfilePicture_SetsPseudoAndDefaultProfilePicture()
+ {
+ var player = new Player("MyPlayer");
+ Assert.Equal("MyPlayer", player.Pseudo);
+ Assert.Equal("DefaultProfilePicture", player.ProfilePicture);
+ }
+
+ [Theory]
+ [InlineData("John Doe", "John Doe", true)]
+ [InlineData("John Doe", "Jane Doe", false)]
+ public void Equals_WithSameOrDifferentPseudo_ReturnsExpectedResult(string pseudo1, string pseudo2, bool expectedResult)
+ {
+ var player1 = new Player(pseudo1);
+ var player2 = new Player(pseudo2);
+ Assert.Equal(expectedResult, player1.Equals(player2));
+ }
+
+ [Theory]
+ [InlineData("John Doe", "John Doe", true)]
+ [InlineData("John Doe", "Jane Doe", false)]
+ public void GetHashCode_ReturnsSameOrDifferentHashCodeForPseudo(string pseudo1, string pseudo2, bool expectedResult)
+ {
+ var player1 = new Player(pseudo1);
+ var player2 = new Player(pseudo2);
+ Assert.Equal(expectedResult, player1.GetHashCode() == player2.GetHashCode());
+ }
+}
\ No newline at end of file
diff --git a/source/Trek-12/Tests/Tests.csproj b/source/Trek-12/Tests/Tests.csproj
new file mode 100644
index 0000000..2fea905
--- /dev/null
+++ b/source/Trek-12/Tests/Tests.csproj
@@ -0,0 +1,29 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+ false
+ true
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
diff --git a/source/Trek-12/Trek-12.sln b/source/Trek-12/Trek-12.sln
index 4dee142..23e752e 100644
--- a/source/Trek-12/Trek-12.sln
+++ b/source/Trek-12/Trek-12.sln
@@ -5,6 +5,12 @@ VisualStudioVersion = 17.8.34408.163
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Trek-12", "Trek-12\Trek-12.csproj", "{41EE7BF8-DDE6-4B00-9434-076589C0B419}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Models", "Models\Models.csproj", "{807AB723-7AD3-42DD-9DA6-7AA5B0A9AAB4}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApp", "ConsoleApp\ConsoleApp.csproj", "{795F2C88-3C43-4795-9764-E52F7330888D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{383C4215-C680-4C2E-BC7E-B62F0B164370}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -17,6 +23,18 @@ Global
{41EE7BF8-DDE6-4B00-9434-076589C0B419}.Release|Any CPU.ActiveCfg = Release|Any CPU
{41EE7BF8-DDE6-4B00-9434-076589C0B419}.Release|Any CPU.Build.0 = Release|Any CPU
{41EE7BF8-DDE6-4B00-9434-076589C0B419}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {807AB723-7AD3-42DD-9DA6-7AA5B0A9AAB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {807AB723-7AD3-42DD-9DA6-7AA5B0A9AAB4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {807AB723-7AD3-42DD-9DA6-7AA5B0A9AAB4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {807AB723-7AD3-42DD-9DA6-7AA5B0A9AAB4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {795F2C88-3C43-4795-9764-E52F7330888D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {795F2C88-3C43-4795-9764-E52F7330888D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {795F2C88-3C43-4795-9764-E52F7330888D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {795F2C88-3C43-4795-9764-E52F7330888D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {383C4215-C680-4C2E-BC7E-B62F0B164370}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {383C4215-C680-4C2E-BC7E-B62F0B164370}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {383C4215-C680-4C2E-BC7E-B62F0B164370}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {383C4215-C680-4C2E-BC7E-B62F0B164370}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/source/Trek-12/Trek-12/AppShell.xaml b/source/Trek-12/Trek-12/AppShell.xaml
index 09d5f2a..4eda938 100644
--- a/source/Trek-12/Trek-12/AppShell.xaml
+++ b/source/Trek-12/Trek-12/AppShell.xaml
@@ -6,16 +6,37 @@
xmlns:local="clr-namespace:Trek_12"
xmlns:views="clr-namespace:Trek_12.Views"
Shell.FlyoutBehavior="Flyout"
- Title="Trek_12">
+ Title="Trek_12"
+ Shell.NavBarIsVisible="False">
+ Route="MenuPrincipal" />
+
+
+
+
+
+
+
+
diff --git a/source/Trek-12/Trek-12/Resources/Images/bg_regles.jpg b/source/Trek-12/Trek-12/Resources/Images/bg_regles.jpg
new file mode 100644
index 0000000..edbea5e
Binary files /dev/null and b/source/Trek-12/Trek-12/Resources/Images/bg_regles.jpg differ
diff --git a/source/Trek-12/Trek-12/Trek-12.csproj b/source/Trek-12/Trek-12/Trek-12.csproj
index fb3ad58..51d65e3 100644
--- a/source/Trek-12/Trek-12/Trek-12.csproj
+++ b/source/Trek-12/Trek-12/Trek-12.csproj
@@ -57,6 +57,7 @@
+
@@ -66,10 +67,16 @@
PageLeaderBoard.xaml
+
+ PageProfils.xaml
+
+
+ PageRegles.xaml
+
-
+
MSBuild:Compile
diff --git a/source/Trek-12/Trek-12/Views/component/ContentLeaderBoard.xaml b/source/Trek-12/Trek-12/Views/Components/ContentLeaderBoard.xaml
similarity index 92%
rename from source/Trek-12/Trek-12/Views/component/ContentLeaderBoard.xaml
rename to source/Trek-12/Trek-12/Views/Components/ContentLeaderBoard.xaml
index abcf339..639b6f3 100644
--- a/source/Trek-12/Trek-12/Views/component/ContentLeaderBoard.xaml
+++ b/source/Trek-12/Trek-12/Views/Components/ContentLeaderBoard.xaml
@@ -1,46 +1,46 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/Trek-12/Trek-12/Views/component/ContentLeaderBoard.xaml.cs b/source/Trek-12/Trek-12/Views/Components/ContentLeaderBoard.xaml.cs
similarity index 72%
rename from source/Trek-12/Trek-12/Views/component/ContentLeaderBoard.xaml.cs
rename to source/Trek-12/Trek-12/Views/Components/ContentLeaderBoard.xaml.cs
index 28e9706..da9bf40 100644
--- a/source/Trek-12/Trek-12/Views/component/ContentLeaderBoard.xaml.cs
+++ b/source/Trek-12/Trek-12/Views/Components/ContentLeaderBoard.xaml.cs
@@ -1,9 +1,9 @@
-namespace Trek_12.Views.component;
-
-public partial class ContentLeaderBoard : ContentView
-{
- public ContentLeaderBoard()
- {
- InitializeComponent();
- }
+namespace Trek_12.Views.Components;
+
+public partial class ContentLeaderBoard : ContentView
+{
+ public ContentLeaderBoard()
+ {
+ InitializeComponent();
+ }
}
\ No newline at end of file
diff --git a/source/Trek-12/Trek-12/Views/viewsProfils.xaml b/source/Trek-12/Trek-12/Views/Components/viewsProfils.xaml
similarity index 90%
rename from source/Trek-12/Trek-12/Views/viewsProfils.xaml
rename to source/Trek-12/Trek-12/Views/Components/viewsProfils.xaml
index f0a3ca0..3b15b2c 100644
--- a/source/Trek-12/Trek-12/Views/viewsProfils.xaml
+++ b/source/Trek-12/Trek-12/Views/Components/viewsProfils.xaml
@@ -1,8 +1,7 @@
+ x:Class="Trek_12.Views.Components.viewsProfils">
-
-
-
-
-
-
+
+
+
+
+
+
| | | | | | | | | | | | | | | | | | | | | | |