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

Commit cb82b0a

Browse files
elootsgianick
andauthored
Integrate feedback from workshop session (#102)
* Duplicate all exercises for refactoring/rearrangement * Revert exercise on toplevel definitions to no-indentation based syntax * When switching to parameter untupling use parens instead of curly braces * Revert to curly braces syntax * Format code with scalafmt * Format code using scalafmt * Format all exercises with scalafmt * Add a note about scalafmt configuration in the exercise instructions * Add illustrations about markdown config & add instructions * Add notes about code formatting & markdown previewing to instructions * Rename exercise * Add an exercise on indentation based syntax * Add links in the exercise instruction to Scala documentation - Links to: - Scala 3 Language Reference - Scala API docs - Scala 3 Book * Add checking of formatting code to CI * Remove comment that is no longer applicable * Update readme/remove unused variable * Update exercises/exercise_000_sudoku_solver_initial_state/README.md Co-authored-by: gianick <[email protected]> * Change variable name to Camel Case * Bump scalafmt version & reformat all code - Bump scalafmt version & scalafmt sbt plugin version - Run scalafmt on all exercises * Change variable name in build definition * Change formatting of coonfiguration file * Moved import around * Update exercise instructions for the syntax rewrite exercise * Remove alternative exercise series that uses Curly Braces syntax * Add IDE set-up instructions * Update exercises/exercise_000_sudoku_solver_initial_state/IDE_setup.md Co-authored-by: gianick <[email protected]> * Review comment updates * Update Scala version to nightly build - Scala 3.3.1-RC1 nightly build has fix for rewrite to curly braces syntax. This fix may still make it in 3.3.0 --------- Co-authored-by: gianick <[email protected]>
1 parent 73a812d commit cb82b0a

File tree

278 files changed

+6356
-5781
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

278 files changed

+6356
-5781
lines changed

.github/workflows/ci.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,14 @@ jobs:
5252
cache: 'sbt'
5353
distribution: 'temurin'
5454

55+
- name: Check code formatting
56+
run: sbt scalafmtCheckAll
57+
working-directory: ${{env.EXERCISES_DIRECTORY}}/${{matrix.exercise}}
58+
5559
- name: Test with sbt
5660
run: sbt test
5761
working-directory: ${{env.EXERCISES_DIRECTORY}}/${{matrix.exercise}}
62+
5863
validate_course_summary:
5964
if: ${{ always() }}
6065
runs-on: ubuntu-latest

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ project/plugins/project/
4848
*.sublime-workspace
4949

5050
# OS specific
51-
.DS_Store
51+
**/.DS_Store
52+
**/__MACOSX
5253

5354
# Other
5455
Preci*.pdf
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
version = 3.7.2
2+
runner.dialect = scala213
3+
4+
style = defaultWithAlign
5+
indentOperator.preset = akka
6+
maxColumn = 120
7+
rewrite.rules = [RedundantParens, AvoidInfix]
8+
align.tokens = [{code = "=>", owner = "Case"}]
9+
align.openParenDefnSite = false
10+
align.openParenCallSite = false
11+
optIn.breakChainOnFirstMethodDot = false
12+
optIn.configStyleArguments = false
13+
danglingParentheses.defnSite = false
14+
danglingParentheses.callSite = false
15+
rewrite.neverInfix.excludeFilters = [
16+
and
17+
min
18+
max
19+
until
20+
to
21+
by
22+
eq
23+
ne
24+
"should.*"
25+
"contain.*"
26+
"must.*"
27+
in
28+
ignore
29+
be
30+
taggedAs
31+
thrownBy
32+
synchronized
33+
have
34+
when
35+
size
36+
only
37+
noneOf
38+
oneElementOf
39+
noElementsOf
40+
atLeastOneElementOf
41+
atMostOneElementOf
42+
allElementsOf
43+
inOrderElementsOf
44+
theSameElementsAs
45+
message
46+
]
47+
rewriteTokens = {
48+
"⇒": "=>"
49+
"→": "->"
50+
"←": "<-"
51+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Setting up IntelliJ Idea or Visual Code Studio for Scala development
2+
3+
## Setting up IntelliJ Idea for Scala development
4+
5+
- 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.
6+
7+
- 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).
8+
9+
## Setting up Visual Code Studio for Scala development
10+
11+
- Download the installation binary for your system (Windows, Mac, Linux) [here](https://code.visualstudio.com/download).
12+
13+
- Follow the set-up instructions [here](https://code.visualstudio.com/docs/setup/setup-overview).
14+
15+
- 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/)
16+
17+
## Other Scala source editors
18+
19+
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

exercises/exercise_000_sudoku_solver_initial_state/README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
# Initial State
22

3+
## Documentation
4+
5+
You may want to have look at the [Scala Language website](https://www3.scala-lang.org)
6+
and bookmark it in your favourite browser.
7+
8+
It has a number of links among which:
9+
10+
- The [Scala 3 Language Reference](https://docs3.scala-lang.org/scala3/reference).
11+
- The [Scala API documentation](https://docs3.scala-lang.org/api/all.html) for every version of Scala.
12+
- The [Scala 3 Book](https://docs3.scala-lang.org/scala3/book/introduction.html) which
13+
gives you a concise introduction to all things Scala 3.
14+
315
## An Akka Typed/Scala based Sudoku Solver
416

517
## Background
@@ -123,3 +135,30 @@ Hit RETURN to stop solver
123135
- You can control the rate at which the Sudoku problem generator sends
124136
problems by tweaking the setting `sudoku-solver.problem-sender.send-interval`
125137
in the `sudokusolver.conf` configuration file.
138+
139+
## Source code formatting & Markdown viewer in IntelliJ
140+
141+
142+
### Source code formatting
143+
144+
[scalafmt](https://github.com/scalameta/scalafmt) based source code formatting is
145+
in place in this project. scalafmt supports both Scala 2 and Scala 3. You can
146+
[re]format the code by running `scalafmtAll` from the sbt prompt. As we switch from
147+
Scala 2 to Scala 3, you need to make sure that a matching scalafmt configuration is
148+
in place. In any of the exercises, you can run `cmtc pull-template .scalafmt.conf`
149+
to "pull-in" the correct configuration file.
150+
151+
### Markdown viewer in IntelliJ IDEA
152+
153+
The font size can be a bit too small for the taste of some people. You can change the
154+
Markdown zoom setting in IntelliJ by pasting the following CSS snippet in the
155+
markdown setting in _" Settings" -> "Languages & Frameworks" -> "Custom CSS -> CSS rules"_ and adjust the font-size setting to your liking:
156+
157+
```
158+
body {
159+
font-size: 120% !important;
160+
}
161+
```
162+
163+
![IntelliJ Markdown viewer settings](images/Markdown-viewer-IntelliJ.png)
164+
Loading

exercises/exercise_000_sudoku_solver_initial_state/project/Build.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ object CompileOptions {
1414
)
1515
}
1616

17-
object Version {
17+
object Versions {
1818
lazy val akkaVer = "2.6.20"
1919
lazy val logbackVer = "1.2.3"
2020
lazy val mUnitVer = "0.7.26"
@@ -26,18 +26,18 @@ object Dependencies {
2626
"com.typesafe.akka" %% "akka-actor-typed",
2727
"com.typesafe.akka" %% "akka-slf4j",
2828
"com.typesafe.akka" %% "akka-stream",
29-
).map (_ % Version.akkaVer)
29+
).map (_ % Versions.akkaVer)
3030

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

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

3939
private lazy val munitDeps = Seq(
40-
"org.scalameta" %% "munit" % Version.mUnitVer % Test
40+
"org.scalameta" %% "munit" % Versions.mUnitVer % Test
4141
)
4242

4343
lazy val dependencies: Seq[ModuleID] =
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.11.0")
2+
addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.3.7")
3+
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.0")
4+
addSbtPlugin("org.scalameta" % "sbt-native-image" % "0.3.1")

exercises/exercise_000_sudoku_solver_initial_state/src/main/resources/application.conf

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
11
akka {
2-
32
log-dead-letters = on
43
logger-startup-timeout = 30s
54

65
actor {
76
provider = local
8-
97
debug {
108
lifecycle = on
119
unhandled = on
1210
}
1311
}
1412

1513
remote {
16-
1714
artery {
1815
canonical {
1916
hostname = "127.0.0.1"

exercises/exercise_000_sudoku_solver_initial_state/src/main/scala/org/lunatechlabs/dotty/SudokuSolverMain.scala

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,27 @@
1-
/**
2-
* Copyright © 2020-2023 Lunatech Labs.
1+
/** Copyright © 2020-2023 Lunatech Labs.
32
*
4-
* Licensed under the Apache License, Version 2.0 (the "License");
5-
* you may not use this file except in compliance with the License.
6-
* You may obtain a copy of the License at
3+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
4+
* the License. You may obtain a copy of the License at
75
*
86
* http://www.apache.org/licenses/LICENSE-2.0
97
*
10-
* Unless required by applicable law or agreed to in writing, software
11-
* distributed under the License is distributed on an "AS IS" BASIS,
12-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
9+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1310
*
14-
* NO COMMERCIAL SUPPORT OR ANY OTHER FORM OF SUPPORT IS OFFERED ON
15-
* THIS SOFTWARE BY Lunatech Labs.
11+
* NO COMMERCIAL SUPPORT OR ANY OTHER FORM OF SUPPORT IS OFFERED ON THIS SOFTWARE BY Lunatech Labs.
1612
*
17-
* See the License for the specific language governing permissions and
18-
* limitations under the License.
13+
* See the License for the specific language governing permissions and limitations under the License.
1914
*/
2015

2116
package org.lunatechlabs.dotty
2217

2318
import akka.NotUsed
2419
import akka.actor.typed.scaladsl.adapter.TypedActorSystemOps
25-
import akka.actor.typed.scaladsl.{ Behaviors, Routers }
26-
import akka.actor.typed.{ ActorSystem, Behavior, Terminated }
27-
import org.lunatechlabs.dotty.sudoku.{ SudokuProblemSender, SudokuSolver, SudokuSolverSettings }
20+
import akka.actor.typed.scaladsl.{Behaviors, Routers}
21+
import akka.actor.typed.{ActorSystem, Behavior, Terminated}
22+
import org.lunatechlabs.dotty.sudoku.{SudokuProblemSender, SudokuSolver, SudokuSolverSettings}
2823

29-
import scala.Console.{ GREEN, RESET }
24+
import scala.Console.{GREEN, RESET}
3025
import scala.io.StdIn
3126

3227
object Main {
@@ -36,13 +31,10 @@ object Main {
3631
// Start a SudokuSolver
3732
val sudokuSolver = context.spawn(SudokuSolver(sudokuSolverSettings), s"sudoku-solver")
3833
// Start a Sudoku problem sender
39-
context.spawn(SudokuProblemSender(sudokuSolver, sudokuSolverSettings),
40-
"sudoku-problem-sender"
41-
)
34+
context.spawn(SudokuProblemSender(sudokuSolver, sudokuSolverSettings), "sudoku-problem-sender")
4235

43-
Behaviors.receiveSignal {
44-
case (_, Terminated(_)) =>
45-
Behaviors.stopped
36+
Behaviors.receiveSignal { case (_, Terminated(_)) =>
37+
Behaviors.stopped
4638
}
4739
}
4840
}

exercises/exercise_000_sudoku_solver_initial_state/src/main/scala/org/lunatechlabs/dotty/sudoku/ReductionRules.scala

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,44 +4,39 @@ object ReductionRules {
44

55
def reductionRuleOne(reductionSet: ReductionSet): ReductionSet = {
66
val inputCellsGrouped = reductionSet.filter(_.size <= 7).groupBy(identity)
7-
val completeInputCellGroups = inputCellsGrouped.filter {
8-
case (set, setOccurrences) => set.size == setOccurrences.length
7+
val completeInputCellGroups = inputCellsGrouped.filter { case (set, setOccurrences) =>
8+
set.size == setOccurrences.length
99
}
1010
val completeAndIsolatedValueSets = completeInputCellGroups.keys.toList
11-
completeAndIsolatedValueSets.foldLeft(reductionSet) {
12-
case (cells, caivSet) =>
13-
cells.map { cell =>
14-
if (cell != caivSet) cell &~ caivSet else cell
15-
}
11+
completeAndIsolatedValueSets.foldLeft(reductionSet) { case (cells, caivSet) =>
12+
cells.map { cell =>
13+
if (cell != caivSet) cell &~ caivSet else cell
14+
}
1615
}
1716
}
1817

1918
def reductionRuleTwo(reductionSet: ReductionSet): ReductionSet = {
20-
val valueOccurrences = CELLPossibleValues.map { value =>
21-
cellIndexesVector.zip(reductionSet).foldLeft(Vector.empty[Int]) {
22-
case (acc, (index, cell)) =>
23-
if (cell contains value) index +: acc else acc
19+
val valueOccurrences = CellPossibleValues.map { value =>
20+
cellIndexesVector.zip(reductionSet).foldLeft(Vector.empty[Int]) { case (acc, (index, cell)) =>
21+
if (cell contains value) index +: acc else acc
2422
}
2523
}
2624

2725
val cellIndexesToValues =
28-
CELLPossibleValues
29-
.zip(valueOccurrences)
30-
.groupBy { case (value, occurrence) => occurrence }
31-
.filter { case (loc, occ) => loc.length == occ.length && loc.length <= 6 }
26+
CellPossibleValues.zip(valueOccurrences).groupBy { case (value, occurrence) => occurrence }.filter {
27+
case (loc, occ) => loc.length == occ.length && loc.length <= 6
28+
}
3229

33-
val cellIndexListToReducedValue = cellIndexesToValues.map {
34-
case (index, seq) => (index, (seq.map { case (value, _) => value }).toSet)
30+
val cellIndexListToReducedValue = cellIndexesToValues.map { case (index, seq) =>
31+
(index, seq.map { case (value, _) => value }.toSet)
3532
}
3633

37-
val cellIndexToReducedValue = cellIndexListToReducedValue.flatMap {
38-
case (cellIndexList, reducedValue) =>
39-
cellIndexList.map(cellIndex => cellIndex -> reducedValue)
34+
val cellIndexToReducedValue = cellIndexListToReducedValue.flatMap { case (cellIndexList, reducedValue) =>
35+
cellIndexList.map(cellIndex => cellIndex -> reducedValue)
4036
}
4137

42-
reductionSet.zipWithIndex.foldRight(Vector.empty[CellContent]) {
43-
case ((cellValue, cellIndex), acc) =>
44-
cellIndexToReducedValue.getOrElse(cellIndex, cellValue) +: acc
38+
reductionSet.zipWithIndex.foldRight(Vector.empty[CellContent]) { case ((cellValue, cellIndex), acc) =>
39+
cellIndexToReducedValue.getOrElse(cellIndex, cellValue) +: acc
4540
}
4641
}
4742
}

0 commit comments

Comments
 (0)