programaker / joguin2 Goto Github PK
View Code? Open in Web Editor NEWToy Scala project to study some cool Functional Programming concepts (version 1 was in Java)
Toy Scala project to study some cool Functional Programming concepts (version 1 was in Java)
Related to #5. In the future we'll have multiple effects to choose, but currently the default one is cats-effect.
As ZIO is getting stronger everyday in the community (many talks, posts, related projects...), making it the default would be a good opportunity to take a look at it and practice a little.
Also, cats-effect is blocking #11 =(
Draft of the idea - https://scastie.scala-lang.org/programaker/QzbOoPCxTIuCvlXhWyUPBA/8
GameProgress.start should accept only defeated Invasions.
defeated
flag will be removed and replaced by type checking.
Put everything into InteractionF
. They are strongly related and hardly used in isolation. There will be less implicit parameters to worry about
Cats typeclasses and data types can give some ideas on refactorings: new abstractions, simplifications, functional design, etc
We are using classes to model the Free programs to have the convenience of importing all algebras at the top to make them accessible to the private helper functions, but the program is actually only a function - play().
Try to figure out a more FP design without the classes, if possible and if worths it. Sometimes itβs better to let Scala be Scala π
Writing the tests for the Game Steps that require a GameProgress made me think that this class is not so well designed - for example, Gen[GameProgress] is using GameProgress logic, which means code that need to be tested is being used as input to other tests =/
It simplifies the use of type classes and context bounds
https://github.com/augustjune/context-applied
After issue#8, GameProgress update became more complicated. Better use a Lens to focus on the experience.
def increaseMainCharacterExperience(experiencePoints: Experience): GameProgress =
refineV[ExperienceR](mainCharacter.experience.value + experiencePoints.value)
.map(updatedXp => copy(mainCharacter = mainCharacter.copy(experience = updatedXp)))
.getOrElse(this)
In the current version, errors coming from type refinement or IO are not being properly handled. The idea is:
Make all functions that can cause errors return Either[Error, A] (Refined already use Either, which makes things easier).
Create an ErrorStep, to inform the error to the player and quit the game. The message to the player should be high level, but it can provide a way to generate a low level error report to "send to the developers"
The game works well when run by sbt or IDE, but when the scripts build.sh and run.sh are used, it crashes - always when player chooses 'Fight' when asked to 'Fight or Retreat'.
When did it start? What changes caused it?
Part of issue #4. Make GameProgress a true ADT, moving all behavior to somewhere else
According to https://github.com/fthomas/refined, section "External Modules", there is a Circe integration! With that, we may not need PersistentGameProgress anymore!
Also, there is integration for ScalaCheck and many more that can be useful. Take a look!
It would be great to show how to do logs in a Free Monad approach!
Currently, the player can't quit the game whenever he/she wants, only at specific moments. Make "Quit" step accessible from any step.
It seems to be more "standard" than Wart-remover
https://scalacenter.github.io/scalafix/docs/users/installation.html
Functions to parse options, functions that do not depend on the implicit algebras... they could be moved from the Steps and go to the package.
This way, we can keep the Step classes as "namespaces containing partially-applied functions"
Now, the argument to keep the experience separated from MainCharacter is not making much sense... Let's go to a more obvious design.
[info] PersistentGameProgress_Properties:
[info] - converting a GameProgress into PersistentGameProgress and back, gives the same GameProgress as Some
[info] - converting an invalid PersistentGameProgress to GameProgress gives None *** FAILED ***
[info] TestFailedException was thrown during property evaluation.
[info] Message: Some(GameProgress(MainCharacter(,Female,43,0),Vector(),0,Set())) was not empty
[info] Location: (PersistentGameProgress_Properties.scala:83)
[info] Occurred when passed generated values (
[info] arg0 = PersistentMainCharacter(,Female,43,0), // 3 shrinks
[info] arg1 = 14, // 3 shrinks
[info] arg2 = Vector(),
[info] arg3 = 0, // 27 shrinks
[info] arg4 = List() // 2 shrinks
[info] )
Some game steps require, like, 4 different algebras to do their work, all provided via implicits. With all the ZIO buzz, what about create some "environment" and pass only it implicitly? It would help with #19
Proposed redesign:
sealed abstract class City extends Product with Serializable
object City {
final case class Free(name: Name, country: Country)
final case class Invaded(city: City.Free, terraformDevice: TerraformDevice)
}
Then, in GameProgress:
final case class GameProgress(
mainCharacter: MainCharacter,
cities: Vector[City],
defeatedInvasions: Count
)
We can remove the defeatedInvasionsTrack: Set[Index]
and replace with pattern-matching. Also, Invasion won't be necessary anymore.
Related to #4
Maintaining these parallel "persistent" types is causing more trouble than just implement the Encoders and Decoders for Circe. In the beginning it was simple and Circe deals with built-in types automatically, but then I need to change the persistent types every time GameProgress changes (and it is changing a lot).
Also (in theory) there is a 3rd-party extension circe-refined
that could help dealing with the refinements.
The "ideal" sum type should be something like:
sealed abstract class Frunfles extends Product with Serializable
final case class Foo(x: String) extends Frunfles
final case class Bar extends Frunfles
final case class Qux(y: Int) extends Frunfles
This design avoid sealed traits and always add "extends Product with Serializable".
The reasons for this are:
https://typelevel.org/blog/2018/05/09/product-with-serializable.html
and
https://stackoverflow.com/questions/35249901/scala-client-composition-with-traits-vs-implementing-an-abstract-class/35251513#35251513
It seems that Const can do exactly what our Tag is doing - a phantom type that helps disambiguate implicits of the same type.
Replace the properties files that hold the messages with conf files in HOCON syntax.
Also, replace Java's ResourceBundle with PureConfig https://github.com/pureconfig/pureconfig.
The messages could be read as Map[MessageSource#Key, String]
or we can define a proper case class for it, dunno... it would be great to use the MessageSources and Keys themselves to get the messages instead of mapping them to Strings.
It is related to #3, so don't forget the localization.
https://github.com/fthomas/refined/blob/master/modules/docs/custom_predicates.md
Message source interpreter only knows English; the locale is hardcoded. Let's add at least one more language: pt-BR of course =P
It will be fun to add a runtime parameter to choose the concrete effect when running the game. It currently only uses cats IO.
This way we can use cats.IO, ZIO, ...
See https://docs.scala-lang.org/overviews/collections/performance-characteristics.html
Vectors have effectively constant performance for operations we need (get by index, get length), while List is O(n).
This change will also eliminate the helper data structures used by GameProgress to deal with List performance issues.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.