From 72feefe65cd0ed51f9eeb4e7666c316c480c112b Mon Sep 17 00:00:00 2001
From: Oskar Marquardt <oskar.marquardt@student.uni-halle.de>
Date: Sat, 29 Jun 2024 19:46:03 +0200
Subject: [PATCH] Readded Sphere Affinity

---
 public/index.html |  15 ++++
 public/main.js    | 188 +++++++++++++++++++++++++++++++++++++++++++---
 src/Character.elm |  10 ++-
 src/Creation.elm  |   6 +-
 src/Main.elm      |  42 ++++++++++-
 src/Stats.elm     |  67 +++++++++++++++--
 6 files changed, 306 insertions(+), 22 deletions(-)

diff --git a/public/index.html b/public/index.html
index d11f072..88f6363 100644
--- a/public/index.html
+++ b/public/index.html
@@ -15,6 +15,21 @@
     crossorigin="anonymous"
   >
   <style>
+    .dropdown-content {
+      max-height: 13em;
+      overflow: auto;
+    }
+
+    .delete.is-not-delete {
+      background-color: hsla(0, 0%, 0%, 0);
+    }
+    .delete.is-not-delete::after {
+      background-color: hsla(0, 0%, 0%, 0);
+    }
+    .delete.is-not-delete::before {
+      background-color: hsla(0, 0%, 0%, 0);
+    }
+
     /* https://github.com/jgthms/bulma/issues/2055#issuecomment-438588152 */
     .dropdown.is-fullwidth {
       display: flex;
diff --git a/public/main.js b/public/main.js
index 54a2a57..217a9f2 100644
--- a/public/main.js
+++ b/public/main.js
@@ -5233,12 +5233,14 @@ var $author$project$Stats$newBackground = F2(
 			statType: $author$project$Stats$Background
 		};
 	});
-var $author$project$Stats$Sphere = {$: 'Sphere'};
+var $author$project$Stats$Sphere = function (a) {
+	return {$: 'Sphere', a: a};
+};
 var $author$project$Stats$newSphere = function (name) {
 	return {
 		dots: A3($author$project$BoundedInt$new, 0, 0, 5),
 		name: name,
-		statType: $author$project$Stats$Sphere
+		statType: $author$project$Stats$Sphere(false)
 	};
 };
 var $author$project$Stats$new = _List_fromArray(
@@ -5517,7 +5519,16 @@ var $author$project$Stats$changeDotsTo = F2(
 		return _Utils_update(
 			stat,
 			{
-				dots: A2($author$project$BoundedInt$changeTo, stat.dots, value)
+				dots: A2($author$project$BoundedInt$changeTo, stat.dots, value),
+				statType: function () {
+					var _v0 = stat.statType;
+					if (_v0.$ === 'Sphere') {
+						var affinity = _v0.a;
+						return (!value) ? $author$project$Stats$Sphere(false) : $author$project$Stats$Sphere(affinity);
+					} else {
+						return stat.statType;
+					}
+				}()
 			});
 	});
 var $author$project$Stats$isStat = F2(
@@ -5550,7 +5561,12 @@ var $author$project$Stats$dotsOfStatInList = F2(
 		}
 	});
 var $author$project$Stats$isSphere = function (stat) {
-	return _Utils_eq(stat.statType, $author$project$Stats$Sphere);
+	var _v0 = stat.statType;
+	if (_v0.$ === 'Sphere') {
+		return true;
+	} else {
+		return false;
+	}
 };
 var $author$project$Stats$spheresInList = function (stats) {
 	return A2($elm$core$List$filter, $author$project$Stats$isSphere, stats);
@@ -5617,6 +5633,53 @@ var $author$project$Main$modalValue = F2(
 	function (modalType, character) {
 		return character.name;
 	});
+var $author$project$Stats$setAffinityIfSame = F2(
+	function (sphere, stat) {
+		var _v0 = stat.statType;
+		if (_v0.$ === 'Sphere') {
+			return A2($author$project$Stats$isStat, sphere.name, stat) ? sphere : stat;
+		} else {
+			return stat;
+		}
+	});
+var $author$project$Stats$unsetAffinity = function (stat) {
+	var _v0 = stat.statType;
+	if (_v0.$ === 'Sphere') {
+		return _Utils_update(
+			stat,
+			{
+				statType: $author$project$Stats$Sphere(false)
+			});
+	} else {
+		return stat;
+	}
+};
+var $author$project$Stats$setAffinity = F2(
+	function (stats, initSphere) {
+		var sphere = (initSphere.dots.value > 0) ? initSphere : _Utils_update(
+			initSphere,
+			{
+				dots: A2($author$project$BoundedInt$changeTo, initSphere.dots, 1)
+			});
+		var _v0 = sphere.statType;
+		if (_v0.$ === 'Sphere') {
+			var affinity = _v0.a;
+			return A2(
+				$elm$core$List$map,
+				$author$project$Stats$setAffinityIfSame(sphere),
+				A2($elm$core$List$map, $author$project$Stats$unsetAffinity, stats));
+		} else {
+			return stats;
+		}
+	});
+var $author$project$Character$setAffinity = F2(
+	function (character, stat) {
+		return _Utils_update(
+			character,
+			{
+				stats: A2($author$project$Stats$setAffinity, character.stats, stat)
+			});
+	});
 var $author$project$Main$update = F2(
 	function (msg, model) {
 		switch (msg.$) {
@@ -5676,13 +5739,22 @@ var $author$project$Main$update = F2(
 							dropdownActive: false
 						}),
 					$elm$core$Platform$Cmd$none);
-			default:
+			case 'SetDropDownActive':
 				var value = msg.a;
 				return _Utils_Tuple2(
 					_Utils_update(
 						model,
 						{dropdownActive: value}),
 					$elm$core$Platform$Cmd$none);
+			default:
+				var stat = msg.a;
+				return _Utils_Tuple2(
+					_Utils_update(
+						model,
+						{
+							character: A2($author$project$Character$setAffinity, model.character, stat)
+						}),
+					$elm$core$Platform$Cmd$none);
 		}
 	});
 var $author$project$Main$Name = {$: 'Name'};
@@ -6819,6 +6891,32 @@ var $author$project$Main$viewModal = function (model) {
 				]));
 	}
 };
+var $elm$core$Basics$neq = _Utils_notEqual;
+var $author$project$Stats$hasSetAffinity = function (spheres) {
+	var affinityCount = $elm$core$List$length(
+		A2(
+			$elm$core$List$filter,
+			function (x) {
+				return _Utils_eq(
+					x.statType,
+					$author$project$Stats$Sphere(true));
+			},
+			spheres));
+	return !(!affinityCount);
+};
+var $author$project$Main$affinityWarning = function (spheres) {
+	var hasSetAffinity = $author$project$Stats$hasSetAffinity(spheres);
+	return hasSetAffinity ? A2($elm$html$Html$div, _List_Nil, _List_Nil) : A2(
+		$elm$html$Html$div,
+		_List_fromArray(
+			[
+				$elm$html$Html$Attributes$class('notification is-danger')
+			]),
+		_List_fromArray(
+			[
+				$elm$html$Html$text('Affinity Sphere not set')
+			]));
+};
 var $author$project$Stats$everyThirdStat = F2(
 	function (stats, offset) {
 		return A2(
@@ -6831,6 +6929,77 @@ var $author$project$Stats$everyThirdStat = F2(
 				},
 				A2($elm$core$List$indexedMap, $elm$core$Tuple$pair, stats)));
 	});
+var $author$project$Main$SetAffinity = function (a) {
+	return {$: 'SetAffinity', a: a};
+};
+var $author$project$Main$viewSphere = function (stat) {
+	return A2(
+		$elm$html$Html$div,
+		_List_fromArray(
+			[
+				$elm$html$Html$Attributes$class('notification')
+			]),
+		_List_fromArray(
+			[
+				A2(
+				$elm$html$Html$p,
+				_List_fromArray(
+					[
+						$elm$html$Html$Attributes$class('delete is-not-delete icon corner'),
+						$elm$html$Html$Events$onClick(
+						$author$project$Main$SetAffinity(
+							_Utils_update(
+								stat,
+								{
+									statType: $author$project$Stats$Sphere(true)
+								})))
+					]),
+				_List_fromArray(
+					[
+						function () {
+						var _v0 = stat.statType;
+						if (_v0.$ === 'Sphere') {
+							var affinity = _v0.a;
+							return affinity ? A2(
+								$elm$html$Html$i,
+								_List_fromArray(
+									[
+										$elm$html$Html$Attributes$class('fas fa-star')
+									]),
+								_List_Nil) : A2(
+								$elm$html$Html$i,
+								_List_fromArray(
+									[
+										$elm$html$Html$Attributes$class('far fa-star')
+									]),
+								_List_Nil);
+						} else {
+							return A2($elm$html$Html$i, _List_Nil, _List_Nil);
+						}
+					}()
+					])),
+				A2(
+				$elm$html$Html$p,
+				_List_fromArray(
+					[
+						$elm$html$Html$Attributes$class('block')
+					]),
+				_List_fromArray(
+					[
+						$elm$html$Html$text(stat.name)
+					])),
+				A2(
+				$elm$html$Html$p,
+				_List_fromArray(
+					[
+						$elm$html$Html$Attributes$class('block')
+					]),
+				_List_fromArray(
+					[
+						$author$project$Main$viewDots(stat)
+					]))
+			]));
+};
 var $author$project$Main$viewSpheres = F2(
 	function (cp, spheres) {
 		var basePoints = cp.spheres;
@@ -6866,7 +7035,8 @@ var $author$project$Main$viewSpheres = F2(
 								]),
 							_List_fromArray(
 								[
-									$author$project$Main$creationInfo(points)
+									$author$project$Main$creationInfo(points),
+									$author$project$Main$affinityWarning(spheres)
 								]))
 						])),
 					A2(
@@ -6885,7 +7055,7 @@ var $author$project$Main$viewSpheres = F2(
 								]),
 							A2(
 								$elm$core$List$map,
-								$author$project$Main$viewStat,
+								$author$project$Main$viewSphere,
 								A2($author$project$Stats$everyThirdStat, spheres, 0))),
 							A2(
 							$elm$html$Html$div,
@@ -6895,7 +7065,7 @@ var $author$project$Main$viewSpheres = F2(
 								]),
 							A2(
 								$elm$core$List$map,
-								$author$project$Main$viewStat,
+								$author$project$Main$viewSphere,
 								A2($author$project$Stats$everyThirdStat, spheres, 1))),
 							A2(
 							$elm$html$Html$div,
@@ -6905,7 +7075,7 @@ var $author$project$Main$viewSpheres = F2(
 								]),
 							A2(
 								$elm$core$List$map,
-								$author$project$Main$viewStat,
+								$author$project$Main$viewSphere,
 								A2($author$project$Stats$everyThirdStat, spheres, 2)))
 						]))
 				]));
diff --git a/src/Character.elm b/src/Character.elm
index c69287a..d9805fb 100644
--- a/src/Character.elm
+++ b/src/Character.elm
@@ -35,7 +35,7 @@ changeStat character stat =
             let
                 stats : List Stat
                 stats = case statType of 
-                    Stats.Sphere -> Stats.spheresInList character.stats
+                    Stats.Sphere _ -> Stats.spheresInList character.stats
                     Stats.Attribute _ -> Stats.attributesInList character.stats
                     Stats.Ability _ -> Stats.abilitiesInList character.stats
                     Stats.Background -> Stats.backgroundsInList character.stats
@@ -43,7 +43,7 @@ changeStat character stat =
                 
                 max : Int
                 max = case statType of
-                    Stats.Sphere -> ( Stats.areteInList character.stats ).dots.value
+                    Stats.Sphere _ -> ( Stats.areteInList character.stats ).dots.value
                     Stats.Attribute _ -> stat.dots.max
                     Stats.Ability _ -> character.creationPoints.abilityDotLimit
                     Stats.Background -> stat.dots.max
@@ -70,4 +70,10 @@ changeOrder : Character -> CategoriesType -> Category -> Int -> Character
 changeOrder character catType category value =
     { character
     | creationPoints = Creation.changeOrder character.creationPoints catType category value 
+    }
+
+setAffinity : Character -> Stat -> Character
+setAffinity character stat =
+    { character
+    | stats = Stats.setAffinity character.stats stat
     }
\ No newline at end of file
diff --git a/src/Creation.elm b/src/Creation.elm
index a170ddd..70b12de 100644
--- a/src/Creation.elm
+++ b/src/Creation.elm
@@ -1,6 +1,6 @@
 module Creation exposing (..)
 
-import OrderedCategories as OCat exposing (OCat, CategoriesType)
+import OrderedCategories as OCat exposing (OCat, CategoriesType(..))
 import Stats exposing (Category)
 
 type alias CreationPoints =
@@ -32,11 +32,11 @@ cost =
 changeOrder : CreationPoints -> CategoriesType -> Category -> Int -> CreationPoints
 changeOrder cp catType category index =
     case catType of
-        OCat.Attribute ->
+        Attribute ->
             { cp 
             | attributes = OCat.changeOrder cp.attributes category index
             }
-        OCat.Ability -> 
+        Ability -> 
             { cp 
             | abilities = OCat.changeOrder cp.abilities category index
             }
\ No newline at end of file
diff --git a/src/Main.elm b/src/Main.elm
index 39c1d63..1fe1c3d 100644
--- a/src/Main.elm
+++ b/src/Main.elm
@@ -47,6 +47,7 @@ type Msg
     | ChangeStat Stat
     | ChangePriority CategoriesType Category Int
     | SetDropDownActive Bool
+    | SetAffinity Stat
 
 type ModalType
     = Name
@@ -99,6 +100,12 @@ update msg model =
                 }
             , Cmd.none
             )
+        SetAffinity stat ->
+            (   { model
+                | character = Character.setAffinity model.character stat
+                }
+            , Cmd.none
+            )
 
 view : Model -> Browser.Document Msg
 view model =
@@ -351,21 +358,50 @@ viewSpheres cp spheres =
             , div [ class "columns is-centered is-mobile" ]
                 [ div [ class "column is-three-fifths" ]
                     [ creationInfo points
+                    , affinityWarning spheres
                     ]
                 ]
             , div [ class "columns is-centered is-mobile" ]
                 [ div [ class "column is-one-fifth" ] 
-                    ( List.map viewStat ( Stats.everyThirdStat spheres 0 )
+                    ( List.map viewSphere ( Stats.everyThirdStat spheres 0 )
                     )
                 , div [ class "column is-one-fifth" ] 
-                    ( List.map viewStat ( Stats.everyThirdStat spheres 1 )
+                    ( List.map viewSphere ( Stats.everyThirdStat spheres 1 )
                     )
                 , div [ class "column is-one-fifth" ] 
-                    ( List.map viewStat ( Stats.everyThirdStat spheres 2 )
+                    ( List.map viewSphere ( Stats.everyThirdStat spheres 2 )
                     )
                 ]
             ]
 
+viewSphere : Stat -> Html Msg
+viewSphere stat =
+    div [ class "notification" ]
+        [ p 
+            [ class "delete is-not-delete icon corner"
+            , onClick ( SetAffinity { stat | statType = Stats.Sphere True } )
+            ] 
+            [ case stat.statType of
+                Stats.Sphere affinity ->
+                    if affinity 
+                    then i [ class "fas fa-star" ] []
+                    else i [ class "far fa-star" ] []
+                _ -> i [] []
+            ]
+        , p [ class "block" ] [ text stat.name ]
+        , p [ class "block" ] [ viewDots stat ]
+        ]
+
+affinityWarning : List Stat -> Html Msg
+affinityWarning spheres = 
+    let
+        hasSetAffinity : Bool
+        hasSetAffinity = Stats.hasSetAffinity spheres
+    in
+        if hasSetAffinity
+        then div [] []
+        else div [ class "notification is-danger" ] [ text "Affinity Sphere not set" ]
+
 creationInfo : Int -> Html Msg
 creationInfo points = 
     let
diff --git a/src/Stats.elm b/src/Stats.elm
index 35e6cd6..250397a 100644
--- a/src/Stats.elm
+++ b/src/Stats.elm
@@ -1,6 +1,7 @@
 module Stats exposing (..)
 
 import BoundedInt exposing (BoundedInt)
+import Svg.Attributes exposing (in_)
 
 type alias Stat =
     { name : String
@@ -9,7 +10,7 @@ type alias Stat =
     }
 
 type StatType
-    = Sphere
+    = Sphere Bool
     | Arete
     | Attribute Category
     | Ability Category
@@ -117,7 +118,7 @@ newSphere : String -> Stat
 newSphere name =
     { name = name
     , dots = BoundedInt.new 0 0 5
-    , statType = Sphere
+    , statType = Sphere False
     }
 
 newArete : Stat
@@ -154,7 +155,13 @@ spheresInList stats =
 
 isSphere : Stat -> Bool
 isSphere stat =
-    stat.statType == Sphere
+    case stat.statType of
+        Sphere _ -> True
+        _ -> False
+    
+isAffinitySphere : Stat -> Bool
+isAffinitySphere sphere =
+    sphere.statType == Sphere True
 
 areteInList : List Stat -> Stat
 areteInList stats =
@@ -244,7 +251,15 @@ changeStatIfSame newStat oldStat =
 
 changeDotsTo : Stat -> Int -> Stat
 changeDotsTo stat value =
-    { stat | dots = BoundedInt.changeTo stat.dots value }
+    { stat 
+    | dots = BoundedInt.changeTo stat.dots value
+    , statType = case stat.statType of
+        Sphere affinity ->
+            if value == 0
+            then Sphere False
+            else Sphere affinity
+        _ -> stat.statType
+    }
 
 everyThirdStat : List Stat -> Int -> List Stat
 everyThirdStat stats offset =
@@ -262,4 +277,46 @@ count stats =
 
 splitZero : List Stat -> ( List Stat, List Stat )
 splitZero stats =
-    List.partition ( \x -> x.dots.value > 0 ) stats
\ No newline at end of file
+    List.partition ( \x -> x.dots.value > 0 ) stats
+
+setAffinity : List Stat -> Stat -> List Stat
+setAffinity stats initSphere =
+    let
+        sphere : Stat
+        sphere =
+            if initSphere.dots.value > 0
+            then initSphere
+            else { initSphere | dots = BoundedInt.changeTo initSphere.dots 1 }
+    in
+        case sphere.statType of
+            Sphere affinity ->
+                stats
+                |> List.map unsetAffinity
+                |> List.map ( setAffinityIfSame sphere )
+            _ -> stats
+
+unsetAffinity : Stat -> Stat
+unsetAffinity stat =
+    case stat.statType of
+        Sphere _ -> { stat | statType = Sphere False }
+        _ -> stat
+
+setAffinityIfSame : Stat -> Stat -> Stat
+setAffinityIfSame sphere stat =
+    case stat.statType of
+        Sphere _ ->
+            if isStat sphere.name stat
+            then sphere
+            else stat
+        _ -> stat
+
+hasSetAffinity : List Stat -> Bool
+hasSetAffinity spheres =
+    let 
+        affinityCount : Int
+        affinityCount =
+            spheres
+            |> List.filter ( \x -> x.statType == Sphere True )
+            |> List.length
+    in 
+        affinityCount /= 0
\ No newline at end of file
-- 
GitLab