Skip to content
This repository was archived by the owner on Mar 27, 2025. It is now read-only.

Integrate feedback from workshop session #102

Merged
merged 28 commits into from
May 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
e775c43
Duplicate all exercises for refactoring/rearrangement
eloots Mar 14, 2023
1c199cf
Revert exercise on toplevel definitions to no-indentation based syntax
eloots Mar 14, 2023
8453f12
When switching to parameter untupling use parens instead of curly braces
eloots Mar 14, 2023
b1cdd59
Revert to curly braces syntax
eloots Mar 15, 2023
6d19c8b
Format code with scalafmt
eloots Mar 15, 2023
abd0353
Format code using scalafmt
eloots Mar 15, 2023
4f7c7d2
Format all exercises with scalafmt
eloots Mar 15, 2023
44418c7
Add a note about scalafmt configuration in the exercise instructions
eloots Mar 15, 2023
fccc88a
Add illustrations about markdown config & add instructions
eloots Mar 15, 2023
1d056c4
Add notes about code formatting & markdown previewing to instructions
eloots Mar 15, 2023
33f2249
Rename exercise
eloots Mar 15, 2023
d0e2f59
Add an exercise on indentation based syntax
eloots Mar 15, 2023
2ec43b1
Add links in the exercise instruction to Scala documentation
eloots Mar 15, 2023
8d76678
Add checking of formatting code to CI
eloots Mar 15, 2023
406fcbb
Remove comment that is no longer applicable
eloots Mar 16, 2023
a1d3129
Update readme/remove unused variable
eloots Mar 16, 2023
9076898
Update exercises/exercise_000_sudoku_solver_initial_state/README.md
eloots Mar 28, 2023
eec7d68
Change variable name to Camel Case
eloots Mar 28, 2023
5d7bffb
Bump scalafmt version & reformat all code
eloots Mar 28, 2023
1d1a00b
Change variable name in build definition
eloots Mar 28, 2023
e532bbd
Change formatting of coonfiguration file
eloots Mar 28, 2023
ec6c948
Moved import around
eloots Mar 28, 2023
f0fdf39
Update exercise instructions for the syntax rewrite exercise
eloots May 9, 2023
fd13d3e
Remove alternative exercise series that uses Curly Braces syntax
eloots May 9, 2023
9f51d9a
Add IDE set-up instructions
eloots May 9, 2023
e493df6
Update exercises/exercise_000_sudoku_solver_initial_state/IDE_setup.md
eloots May 9, 2023
231e64f
Review comment updates
eloots May 9, 2023
f46f083
Update Scala version to nightly build
eloots May 9, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,14 @@ jobs:
cache: 'sbt'
distribution: 'temurin'

- name: Check code formatting
run: sbt scalafmtCheckAll
working-directory: ${{env.EXERCISES_DIRECTORY}}/${{matrix.exercise}}

- name: Test with sbt
run: sbt test
working-directory: ${{env.EXERCISES_DIRECTORY}}/${{matrix.exercise}}

validate_course_summary:
if: ${{ always() }}
runs-on: ubuntu-latest
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ project/plugins/project/
*.sublime-workspace

# OS specific
.DS_Store
**/.DS_Store
**/__MACOSX

# Other
Preci*.pdf
51 changes: 51 additions & 0 deletions exercises/exercise_000_sudoku_solver_initial_state/.scalafmt.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
version = 3.7.2
runner.dialect = scala213

style = defaultWithAlign
indentOperator.preset = akka
maxColumn = 120
rewrite.rules = [RedundantParens, AvoidInfix]
align.tokens = [{code = "=>", owner = "Case"}]
align.openParenDefnSite = false
align.openParenCallSite = false
optIn.breakChainOnFirstMethodDot = false
optIn.configStyleArguments = false
danglingParentheses.defnSite = false
danglingParentheses.callSite = false
rewrite.neverInfix.excludeFilters = [
and
min
max
until
to
by
eq
ne
"should.*"
"contain.*"
"must.*"
in
ignore
be
taggedAs
thrownBy
synchronized
have
when
size
only
noneOf
oneElementOf
noElementsOf
atLeastOneElementOf
atMostOneElementOf
allElementsOf
inOrderElementsOf
theSameElementsAs
message
]
rewriteTokens = {
"⇒": "=>"
"→": "->"
"←": "<-"
}
19 changes: 19 additions & 0 deletions exercises/exercise_000_sudoku_solver_initial_state/IDE_setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Setting up IntelliJ Idea or Visual Code Studio for Scala development

## Setting up IntelliJ Idea for Scala development

- If you haven't already installed the IntelliJ Idea, follow the [Getting started](https://www.jetbrains.com/help/idea/installation-guide.html) instructions on the JetBrains website. The Community Edition should be sufficient for this workshop.

- After installing the IDE, install the Scala plugin for IntelliJ Idea by following [these instructions](https://www.jetbrains.com/help/idea/discover-intellij-idea-for-scala.html#scala_plugin).

## Setting up Visual Code Studio for Scala development

- Download the installation binary for your system (Windows, Mac, Linux) [here](https://code.visualstudio.com/download).

- Follow the set-up instructions [here](https://code.visualstudio.com/docs/setup/setup-overview).

- Install the Metals (a Scala language server with rich IDE features) plugin for Visual Code Studio by following the instructions [here](https://scalameta.org/metals/docs/editors/vscode/)

## Other Scala source editors

There are plenty of other options for Source Code editing. For example, Metals supports Vim, Sublime Text and Emacs. For more information, have a look at the [Text Editors section](https://scalameta.org/metals/docs) in the Metals Documentation
39 changes: 39 additions & 0 deletions exercises/exercise_000_sudoku_solver_initial_state/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# Initial State

## Documentation

You may want to have look at the [Scala Language website](https://www3.scala-lang.org)
and bookmark it in your favourite browser.

It has a number of links among which:

- The [Scala 3 Language Reference](https://docs3.scala-lang.org/scala3/reference).
- The [Scala API documentation](https://docs3.scala-lang.org/api/all.html) for every version of Scala.
- The [Scala 3 Book](https://docs3.scala-lang.org/scala3/book/introduction.html) which
gives you a concise introduction to all things Scala 3.

## An Akka Typed/Scala based Sudoku Solver

## Background
Expand Down Expand Up @@ -123,3 +135,30 @@ Hit RETURN to stop solver
- You can control the rate at which the Sudoku problem generator sends
problems by tweaking the setting `sudoku-solver.problem-sender.send-interval`
in the `sudokusolver.conf` configuration file.

## Source code formatting & Markdown viewer in IntelliJ


### Source code formatting

[scalafmt](https://github.com/scalameta/scalafmt) based source code formatting is
in place in this project. scalafmt supports both Scala 2 and Scala 3. You can
[re]format the code by running `scalafmtAll` from the sbt prompt. As we switch from
Scala 2 to Scala 3, you need to make sure that a matching scalafmt configuration is
in place. In any of the exercises, you can run `cmtc pull-template .scalafmt.conf`
to "pull-in" the correct configuration file.

### Markdown viewer in IntelliJ IDEA

The font size can be a bit too small for the taste of some people. You can change the
Markdown zoom setting in IntelliJ by pasting the following CSS snippet in the
markdown setting in _" Settings" -> "Languages & Frameworks" -> "Custom CSS -> CSS rules"_ and adjust the font-size setting to your liking:

```
body {
font-size: 120% !important;
}
```

![IntelliJ Markdown viewer settings](images/Markdown-viewer-IntelliJ.png)

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ object CompileOptions {
)
}

object Version {
object Versions {
lazy val akkaVer = "2.6.20"
lazy val logbackVer = "1.2.3"
lazy val mUnitVer = "0.7.26"
Expand All @@ -26,18 +26,18 @@ object Dependencies {
"com.typesafe.akka" %% "akka-actor-typed",
"com.typesafe.akka" %% "akka-slf4j",
"com.typesafe.akka" %% "akka-stream",
).map (_ % Version.akkaVer)
).map (_ % Versions.akkaVer)

private lazy val akkaTestkitDeps = Seq(
"com.typesafe.akka" %% "akka-actor-testkit-typed" % Version.akkaVer % Test
"com.typesafe.akka" %% "akka-actor-testkit-typed" % Versions.akkaVer % Test
)

private lazy val logbackDeps = Seq (
"ch.qos.logback" % "logback-classic",
).map (_ % Version.logbackVer)
).map (_ % Versions.logbackVer)

private lazy val munitDeps = Seq(
"org.scalameta" %% "munit" % Version.mUnitVer % Test
"org.scalameta" %% "munit" % Versions.mUnitVer % Test
)

lazy val dependencies: Seq[ModuleID] =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.11.0")
addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.3.7")
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.0")
addSbtPlugin("org.scalameta" % "sbt-native-image" % "0.3.1")
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
akka {

log-dead-letters = on
logger-startup-timeout = 30s

actor {
provider = local

debug {
lifecycle = on
unhandled = on
}
}

remote {

artery {
canonical {
hostname = "127.0.0.1"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,27 @@
/**
* Copyright © 2020-2023 Lunatech Labs.
/** Copyright © 2020-2023 Lunatech Labs.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* NO COMMERCIAL SUPPORT OR ANY OTHER FORM OF SUPPORT IS OFFERED ON
* THIS SOFTWARE BY Lunatech Labs.
* NO COMMERCIAL SUPPORT OR ANY OTHER FORM OF SUPPORT IS OFFERED ON THIS SOFTWARE BY Lunatech Labs.
*
* See the License for the specific language governing permissions and
* limitations under the License.
* See the License for the specific language governing permissions and limitations under the License.
*/

package org.lunatechlabs.dotty

import akka.NotUsed
import akka.actor.typed.scaladsl.adapter.TypedActorSystemOps
import akka.actor.typed.scaladsl.{ Behaviors, Routers }
import akka.actor.typed.{ ActorSystem, Behavior, Terminated }
import org.lunatechlabs.dotty.sudoku.{ SudokuProblemSender, SudokuSolver, SudokuSolverSettings }
import akka.actor.typed.scaladsl.{Behaviors, Routers}
import akka.actor.typed.{ActorSystem, Behavior, Terminated}
import org.lunatechlabs.dotty.sudoku.{SudokuProblemSender, SudokuSolver, SudokuSolverSettings}

import scala.Console.{ GREEN, RESET }
import scala.Console.{GREEN, RESET}
import scala.io.StdIn

object Main {
Expand All @@ -36,13 +31,10 @@ object Main {
// Start a SudokuSolver
val sudokuSolver = context.spawn(SudokuSolver(sudokuSolverSettings), s"sudoku-solver")
// Start a Sudoku problem sender
context.spawn(SudokuProblemSender(sudokuSolver, sudokuSolverSettings),
"sudoku-problem-sender"
)
context.spawn(SudokuProblemSender(sudokuSolver, sudokuSolverSettings), "sudoku-problem-sender")

Behaviors.receiveSignal {
case (_, Terminated(_)) =>
Behaviors.stopped
Behaviors.receiveSignal { case (_, Terminated(_)) =>
Behaviors.stopped
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,44 +4,39 @@ object ReductionRules {

def reductionRuleOne(reductionSet: ReductionSet): ReductionSet = {
val inputCellsGrouped = reductionSet.filter(_.size <= 7).groupBy(identity)
val completeInputCellGroups = inputCellsGrouped.filter {
case (set, setOccurrences) => set.size == setOccurrences.length
val completeInputCellGroups = inputCellsGrouped.filter { case (set, setOccurrences) =>
set.size == setOccurrences.length
}
val completeAndIsolatedValueSets = completeInputCellGroups.keys.toList
completeAndIsolatedValueSets.foldLeft(reductionSet) {
case (cells, caivSet) =>
cells.map { cell =>
if (cell != caivSet) cell &~ caivSet else cell
}
completeAndIsolatedValueSets.foldLeft(reductionSet) { case (cells, caivSet) =>
cells.map { cell =>
if (cell != caivSet) cell &~ caivSet else cell
}
}
}

def reductionRuleTwo(reductionSet: ReductionSet): ReductionSet = {
val valueOccurrences = CELLPossibleValues.map { value =>
cellIndexesVector.zip(reductionSet).foldLeft(Vector.empty[Int]) {
case (acc, (index, cell)) =>
if (cell contains value) index +: acc else acc
val valueOccurrences = CellPossibleValues.map { value =>
cellIndexesVector.zip(reductionSet).foldLeft(Vector.empty[Int]) { case (acc, (index, cell)) =>
if (cell contains value) index +: acc else acc
}
}

val cellIndexesToValues =
CELLPossibleValues
.zip(valueOccurrences)
.groupBy { case (value, occurrence) => occurrence }
.filter { case (loc, occ) => loc.length == occ.length && loc.length <= 6 }
CellPossibleValues.zip(valueOccurrences).groupBy { case (value, occurrence) => occurrence }.filter {
case (loc, occ) => loc.length == occ.length && loc.length <= 6
}

val cellIndexListToReducedValue = cellIndexesToValues.map {
case (index, seq) => (index, (seq.map { case (value, _) => value }).toSet)
val cellIndexListToReducedValue = cellIndexesToValues.map { case (index, seq) =>
(index, seq.map { case (value, _) => value }.toSet)
}

val cellIndexToReducedValue = cellIndexListToReducedValue.flatMap {
case (cellIndexList, reducedValue) =>
cellIndexList.map(cellIndex => cellIndex -> reducedValue)
val cellIndexToReducedValue = cellIndexListToReducedValue.flatMap { case (cellIndexList, reducedValue) =>
cellIndexList.map(cellIndex => cellIndex -> reducedValue)
}

reductionSet.zipWithIndex.foldRight(Vector.empty[CellContent]) {
case ((cellValue, cellIndex), acc) =>
cellIndexToReducedValue.getOrElse(cellIndex, cellValue) +: acc
reductionSet.zipWithIndex.foldRight(Vector.empty[CellContent]) { case ((cellValue, cellIndex), acc) =>
cellIndexToReducedValue.getOrElse(cellIndex, cellValue) +: acc
}
}
}
Loading