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).
|
||||
* сделать **приватный форк** данного репозитория. Это описано в [инструкции по созданию форка](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")
|
||||
|
||||
}
|
||||
|
||||
}
|