Compare commits
9 commits
main
...
homework/l
Author | SHA1 | Date | |
---|---|---|---|
|
594525aeeb | ||
![]() |
b79c3daa6f | ||
![]() |
7a94db6196 | ||
![]() |
b7568007b3 | ||
![]() |
a56cc694c6 | ||
![]() |
cb78e90533 | ||
![]() |
d1c716856f | ||
![]() |
ce9b994d34 | ||
![]() |
177cf65c81 |
23
.github/workflows/scala.yml
vendored
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
name: Scala CI
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- 'homework/*'
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- 'homework/*'
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Run tests
|
||||||
|
run: sbt test
|
||||||
|
lint:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Formatting
|
||||||
|
run: sbt scalafmtCheck test:scalafmtCheck
|
8
.scalafmt.conf
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
binPack.parentConstructors = true
|
||||||
|
maxColumn = 120
|
||||||
|
includeCurlyBraceInSelectChains = false
|
||||||
|
align = most
|
||||||
|
version = "2.4.2"
|
||||||
|
trailingCommas = preserve
|
||||||
|
newlines.penalizeSingleSelectMultiArgList = false
|
||||||
|
newlines.alwaysBeforeMultilineDef = false
|
|
@ -1,7 +1,11 @@
|
||||||
# Домашние задания по курсу Scala в бакалавриате МФТИ
|
# Постановка задачи
|
||||||
|
|
||||||
Все домашние задания привязаны к лекциям по номеру. Каждое задание располагается в ветке *homework/lecture-N-M*, где N - номер семестра, M - номер лекции в семестре.
|
Задание предназначено для освоения темы наследования типов в Scala. Нужно выполнить задания в:
|
||||||
|
* [TraitLineization](src/main/scala/mipt/homework6/TraitLineization.scala) реализовать алгоритм линеизации для множественного наследования типов
|
||||||
|
|
||||||
|
# Подготовка к выполнению домашнего задания
|
||||||
|
|
||||||
Для работы над домашними заданиями нужно:
|
Для работы над домашними заданиями нужно:
|
||||||
* установить IntelliJ IDEA и подготовить ее для работы со Scala. Это описано в [инструкции по установке IDEA](docs/idea-install/install.md).
|
* установить IntelliJ IDEA и подготовить ее для работы со Scala. Это описано в [инструкции по установке IDEA](docs/idea-install/install.md).
|
||||||
* сделать **приватный форк** данного репозитория. Это описано в [инструкции по созданию форка](docs/create-fork/private-fork.md).
|
* сделать **приватный форк** данного репозитория. Это описано в [инструкции по созданию форка](docs/create-fork/private-fork.md).
|
||||||
|
* в проекте стоит настроить [форматирование в scalafmt](docs/code-style/code-style.md).
|
||||||
|
|
21
build.sbt
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import _root_.sbt.Keys._
|
||||||
|
import wartremover.Wart
|
||||||
|
import wartremover.Wart._
|
||||||
|
|
||||||
|
name := "bachelor-homeworks"
|
||||||
|
version := "0.1"
|
||||||
|
scalaVersion := "2.13.10"
|
||||||
|
|
||||||
|
scalacOptions := List(
|
||||||
|
"-encoding",
|
||||||
|
"utf8",
|
||||||
|
"-feature",
|
||||||
|
"-unchecked",
|
||||||
|
"-deprecation",
|
||||||
|
"-language:_",
|
||||||
|
"-Ymacro-annotations"
|
||||||
|
)
|
||||||
|
|
||||||
|
libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.0" % "test"
|
||||||
|
|
||||||
|
wartremoverErrors ++= Seq[Wart](Any, AsInstanceOf, Null, Return, Throw, While, MutableDataStructures)
|
12
docs/code-style/code-style.md
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
# Настройка форматирования
|
||||||
|
|
||||||
|
Если не настроено форматирование, у вас будет падать таск lint на CI, который проверяет сode style.
|
||||||
|
Поэтому стоит настроить плагин scalafmt, который сам следит за кодстайлом и помогает переформатировать код как надо.
|
||||||
|
|
||||||
|
1. Перейти в File > Settings
|
||||||
|
2. Вбить в поиск `scalafmt`
|
||||||
|
3. Выбрать меню Editor > Code Style > Scala
|
||||||
|
4. Выбрать в качестве форматировщика `Scalafmt`
|
||||||
|
5. Отметить галочку "reformat on Save"! Тогда при явном сохранении исходника scalafmt автоматически обновит ваш файл.
|
||||||
|
|
||||||
|
![Scalafmt](images/scalafmt.png "scalafmt")
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 55 KiB |
Before Width: | Height: | Size: 344 KiB |
Before Width: | Height: | Size: 336 KiB |
Before Width: | Height: | Size: 284 KiB |
Before Width: | Height: | Size: 120 KiB |
Before Width: | Height: | Size: 378 KiB |
Before Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 98 KiB |
Before Width: | Height: | Size: 127 KiB |
Before Width: | Height: | Size: 122 KiB |
Before Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 55 KiB |
Before Width: | Height: | Size: 116 KiB |
|
@ -1,96 +0,0 @@
|
||||||
# Создание приватного форка репозитория с домашними заданиями
|
|
||||||
|
|
||||||
Репозитории в git можно fork-ать, то есть делать его полную копию с возможностью синхронизации с начальным репозиторием.
|
|
||||||
Этот механизм похож на ветки, но отличается тем, что форк может иметь свои настройки доступа и видимости и может существовать независимо от изначального репозитория.
|
|
||||||
|
|
||||||
Гитхаб не позвляет создавать приватные форки через кнопку Fork, поэтому придет делать форк вручную. К счастью, это не сложно.
|
|
||||||
|
|
||||||
### Подготовка проекта
|
|
||||||
|
|
||||||
1. Создать у себя в профиле пустой приватный репозиторий - [https://github.com/new](https://github.com/new)
|
|
||||||
1. Назвать `bachelor-homeworks`
|
|
||||||
2. Сделать его приватным
|
|
||||||
3. Добавлять никаких файлов не надо
|
|
||||||
![Create repository](images/create_repository.png "create repository")
|
|
||||||
4. Далее перейти в настройки репозитория, в раздел Collaborators
|
|
||||||
![Collaborators](images/collaborators.png "collaborators")
|
|
||||||
5. Нажав `Add people`, добавить в свой проект своего преподавателя
|
|
||||||
2. Скопировать ссылку на клонирование с главной страницы репозитория с заданием
|
|
||||||
![clone_link](images/fork_link.png "clone link")
|
|
||||||
3. В окне Intellij выбрать Get from VCS
|
|
||||||
![Get from VCS](images/get_from_vcs.png "Get from vcs")
|
|
||||||
4. В поле `Ссылка` вставить скопированный линк
|
|
||||||
1. IDEA может написать, что не установлен GIT, тогда следует нажать кнопку `Скачать и установить`
|
|
||||||
5. Нажать кнопку `Clone`, желательно, чтобы итоговый путь до проекта не содержал русских символов и пробелов
|
|
||||||
6. Далее необходимо добавить ваш репозиторий в качестве основного, подменив наш.
|
|
||||||
1. Скопировать ссылку на ваш репозиторий
|
|
||||||
![fork_clone](images/fork_link.png "Link to fork")
|
|
||||||
1. Windows
|
|
||||||
1. открыть приложение Git CMD
|
|
||||||
2. Linux / MacOS
|
|
||||||
1. открыть терминал
|
|
||||||
3. Перейти в директорию с проектом
|
|
||||||
4. ввести следующие команды по очереди:
|
|
||||||
1. `git remote rename origin upstream`
|
|
||||||
2. `git remote add origin <ссылка на ваш репозиторий>`
|
|
||||||
![Git cmd](images/git_cmd.png "Git cmd")
|
|
||||||
7. Далее необходимо настроить корректную сборку проекта
|
|
||||||
1. Переходим в File > Settings
|
|
||||||
2. Вбить в поиск sbt
|
|
||||||
3. Выбрать меню Build, Execution, Deployment > Build Tools > sbt
|
|
||||||
4. Поставить следующие настройки
|
|
||||||
![SBT settings](images/sbt_settings.png "SBT settings")
|
|
||||||
8. Запускаем импорт проекта - нажать на маленькую красную кнопку справа-сверху
|
|
||||||
![Reload sbt project](images/reload_sbt_project.png "Reload sbt project")
|
|
||||||
9. Пока проект импортируется, можно переключить форматировщик
|
|
||||||
1. Перейти в File > Settings
|
|
||||||
2. Вбить в поиск `scalafmt`
|
|
||||||
3. Выбрать меню Editor > Code Style > Scala
|
|
||||||
4. Выбрать в качестве форматировщика `Scalafmt`
|
|
||||||
|
|
||||||
![Scalafmt](images/scalafmt.png "scalafmt")
|
|
||||||
10. ***Далее необходимо сделать `push` в свой пустой репозиторий - `git push origin` в терминале гита или через UI intellij, ничего не изменяя. Так вы добавите актуальную ветку main к себе проект.***
|
|
||||||
|
|
||||||
> Обратите на последний шаг внимание - если этого не сделать, то main не будет основной веткой.
|
|
||||||
|
|
||||||
### Регистрация на портале образования
|
|
||||||
|
|
||||||
1. Зарегистрироваться на [https://edu.tinkoff.ru/](https://edu.tinkoff.ru/);
|
|
||||||
2. Присоединиться к курсу
|
|
||||||
3. Когда вы создадите Pull Request на гитхабе, нужно сдать соответствуещее ей задание в этом курсе - просто прикрепите в поле для ответа ссылку на ваш PR. Баллы за задание тоже будут там.
|
|
||||||
1. Перейдите на страницу нужной практики
|
|
||||||
![Task page](images/task_page.jpeg)
|
|
||||||
2. Вставьте в поле "Ответ" ссылку на ваш PR и отправьте работу
|
|
||||||
![Send task](images/pull_request_link.jpeg)
|
|
||||||
|
|
||||||
## Работа с github по SSH
|
|
||||||
|
|
||||||
При работе по https необходимо вводить логин и пароль, сохранять его на локальной машине в настройках git и т.д.
|
|
||||||
Чтобы этого не делать, можно воспользоваться функциональностью создания и добавления SSH-ключа в github.
|
|
||||||
|
|
||||||
### Создание SSH ключа
|
|
||||||
|
|
||||||
1. Windows
|
|
||||||
1. Открыть cmd.exe
|
|
||||||
2. Ввести команду `ssh-keygen -b 2048 -t rsa`
|
|
||||||
3. Если не сработало, то надо установить клиент OpenSSH:
|
|
||||||
1. Открыть Настройки > Приложения > Приложения и возможности > Дополнительные компоненты
|
|
||||||
2. Нажать сверху "Добавить компонент" и там через поиск установить "Клиент OpenSSH".
|
|
||||||
4. Проследовать всем пунктам установки, пароль устанавливать смысла нет, менять путь тоже не стоит
|
|
||||||
5. После завершения будет сгенерирована пара файлов - `id_rsa` и `id_rsa.pub`, путь к ним был указан в процессе установки
|
|
||||||
6. Необходимо скопировать в буфер обмена содержимое файла `id_rsa.pub`
|
|
||||||
2. Linux / Macos
|
|
||||||
1. Открыть терминал
|
|
||||||
2. Аналогично windows, начиная с 3-го шага
|
|
||||||
|
|
||||||
### Установка SSH ключа в GitHub
|
|
||||||
|
|
||||||
1. Перейти на [https://github.com/settings/keys](https://github.com/settings/keys)
|
|
||||||
2. Нажать на кнопку `New SSH key`
|
|
||||||
![New ssh key](images/new_ssh_key.png "new ssh key")
|
|
||||||
3. Дать удобное вам название, например <имя пользователя>_<операционная система>
|
|
||||||
4. В поле `Key` вставить содержимое файла `id_rsa.pub`
|
|
||||||
5. Нажать кнопку `Add SSH key`
|
|
||||||
|
|
||||||
> Впредь вы сможете взаимодействовать со своим GitHub аккаунтом по SSH - клонировать, пушить и т.д. без ввода пароля
|
|
||||||
> Для клонирования надо использовать SSH-ссылку вместо HTTPS
|
|
1
project/build.properties
Normal file
|
@ -0,0 +1 @@
|
||||||
|
sbt.version=1.6.2
|
2
project/plugins.sbt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
addSbtPlugin("org.wartremover" % "sbt-wartremover" % "3.0.9")
|
||||||
|
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.0")
|
31
src/main/scala/mipt/homework6/TraitLineization.scala
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
package mipt.homework6
|
||||||
|
|
||||||
|
import mipt.utils.Homeworks._
|
||||||
|
|
||||||
|
import scala.collection.mutable.Set
|
||||||
|
|
||||||
|
object TraitLineization {
|
||||||
|
|
||||||
|
type MethodDef = String
|
||||||
|
case class TraitDef(parents: List[TraitDef], methods: Map[String, MethodDef])
|
||||||
|
|
||||||
|
def resolveMethod(traitDef: TraitDef, method: String): Option[MethodDef] = {
|
||||||
|
val visited: Set[TraitDef] = Set.empty
|
||||||
|
|
||||||
|
def dfs(currentTrait: TraitDef): Option[MethodDef] = {
|
||||||
|
if (visited.contains(currentTrait)) {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
visited.add(currentTrait)
|
||||||
|
|
||||||
|
val result_dfs = currentTrait.parents.foldLeft(Option.empty[MethodDef]) {
|
||||||
|
case (result, parent) =>
|
||||||
|
dfs(parent).orElse(result)
|
||||||
|
}
|
||||||
|
currentTrait.methods.get(method).orElse(result_dfs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dfs(traitDef)
|
||||||
|
}
|
||||||
|
}
|
21
src/main/scala/mipt/utils/Homeworks.scala
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
package mipt.utils
|
||||||
|
|
||||||
|
object Homeworks {
|
||||||
|
|
||||||
|
final case class TaskNotDone(num: String, text: String) extends RuntimeException(s"выполните задание $num : \n $text")
|
||||||
|
|
||||||
|
trait TaskDef {
|
||||||
|
def applySeq(num: Seq[Int]): Nothing
|
||||||
|
|
||||||
|
def apply(num: Int*): Nothing = applySeq(num)
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings(Array("org.wartremover.warts.Throw"))
|
||||||
|
implicit class TaskSyntax(private val cs: StringContext) extends AnyVal {
|
||||||
|
def task(refs: Any*): TaskDef = xs => {
|
||||||
|
val message = cs.s(refs: _*).stripMargin
|
||||||
|
throw TaskNotDone(xs.mkString("."), message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
47
src/test/scala/mipt/homework6/TraitLineizationSpec.scala
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
package mipt.homework6
|
||||||
|
|
||||||
|
import TraitLineization._
|
||||||
|
import org.scalatest.flatspec.AnyFlatSpec
|
||||||
|
import org.scalatest.matchers.should.Matchers
|
||||||
|
|
||||||
|
class TraitLineizationSpec extends AnyFlatSpec with Matchers {
|
||||||
|
|
||||||
|
"resolveMethod" should "correctly resolve method for multi-trait extension chain" in {
|
||||||
|
|
||||||
|
val traitDefA = TraitDef(
|
||||||
|
parents = List.empty,
|
||||||
|
methods = Map("foo" -> "println bar")
|
||||||
|
)
|
||||||
|
|
||||||
|
val traitDefB = TraitDef(
|
||||||
|
parents = List(traitDefA),
|
||||||
|
methods = Map("foo" -> "println lol")
|
||||||
|
)
|
||||||
|
|
||||||
|
val traitDefC = TraitDef(
|
||||||
|
parents = List(traitDefA),
|
||||||
|
methods = Map("foo" -> "println kek")
|
||||||
|
)
|
||||||
|
|
||||||
|
val traitDefFin1 = TraitDef(
|
||||||
|
parents = List(
|
||||||
|
traitDefB,
|
||||||
|
traitDefC,
|
||||||
|
traitDefA
|
||||||
|
),
|
||||||
|
methods = Map.empty
|
||||||
|
)
|
||||||
|
val traitDefFin2 = TraitDef(
|
||||||
|
parents = List(
|
||||||
|
traitDefA,
|
||||||
|
traitDefB
|
||||||
|
),
|
||||||
|
methods = Map.empty
|
||||||
|
)
|
||||||
|
|
||||||
|
resolveMethod(traitDefFin1, "foo") shouldBe Some("println kek")
|
||||||
|
resolveMethod(traitDefFin2, "foo") shouldBe Some("println lol")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|