diff --git a/.gitignore b/.gitignore
index f089bc4..3bbe47c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+/Before you start/*/build
/Coroutines/*/build/
/.coursecreator/
/.gradle/
diff --git a/Before you start/Course structure/src/Main.kt b/Before you start/Course structure/src/Main.kt
new file mode 100644
index 0000000..2d5aa02
--- /dev/null
+++ b/Before you start/Course structure/src/Main.kt
@@ -0,0 +1,3 @@
+fun main() {
+ // Write your solution here
+}
diff --git a/Before you start/Course structure/task-info.yaml b/Before you start/Course structure/task-info.yaml
new file mode 100644
index 0000000..cc8f611
--- /dev/null
+++ b/Before you start/Course structure/task-info.yaml
@@ -0,0 +1,4 @@
+type: theory
+files:
+ - name: src/Main.kt
+ visible: true
diff --git a/Before you start/Course structure/task-remote-info.yaml b/Before you start/Course structure/task-remote-info.yaml
new file mode 100644
index 0000000..57baea9
--- /dev/null
+++ b/Before you start/Course structure/task-remote-info.yaml
@@ -0,0 +1 @@
+id: 1972445880
diff --git a/Before you start/Course structure/task.md b/Before you start/Course structure/task.md
new file mode 100644
index 0000000..313cb8a
--- /dev/null
+++ b/Before you start/Course structure/task.md
@@ -0,0 +1,25 @@
+## Course structure
+The course consists of 14 tasks in each of which you will improve the result of the previous task using new knowledge. Some tasks will give you theoretical knowledge
+
+
+- Task 1: Run the code
+- Task 2: Blocking requests
+
+- Task 4: Callbacks
+
+ - Task 5: Retrofit callback API
+
+- Task 6: Suspending functions
+- Task 7: Coroutines
+- Task 8: Concurrency
+- Task 9: Structured concurrency
+
+ - Task 10: Canceling
+ - Task 11: Outer scope
+
+- Task 12: Showing progress
+- Task 13: Channels
+- Task 14: Testing
+
\ No newline at end of file
diff --git a/Before you start/Getting to know you/src/Main.kt b/Before you start/Getting to know you/src/Main.kt
new file mode 100644
index 0000000..2d5aa02
--- /dev/null
+++ b/Before you start/Getting to know you/src/Main.kt
@@ -0,0 +1,3 @@
+fun main() {
+ // Write your solution here
+}
diff --git a/Before you start/Getting to know you/task-info.yaml b/Before you start/Getting to know you/task-info.yaml
new file mode 100644
index 0000000..cc8f611
--- /dev/null
+++ b/Before you start/Getting to know you/task-info.yaml
@@ -0,0 +1,4 @@
+type: theory
+files:
+ - name: src/Main.kt
+ visible: true
diff --git a/Before you start/Getting to know you/task-remote-info.yaml b/Before you start/Getting to know you/task-remote-info.yaml
new file mode 100644
index 0000000..b952413
--- /dev/null
+++ b/Before you start/Getting to know you/task-remote-info.yaml
@@ -0,0 +1 @@
+id: 1043970691
diff --git a/Before you start/Getting to know you/task.md b/Before you start/Getting to know you/task.md
new file mode 100644
index 0000000..915fc87
--- /dev/null
+++ b/Before you start/Getting to know you/task.md
@@ -0,0 +1,5 @@
+# Getting to know you
+
+Thank you for taking our Coroutines and channels course!
+We would be happy to get to know you a bit better, so we’re asking you to fill
+in [this brief form](https://surveys.jetbrains.com/s3/course-introduction-coroutines-channels).
diff --git a/Before you start/GitHub developer token/images/generating-token.png b/Before you start/GitHub developer token/images/generating-token.png
new file mode 100644
index 0000000..497b509
Binary files /dev/null and b/Before you start/GitHub developer token/images/generating-token.png differ
diff --git a/Before you start/GitHub developer token/images/generating-token_dark.png b/Before you start/GitHub developer token/images/generating-token_dark.png
new file mode 100644
index 0000000..6bf4b01
Binary files /dev/null and b/Before you start/GitHub developer token/images/generating-token_dark.png differ
diff --git a/Before you start/GitHub developer token/task-info.yaml b/Before you start/GitHub developer token/task-info.yaml
index d0523a4..9553f81 100644
--- a/Before you start/GitHub developer token/task-info.yaml
+++ b/Before you start/GitHub developer token/task-info.yaml
@@ -1,4 +1,8 @@
type: theory
files:
-- name: src/Main.kt
- visible: true
+ - name: src/Main.kt
+ visible: true
+ - name: images/generating-token.png
+ visible: false
+ - name: images/generating-token_dark.png
+ visible: false
diff --git a/Before you start/GitHub developer token/task.md b/Before you start/GitHub developer token/task.md
index 9fe6d66..ee36e32 100644
--- a/Before you start/GitHub developer token/task.md
+++ b/Before you start/GitHub developer token/task.md
@@ -1,9 +1,12 @@
-You'll be using the GitHub API in your project. To get access, provide your GitHub account name and either a password or a token. If you have two-factor authentication enabled, a token will be enough.
+In this course, you'll learn how to use coroutines in the example of a program that loads the contributors for all of the repositories under the given GitHub organization.
+
+So, you'll be using the GitHub API in your project. To get access, you'll need to provide your GitHub account name and either a password or a token. If you have two-factor authentication enabled, a token will be enough.
Generate a new GitHub token to use the GitHub API with [your account](https://github.com/settings/tokens/new):
1. Specify the name of your token, for example, `coroutines-tutorial`:
-
+![Generating token interface](images/generating-token.png)
2. Do not select any scopes. **Click Generate** token at the bottom of the page.
-3. Copy the generated token.
+3. Copy the generated token to safe place. You won't be able to see him again in the future. If you lose it, you will need to create a new one.
+For a more detailed description, you can look at [this article](https://kotlinlang.org/docs/coroutines-and-channels.html#generate-a-github-developer-token)
\ No newline at end of file
diff --git a/Before you start/lesson-info.yaml b/Before you start/lesson-info.yaml
index 20803b2..0a286e0 100644
--- a/Before you start/lesson-info.yaml
+++ b/Before you start/lesson-info.yaml
@@ -1,2 +1,4 @@
content:
-- GitHub developer token
+ - Course structure
+ - GitHub developer token
+ - Getting to know you
diff --git a/Coroutines/Aggregation/task.md b/Coroutines/Aggregation/task.md
index 3eef805..baa4153 100644
--- a/Coroutines/Aggregation/task.md
+++ b/Coroutines/Aggregation/task.md
@@ -18,4 +18,6 @@ The corresponding test file [test/tasks/AggregationKtTest.kt](course://Coroutine
After implementing this task, the resulting list for the "kotlin" organization should be similar to the following:
-![The list for the "kotlin" organization](images/aggregate.png)
\ No newline at end of file
+![The list for the "kotlin" organization](images/aggregate.png)
+
+For a more detailed description, you can look at [this article](https://kotlinlang.org/docs/coroutines-and-channels.html#task-1)
\ No newline at end of file
diff --git a/Coroutines/Blocking requests/images/blocking_dark.png b/Coroutines/Blocking requests/images/blocking_dark.png
new file mode 100644
index 0000000..f2f45d5
Binary files /dev/null and b/Coroutines/Blocking requests/images/blocking_dark.png differ
diff --git a/Coroutines/Blocking requests/task-info.yaml b/Coroutines/Blocking requests/task-info.yaml
index b9ad418..1b8e966 100644
--- a/Coroutines/Blocking requests/task-info.yaml
+++ b/Coroutines/Blocking requests/task-info.yaml
@@ -50,3 +50,5 @@ files:
visible: false
- name: runConfigurations/MainKt-Blocking_requests.run.xml
visible: false
+ - name: images/blocking_dark.png
+ visible: false
diff --git a/Coroutines/Blocking requests/task.md b/Coroutines/Blocking requests/task.md
index e4bad8d..1f5084c 100644
--- a/Coroutines/Blocking requests/task.md
+++ b/Coroutines/Blocking requests/task.md
@@ -33,6 +33,7 @@ This API is used by the `loadContributorsBlocking()` function to fetch the list
name in square brackets. You can see from which thread the loading request is called.
* The final item on each line is the actual message: how many repositories or contributors were loaded.
+
This log output demonstrates that all of the results were logged from the main thread. When you run the code with a _BLOCKING_
option, the window freezes and doesn't react to input until the loading is finished. All of the requests are executed from
the same thread as the one called `loadContributorsBlocking()` is from, which is the main UI thread (in Swing, it's an AWT
@@ -49,4 +50,4 @@ This API is used by the `loadContributorsBlocking()` function to fetch the list
* Since `loadContributorsBlocking()` is also called from the UI thread, the UI thread becomes blocked and the UI is
frozen.
-
+For a more detailed description, you can look at [this article](https://kotlinlang.org/docs/coroutines-and-channels.html#blocking-requests)
diff --git a/Coroutines/Callbacks/images/background_dark.png b/Coroutines/Callbacks/images/background_dark.png
new file mode 100644
index 0000000..5dcca6f
Binary files /dev/null and b/Coroutines/Callbacks/images/background_dark.png differ
diff --git a/Coroutines/Callbacks/task-info.yaml b/Coroutines/Callbacks/task-info.yaml
index 1a678a0..b86d98d 100644
--- a/Coroutines/Callbacks/task-info.yaml
+++ b/Coroutines/Callbacks/task-info.yaml
@@ -62,3 +62,5 @@ files:
visible: false
- name: test/tasks/Request2BackgroundKtTest.kt
visible: true
+ - name: images/background_dark.png
+ visible: false
diff --git a/Coroutines/Callbacks/task.md b/Coroutines/Callbacks/task.md
index 89f89af..eff720b 100644
--- a/Coroutines/Callbacks/task.md
+++ b/Coroutines/Callbacks/task.md
@@ -41,7 +41,9 @@ which uses callbacks instead of blocking calls.
However, if you try to load the contributors via the `BACKGROUND` option, you can see that the list is updated but
nothing changes.
-### Task
+## Task
Fix the `loadContributorsBackground()` function in [src/tasks/Request2Background.kt](course://Coroutines/Callbacks/src/tasks/Request2Background.kt) so that the resulting list is shown
-in the UI.
\ No newline at end of file
+in the UI.
+
+For a more detailed description, you can look at [this article](https://kotlinlang.org/docs/coroutines-and-channels.html#callbacks)
\ No newline at end of file
diff --git a/Coroutines/Canceling/task.md b/Coroutines/Canceling/task.md
index c7d0319..0011800 100644
--- a/Coroutines/Canceling/task.md
+++ b/Coroutines/Canceling/task.md
@@ -1,15 +1,14 @@
-Create two versions of the function that loads the list of contributors. Compare how both versions behave when you try to
-cancel the parent coroutine. The first version will use `coroutineScope` to start all of the child coroutines,
-whereas the second will use `GlobalScope`.
+Look at two versions of the function that loads the list of contributors. Compare how both versions behave when you try to
+cancel the parent coroutine. The first version is using `coroutineScope` to start all of the child coroutines,
+whereas the second is using `GlobalScope`.
-1. In [Request5Concurrent.kt](course://Coroutines/Canceling/src/tasks/Request5Concurrent.kt), add a 3-second delay to the `loadContributorsConcurrent()` function.
+1. In [src/tasks/Request5Concurrent.kt](course://Coroutines/Canceling/src/tasks/Request5Concurrent.kt), uncomment 3-second delay in the `loadContributorsConcurrent()` function.
The delay affects all of the coroutines that send requests, so that there's enough time to cancel the loading
after the coroutines are started but before the requests are sent.
-2. Create the second version of the loading function: copy the implementation of `loadContributorsConcurrent()` to
- `loadContributorsNotCancellable()` in [Request5NotCancellable.kt](course://Coroutines/Canceling/src/tasks/Request5NotCancellable.kt) and then remove the creation of a new `coroutineScope`.
-3. The `async` calls now fail to resolve, so start them by using `GlobalScope.async`:
+2. Look at the second version of the loading function: `loadContributorsNotCancellable()` in [src/tasks/Request5NotCancellable.kt](course://Coroutines/Canceling/src/tasks/Request5NotCancellable.kt)
+3. It is using `GlobalScope.async`:
```kotlin
suspend fun loadContributorsNotCancellable(
@@ -30,7 +29,7 @@ whereas the second will use `GlobalScope`.
* All of the "contributors" coroutines are started inside the `GlobalScope`, not as children of the coroutine scope
(line `#2`).
-4. Run the program and choose the _CONCURRENT_ option to load the contributors.
+4. Run the program and choose the `CONCURRENT` option to load the contributors.
5. Wait until all of the "contributors" coroutines are started, and then click _Cancel_. The log shows no new results,
which means that all of the requests were indeed canceled:
@@ -59,7 +58,7 @@ whereas the second will use `GlobalScope`.
In this case, no coroutines are canceled, and all the requests are still sent.
-7. Check how the cancellation is triggered in the [Contributors.kt](course://Coroutines/Canceling/src/contributors/Contributors.kt). When the _Cancel_ button is clicked,
+7. Check how the cancellation is triggered in the [src/contributors/Contributors.kt](course://Coroutines/Canceling/src/contributors/Contributors.kt). When the _Cancel_ button is clicked,
the main "loading" coroutine is explicitly canceled and the child coroutines are canceled automatically.
The `launch` function returns an instance of `Job`. `Job` stores a reference to the "loading coroutine", which loads
@@ -78,4 +77,6 @@ job.setUpCancellation()
* Then you could add a listener to the _Cancel_ button so that when it's clicked, the `loadingJob` is canceled (line `#3`).
With structured concurrency, you only need to cancel the parent coroutine and this automatically propagates cancellation
-to all of the child coroutines.
\ No newline at end of file
+to all of the child coroutines.
+
+For a more detailed description, you can look at [this article](https://kotlinlang.org/docs/coroutines-and-channels.html#canceling-the-loading-of-contributors)
\ No newline at end of file
diff --git a/Coroutines/Channels/images/buffered-channel_dark.png b/Coroutines/Channels/images/buffered-channel_dark.png
new file mode 100644
index 0000000..4004afa
Binary files /dev/null and b/Coroutines/Channels/images/buffered-channel_dark.png differ
diff --git a/Coroutines/Channels/images/conflated-channel_dark.gif b/Coroutines/Channels/images/conflated-channel_dark.gif
new file mode 100644
index 0000000..c6351bd
Binary files /dev/null and b/Coroutines/Channels/images/conflated-channel_dark.gif differ
diff --git a/Coroutines/Channels/images/progress-and-concurrency_dark.png b/Coroutines/Channels/images/progress-and-concurrency_dark.png
new file mode 100644
index 0000000..f37b2b5
Binary files /dev/null and b/Coroutines/Channels/images/progress-and-concurrency_dark.png differ
diff --git a/Coroutines/Channels/images/progress_dark.png b/Coroutines/Channels/images/progress_dark.png
new file mode 100644
index 0000000..0495f44
Binary files /dev/null and b/Coroutines/Channels/images/progress_dark.png differ
diff --git a/Coroutines/Channels/images/rendezvous-channel_dark.png b/Coroutines/Channels/images/rendezvous-channel_dark.png
new file mode 100644
index 0000000..b0669cc
Binary files /dev/null and b/Coroutines/Channels/images/rendezvous-channel_dark.png differ
diff --git a/Coroutines/Channels/images/unlimited-channel_dark.png b/Coroutines/Channels/images/unlimited-channel_dark.png
new file mode 100644
index 0000000..91ab3b5
Binary files /dev/null and b/Coroutines/Channels/images/unlimited-channel_dark.png differ
diff --git a/Coroutines/Channels/images/using-channel-many-coroutines_dark.png b/Coroutines/Channels/images/using-channel-many-coroutines_dark.png
new file mode 100644
index 0000000..cfaa936
Binary files /dev/null and b/Coroutines/Channels/images/using-channel-many-coroutines_dark.png differ
diff --git a/Coroutines/Channels/images/using-channel_dark.png b/Coroutines/Channels/images/using-channel_dark.png
new file mode 100644
index 0000000..91d3621
Binary files /dev/null and b/Coroutines/Channels/images/using-channel_dark.png differ
diff --git a/Coroutines/Channels/task-info.yaml b/Coroutines/Channels/task-info.yaml
index 4bac59c..0cfe44f 100644
--- a/Coroutines/Channels/task-info.yaml
+++ b/Coroutines/Channels/task-info.yaml
@@ -86,3 +86,19 @@ files:
visible: false
- name: test/tasks/Request2BackgroundKtTest.kt
visible: true
+ - name: images/conflated-channel_dark.gif
+ visible: false
+ - name: images/using-channel-many-coroutines_dark.png
+ visible: false
+ - name: images/progress_dark.png
+ visible: false
+ - name: images/progress-and-concurrency_dark.png
+ visible: false
+ - name: images/using-channel_dark.png
+ visible: false
+ - name: images/unlimited-channel_dark.png
+ visible: false
+ - name: images/buffered-channel_dark.png
+ visible: false
+ - name: images/rendezvous-channel_dark.png
+ visible: false
diff --git a/Coroutines/Channels/task.md b/Coroutines/Channels/task.md
index 4f089ae..7f98148 100644
--- a/Coroutines/Channels/task.md
+++ b/Coroutines/Channels/task.md
@@ -1,4 +1,4 @@
-#### Consecutive vs concurrent
+## Consecutive vs concurrent
An `updateResults()` callback is called after each request is completed:
@@ -103,23 +103,22 @@ val unlimitedChannel = Channel(UNLIMITED)
By default, a "Rendezvous" channel is created.
-In the following task, you'll create a "Rendezvous" channel, two producer coroutines, and a consumer coroutine. Check out [ChannelsSample.kt](course://Coroutines/Channels/src/samples/ChannelsSample.kt)
+In the following task, you'll create a "Rendezvous" channel, two producer coroutines, and a consumer coroutine. Check out [src/samples/ChannelsSample.kt](course://Coroutines/Channels/src/samples/ChannelsSample.kt)
-> Watch [this video](https://www.youtube.com/watch?v=HpWQUoVURWQ) for a better understanding of channels.
->
+> Watch
this video for a better understanding of channels.
-### Task
+## Task
In [src/tasks/Request7Channels.kt](course://Coroutines/Channels/src/tasks/Request7Channels.kt), implement the function `loadContributorsChannels()` that requests all of the GitHub
contributors concurrently and shows intermediate progress at the same time.
-Use the previous functions, `loadContributorsConcurrent()` from [Request5Concurrent.kt](course://Coroutines/Channels/src/tasks/Request5Concurrent.kt)
-and `loadContributorsProgress()` from [Request6Progress.kt](course://Coroutines/Channels/src/tasks/Request6Progress.kt).
+Use the previous functions, `loadContributorsConcurrent()` from [src/tasks/Request5Concurrent.kt](course://Coroutines/Channels/src/tasks/Request5Concurrent.kt)
+and `loadContributorsProgress()` from [src/tasks/Request6Progress.kt](course://Coroutines/Channels/src/tasks/Request6Progress.kt).
@@ -148,4 +147,6 @@ repeat(repos.size) {
```
Since the `receive()` calls are sequential, no additional synchronization is needed.
-
\ No newline at end of file
+
+
+For a more detailed description, you can look at [this article](https://kotlinlang.org/docs/coroutines-and-channels.html#channels)
\ No newline at end of file
diff --git a/Coroutines/Concurrency/images/concurrency_dark.png b/Coroutines/Concurrency/images/concurrency_dark.png
new file mode 100644
index 0000000..5ea4cbf
Binary files /dev/null and b/Coroutines/Concurrency/images/concurrency_dark.png differ
diff --git a/Coroutines/Concurrency/task-info.yaml b/Coroutines/Concurrency/task-info.yaml
index bc81ee4..64d3095 100644
--- a/Coroutines/Concurrency/task-info.yaml
+++ b/Coroutines/Concurrency/task-info.yaml
@@ -65,6 +65,8 @@ files:
- name: test/tasks/Request5ConcurrentKtTest.kt
visible: true
- name: images/concurrency.png
- visible: true
+ visible: false
- name: test/tasks/Request2BackgroundKtTest.kt
visible: true
+ - name: images/concurrency_dark.png
+ visible: false
diff --git a/Coroutines/Concurrency/task.md b/Coroutines/Concurrency/task.md
index 1121a73..3d19747 100644
--- a/Coroutines/Concurrency/task.md
+++ b/Coroutines/Concurrency/task.md
@@ -16,15 +16,15 @@ by calling `Job.join()`.
depending on what the lambda returns (the last expression inside the lambda is the result).
To get the result of a coroutine, you can call `await()` on the `Deferred` instance. While waiting for the result,
-the coroutine that this `await()` is called from is suspended. See the example in the [ConcurrencySample.kt](course://Coroutines/Concurrency/src/samples/ConcurrencySample.kt).
+the coroutine that this `await()` is called from is suspended. See the example in the [src/samples/ConcurrencySample.kt](course://Coroutines/Concurrency/src/samples/ConcurrencySample.kt).
`runBlocking` is used as a bridge between regular and suspending functions, or between the blocking and non-blocking worlds. It works
as an adaptor for starting the top-level main coroutine. It is intended primarily to be used in `main()` functions and
tests.
-> Watch [this video](https://www.youtube.com/watch?v=zEZc5AmHQhk) for a better understanding of coroutines.
+> Watch this video for a better understanding of coroutines.
-If there is a list of deferred objects, you can call `awaitAll()` to await the results of all of them. See the example in the [ConcurrencySample.kt](course://Coroutines/Concurrency/src/samples/ConcurrencySample.kt)
+If there is a list of deferred objects, you can call `awaitAll()` to await the results of all of them. See the example in the [src/samples/ConcurrencySample.kt](course://Coroutines/Concurrency/src/samples/ConcurrencySample.kt)
When each "contributors" request is started in a new coroutine, all of the requests are started asynchronously. A new request
can be sent before the result for the previous one is received:
@@ -34,9 +34,9 @@ can be sent before the result for the previous one is received:
The total loading time is approximately the same as in the _CALLBACKS_ version, but it doesn't need any callbacks.
What's more, `async` explicitly emphasizes which parts run concurrently in the code.
-### Task 5
+## Task
-In the [Request5Concurrent.kt](course://Coroutines/Concurrency/src/tasks/Request5Concurrent.kt) file, implement a `loadContributorsConcurrent()` function by using the
+In the [src/tasks/Request5Concurrent.kt](course://Coroutines/Concurrency/src/tasks/Request5Concurrent.kt) file, implement a `loadContributorsConcurrent()` function by using the
previous `loadContributorsSuspend()` function.
@@ -62,4 +62,6 @@ val deferreds: List>> = repos.map { repo ->
}
deferreds.awaitAll() // List>
```
-
\ No newline at end of file
+
+
+For a more detailed description, you can look at [this article](https://kotlinlang.org/docs/coroutines-and-channels.html#concurrency)
diff --git a/Coroutines/Coroutines/images/run-configuration.png b/Coroutines/Coroutines/images/run-configuration.png
index 9661f8f..dee545b 100644
Binary files a/Coroutines/Coroutines/images/run-configuration.png and b/Coroutines/Coroutines/images/run-configuration.png differ
diff --git a/Coroutines/Coroutines/images/run-configuration_dark.png b/Coroutines/Coroutines/images/run-configuration_dark.png
new file mode 100644
index 0000000..720aeb1
Binary files /dev/null and b/Coroutines/Coroutines/images/run-configuration_dark.png differ
diff --git a/Coroutines/Coroutines/images/suspend-requests_dark.png b/Coroutines/Coroutines/images/suspend-requests_dark.png
new file mode 100644
index 0000000..4bebe2b
Binary files /dev/null and b/Coroutines/Coroutines/images/suspend-requests_dark.png differ
diff --git a/Coroutines/Coroutines/images/suspension-process_dark.gif b/Coroutines/Coroutines/images/suspension-process_dark.gif
new file mode 100644
index 0000000..c340f0d
Binary files /dev/null and b/Coroutines/Coroutines/images/suspension-process_dark.gif differ
diff --git a/Coroutines/Coroutines/task-info.yaml b/Coroutines/Coroutines/task-info.yaml
index 038cc6e..079a987 100644
--- a/Coroutines/Coroutines/task-info.yaml
+++ b/Coroutines/Coroutines/task-info.yaml
@@ -54,3 +54,9 @@ files:
visible: false
- name: runConfigurations/MainKt-Coroutines.run.xml
visible: false
+ - name: images/suspension-process_dark.gif
+ visible: false
+ - name: images/suspend-requests_dark.png
+ visible: false
+ - name: images/run-configuration_dark.png
+ visible: false
diff --git a/Coroutines/Coroutines/task.md b/Coroutines/Coroutines/task.md
index 8d62810..04b4ce1 100644
--- a/Coroutines/Coroutines/task.md
+++ b/Coroutines/Coroutines/task.md
@@ -58,7 +58,7 @@ despite all the requests taking place on the main UI thread:
11252 [AWT-EventQueue-0 @coroutine#1] INFO Contributors - kotlin-coroutines-workshop: loaded 1 contributors
```
-2. The log can show you which coroutine the corresponding code is running on. To enable it, open **Run | Edit configurations**
+2. The log can show you which coroutine the corresponding code is running on. For the configuration invoked by clicking `Run` button this is already set up. To enable it in your own configurations, open **Run | Edit configurations**
and add the `-Dkotlinx.coroutines.debug` VM option:
@@ -73,3 +73,5 @@ written sequentially. The new request is sent only when the previous result is r
Suspending functions treat the thread fairly and don't block it for "waiting". However, this doesn't yet bring any concurrency
into the picture.
+
+For a more detailed description, you can look at [this article](https://kotlinlang.org/docs/coroutines-and-channels.html#coroutines)
\ No newline at end of file
diff --git a/Coroutines/Outer scope/task.md b/Coroutines/Outer scope/task.md
index adddfa5..39a27b2 100644
--- a/Coroutines/Outer scope/task.md
+++ b/Coroutines/Outer scope/task.md
@@ -38,3 +38,4 @@ top-level coroutine. All the nested coroutines then inherit the context and modi
> you need to run the code on a different thread.
+For a more detailed description, you can look at [this article](https://kotlinlang.org/docs/coroutines-and-channels.html#using-the-outer-scope-s-context)
\ No newline at end of file
diff --git a/Coroutines/Retrofit callback API/images/callbacks_dark.png b/Coroutines/Retrofit callback API/images/callbacks_dark.png
new file mode 100644
index 0000000..3bf38b9
Binary files /dev/null and b/Coroutines/Retrofit callback API/images/callbacks_dark.png differ
diff --git a/Coroutines/Retrofit callback API/task-info.yaml b/Coroutines/Retrofit callback API/task-info.yaml
index bc85794..3911660 100644
--- a/Coroutines/Retrofit callback API/task-info.yaml
+++ b/Coroutines/Retrofit callback API/task-info.yaml
@@ -73,3 +73,5 @@ files:
visible: false
- name: test/tasks/Request2BackgroundKtTest.kt
visible: true
+ - name: images/callbacks_dark.png
+ visible: false
diff --git a/Coroutines/Retrofit callback API/task.md b/Coroutines/Retrofit callback API/task.md
index bf330d8..4a18fd7 100644
--- a/Coroutines/Retrofit callback API/task.md
+++ b/Coroutines/Retrofit callback API/task.md
@@ -23,6 +23,8 @@ Open [src/tasks/Request3Callbacks.kt](course://Coroutines/Retrofit callback API/
However, the provided solution doesn't work. If you run the program and load contributors by choosing the _CALLBACKS_
option, you'll see that nothing is shown. However, the tests that immediately return the result pass.
-### Task
+## Task
-Rewrite the code in the [src/tasks/Request3Callbacks.kt](course://Coroutines/Retrofit callback API/src/tasks/Request3Callbacks.kt) file so that the loaded list of contributors is shown.
\ No newline at end of file
+Rewrite the code in the [src/tasks/Request3Callbacks.kt](course://Coroutines/Retrofit callback API/src/tasks/Request3Callbacks.kt) file so that the loaded list of contributors is shown.
+
+For a more detailed description, you can look at [this article](https://kotlinlang.org/docs/coroutines-and-channels.html#use-the-retrofit-callback-api)
\ No newline at end of file
diff --git a/Coroutines/Run the code/task.md b/Coroutines/Run the code/task.md
index ce0053b..ba0dbe3 100644
--- a/Coroutines/Run the code/task.md
+++ b/Coroutines/Run the code/task.md
@@ -1,6 +1,6 @@
The program loads the contributors for all of the repositories under the given organization (named “kotlin” by default). Later you'll add logic to sort the users by the number of their contributions.
-Open the [src/contributors/main.kt](course://Coroutines/Run the code/src/contributors/main.kt) file and run the `main()` function. You'll see the following window:
+Open the [src/contributors/main.kt](course://Coroutines/Run the code/src/contributors/main.kt) file and run the `main()` function or just use the "Run" button below. You'll see the following window:
![First window](images/initial-window.png)
diff --git a/Coroutines/Showing progress/task.md b/Coroutines/Showing progress/task.md
index 1bab6b7..6ab9d6d 100644
--- a/Coroutines/Showing progress/task.md
+++ b/Coroutines/Showing progress/task.md
@@ -21,7 +21,7 @@ suspend fun loadContributorsProgress(
}
```
-On the call site in [Contributors.kt](course://Coroutines/Showing progress/src/contributors/Contributors.kt), the callback is passed to update the results from the `Main` thread for
+On the call site in [src/contributors/Contributors.kt](course://Coroutines/Showing progress/src/contributors/Contributors.kt), the callback is passed to update the results from the `Main` thread for
the _PROGRESS_ option:
```kotlin
@@ -39,13 +39,15 @@ launch(Dispatchers.Default) {
* `updateResults()` callback takes an additional Boolean parameter as an argument specifying whether the loading has
completed and the results are final.
-### Task
+## Task
In the [src/tasks/Request6Progress.kt](course://Coroutines/Showing progress/src/tasks/Request6Progress.kt) file, implement the `loadContributorsProgress()` function that shows the intermediate
-progress. Base it on the `loadContributorsSuspend()` function from [Request4Suspend.kt](course://Coroutines/Showing progress/src/tasks/Request4Suspend.kt).
+progress. Base it on the `loadContributorsSuspend()` function from [src/tasks/Request4Suspend.kt](course://Coroutines/Showing progress/src/tasks/Request4Suspend.kt).
* Use a simple version without concurrency; you'll add it later in the next section.
* The intermediate list of contributors should be shown in an "aggregated" state, not just the list of users loaded for
each repository.
* The total number of contributions for each user should be increased when the data for each new
- repository is loaded.
\ No newline at end of file
+ repository is loaded.
+
+For a more detailed description, you can look at [this article](https://kotlinlang.org/docs/coroutines-and-channels.html#showing-progress)
\ No newline at end of file
diff --git a/Coroutines/Structured concurrency/task.md b/Coroutines/Structured concurrency/task.md
index 31c4117..f5c3c8a 100644
--- a/Coroutines/Structured concurrency/task.md
+++ b/Coroutines/Structured concurrency/task.md
@@ -58,3 +58,5 @@ When using `GlobalScope.async`, there is no structure that binds several corouti
Coroutines started from the global scope are all independent – their lifetime is limited only by the lifetime of the
whole application. It's possible to store a reference to the coroutine started from the global scope and wait for its
completion or cancel it explicitly, but that won't happen automatically as it would with structured concurrency.
+
+For a more detailed description, you can look at [this article](https://kotlinlang.org/docs/coroutines-and-channels.html#structured-concurrency)
\ No newline at end of file
diff --git a/Coroutines/Suspending functions/task.md b/Coroutines/Suspending functions/task.md
index dc96e0f..a4edeab 100644
--- a/Coroutines/Suspending functions/task.md
+++ b/Coroutines/Suspending functions/task.md
@@ -18,9 +18,9 @@ interface GitHubService {
Alternatively, Retrofit allows returning the result wrapped in `Response`. In this case, the result body is
provided, and it is possible to check for errors manually. This tutorial uses the versions that return `Response`.
-See the new declarations `getOrgRepos` and `getRepoContributors` in [src/contributors/GitHubService.kt](course://Coroutines/Suspending functions/src/contributors/GitHubService.kt):
+See the new declarations `getOrgRepos` and `getRepoContributors` in [src/contributors/GitHubService.kt](course://Coroutines/Suspending functions/src/contributors/GitHubService.kt)
-### Task
+## Task
Your task is to change the code of the function that loads contributors to make use of two new suspending functions,
`getOrgRepos()` and `getRepoContributors()`. The new `loadContributorsSuspend()` function is marked as `suspend` to use the
@@ -35,4 +35,6 @@ new API.
into the `loadContributorsSuspend()` that is defined in [src/tasks/Request4Suspend.kt](course://Coroutines/Suspending functions/src/tasks/Request4Suspend.kt).
2. Modify the code so that the new suspending functions are used instead of the ones that return `Call`s.
3. Run the program by choosing the _SUSPEND_ option and ensure that the UI is still responsive while the GitHub requests
- are performed.
\ No newline at end of file
+ are performed.
+
+For a more detailed description, you can look at [this article](https://kotlinlang.org/docs/coroutines-and-channels.html#suspending-functions)
\ No newline at end of file
diff --git a/Coroutines/Testing/images/time-comparison.png b/Coroutines/Testing/images/time-comparison.png
index b1a52a3..f275924 100644
Binary files a/Coroutines/Testing/images/time-comparison.png and b/Coroutines/Testing/images/time-comparison.png differ
diff --git a/Coroutines/Testing/images/time-comparison_dark.png b/Coroutines/Testing/images/time-comparison_dark.png
new file mode 100644
index 0000000..81df5ac
Binary files /dev/null and b/Coroutines/Testing/images/time-comparison_dark.png differ
diff --git a/Coroutines/Testing/task-info.yaml b/Coroutines/Testing/task-info.yaml
index a0f7a03..2bdef48 100644
--- a/Coroutines/Testing/task-info.yaml
+++ b/Coroutines/Testing/task-info.yaml
@@ -158,3 +158,5 @@ files:
visible: false
- name: test/tasks/Request2BackgroundKtTest.kt
visible: true
+ - name: images/time-comparison_dark.png
+ visible: false
diff --git a/Coroutines/Testing/task.md b/Coroutines/Testing/task.md
index 8122503..6070e94 100644
--- a/Coroutines/Testing/task.md
+++ b/Coroutines/Testing/task.md
@@ -16,8 +16,8 @@ The concurrent solution should take around 2200 ms (2200 = 1000 + max(1000, 1200
For the solutions that show progress, you can also check the intermediate results with timestamps.
-The corresponding test data is defined in [test/contributors/testData.kt](course://Coroutines/Testing/test/contributors/testData.kt), and the files [Request4SuspendKtTest.kt](course://Coroutines/Testing/test/tasks/Request4SuspendKtTest.kt),
-[Request7ChannelsKtTest.kt](course://Coroutines/Testing/test/tasks/Request7ChannelsKtTest.kt), and so on contain the straightforward tests that use mock service calls.
+The corresponding test data is defined in [test/contributors/testData.kt](course://Coroutines/Testing/test/contributors/testData.kt), and the files [test/tasks/Request4SuspendKtTest.kt](course://Coroutines/Testing/test/tasks/Request4SuspendKtTest.kt),
+[test/tasks/Request7ChannelsKtTest.kt](course://Coroutines/Testing/test/tasks/Request7ChannelsKtTest.kt), and so on contain the straightforward tests that use mock service calls.
However, there are two problems here:
@@ -39,7 +39,7 @@ the `delay` will return immediately and advance the virtual time.
Tests that use this mechanism run fast, but you can still check what happens at different moments in virtual time. The
total running time drastically decreases:
-![Comparison for total running time](images/time-comparison.png){width=700}
+![Comparison for total running time](images/time-comparison.png)
To use virtual time, replace the `runBlocking` invocation with a `runTest`. `runTest` takes an
extension lambda to `TestScope` as an argument.
@@ -101,9 +101,7 @@ inherited context, without modifying it using the `Dispatchers.Default` dispatch
You can specify the context elements like the dispatcher when _calling_ a function rather than when _defining_ it,
which allows for more flexibility and easier testing.
-> The testing API that supports virtual time is [Experimental](components-stability.md) and may change in the future.
->
-{type="warning"}
+> The testing API that supports virtual time is [Experimental](https://kotlinlang.org/docs/components-stability.html) and may change in the future.
By default, the compiler shows warnings if you use the experimental testing API. To suppress these warnings, annotate
the test function or the whole class containing the tests with `@OptIn(ExperimentalCoroutinesApi::class)`.
@@ -119,13 +117,29 @@ compileTestKotlin {
In the project corresponding to this tutorial, the compiler argument has already been added to the Gradle script.
-### Task
+## Task
Refactor the following tests in [tests/tasks/](course://Coroutines/Testing/test/tasks/) to use virtual time instead of real time:
-* Request4SuspendKtTest.kt
-* Request5ConcurrentKtTest.kt
-* Request6ProgressKtTest.kt
-* Request7ChannelsKtTest.kt
+* [Request4SuspendKtTest.kt](course://Coroutines/Testing/test/tasks/Request4SuspendKtTest.kt)
+* [Request5ConcurrentKtTest.kt](course://Coroutines/Testing/test/tasks/Request5ConcurrentKtTest.kt)
+* [Request6ProgressKtTest.kt](course://Coroutines/Testing/test/tasks/Request6ProgressKtTest.kt)
+* [Request7ChannelsKtTest.kt](course://Coroutines/Testing/test/tasks/Request7ChannelsKtTest.kt)
+
+
+
+1. Replace the `runBlocking` invocation with `runTest`, and replace `System.currentTimeMillis()` with `currentTime`:
+ ```kotlin
+ @Test
+ fun test() = runTest {
+ val startTime = currentTime
+ // action
+ val totalTime = currentTime - startTime
+ // testing result
+ }
+ ```
+2. Don't forget to add `@UseExperimental(ExperimentalCoroutinesApi::class)`.
+
+
-Compare the total running times before and after applying your refactoring.
\ No newline at end of file
+For a more detailed description, you can look at [this article](https://kotlinlang.org/docs/coroutines-and-channels.html#testing-coroutines)
\ No newline at end of file
diff --git a/Feedback survey/Feedback survey/src/Main.kt b/Feedback survey/Feedback survey/src/Main.kt
new file mode 100644
index 0000000..2d5aa02
--- /dev/null
+++ b/Feedback survey/Feedback survey/src/Main.kt
@@ -0,0 +1,3 @@
+fun main() {
+ // Write your solution here
+}
diff --git a/Feedback survey/Feedback survey/task-info.yaml b/Feedback survey/Feedback survey/task-info.yaml
new file mode 100644
index 0000000..cc8f611
--- /dev/null
+++ b/Feedback survey/Feedback survey/task-info.yaml
@@ -0,0 +1,4 @@
+type: theory
+files:
+ - name: src/Main.kt
+ visible: true
diff --git a/Feedback survey/Feedback survey/task-remote-info.yaml b/Feedback survey/Feedback survey/task-remote-info.yaml
new file mode 100644
index 0000000..ead1f9a
--- /dev/null
+++ b/Feedback survey/Feedback survey/task-remote-info.yaml
@@ -0,0 +1 @@
+id: 1584654591
diff --git a/Feedback survey/Feedback survey/task.md b/Feedback survey/Feedback survey/task.md
new file mode 100644
index 0000000..b2bb109
--- /dev/null
+++ b/Feedback survey/Feedback survey/task.md
@@ -0,0 +1,6 @@
+# Feedback survey
+
+Thank you for taking our Coroutines and channels course!
+We would really appreciate it if you could take a few minutes to
+answer [our survey](https://surveys.jetbrains.com/s3/course-feedback-coroutines-channels).
+Your feedback will help us improve this course and make it relevant for future students.
\ No newline at end of file
diff --git a/Feedback survey/lesson-info.yaml b/Feedback survey/lesson-info.yaml
new file mode 100644
index 0000000..6e6d109
--- /dev/null
+++ b/Feedback survey/lesson-info.yaml
@@ -0,0 +1,2 @@
+content:
+ - Feedback survey
diff --git a/Feedback survey/lesson-remote-info.yaml b/Feedback survey/lesson-remote-info.yaml
new file mode 100644
index 0000000..6b00901
--- /dev/null
+++ b/Feedback survey/lesson-remote-info.yaml
@@ -0,0 +1 @@
+id: 691890448
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..fa42494
--- /dev/null
+++ b/README.md
@@ -0,0 +1,21 @@
+[![official project](https://jb.gg/badges/official.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
+
+# Kotlin: Coroutines and channels
+
+This course is based on Coroutines and channels tutorial
+and explains how to use coroutines in IntelliJ IDEA to perform network requests without blocking the underlying thread or callbacks.
+
+- Why and how to use suspending functions to perform network requests.
+- How to send requests concurrently using coroutines.
+- How to share information between different coroutines using channels.
+
+You'll learn all of this with an example of a step-by-step modification a program that loads the contributors for all of the repositories under the given GitHub organization.
+
+## Want to know more?
+
+If you have questions about the course or the tasks or if you find some errors,
+you can ask questions and participate in discussions in repository [issues](https://github.com/jetbrains-academy/Coroutines-and-channels/issues).
+
+## Contribution
+
+Please be sure to review the [project's contributing guidelines](./contributing.md) to learn how to help the project.
diff --git a/contributing.md b/contributing.md
new file mode 100644
index 0000000..1413a3e
--- /dev/null
+++ b/contributing.md
@@ -0,0 +1,41 @@
+# What this repository is
+
+This repository contains sources of the Coroutines and channels course.
+
+# Contributing
+
+We love contributions!
+We are happy to see fixes of the existing bugs and tasks and tests mistakes.
+The current tasks can be found in the [open issues](https://github.com/jetbrains-academy/Coroutines-and-channels/issues) in the project.
+If you have some questions or find bugs or mistakes, please do not hesitate to open new ones.
+
+Please, add a comment to the issue, if you're starting work on it.
+
+If you add some common functionality, e.g. for the test system, it is important to add comments to describe new behaviour.
+This will help other developers and users to use them correctly.
+
+## Submitting patches
+
+The best way to submit a patch is to [fork the project on GitHub](https://help.github.com/articles/fork-a-repo/)
+and then send us a [pull request](https://help.github.com/articles/creating-a-pull-request/)
+to the `main` branch via [GitHub Pull requests](https://github.com/jetbrains-academy/Coroutines-and-channels/pulls).
+
+If you create your own fork, it might help to enable rebase by default
+when you pull by executing
+``` bash
+git config --global pull.rebase true
+```
+This will avoid your local repo having too many merge commits
+which will help keep your pull request simple and easy to apply.
+
+## Checklist
+
+Before submitting the pull request, make sure that you can say "YES" to each point in this short checklist:
+
+-[ ] You provided the link to the related issue(s) from the repository;
+-[ ] You made a reasonable amount of changes related only to the provided issues;
+-[ ] You can explain changes made in the pull request;
+-[ ] You ran the build locally and verified new functionality/fixed bugs;
+-[ ] You ran related tests locally (or add new ones) and they passed;
+-[ ] You do not have merge conflicts in the pull request.
+-[ ] You've made sure that all tests in [GitHub Actions](https://github.com/jetbrains-academy/Coroutines-and-channels/tree/main/.github/workflows) pass
diff --git a/course-info.yaml b/course-info.yaml
index 23d5f99..fc00249 100644
--- a/course-info.yaml
+++ b/course-info.yaml
@@ -2,15 +2,16 @@ type: marketplace
title: Coroutines and channels
language: English
summary: |-
- In this tutorial, you'll learn how to use coroutines in IntelliJ IDEA to perform network requests without blocking the underlying thread or callbacks.
+ In this course, you'll learn how to use coroutines in IntelliJ IDEA to perform network requests without blocking the underlying thread or callbacks.
You'll learn:
- Why and how to use suspending functions to perform network requests.
- How to send requests concurrently using coroutines.
- How to share information between different coroutines using channels.
- This tutorial is based on https://kotlinlang.org/docs/coroutines-and-channels.html
+ This course is based on Coroutines and channels tutorial
programming_language: Kotlin
content:
-- Before you start
-- Coroutines
+ - Before you start
+ - Coroutines
+ - Feedback survey