You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@beam.apache.org by pa...@apache.org on 2020/06/02 20:39:03 UTC

[beam] branch master updated: [BEAM-10027] Support for Kotlin-based Beam Katas (#11761)

This is an automated email from the ASF dual-hosted git repository.

pabloem pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/beam.git


The following commit(s) were added to refs/heads/master by this push:
     new efa8337  [BEAM-10027] Support for Kotlin-based Beam Katas (#11761)
efa8337 is described below

commit efa8337b3be5aa464dffb96733405e5fc636347a
Author: Rion Williams <ri...@gmail.com>
AuthorDate: Tue Jun 2 15:38:42 2020 -0500

    [BEAM-10027] Support for Kotlin-based Beam Katas (#11761)
    
    * initial commit and copy from existing java katas
    
    * added kotlin dependencies to gradle
    
    * updated course info and related README to reference Kotlin
    
    * converted Introduction section and tests to Kotlin; updated course metadata
    
    * converted Map section to Kotlin
    
    * converted GroupByKey section to Kotlin
    
    * converted CoGroupByKey section to Kotlin
    
    * converted remaining Combine tasks to Kotlin
    
    * minor readability improvements to tests and test naming
    
    * additional tests / readability clean-up
    
    * converted Flatten section to Kotlin
    
    * updated test to follow previous naming conventions
    
    * converted Partition lesson to Kotlin
    
    * converted Side Input section to Kotlin
    
    * updated test name to follow convention
    
    * converted Side Output lesson to Kotlin
    
    * converted remaining Core Transform sections and tests
    
    * converted Filter lessons to Kotlin
    
    * reformatted earlier conversions to mimic Java readability/spacing
    
    * updated consistent formatting per existing Java examples
    
    * additional formatting changes
    
    * additional formatting changes for previous lessons
    
    * converted remaining Common Transforms lessons
    
    * converted IO lessons
    
    * converted Windowing lessons to Kotlin
    
    * converted Triggers lessons to Kotlin
    
    * additional formatting; ensuring tests pass as expected
    
    * cleanup kotlin-specific warnings for core transforms
    
    * updated remaining core transforms
    
    * cleaned up common transforms
    
    * cleaned up io transforms
    
    * cleaned up windowing lessons
    
    * updated triggering and examples lessons
    
    * removed html task documentation and updated placeholders
    
    * added placeholders and updated descriptions
    
    * updated descrptions and placeholders
    
    * updated cogroupbykey placeholders and descriptions
    
    * updated combine lesson descriptions and placeholders
    
    * updated flatten lesson descriptions, etc.
    
    * updated partition lessons, descriptions, and placeholders
    
    * updated side output lessons, descriptions, and placeholders
    
    * updated side input/output lessons, descriptions, and placeholders
    
    * updated branching and composite transform lessons, descriptions, and placeholders
    
    * updated filter lessons, descriptions, and placeholders
    
    * updated aggregation lessons, descriptions, and placeholders
    
    * updated withkeys lessons, descriptions, and placeholders
    
    * updated io transforms, lessons, and placeholders
    
    * updated windowing lessons, descriptions, and placeholders
    
    * updated trigger lessons, descriptions, and placeholders
    
    * updated remaining triggers and examples
    
    * fixed bad placeholder
    
    * updates for initial stepik course creation
    
    * removed lingering html files
    
    * improved placeholder positioning and answer
    
    * improved combine function by exposing accumulator at task-time; removed cruft
    
    * removed unnecessary scaffolding for binary combine lesson
    
    * more placeholder updates/clean-up
    
    * more placeholder updates
    
    * reformatted per Kotlin style guide; updated placeholders through core transforms
    
    * updated placeholders for Common Transforms, IO, and Windowing sections
    
    * updated Triggers and Examples section placeholders
    
    * changed WordAlphabet to data class
    
    * converted classes to data classes where applicable; removed unused imports
    
    * updated stepik course and adjusted course summary metadata
    
    * added missing data class
    
    * minor requested changes
    
    * fixed accumulator syntax
    
    * adjust windowed event to data class
    
    * updated stepik course
    
    * added 2 space indenting, updated placeholders, removed unused imports
    
    * updated course post formatting changes
    
    * removed returns from Map-related placeholders; updated course
    
    * added licensing information to task metadata
    
    * added missing license header to Introduction section
---
 .../commontransforms/aggregation/count/Task.kt     |  46 +++++
 .../Aggregation/Count/task-info.yaml               |  29 ++++
 .../Aggregation/Count/task-remote-info.yaml        |   2 +
 .../Common Transforms/Aggregation/Count/task.md    |  27 +++
 .../commontransforms/aggregation/count/TaskTest.kt |  43 +++++
 .../katas/commontransforms/aggregation/max/Task.kt |  46 +++++
 .../Aggregation/Max/task-info.yaml                 |  29 ++++
 .../Aggregation/Max/task-remote-info.yaml          |   2 +
 .../Common Transforms/Aggregation/Max/task.md      |  27 +++
 .../commontransforms/aggregation/max/TaskTest.kt   |  43 +++++
 .../commontransforms/aggregation/mean/Task.kt      |  46 +++++
 .../Aggregation/Mean/task-info.yaml                |  29 ++++
 .../Aggregation/Mean/task-remote-info.yaml         |   2 +
 .../Common Transforms/Aggregation/Mean/task.md     |  27 +++
 .../commontransforms/aggregation/mean/TaskTest.kt  |  43 +++++
 .../katas/commontransforms/aggregation/min/Task.kt |  46 +++++
 .../Aggregation/Min/task-info.yaml                 |  29 ++++
 .../Aggregation/Min/task-remote-info.yaml          |   2 +
 .../Common Transforms/Aggregation/Min/task.md      |  27 +++
 .../commontransforms/aggregation/min/TaskTest.kt   |  43 +++++
 .../katas/commontransforms/aggregation/sum/Task.kt |  45 +++++
 .../Aggregation/Sum/task-info.yaml                 |  29 ++++
 .../Aggregation/Sum/task-remote-info.yaml          |   2 +
 .../Common Transforms/Aggregation/Sum/task.md      |  27 +++
 .../commontransforms/aggregation/sum/TaskTest.kt   |  42 +++++
 .../Common Transforms/Aggregation/lesson-info.yaml |  25 +++
 .../Aggregation/lesson-remote-info.yaml            |   3 +
 .../katas/commontransforms/filter/filter/Task.kt   |  47 +++++
 .../Common Transforms/Filter/Filter/task-info.yaml |  29 ++++
 .../Filter/Filter/task-remote-info.yaml            |   2 +
 .../kotlin/Common Transforms/Filter/Filter/task.md |  30 ++++
 .../commontransforms/filter/filter/TaskTest.kt     |  43 +++++
 .../katas/commontransforms/filter/pardo/Task.kt    |  57 +++++++
 .../Common Transforms/Filter/ParDo/task-info.yaml  |  29 ++++
 .../Filter/ParDo/task-remote-info.yaml             |   2 +
 .../kotlin/Common Transforms/Filter/ParDo/task.md  |  30 ++++
 .../commontransforms/filter/pardo/TaskTest.kt      |  43 +++++
 .../Common Transforms/Filter/lesson-info.yaml      |  22 +++
 .../Filter/lesson-remote-info.yaml                 |   3 +
 .../katas/commontransforms/withkeys/Task.kt        |  53 ++++++
 .../WithKeys/WithKeys/task-info.yaml               |  29 ++++
 .../WithKeys/WithKeys/task-remote-info.yaml        |   2 +
 .../Common Transforms/WithKeys/WithKeys/task.md    |  33 ++++
 .../katas/commontransforms/withkeys/TaskTest.kt    |  51 ++++++
 .../Common Transforms/WithKeys/lesson-info.yaml    |  21 +++
 .../WithKeys/lesson-remote-info.yaml               |   3 +
 .../kotlin/Common Transforms/section-info.yaml     |  23 +++
 .../Common Transforms/section-remote-info.yaml     |   2 +
 .../katas/coretransforms/branching/Task.kt         |  63 +++++++
 .../Branching/Branching/task-info.yaml             |  32 ++++
 .../Branching/Branching/task-remote-info.yaml      |   2 +
 .../Core Transforms/Branching/Branching/task.md    |  32 ++++
 .../katas/coretransforms/branching/TaskTest.kt     |  47 +++++
 .../Core Transforms/Branching/lesson-info.yaml     |  21 +++
 .../Branching/lesson-remote-info.yaml              |   3 +
 .../katas/coretransforms/cogroupbykey/Task.kt      |  84 +++++++++
 .../coretransforms/cogroupbykey/WordsAlphabet.kt   |  24 +++
 .../CoGroupByKey/CoGroupByKey/task-info.yaml       |  31 ++++
 .../CoGroupByKey/task-remote-info.yaml             |   2 +
 .../CoGroupByKey/CoGroupByKey/task.md              |  43 +++++
 .../katas/coretransforms/cogroupbykey/TaskTest.kt  |  54 ++++++
 .../Core Transforms/CoGroupByKey/lesson-info.yaml  |  21 +++
 .../CoGroupByKey/lesson-remote-info.yaml           |   3 +
 .../combine/binarycombinefnlambda/Task.kt          |  52 ++++++
 .../Combine/BinaryCombineFn Lambda/task-info.yaml  |  29 ++++
 .../BinaryCombineFn Lambda/task-remote-info.yaml   |   2 +
 .../Combine/BinaryCombineFn Lambda/task.md         |  40 +++++
 .../combine/binarycombinefnlambda/TaskTest.kt      |  47 +++++
 .../coretransforms/combine/binarycombinefn/Task.kt |  59 +++++++
 .../Combine/BinaryCombineFn/task-info.yaml         |  29 ++++
 .../Combine/BinaryCombineFn/task-remote-info.yaml  |   2 +
 .../Combine/BinaryCombineFn/task.md                |  45 +++++
 .../combine/binarycombinefn/TaskTest.kt            |  47 +++++
 .../coretransforms/combine/combineperkey/Task.kt   |  63 +++++++
 .../Combine/Combine PerKey/task-info.yaml          |  32 ++++
 .../Combine/Combine PerKey/task-remote-info.yaml   |   2 +
 .../Core Transforms/Combine/Combine PerKey/task.md |  46 +++++
 .../combine/combineperkey/TaskTest.kt              |  49 ++++++
 .../katas/coretransforms/combine/combinefn/Task.kt |  79 +++++++++
 .../Combine/CombineFn/task-info.yaml               |  29 ++++
 .../Combine/CombineFn/task-remote-info.yaml        |   2 +
 .../Core Transforms/Combine/CombineFn/task.md      |  47 +++++
 .../coretransforms/combine/combinefn/TaskTest.kt   |  43 +++++
 .../katas/coretransforms/combine/simple/Task.kt    |  53 ++++++
 .../Combine/Simple Function/task-info.yaml         |  29 ++++
 .../Combine/Simple Function/task-remote-info.yaml  |   2 +
 .../Combine/Simple Function/task.md                |  44 +++++
 .../coretransforms/combine/simple/TaskTest.kt      |  43 +++++
 .../Core Transforms/Combine/lesson-info.yaml       |  25 +++
 .../Combine/lesson-remote-info.yaml                |   3 +
 .../katas/coretransforms/composite/Task.kt         |  62 +++++++
 .../Composite Transform/task-info.yaml             |  29 ++++
 .../Composite Transform/task-remote-info.yaml      |   2 +
 .../Composite Transform/task.md                    |  47 +++++
 .../katas/coretransforms/composite/TaskTest.kt     |  44 +++++
 .../Composite Transform/lesson-info.yaml           |  21 +++
 .../Composite Transform/lesson-remote-info.yaml    |   3 +
 .../coretransforms/dofnadditionalparams/Task.kt    |  31 ++++
 .../DoFn Additional Parameters/task-info.yaml      |  25 +++
 .../task-remote-info.yaml                          |   2 +
 .../DoFn Additional Parameters/task.md             |  38 +++++
 .../dofnadditionalparams/TaskTest.kt               |  20 +++
 .../DoFn Additional Parameters/lesson-info.yaml    |  21 +++
 .../lesson-remote-info.yaml                        |   3 +
 .../learning/katas/coretransforms/flatten/Task.kt  |  58 +++++++
 .../Core Transforms/Flatten/Flatten/task-info.yaml |  29 ++++
 .../Flatten/Flatten/task-remote-info.yaml          |   2 +
 .../kotlin/Core Transforms/Flatten/Flatten/task.md |  39 +++++
 .../katas/coretransforms/flatten/TaskTest.kt       |  49 ++++++
 .../Core Transforms/Flatten/lesson-info.yaml       |  21 +++
 .../Flatten/lesson-remote-info.yaml                |   3 +
 .../katas/coretransforms/groupbykey/Task.kt        |  58 +++++++
 .../GroupByKey/GroupByKey/task-info.yaml           |  29 ++++
 .../GroupByKey/GroupByKey/task-remote-info.yaml    |   2 +
 .../Core Transforms/GroupByKey/GroupByKey/task.md  |  43 +++++
 .../katas/coretransforms/groupbykey/TaskTest.kt    |  52 ++++++
 .../Core Transforms/GroupByKey/lesson-info.yaml    |  21 +++
 .../GroupByKey/lesson-remote-info.yaml             |   3 +
 .../coretransforms/map/flatmapelements/Task.kt     |  54 ++++++
 .../Map/FlatMapElements/task-info.yaml             |  29 ++++
 .../Map/FlatMapElements/task-remote-info.yaml      |   2 +
 .../Core Transforms/Map/FlatMapElements/task.md    |  39 +++++
 .../coretransforms/map/flatmapelements/TaskTest.kt |  44 +++++
 .../katas/coretransforms/map/mapelements/Task.kt   |  52 ++++++
 .../Core Transforms/Map/MapElements/task-info.yaml |  29 ++++
 .../Map/MapElements/task-remote-info.yaml          |   2 +
 .../kotlin/Core Transforms/Map/MapElements/task.md |  38 +++++
 .../coretransforms/map/mapelements/TaskTest.kt     |  43 +++++
 .../coretransforms/map/pardoonetomany/Task.kt      |  55 ++++++
 .../Map/ParDo OneToMany/task-info.yaml             |  29 ++++
 .../Map/ParDo OneToMany/task-remote-info.yaml      |   2 +
 .../Core Transforms/Map/ParDo OneToMany/task.md    |  37 ++++
 .../coretransforms/map/pardoonetomany/TaskTest.kt  |  41 +++++
 .../katas/coretransforms/map/pardo/Task.kt         |  54 ++++++
 .../Core Transforms/Map/ParDo/task-info.yaml       |  29 ++++
 .../Map/ParDo/task-remote-info.yaml                |   2 +
 .../katas/kotlin/Core Transforms/Map/ParDo/task.md |  40 +++++
 .../katas/coretransforms/map/pardo/TaskTest.kt     |  44 +++++
 .../kotlin/Core Transforms/Map/lesson-info.yaml    |  24 +++
 .../Core Transforms/Map/lesson-remote-info.yaml    |   3 +
 .../katas/coretransforms/partition/Task.kt         |  57 +++++++
 .../Partition/Partition/task-info.yaml             |  29 ++++
 .../Partition/Partition/task-remote-info.yaml      |   2 +
 .../Core Transforms/Partition/Partition/task.md    |  44 +++++
 .../katas/coretransforms/partition/TaskTest.kt     |  44 +++++
 .../Core Transforms/Partition/lesson-info.yaml     |  21 +++
 .../Partition/lesson-remote-info.yaml              |   3 +
 .../katas/coretransforms/sideinput/Person.kt       |  22 +++
 .../katas/coretransforms/sideinput/Task.kt         |  90 ++++++++++
 .../Side Input/Side Input/src/task.md              |  52 ++++++
 .../Side Input/Side Input/task-info.yaml           |  34 ++++
 .../Side Input/Side Input/task-remote-info.yaml    |   2 +
 .../Core Transforms/Side Input/Side Input/task.md  |  52 ++++++
 .../katas/coretransforms/sideinput/TaskTest.kt     |  72 ++++++++
 .../Core Transforms/Side Input/lesson-info.yaml    |  21 +++
 .../Side Input/lesson-remote-info.yaml             |   3 +
 .../katas/coretransforms/sideoutput/Task.kt        |  68 ++++++++
 .../Side Output/Side Output/src/task.md            |  42 +++++
 .../Side Output/Side Output/task-info.yaml         |  29 ++++
 .../Side Output/Side Output/task-remote-info.yaml  |   2 +
 .../Side Output/Side Output/task.md                |  42 +++++
 .../katas/coretransforms/sideoutput/TaskTest.kt    |  49 ++++++
 .../Core Transforms/Side Output/lesson-info.yaml   |  21 +++
 .../Side Output/lesson-remote-info.yaml            |   3 +
 .../katas/kotlin/Core Transforms/section-info.yaml |  31 ++++
 .../Core Transforms/section-remote-info.yaml       |   2 +
 .../beam/learning/katas/examples/wordcount/Task.kt |  66 +++++++
 .../Examples/Word Count/Word Count/task-info.yaml  |  29 ++++
 .../Word Count/Word Count/task-remote-info.yaml    |   2 +
 .../kotlin/Examples/Word Count/Word Count/task.md  |  33 ++++
 .../learning/katas/examples/wordcount/TaskTest.kt  |  53 ++++++
 .../kotlin/Examples/Word Count/lesson-info.yaml    |  21 +++
 .../Examples/Word Count/lesson-remote-info.yaml    |   3 +
 learning/katas/kotlin/Examples/section-info.yaml   |  21 +++
 .../katas/kotlin/Examples/section-remote-info.yaml |   2 +
 .../beam/learning/katas/io/builtinios/Task.kt      |  31 ++++
 .../IO/Built-in IOs/Built-in IOs/task-info.yaml    |  25 +++
 .../Built-in IOs/task-remote-info.yaml             |   2 +
 .../kotlin/IO/Built-in IOs/Built-in IOs/task.md    |  29 ++++
 .../beam/learning/katas/io/builtinios/TaskTest.kt  |  20 +++
 .../katas/kotlin/IO/Built-in IOs/lesson-info.yaml  |  21 +++
 .../kotlin/IO/Built-in IOs/lesson-remote-info.yaml |   3 +
 .../kotlin/IO/TextIO/TextIO Read/countries.txt     |  10 ++
 .../beam/learning/katas/io/textio/read/Task.kt     |  54 ++++++
 .../kotlin/IO/TextIO/TextIO Read/task-info.yaml    |  34 ++++
 .../IO/TextIO/TextIO Read/task-remote-info.yaml    |   2 +
 .../katas/kotlin/IO/TextIO/TextIO Read/task.md     |  44 +++++
 .../beam/learning/katas/io/textio/read/TaskTest.kt |  53 ++++++
 learning/katas/kotlin/IO/TextIO/lesson-info.yaml   |  21 +++
 .../katas/kotlin/IO/TextIO/lesson-remote-info.yaml |   3 +
 learning/katas/kotlin/IO/section-info.yaml         |  22 +++
 learning/katas/kotlin/IO/section-remote-info.yaml  |   2 +
 .../apache/beam/learning/katas/intro/hello/Task.kt |  43 +++++
 .../Hello Beam/Hello Beam/task-info.yaml           |  29 ++++
 .../Hello Beam/Hello Beam/task-remote-info.yaml    |   2 +
 .../Introduction/Hello Beam/Hello Beam/task.md     |   0
 .../beam/learning/katas/intro/hello/TaskTest.kt    |  40 +++++
 .../Introduction/Hello Beam/lesson-info.yaml       |  21 +++
 .../Hello Beam/lesson-remote-info.yaml             |   3 +
 .../katas/kotlin/Introduction/section-info.yaml    |  21 +++
 .../kotlin/Introduction/section-remote-info.yaml   |   2 +
 learning/katas/kotlin/README.md                    |  31 ++++
 .../katas/triggers/earlytriggers/GenerateEvent.kt  |  41 +++++
 .../learning/katas/triggers/earlytriggers/Task.kt  |  62 +++++++
 .../Early Triggers/Early Triggers/task-info.yaml   |  31 ++++
 .../Early Triggers/task-remote-info.yaml           |   2 +
 .../Triggers/Early Triggers/Early Triggers/task.md |  60 +++++++
 .../katas/triggers/earlytriggers/TaskTest.kt       |  64 +++++++
 .../Triggers/Early Triggers/lesson-info.yaml       |  21 +++
 .../Early Triggers/lesson-remote-info.yaml         |   3 +
 .../triggers/eventtimetriggers/GenerateEvent.kt    |  41 +++++
 .../katas/triggers/eventtimetriggers/Task.kt       |  57 +++++++
 .../Event Time Triggers/task-info.yaml             |  31 ++++
 .../Event Time Triggers/task-remote-info.yaml      |   2 +
 .../Event Time Triggers/task.md                    |  72 ++++++++
 .../katas/triggers/eventtimetriggers/TaskTest.kt   |  67 ++++++++
 .../Triggers/Event Time Triggers/lesson-info.yaml  |  21 +++
 .../Event Time Triggers/lesson-remote-info.yaml    |   3 +
 .../triggers/windowaccummode/GenerateEvent.kt      |  41 +++++
 .../katas/triggers/windowaccummode/Task.kt         |  62 +++++++
 .../Window Accumulation Mode/task-info.yaml        |  31 ++++
 .../Window Accumulation Mode/task-remote-info.yaml |   2 +
 .../Window Accumulation Mode/task.md               |  65 +++++++
 .../katas/triggers/windowaccummode/TaskTest.kt     |  64 +++++++
 .../Window Accumulation Mode/lesson-info.yaml      |  21 +++
 .../lesson-remote-info.yaml                        |   3 +
 learning/katas/kotlin/Triggers/section-info.yaml   |  23 +++
 .../katas/kotlin/Triggers/section-remote-info.yaml |   2 +
 .../katas/windowing/addingtimestamp/pardo/Event.kt |  23 +++
 .../katas/windowing/addingtimestamp/pardo/Task.kt  |  61 +++++++
 .../Adding Timestamp/ParDo/task-info.yaml          |  31 ++++
 .../Adding Timestamp/ParDo/task-remote-info.yaml   |   2 +
 .../Windowing/Adding Timestamp/ParDo/task.md       |  46 +++++
 .../windowing/addingtimestamp/pardo/TaskTest.kt    |  77 +++++++++
 .../addingtimestamp/withtimestamps/Event.kt        |  23 +++
 .../addingtimestamp/withtimestamps/Task.kt         |  55 ++++++
 .../Adding Timestamp/WithTimestamps/task-info.yaml |  31 ++++
 .../WithTimestamps/task-remote-info.yaml           |   2 +
 .../Adding Timestamp/WithTimestamps/task.md        |  39 +++++
 .../addingtimestamp/withtimestamps/TaskTest.kt     |  75 ++++++++
 .../Windowing/Adding Timestamp/lesson-info.yaml    |  22 +++
 .../Adding Timestamp/lesson-remote-info.yaml       |   3 +
 .../learning/katas/windowing/fixedwindow/Task.kt   |  66 +++++++
 .../Fixed Time Window/task-info.yaml               |  31 ++++
 .../Fixed Time Window/task-remote-info.yaml        |   2 +
 .../Fixed Time Window/Fixed Time Window/task.md    |  53 ++++++
 .../katas/windowing/fixedwindow/TaskTest.kt        |  81 +++++++++
 .../katas/windowing/fixedwindow/WindowedEvent.kt   |  22 +++
 .../Windowing/Fixed Time Window/lesson-info.yaml   |  21 +++
 .../Fixed Time Window/lesson-remote-info.yaml      |   3 +
 learning/katas/kotlin/Windowing/section-info.yaml  |  22 +++
 .../kotlin/Windowing/section-remote-info.yaml      |   2 +
 learning/katas/kotlin/build.gradle                 | 134 +++++++++++++++
 learning/katas/kotlin/course-info.yaml             |  32 ++++
 learning/katas/kotlin/course-remote-info.yaml      |   2 +
 .../katas/kotlin/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 55190 bytes
 .../gradle/wrapper/gradle-wrapper.properties       |  23 +++
 learning/katas/kotlin/gradlew                      | 190 +++++++++++++++++++++
 learning/katas/kotlin/gradlew.bat                  | 102 +++++++++++
 learning/katas/kotlin/settings.gradle              |  43 +++++
 learning/katas/kotlin/util/resources/log4j2.xml    |  31 ++++
 .../src/org/apache/beam/learning/katas/util/Log.kt |  63 +++++++
 .../apache/beam/learning/katas/util/ContainsKvs.kt |  58 +++++++
 .../apache/beam/learning/katas/util/KvMatcher.kt   |  47 +++++
 264 files changed, 8214 insertions(+)

diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Count/src/org/apache/beam/learning/katas/commontransforms/aggregation/count/Task.kt b/learning/katas/kotlin/Common Transforms/Aggregation/Count/src/org/apache/beam/learning/katas/commontransforms/aggregation/count/Task.kt
new file mode 100644
index 0000000..5f689c3
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Count/src/org/apache/beam/learning/katas/commontransforms/aggregation/count/Task.kt	
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.aggregation.count
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Count
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.values.PCollection
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val numbers = pipeline.apply(Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
+
+    val output = applyTransform(numbers)
+
+    output.apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun applyTransform(input: PCollection<Int>): PCollection<Long> {
+    return input.apply(Count.globally())
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Count/task-info.yaml b/learning/katas/kotlin/Common Transforms/Aggregation/Count/task-info.yaml
new file mode 100644
index 0000000..5718c4c
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Count/task-info.yaml	
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/commontransforms/aggregation/count/Task.kt
+  visible: true
+  placeholders:
+  - offset: 1599
+    length: 29
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/commontransforms/aggregation/count/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Count/task-remote-info.yaml b/learning/katas/kotlin/Common Transforms/Aggregation/Count/task-remote-info.yaml
new file mode 100644
index 0000000..0e9dafb
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Count/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326891
+update_date: Sat, 30 May 2020 18:48:45 UTC
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Count/task.md b/learning/katas/kotlin/Common Transforms/Aggregation/Count/task.md
new file mode 100644
index 0000000..1c4eba0
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Count/task.md	
@@ -0,0 +1,27 @@
+<!--
+  ~  Licensed to the Apache Software Foundation (ASF) under one
+  ~  or more contributor license agreements.  See the NOTICE file
+  ~  distributed with this work for additional information
+  ~  regarding copyright ownership.  The ASF licenses this file
+  ~  to you 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.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  -->
+
+Aggregation - Count
+-------------------
+
+**Kata:** Count the number of elements from an input.
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Count.html">
+  Count</a>.
+</div>
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Count/test/org/apache/beam/learning/katas/commontransforms/aggregation/count/TaskTest.kt b/learning/katas/kotlin/Common Transforms/Aggregation/Count/test/org/apache/beam/learning/katas/commontransforms/aggregation/count/TaskTest.kt
new file mode 100644
index 0000000..a979bd7
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Count/test/org/apache/beam/learning/katas/commontransforms/aggregation/count/TaskTest.kt	
@@ -0,0 +1,43 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.aggregation.count
+
+import org.apache.beam.learning.katas.commontransforms.aggregation.count.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+  @Transient
+  @get:Rule
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun common_transforms_aggregation_count() {
+    val values = Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+    val numbers = testPipeline.apply(values)
+
+    val results = applyTransform(numbers)
+
+    PAssert.that(results).containsInAnyOrder(10L)
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Max/src/org/apache/beam/learning/katas/commontransforms/aggregation/max/Task.kt b/learning/katas/kotlin/Common Transforms/Aggregation/Max/src/org/apache/beam/learning/katas/commontransforms/aggregation/max/Task.kt
new file mode 100644
index 0000000..cab0f68
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Max/src/org/apache/beam/learning/katas/commontransforms/aggregation/max/Task.kt	
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.aggregation.max
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.Max
+import org.apache.beam.sdk.values.PCollection
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val numbers = pipeline.apply(Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
+
+    val output = applyTransform(numbers)
+
+    output.apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun applyTransform(input: PCollection<Int>): PCollection<Int> {
+    return input.apply(Max.integersGlobally())
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Max/task-info.yaml b/learning/katas/kotlin/Common Transforms/Aggregation/Max/task-info.yaml
new file mode 100644
index 0000000..aa6cfca
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Max/task-info.yaml	
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/commontransforms/aggregation/max/Task.kt
+  visible: true
+  placeholders:
+  - offset: 1594
+    length: 35
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/commontransforms/aggregation/max/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Max/task-remote-info.yaml b/learning/katas/kotlin/Common Transforms/Aggregation/Max/task-remote-info.yaml
new file mode 100644
index 0000000..6e6314a
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Max/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326899
+update_date: Sat, 30 May 2020 18:48:55 UTC
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Max/task.md b/learning/katas/kotlin/Common Transforms/Aggregation/Max/task.md
new file mode 100644
index 0000000..541a380
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Max/task.md	
@@ -0,0 +1,27 @@
+<!--
+  ~  Licensed to the Apache Software Foundation (ASF) under one
+  ~  or more contributor license agreements.  See the NOTICE file
+  ~  distributed with this work for additional information
+  ~  regarding copyright ownership.  The ASF licenses this file
+  ~  to you 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.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  -->
+
+Aggregation - Max
+-----------------
+
+**Kata:** Compute the maximum of the elements from an input.
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Max.html">
+  Max</a>.
+</div>
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Max/test/org/apache/beam/learning/katas/commontransforms/aggregation/max/TaskTest.kt b/learning/katas/kotlin/Common Transforms/Aggregation/Max/test/org/apache/beam/learning/katas/commontransforms/aggregation/max/TaskTest.kt
new file mode 100644
index 0000000..e17b1fc
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Max/test/org/apache/beam/learning/katas/commontransforms/aggregation/max/TaskTest.kt	
@@ -0,0 +1,43 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.aggregation.max
+
+import org.apache.beam.learning.katas.commontransforms.aggregation.max.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun common_transforms_aggregation_max() {
+    val values = Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+    val numbers = testPipeline.apply(values)
+
+    val results = applyTransform(numbers)
+
+    PAssert.that(results).containsInAnyOrder(10)
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Mean/src/org/apache/beam/learning/katas/commontransforms/aggregation/mean/Task.kt b/learning/katas/kotlin/Common Transforms/Aggregation/Mean/src/org/apache/beam/learning/katas/commontransforms/aggregation/mean/Task.kt
new file mode 100644
index 0000000..0c4943d
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Mean/src/org/apache/beam/learning/katas/commontransforms/aggregation/mean/Task.kt	
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.aggregation.mean
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.Mean
+import org.apache.beam.sdk.values.PCollection
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val numbers = pipeline.apply(Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
+
+    val output = applyTransform(numbers)
+
+    output.apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun applyTransform(input: PCollection<Int>): PCollection<Double> {
+    return input.apply(Mean.globally())
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Mean/task-info.yaml b/learning/katas/kotlin/Common Transforms/Aggregation/Mean/task-info.yaml
new file mode 100644
index 0000000..6f46aa6
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Mean/task-info.yaml	
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/commontransforms/aggregation/mean/Task.kt
+  visible: true
+  placeholders:
+  - offset: 1599
+    length: 28
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/commontransforms/aggregation/mean/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Mean/task-remote-info.yaml b/learning/katas/kotlin/Common Transforms/Aggregation/Mean/task-remote-info.yaml
new file mode 100644
index 0000000..bd2f905
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Mean/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326897
+update_date: Sat, 30 May 2020 18:48:51 UTC
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Mean/task.md b/learning/katas/kotlin/Common Transforms/Aggregation/Mean/task.md
new file mode 100644
index 0000000..b08fd97
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Mean/task.md	
@@ -0,0 +1,27 @@
+<!--
+  ~  Licensed to the Apache Software Foundation (ASF) under one
+  ~  or more contributor license agreements.  See the NOTICE file
+  ~  distributed with this work for additional information
+  ~  regarding copyright ownership.  The ASF licenses this file
+  ~  to you 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.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  -->
+
+Aggregation - Mean
+------------------
+
+**Kata:** Compute the mean/average of all elements from an input.
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Mean.html">
+  Mean</a>.
+</div>
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Mean/test/org/apache/beam/learning/katas/commontransforms/aggregation/mean/TaskTest.kt b/learning/katas/kotlin/Common Transforms/Aggregation/Mean/test/org/apache/beam/learning/katas/commontransforms/aggregation/mean/TaskTest.kt
new file mode 100644
index 0000000..48657a8
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Mean/test/org/apache/beam/learning/katas/commontransforms/aggregation/mean/TaskTest.kt	
@@ -0,0 +1,43 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.aggregation.mean
+
+import org.apache.beam.learning.katas.commontransforms.aggregation.mean.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun common_transforms_aggregation_mean() {
+    val values = Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+    val numbers = testPipeline.apply(values)
+
+    val results = applyTransform(numbers)
+
+    PAssert.that(results).containsInAnyOrder(5.5)
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Min/src/org/apache/beam/learning/katas/commontransforms/aggregation/min/Task.kt b/learning/katas/kotlin/Common Transforms/Aggregation/Min/src/org/apache/beam/learning/katas/commontransforms/aggregation/min/Task.kt
new file mode 100644
index 0000000..7d1c95d
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Min/src/org/apache/beam/learning/katas/commontransforms/aggregation/min/Task.kt	
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.aggregation.min
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.Min
+import org.apache.beam.sdk.values.PCollection
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val numbers = pipeline.apply(Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
+
+    val output = applyTransform(numbers)
+
+    output.apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun applyTransform(input: PCollection<Int>): PCollection<Int> {
+    return input.apply(Min.integersGlobally())
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Min/task-info.yaml b/learning/katas/kotlin/Common Transforms/Aggregation/Min/task-info.yaml
new file mode 100644
index 0000000..5fbe869
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Min/task-info.yaml	
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/commontransforms/aggregation/min/Task.kt
+  visible: true
+  placeholders:
+  - offset: 1594
+    length: 35
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/commontransforms/aggregation/min/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Min/task-remote-info.yaml b/learning/katas/kotlin/Common Transforms/Aggregation/Min/task-remote-info.yaml
new file mode 100644
index 0000000..0d5fbea
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Min/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326898
+update_date: Sat, 30 May 2020 18:48:53 UTC
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Min/task.md b/learning/katas/kotlin/Common Transforms/Aggregation/Min/task.md
new file mode 100644
index 0000000..da5b319
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Min/task.md	
@@ -0,0 +1,27 @@
+<!--
+  ~  Licensed to the Apache Software Foundation (ASF) under one
+  ~  or more contributor license agreements.  See the NOTICE file
+  ~  distributed with this work for additional information
+  ~  regarding copyright ownership.  The ASF licenses this file
+  ~  to you 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.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  -->
+
+Aggregation - Min
+-----------------
+
+**Kata:** Compute the minimum of the elements from an input.
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Min.html">
+  Min</a>.
+</div>
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Min/test/org/apache/beam/learning/katas/commontransforms/aggregation/min/TaskTest.kt b/learning/katas/kotlin/Common Transforms/Aggregation/Min/test/org/apache/beam/learning/katas/commontransforms/aggregation/min/TaskTest.kt
new file mode 100644
index 0000000..ffcfee1
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Min/test/org/apache/beam/learning/katas/commontransforms/aggregation/min/TaskTest.kt	
@@ -0,0 +1,43 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.aggregation.min
+
+import org.apache.beam.learning.katas.commontransforms.aggregation.min.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun common_transforms_aggregation_min() {
+    val values = Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+    val numbers = testPipeline.apply(values)
+
+    val results = applyTransform(numbers)
+
+    PAssert.that(results).containsInAnyOrder(1)
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Sum/src/org/apache/beam/learning/katas/commontransforms/aggregation/sum/Task.kt b/learning/katas/kotlin/Common Transforms/Aggregation/Sum/src/org/apache/beam/learning/katas/commontransforms/aggregation/sum/Task.kt
new file mode 100644
index 0000000..1dce924
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Sum/src/org/apache/beam/learning/katas/commontransforms/aggregation/sum/Task.kt	
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.aggregation.sum
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.Sum
+import org.apache.beam.sdk.values.PCollection
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val numbers = pipeline.apply(Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
+
+    val output = applyTransform(numbers)
+
+    output.apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  fun applyTransform(input: PCollection<Int>): PCollection<Int> {
+    return input.apply(Sum.integersGlobally())
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Sum/task-info.yaml b/learning/katas/kotlin/Common Transforms/Aggregation/Sum/task-info.yaml
new file mode 100644
index 0000000..f2b427d
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Sum/task-info.yaml	
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: test/org/apache/beam/learning/katas/commontransforms/aggregation/sum/TaskTest.kt
+  visible: false
+- name: src/org/apache/beam/learning/katas/commontransforms/aggregation/sum/Task.kt
+  visible: true
+  placeholders:
+  - offset: 1581
+    length: 35
+    placeholder_text: TODO()
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Sum/task-remote-info.yaml b/learning/katas/kotlin/Common Transforms/Aggregation/Sum/task-remote-info.yaml
new file mode 100644
index 0000000..4660c8e
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Sum/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326894
+update_date: Sat, 30 May 2020 18:48:47 UTC
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Sum/task.md b/learning/katas/kotlin/Common Transforms/Aggregation/Sum/task.md
new file mode 100644
index 0000000..2031bba
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Sum/task.md	
@@ -0,0 +1,27 @@
+<!--
+  ~  Licensed to the Apache Software Foundation (ASF) under one
+  ~  or more contributor license agreements.  See the NOTICE file
+  ~  distributed with this work for additional information
+  ~  regarding copyright ownership.  The ASF licenses this file
+  ~  to you 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.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  -->
+
+Aggregation - Sum
+-----------------
+
+**Kata:** Compute the sum of all elements from an input.
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Sum.html">
+  Sum</a>.
+</div>
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/Sum/test/org/apache/beam/learning/katas/commontransforms/aggregation/sum/TaskTest.kt b/learning/katas/kotlin/Common Transforms/Aggregation/Sum/test/org/apache/beam/learning/katas/commontransforms/aggregation/sum/TaskTest.kt
new file mode 100644
index 0000000..3e6d586
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/Sum/test/org/apache/beam/learning/katas/commontransforms/aggregation/sum/TaskTest.kt	
@@ -0,0 +1,42 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.aggregation.sum
+
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun common_transforms_aggregation_sum() {
+    val values = Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+    val numbers = testPipeline.apply(values)
+
+    val results = Task.applyTransform(numbers)
+
+    PAssert.that(results).containsInAnyOrder(55)
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/lesson-info.yaml b/learning/katas/kotlin/Common Transforms/Aggregation/lesson-info.yaml
new file mode 100644
index 0000000..8ea5f25
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/lesson-info.yaml	
@@ -0,0 +1,25 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Count
+- Sum
+- Mean
+- Min
+- Max
diff --git a/learning/katas/kotlin/Common Transforms/Aggregation/lesson-remote-info.yaml b/learning/katas/kotlin/Common Transforms/Aggregation/lesson-remote-info.yaml
new file mode 100644
index 0000000..45fb600
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Aggregation/lesson-remote-info.yaml	
@@ -0,0 +1,3 @@
+id: 358533
+update_date: Wed, 20 May 2020 20:28:33 UTC
+unit: 342734
diff --git a/learning/katas/kotlin/Common Transforms/Filter/Filter/src/org/apache/beam/learning/katas/commontransforms/filter/filter/Task.kt b/learning/katas/kotlin/Common Transforms/Filter/Filter/src/org/apache/beam/learning/katas/commontransforms/filter/filter/Task.kt
new file mode 100644
index 0000000..1e34761
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Filter/Filter/src/org/apache/beam/learning/katas/commontransforms/filter/filter/Task.kt	
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.filter.filter
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.Filter
+import org.apache.beam.sdk.transforms.SerializableFunction
+import org.apache.beam.sdk.values.PCollection
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val numbers = pipeline.apply(Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
+
+    val output = applyTransform(numbers)
+
+    output.apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun applyTransform(input: PCollection<Int>): PCollection<Int> {
+    return input.apply(Filter.by(SerializableFunction { number: Int -> number % 2 == 0 }))
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/Filter/Filter/task-info.yaml b/learning/katas/kotlin/Common Transforms/Filter/Filter/task-info.yaml
new file mode 100644
index 0000000..ccfec4b
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Filter/Filter/task-info.yaml	
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/commontransforms/filter/filter/Task.kt
+  visible: true
+  placeholders:
+  - offset: 1654
+    length: 79
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/commontransforms/filter/filter/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Common Transforms/Filter/Filter/task-remote-info.yaml b/learning/katas/kotlin/Common Transforms/Filter/Filter/task-remote-info.yaml
new file mode 100644
index 0000000..142dd53
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Filter/Filter/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326890
+update_date: Sat, 30 May 2020 18:48:43 UTC
diff --git a/learning/katas/kotlin/Common Transforms/Filter/Filter/task.md b/learning/katas/kotlin/Common Transforms/Filter/Filter/task.md
new file mode 100644
index 0000000..e499074
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Filter/Filter/task.md	
@@ -0,0 +1,30 @@
+<!--
+  ~  Licensed to the Apache Software Foundation (ASF) under one
+  ~  or more contributor license agreements.  See the NOTICE file
+  ~  distributed with this work for additional information
+  ~  regarding copyright ownership.  The ASF licenses this file
+  ~  to you 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.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  -->
+
+Filter
+------
+
+The Beam SDKs provide language-specific ways to simplify how you provide your DoFn implementation.
+
+**Kata:** Implement a filter function that filters out the odd numbers by using 
+[Filter](https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Filter.html).
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Filter.html">
+  Filter.by(...)</a>.
+</div>
diff --git a/learning/katas/kotlin/Common Transforms/Filter/Filter/test/org/apache/beam/learning/katas/commontransforms/filter/filter/TaskTest.kt b/learning/katas/kotlin/Common Transforms/Filter/Filter/test/org/apache/beam/learning/katas/commontransforms/filter/filter/TaskTest.kt
new file mode 100644
index 0000000..57efeba
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Filter/Filter/test/org/apache/beam/learning/katas/commontransforms/filter/filter/TaskTest.kt	
@@ -0,0 +1,43 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.filter.filter
+
+import org.apache.beam.learning.katas.commontransforms.filter.filter.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun common_transforms_filter_filter() {
+    val values = Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+    val numbers = testPipeline.apply(values)
+
+    val results = applyTransform(numbers)
+
+    PAssert.that(results).containsInAnyOrder(2, 4, 6, 8, 10)
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/Filter/ParDo/src/org/apache/beam/learning/katas/commontransforms/filter/pardo/Task.kt b/learning/katas/kotlin/Common Transforms/Filter/ParDo/src/org/apache/beam/learning/katas/commontransforms/filter/pardo/Task.kt
new file mode 100644
index 0000000..181e31a
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Filter/ParDo/src/org/apache/beam/learning/katas/commontransforms/filter/pardo/Task.kt	
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.filter.pardo
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.DoFn
+import org.apache.beam.sdk.transforms.ParDo
+import org.apache.beam.sdk.values.PCollection
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val numbers = pipeline.apply(Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
+
+    val output = applyTransform(numbers)
+
+    output.apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun applyTransform(input: PCollection<Int>): PCollection<Int> {
+    return input.apply(
+      ParDo.of(object : DoFn<Int, Int>() {
+        @ProcessElement
+        fun processElement(context: ProcessContext, out: OutputReceiver<Int>) {
+          val number = context.element()
+          if (number % 2 == 1) {
+            out.output(number)
+          }
+        }
+      })
+    )
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/Filter/ParDo/task-info.yaml b/learning/katas/kotlin/Common Transforms/Filter/ParDo/task-info.yaml
new file mode 100644
index 0000000..dcd5326
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Filter/ParDo/task-info.yaml	
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/commontransforms/filter/pardo/Task.kt
+  visible: true
+  placeholders:
+  - offset: 1636
+    length: 301
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/commontransforms/filter/pardo/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Common Transforms/Filter/ParDo/task-remote-info.yaml b/learning/katas/kotlin/Common Transforms/Filter/ParDo/task-remote-info.yaml
new file mode 100644
index 0000000..352082b
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Filter/ParDo/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326889
+update_date: Sat, 30 May 2020 18:48:41 UTC
diff --git a/learning/katas/kotlin/Common Transforms/Filter/ParDo/task.md b/learning/katas/kotlin/Common Transforms/Filter/ParDo/task.md
new file mode 100644
index 0000000..be21a28
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Filter/ParDo/task.md	
@@ -0,0 +1,30 @@
+<!--
+  ~  Licensed to the Apache Software Foundation (ASF) under one
+  ~  or more contributor license agreements.  See the NOTICE file
+  ~  distributed with this work for additional information
+  ~  regarding copyright ownership.  The ASF licenses this file
+  ~  to you 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.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  -->
+
+Filter using ParDo
+------------------
+
+**Kata:** Implement a filter function that filters out the even numbers by using 
+[DoFn](https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/DoFn.html).
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/ParDo.html">
+  ParDo</a> with
+  <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/DoFn.html">
+    DoFn</a> and only output the intended element.
+</div>
diff --git a/learning/katas/kotlin/Common Transforms/Filter/ParDo/test/org/apache/beam/learning/katas/commontransforms/filter/pardo/TaskTest.kt b/learning/katas/kotlin/Common Transforms/Filter/ParDo/test/org/apache/beam/learning/katas/commontransforms/filter/pardo/TaskTest.kt
new file mode 100644
index 0000000..0f5a485
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Filter/ParDo/test/org/apache/beam/learning/katas/commontransforms/filter/pardo/TaskTest.kt	
@@ -0,0 +1,43 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.filter.pardo
+
+import org.apache.beam.learning.katas.commontransforms.filter.pardo.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun common_transforms_filter_pardo() {
+    val values = Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+    val numbers = testPipeline.apply(values)
+
+    val results = applyTransform(numbers)
+
+    PAssert.that(results).containsInAnyOrder(1, 3, 5, 7, 9)
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/Filter/lesson-info.yaml b/learning/katas/kotlin/Common Transforms/Filter/lesson-info.yaml
new file mode 100644
index 0000000..93f7b5a
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Filter/lesson-info.yaml	
@@ -0,0 +1,22 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- ParDo
+- Filter
diff --git a/learning/katas/kotlin/Common Transforms/Filter/lesson-remote-info.yaml b/learning/katas/kotlin/Common Transforms/Filter/lesson-remote-info.yaml
new file mode 100644
index 0000000..f0d6a9f
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/Filter/lesson-remote-info.yaml	
@@ -0,0 +1,3 @@
+id: 358532
+update_date: Wed, 20 May 2020 20:28:26 UTC
+unit: 342733
diff --git a/learning/katas/kotlin/Common Transforms/WithKeys/WithKeys/src/org/apache/beam/learning/katas/commontransforms/withkeys/Task.kt b/learning/katas/kotlin/Common Transforms/WithKeys/WithKeys/src/org/apache/beam/learning/katas/commontransforms/withkeys/Task.kt
new file mode 100644
index 0000000..778481d
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/WithKeys/WithKeys/src/org/apache/beam/learning/katas/commontransforms/withkeys/Task.kt	
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.withkeys
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.WithKeys
+import org.apache.beam.sdk.values.KV
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.TypeDescriptors
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val words = pipeline.apply(
+      Create.of("apple", "banana", "cherry", "durian", "guava", "melon")
+    )
+
+    val output = applyTransform(words)
+
+    output.apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun applyTransform(input: PCollection<String>): PCollection<KV<String, String>> {
+    return input.apply(WithKeys
+      .of { fruit: String -> fruit.substring(0, 1) }
+      .withKeyType(TypeDescriptors.strings())
+    )
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/WithKeys/WithKeys/task-info.yaml b/learning/katas/kotlin/Common Transforms/WithKeys/WithKeys/task-info.yaml
new file mode 100644
index 0000000..015ef56
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/WithKeys/WithKeys/task-info.yaml	
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/commontransforms/withkeys/Task.kt
+  visible: true
+  placeholders:
+  - offset: 1731
+    length: 125
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/commontransforms/withkeys/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Common Transforms/WithKeys/WithKeys/task-remote-info.yaml b/learning/katas/kotlin/Common Transforms/WithKeys/WithKeys/task-remote-info.yaml
new file mode 100644
index 0000000..5361a97
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/WithKeys/WithKeys/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326900
+update_date: Sat, 30 May 2020 18:48:58 UTC
diff --git a/learning/katas/kotlin/Common Transforms/WithKeys/WithKeys/task.md b/learning/katas/kotlin/Common Transforms/WithKeys/WithKeys/task.md
new file mode 100644
index 0000000..15738d6
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/WithKeys/WithKeys/task.md	
@@ -0,0 +1,33 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you 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.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+WithKeys
+--------
+
+**Kata:** Convert each fruit name into a KV of its first letter and itself, e.g. 
+`apple => KV.of("a", "apple")`
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/WithKeys.html">
+  WithKeys</a>.
+</div>
+
+<div class="hint">
+  If using a lambda in Java 8, <code>withKeyType(TypeDescriptor)</code> must be called on the
+  result PTransform.
+</div>
diff --git a/learning/katas/kotlin/Common Transforms/WithKeys/WithKeys/test/org/apache/beam/learning/katas/commontransforms/withkeys/TaskTest.kt b/learning/katas/kotlin/Common Transforms/WithKeys/WithKeys/test/org/apache/beam/learning/katas/commontransforms/withkeys/TaskTest.kt
new file mode 100644
index 0000000..268bdcc
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/WithKeys/WithKeys/test/org/apache/beam/learning/katas/commontransforms/withkeys/TaskTest.kt	
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.commontransforms.withkeys
+
+import org.apache.beam.learning.katas.commontransforms.withkeys.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.values.KV
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun `Common Transforms - WithKeys - WithKeys`() {
+    val numbers = testPipeline.apply(
+      Create.of("apple", "banana", "cherry", "durian", "guava", "melon")
+    )
+    val results = applyTransform(numbers)
+
+    PAssert.that(results).containsInAnyOrder(
+      KV.of("a", "apple"),
+      KV.of("b", "banana"),
+      KV.of("c", "cherry"),
+      KV.of("d", "durian"),
+      KV.of("g", "guava"),
+      KV.of("m", "melon")
+    )
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Common Transforms/WithKeys/lesson-info.yaml b/learning/katas/kotlin/Common Transforms/WithKeys/lesson-info.yaml
new file mode 100644
index 0000000..1179567
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/WithKeys/lesson-info.yaml	
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- WithKeys
diff --git a/learning/katas/kotlin/Common Transforms/WithKeys/lesson-remote-info.yaml b/learning/katas/kotlin/Common Transforms/WithKeys/lesson-remote-info.yaml
new file mode 100644
index 0000000..f6b42c2
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/WithKeys/lesson-remote-info.yaml	
@@ -0,0 +1,3 @@
+id: 358534
+update_date: Wed, 20 May 2020 20:28:44 UTC
+unit: 342735
diff --git a/learning/katas/kotlin/Common Transforms/section-info.yaml b/learning/katas/kotlin/Common Transforms/section-info.yaml
new file mode 100644
index 0000000..b32b98a
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/section-info.yaml	
@@ -0,0 +1,23 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Filter
+- Aggregation
+- WithKeys
diff --git a/learning/katas/kotlin/Common Transforms/section-remote-info.yaml b/learning/katas/kotlin/Common Transforms/section-remote-info.yaml
new file mode 100644
index 0000000..bc801ce
--- /dev/null
+++ b/learning/katas/kotlin/Common Transforms/section-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 133889
+update_date: Wed, 20 May 2020 20:28:25 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Branching/Branching/src/org/apache/beam/learning/katas/coretransforms/branching/Task.kt b/learning/katas/kotlin/Core Transforms/Branching/Branching/src/org/apache/beam/learning/katas/coretransforms/branching/Task.kt
new file mode 100644
index 0000000..25185f8
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Branching/Branching/src/org/apache/beam/learning/katas/coretransforms/branching/Task.kt	
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.branching
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.MapElements
+import org.apache.beam.sdk.transforms.SerializableFunction
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.TypeDescriptors
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val numbers = pipeline.apply(Create.of(1, 2, 3, 4, 5))
+
+    val mult5Results = applyMultiply5Transform(numbers)
+    val mult10Results = applyMultiply10Transform(numbers)
+
+    mult5Results.apply("Log multiply 5", Log.ofElements("Multiplied by 5: "))
+    mult10Results.apply("Log multiply 10", Log.ofElements("Multiplied by 10: "))
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun applyMultiply5Transform(input: PCollection<Int>): PCollection<Int> {
+    return input.apply(
+      "Multiply by 5", MapElements
+        .into(TypeDescriptors.integers())
+        .via(SerializableFunction { num: Int -> num * 5 })
+    )
+  }
+
+  @JvmStatic
+  fun applyMultiply10Transform(input: PCollection<Int>): PCollection<Int> {
+    return input.apply(
+      "Multiply by 10", MapElements
+        .into(TypeDescriptors.integers())
+        .via(SerializableFunction { num: Int -> num * 10 })
+    )
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Branching/Branching/task-info.yaml b/learning/katas/kotlin/Core Transforms/Branching/Branching/task-info.yaml
new file mode 100644
index 0000000..581f2d6
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Branching/Branching/task-info.yaml	
@@ -0,0 +1,32 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/branching/Task.kt
+  visible: true
+  placeholders:
+  - offset: 1893
+    length: 154
+    placeholder_text: TODO()
+  - offset: 2153
+    length: 156
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/branching/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Core Transforms/Branching/Branching/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Branching/Branching/task-remote-info.yaml
new file mode 100644
index 0000000..8f3b7b8
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Branching/Branching/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326886
+update_date: Sat, 30 May 2020 18:51:41 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Branching/Branching/task.md b/learning/katas/kotlin/Core Transforms/Branching/Branching/task.md
new file mode 100644
index 0000000..3677fa9
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Branching/Branching/task.md	
@@ -0,0 +1,32 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you 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.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+Branching
+---------
+
+You can use the same PCollection as input for multiple transforms without consuming the input or 
+altering it.
+
+**Kata:** Branch out the numbers to two different transforms: one transform is multiplying each 
+number by 5 and the other transform is multiplying each number by 10.
+
+<div class="hint">
+  Refer to the Beam Design Your Pipeline Guide
+  <a href="https://beam.apache.org/documentation/pipelines/design-your-pipeline/#multiple-transforms-process-the-same-pcollection">
+    "Multiple transforms process the same PCollection"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Branching/Branching/test/org/apache/beam/learning/katas/coretransforms/branching/TaskTest.kt b/learning/katas/kotlin/Core Transforms/Branching/Branching/test/org/apache/beam/learning/katas/coretransforms/branching/TaskTest.kt
new file mode 100644
index 0000000..34c55a1
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Branching/Branching/test/org/apache/beam/learning/katas/coretransforms/branching/TaskTest.kt	
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.branching
+
+import org.apache.beam.learning.katas.coretransforms.branching.Task.applyMultiply10Transform
+import org.apache.beam.learning.katas.coretransforms.branching.Task.applyMultiply5Transform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun core_transforms_branching_branching() {
+    val values = Create.of(1, 2, 3, 4, 5)
+    val numbers = testPipeline.apply(values)
+
+    val mult5Results = applyMultiply5Transform(numbers)
+    val mult10Results = applyMultiply10Transform(numbers)
+
+    PAssert.that(mult5Results).containsInAnyOrder(5, 10, 15, 20, 25)
+
+    PAssert.that(mult10Results).containsInAnyOrder(10, 20, 30, 40, 50)
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Branching/lesson-info.yaml b/learning/katas/kotlin/Core Transforms/Branching/lesson-info.yaml
new file mode 100644
index 0000000..25ecc7c
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Branching/lesson-info.yaml	
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Branching
diff --git a/learning/katas/kotlin/Core Transforms/Branching/lesson-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Branching/lesson-remote-info.yaml
new file mode 100644
index 0000000..19d2d8d
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Branching/lesson-remote-info.yaml	
@@ -0,0 +1,3 @@
+id: 358529
+update_date: Wed, 20 May 2020 20:28:09 UTC
+unit: 342730
diff --git a/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/src/org/apache/beam/learning/katas/coretransforms/cogroupbykey/Task.kt b/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/src/org/apache/beam/learning/katas/coretransforms/cogroupbykey/Task.kt
new file mode 100644
index 0000000..b1f442c
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/src/org/apache/beam/learning/katas/coretransforms/cogroupbykey/Task.kt	
@@ -0,0 +1,84 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.cogroupbykey
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.*
+import org.apache.beam.sdk.transforms.join.CoGbkResult
+import org.apache.beam.sdk.transforms.join.CoGroupByKey
+import org.apache.beam.sdk.transforms.join.KeyedPCollectionTuple
+import org.apache.beam.sdk.values.KV
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.TupleTag
+import org.apache.beam.sdk.values.TypeDescriptors
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val fruits = pipeline.apply(
+      "Fruits",
+      Create.of("apple", "banana", "cherry")
+    )
+
+    val countries = pipeline.apply(
+      "Countries",
+      Create.of("australia", "brazil", "canada")
+    )
+
+    val output = applyTransform(fruits, countries)
+
+    output.apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun applyTransform(fruits: PCollection<String>, countries: PCollection<String>): PCollection<String> {
+    val fruitsTag = TupleTag<String>()
+    val countriesTag = TupleTag<String>()
+
+    val mapToAlphabetKv = MapElements
+      .into(TypeDescriptors.kvs(TypeDescriptors.strings(), TypeDescriptors.strings()))
+      .via(SerializableFunction { word: String -> KV.of(word.substring(0, 1), word) })
+
+    val fruitsPColl = fruits.apply("Fruit to KV", mapToAlphabetKv)
+    val countriesPColl = countries.apply("Country to KV", mapToAlphabetKv)
+
+    return KeyedPCollectionTuple
+      .of(fruitsTag, fruitsPColl)
+      .and(countriesTag, countriesPColl)
+      .apply(CoGroupByKey.create())
+      .apply(ParDo.of(object : DoFn<KV<String, CoGbkResult>, String>() {
+        @ProcessElement
+        fun processElement(@Element element: KV<String, CoGbkResult>, out: OutputReceiver<String>) {
+          val alphabet = element.key
+          val coGbkResult = element.value
+
+          val fruit = coGbkResult.getOnly(fruitsTag)
+          val country = coGbkResult.getOnly(countriesTag)
+
+          out.output(WordsAlphabet(alphabet, fruit, country).toString())
+        }
+      }))
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/src/org/apache/beam/learning/katas/coretransforms/cogroupbykey/WordsAlphabet.kt b/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/src/org/apache/beam/learning/katas/coretransforms/cogroupbykey/WordsAlphabet.kt
new file mode 100644
index 0000000..95c401a
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/src/org/apache/beam/learning/katas/coretransforms/cogroupbykey/WordsAlphabet.kt	
@@ -0,0 +1,24 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.cogroupbykey
+
+data class WordsAlphabet(private val alphabet: String?, private val fruit: String, private val country: String) {
+  override fun toString(): String {
+    return "WordsAlphabet{alphabet='$alphabet', fruit='$fruit', country='$country'}"
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/task-info.yaml b/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/task-info.yaml
new file mode 100644
index 0000000..a371983
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/task-info.yaml	
@@ -0,0 +1,31 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/cogroupbykey/Task.kt
+  visible: true
+  placeholders:
+  - offset: 2039
+    length: 1060
+    placeholder_text: TODO()
+- name: src/org/apache/beam/learning/katas/coretransforms/cogroupbykey/WordsAlphabet.kt
+  visible: true
+- name: test/org/apache/beam/learning/katas/coretransforms/cogroupbykey/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/task-remote-info.yaml
new file mode 100644
index 0000000..fc69d68
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326877
+update_date: Sat, 30 May 2020 18:48:13 UTC
diff --git a/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/task.md b/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/task.md
new file mode 100644
index 0000000..8b24f7a
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/task.md	
@@ -0,0 +1,43 @@
+<!--
+  ~  Licensed to the Apache Software Foundation (ASF) under one
+  ~  or more contributor license agreements.  See the NOTICE file
+  ~  distributed with this work for additional information
+  ~  regarding copyright ownership.  The ASF licenses this file
+  ~  to you 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.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  -->
+
+CoGroupByKey
+------------
+
+CoGroupByKey performs a relational join of two or more key/value PCollections that have the same 
+key type.
+
+**Kata:** Implement a 
+[CoGroupByKey](https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/join/CoGroupByKey.html) 
+transform that join words by its first alphabetical letter, and then produces the toString() 
+representation of the WordsAlphabet model.
+
+<div class="hint">
+  Refer to <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/join/CoGroupByKey.html">
+  CoGroupByKey</a>,
+  <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/values/TupleTag.html">
+    TupleTag</a>, and
+  <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/join/CoGbkResult.html">
+    CoGbkResult</a>.
+</div>
+
+<div class="hint">
+  Refer to the Beam Programming Guide
+  <a href="https://beam.apache.org/documentation/programming-guide/#cogroupbykey">
+    "CoGroupByKey"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/test/org/apache/beam/learning/katas/coretransforms/cogroupbykey/TaskTest.kt b/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/test/org/apache/beam/learning/katas/coretransforms/cogroupbykey/TaskTest.kt
new file mode 100644
index 0000000..7a348fb
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/CoGroupByKey/CoGroupByKey/test/org/apache/beam/learning/katas/coretransforms/cogroupbykey/TaskTest.kt	
@@ -0,0 +1,54 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.cogroupbykey
+
+import org.apache.beam.learning.katas.coretransforms.cogroupbykey.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun core_transforms_cogroupbykey_cogroupbykey() {
+    val fruits = testPipeline.apply(
+      "Fruits",
+      Create.of("apple", "banana", "cherry")
+    )
+
+    val countries = testPipeline.apply(
+      "Countries",
+      Create.of("australia", "brazil", "canada")
+    )
+
+    val results = applyTransform(fruits, countries)
+
+    PAssert.that(results).containsInAnyOrder(
+      "WordsAlphabet{alphabet='a', fruit='apple', country='australia'}",
+      "WordsAlphabet{alphabet='b', fruit='banana', country='brazil'}",
+      "WordsAlphabet{alphabet='c', fruit='cherry', country='canada'}"
+    )
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/CoGroupByKey/lesson-info.yaml b/learning/katas/kotlin/Core Transforms/CoGroupByKey/lesson-info.yaml
new file mode 100644
index 0000000..273c077
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/CoGroupByKey/lesson-info.yaml	
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- CoGroupByKey
diff --git a/learning/katas/kotlin/Core Transforms/CoGroupByKey/lesson-remote-info.yaml b/learning/katas/kotlin/Core Transforms/CoGroupByKey/lesson-remote-info.yaml
new file mode 100644
index 0000000..29dd24d
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/CoGroupByKey/lesson-remote-info.yaml	
@@ -0,0 +1,3 @@
+id: 358523
+update_date: Wed, 20 May 2020 20:27:27 UTC
+unit: 342724
diff --git a/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn Lambda/src/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefnlambda/Task.kt b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn Lambda/src/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefnlambda/Task.kt
new file mode 100644
index 0000000..8e7bd47
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn Lambda/src/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefnlambda/Task.kt	
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.combine.binarycombinefnlambda
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Combine
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.values.PCollection
+import java.math.BigInteger
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val numbers = pipeline.apply(
+      Create.of(
+        BigInteger.valueOf(10), BigInteger.valueOf(20), BigInteger.valueOf(30),
+        BigInteger.valueOf(40), BigInteger.valueOf(50)
+      )
+    )
+
+    val output = applyTransform(numbers)
+
+    output.apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun applyTransform(input: PCollection<BigInteger>): PCollection<BigInteger> {
+    return input.apply(Combine.globally(BigInteger::add))
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn Lambda/task-info.yaml b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn Lambda/task-info.yaml
new file mode 100644
index 0000000..cc5d325
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn Lambda/task-info.yaml	
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefnlambda/Task.kt
+  visible: true
+  placeholders:
+  - offset: 1777
+    length: 46
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefnlambda/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn Lambda/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn Lambda/task-remote-info.yaml
new file mode 100644
index 0000000..bda3554
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn Lambda/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326880
+update_date: Sat, 30 May 2020 18:48:20 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn Lambda/task.md b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn Lambda/task.md
new file mode 100644
index 0000000..45a3e4d
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn Lambda/task.md	
@@ -0,0 +1,40 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you 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.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+Combine - BinaryCombineFn Lambda
+--------------------------------
+
+BinaryCombineFn is used for implementing combiners that are more easily expressed as binary 
+operations.
+
+Since Beam v2.13.0, you can also use lambda or method reference in order to create the 
+BinaryCombineFn.
+
+**Kata:** Implement the summation of BigInteger using lambda or method reference.
+
+<div class="hint">
+  Refer to
+  <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/SerializableBiFunction.html">
+    SerializableBiFunction</a>.
+</div>
+
+<div class="hint">
+  Refer to the Beam Programming Guide
+  <a href="https://beam.apache.org/documentation/programming-guide/#combine">
+    "Combine"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn Lambda/test/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefnlambda/TaskTest.kt b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn Lambda/test/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefnlambda/TaskTest.kt
new file mode 100644
index 0000000..09d5551
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn Lambda/test/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefnlambda/TaskTest.kt	
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.combine.binarycombinefnlambda
+
+import org.apache.beam.learning.katas.coretransforms.combine.binarycombinefnlambda.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+import java.math.BigInteger
+
+class TaskTest {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun core_transforms_combine_binarycombinefn_lambda() {
+    val values = Create.of(
+      BigInteger.valueOf(10), BigInteger.valueOf(20), BigInteger.valueOf(30),
+      BigInteger.valueOf(40), BigInteger.valueOf(50)
+    )
+    val numbers = testPipeline.apply(values)
+
+    val results = applyTransform(numbers)
+
+    PAssert.that(results).containsInAnyOrder(BigInteger.valueOf(150))
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn/src/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefn/Task.kt b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn/src/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefn/Task.kt
new file mode 100644
index 0000000..f483dd7
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn/src/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefn/Task.kt	
@@ -0,0 +1,59 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.combine.binarycombinefn
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Combine
+import org.apache.beam.sdk.transforms.Combine.BinaryCombineFn
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.values.PCollection
+import java.math.BigInteger
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val numbers = pipeline.apply(
+      Create.of(
+        BigInteger.valueOf(10), BigInteger.valueOf(20), BigInteger.valueOf(30),
+        BigInteger.valueOf(40), BigInteger.valueOf(50)
+      )
+    )
+
+    val output = applyTransform(numbers)
+
+    output.apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun applyTransform(input: PCollection<BigInteger>): PCollection<BigInteger> {
+    return input.apply(Combine.globally(SumBigIntegerFn()))
+  }
+
+  internal class SumBigIntegerFn : BinaryCombineFn<BigInteger>() {
+    override fun apply(left: BigInteger, right: BigInteger): BigInteger {
+      return left.add(right)
+    }
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn/task-info.yaml b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn/task-info.yaml
new file mode 100644
index 0000000..f0bb107
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn/task-info.yaml	
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefn/Task.kt
+  visible: true
+  placeholders:
+  - offset: 1971
+    length: 104
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefn/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn/task-remote-info.yaml
new file mode 100644
index 0000000..9fde7d9
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326915
+update_date: Sat, 30 May 2020 18:50:08 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn/task.md b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn/task.md
new file mode 100644
index 0000000..ea026b1
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn/task.md	
@@ -0,0 +1,45 @@
+<!--
+  ~  Licensed to the Apache Software Foundation (ASF) under one
+  ~  or more contributor license agreements.  See the NOTICE file
+  ~  distributed with this work for additional information
+  ~  regarding copyright ownership.  The ASF licenses this file
+  ~  to you 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.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  -->
+
+Combine - BinaryCombineFn
+-------------------------
+
+Combine is a Beam transform for combining collections of elements or values in your data. When you 
+apply a Combine transform, you must provide the function that contains the logic for combining the 
+elements or values. The combining function should be commutative and associative, as the function 
+is not necessarily invoked exactly once on all values with a given key. Because the input data 
+(including the value collection) may be distributed across multiple workers, the combining function 
+might be called multiple times to perform partial combining on subsets of the value collection.
+
+BinaryCombineFn is used for implementing combiners that are more easily expressed as binary 
+operations.
+
+**Kata:** Implement the summation of BigInteger using 
+[Combine.BinaryCombineFn](https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Combine.BinaryCombineFn.html).
+
+<div class="hint">
+  Extend the
+  <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Combine.BinaryCombineFn.html">
+    Combine.BinaryCombineFn</a> class that counts the sum of the number.
+</div>
+
+<div class="hint">
+  Refer to the Beam Programming Guide
+  <a href="https://beam.apache.org/documentation/programming-guide/#combine">
+    "Combine"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn/test/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefn/TaskTest.kt b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn/test/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefn/TaskTest.kt
new file mode 100644
index 0000000..4ca5139
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/BinaryCombineFn/test/org/apache/beam/learning/katas/coretransforms/combine/binarycombinefn/TaskTest.kt	
@@ -0,0 +1,47 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.combine.binarycombinefn
+
+import org.apache.beam.learning.katas.coretransforms.combine.binarycombinefn.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+import java.math.BigInteger
+
+class TaskTest {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun core_transforms_combine_binarycombinefn() {
+    val values = Create.of(
+      BigInteger.valueOf(10), BigInteger.valueOf(20), BigInteger.valueOf(30),
+      BigInteger.valueOf(40), BigInteger.valueOf(50)
+    )
+    val numbers = testPipeline.apply(values)
+
+    val results = applyTransform(numbers)
+
+    PAssert.that(results).containsInAnyOrder(BigInteger.valueOf(150))
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Combine/Combine PerKey/src/org/apache/beam/learning/katas/coretransforms/combine/combineperkey/Task.kt b/learning/katas/kotlin/Core Transforms/Combine/Combine PerKey/src/org/apache/beam/learning/katas/coretransforms/combine/combineperkey/Task.kt
new file mode 100644
index 0000000..f762ef1
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/Combine PerKey/src/org/apache/beam/learning/katas/coretransforms/combine/combineperkey/Task.kt	
@@ -0,0 +1,63 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.combine.combineperkey
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Combine
+import org.apache.beam.sdk.transforms.Combine.BinaryCombineFn
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.values.KV
+import org.apache.beam.sdk.values.PCollection
+
+object Task {
+  const val PLAYER_1 = "Player 1"
+  const val PLAYER_2 = "Player 2"
+  const val PLAYER_3 = "Player 3"
+
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val scores = pipeline.apply(
+      Create.of(
+        KV.of(PLAYER_1, 15), KV.of(PLAYER_2, 10), KV.of(PLAYER_1, 100),
+        KV.of(PLAYER_3, 25), KV.of(PLAYER_2, 75)
+      )
+    )
+
+    val output = applyTransform(scores)
+
+    output.apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun applyTransform(input: PCollection<KV<String, Int>>): PCollection<KV<String, Int>> {
+    return input.apply<PCollection<KV<String, Int>>>(Combine.perKey(SumIntBinaryCombineFn()))
+  }
+
+  internal class SumIntBinaryCombineFn : BinaryCombineFn<Int>() {
+    override fun apply(left: Int, right: Int): Int {
+      return left + right
+    }
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Combine/Combine PerKey/task-info.yaml b/learning/katas/kotlin/Core Transforms/Combine/Combine PerKey/task-info.yaml
new file mode 100644
index 0000000..95a9502
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/Combine PerKey/task-info.yaml	
@@ -0,0 +1,32 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/combine/combineperkey/Task.kt
+  visible: true
+  placeholders:
+  - offset: 1950
+    length: 82
+    placeholder_text: TODO()
+  - offset: 2108
+    length: 80
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/combine/combineperkey/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Core Transforms/Combine/Combine PerKey/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Combine/Combine PerKey/task-remote-info.yaml
new file mode 100644
index 0000000..f273b81
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/Combine PerKey/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326881
+update_date: Sat, 30 May 2020 18:48:22 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Combine/Combine PerKey/task.md b/learning/katas/kotlin/Core Transforms/Combine/Combine PerKey/task.md
new file mode 100644
index 0000000..3f80616
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/Combine PerKey/task.md	
@@ -0,0 +1,46 @@
+<!--
+  ~  Licensed to the Apache Software Foundation (ASF) under one
+  ~  or more contributor license agreements.  See the NOTICE file
+  ~  distributed with this work for additional information
+  ~  regarding copyright ownership.  The ASF licenses this file
+  ~  to you 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.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  -->
+
+Combine - Combine PerKey
+------------------------
+
+After creating a keyed PCollection (for example, by using a GroupByKey transform), a common pattern 
+is to combine the collection of values associated with each key into a single, merged value. This 
+pattern of a GroupByKey followed by merging the collection of values is equivalent to Combine 
+PerKey transform. The combine function you supply to Combine PerKey must be an associative 
+reduction function or a subclass of CombineFn.
+
+**Kata:** Implement the sum of scores per player using 
+[Combine.perKey](https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/CombineFnBase.GlobalCombineFn.html).
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/CombineFnBase.GlobalCombineFn.html">
+  Combine.perKey(GlobalCombineFn)</a>.
+</div>
+
+<div class="hint">
+  Extend the
+  <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Combine.BinaryCombineFn.html">
+    Combine.BinaryCombineFn</a> class that counts the sum of the number.
+</div>
+
+<div class="hint">
+  Refer to the Beam Programming Guide
+  <a href="https://beam.apache.org/documentation/programming-guide/#combining-values-in-a-keyed-pcollection">
+    "Combining values in a keyed PCollection"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Combine/Combine PerKey/test/org/apache/beam/learning/katas/coretransforms/combine/combineperkey/TaskTest.kt b/learning/katas/kotlin/Core Transforms/Combine/Combine PerKey/test/org/apache/beam/learning/katas/coretransforms/combine/combineperkey/TaskTest.kt
new file mode 100644
index 0000000..199bd30
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/Combine PerKey/test/org/apache/beam/learning/katas/coretransforms/combine/combineperkey/TaskTest.kt	
@@ -0,0 +1,49 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.combine.combineperkey
+
+import org.apache.beam.learning.katas.coretransforms.combine.combineperkey.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.values.KV
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun core_transforms_combine_combine_perkey() {
+    val values = Create.of(
+      KV.of(Task.PLAYER_1, 15), KV.of(Task.PLAYER_2, 10), KV.of(Task.PLAYER_1, 100),
+      KV.of(Task.PLAYER_3, 25), KV.of(Task.PLAYER_2, 75)
+    )
+    val numbers = testPipeline.apply(values)
+
+    val results = applyTransform(numbers)
+
+    PAssert.that(results).containsInAnyOrder(
+      KV.of(Task.PLAYER_1, 115), KV.of(Task.PLAYER_2, 85), KV.of(Task.PLAYER_3, 25)
+    )
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Combine/CombineFn/src/org/apache/beam/learning/katas/coretransforms/combine/combinefn/Task.kt b/learning/katas/kotlin/Core Transforms/Combine/CombineFn/src/org/apache/beam/learning/katas/coretransforms/combine/combinefn/Task.kt
new file mode 100644
index 0000000..97935aa
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/CombineFn/src/org/apache/beam/learning/katas/coretransforms/combine/combinefn/Task.kt	
@@ -0,0 +1,79 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.combine.combinefn
+
+import org.apache.beam.learning.katas.coretransforms.combine.combinefn.Task.AverageFn.Accum
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Combine
+import org.apache.beam.sdk.transforms.Combine.CombineFn
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.values.PCollection
+import java.io.Serializable
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val numbers = pipeline.apply(Create.of(10, 20, 50, 70, 90))
+
+    val output = applyTransform(numbers)
+
+    output.apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun applyTransform(input: PCollection<Int>): PCollection<Double> {
+    return input.apply(Combine.globally(AverageFn()))
+  }
+
+  internal class AverageFn : CombineFn<Int, Accum, Double>() {
+    internal data class Accum(var sum: Int = 0, var count: Int = 0) : Serializable
+
+    override fun createAccumulator(): Accum {
+      return Accum()
+    }
+
+    override fun addInput(accumulator: Accum, input: Int): Accum {
+      accumulator.sum += input
+      accumulator.count++
+
+      return accumulator
+    }
+
+    override fun mergeAccumulators(accumulators: Iterable<Accum>): Accum {
+      val merged = createAccumulator()
+
+      for (accumulator in accumulators) {
+        merged.sum += accumulator.sum
+        merged.count += accumulator.count
+      }
+
+      return merged
+    }
+
+    override fun extractOutput(accumulator: Accum): Double {
+      return accumulator.sum.toDouble() / accumulator.count
+    }
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Combine/CombineFn/task-info.yaml b/learning/katas/kotlin/Core Transforms/Combine/CombineFn/task-info.yaml
new file mode 100644
index 0000000..4ed3edb
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/CombineFn/task-info.yaml	
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/combine/combinefn/Task.kt
+  visible: true
+  placeholders:
+  - offset: 1894
+    length: 710
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/combine/combinefn/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Core Transforms/Combine/CombineFn/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Combine/CombineFn/task-remote-info.yaml
new file mode 100644
index 0000000..9758afb
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/CombineFn/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326879
+update_date: Sat, 30 May 2020 18:50:05 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Combine/CombineFn/task.md b/learning/katas/kotlin/Core Transforms/Combine/CombineFn/task.md
new file mode 100644
index 0000000..13bce44
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/CombineFn/task.md	
@@ -0,0 +1,47 @@
+<!--
+  ~  Licensed to the Apache Software Foundation (ASF) under one
+  ~  or more contributor license agreements.  See the NOTICE file
+  ~  distributed with this work for additional information
+  ~  regarding copyright ownership.  The ASF licenses this file
+  ~  to you 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.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  -->
+
+Combine - CombineFn
+-------------------
+
+Combine is a Beam transform for combining collections of elements or values in your data. When you 
+apply a Combine transform, you must provide the function that contains the logic for combining the 
+elements or values. The combining function should be commutative and associative, as the function 
+is not necessarily invoked exactly once on all values with a given key. Because the input data 
+(including the value collection) may be distributed across multiple workers, the combining function 
+might be called multiple times to perform partial combining on subsets of the value collection.
+
+Complex combination operations might require you to create a subclass of CombineFn that has an 
+accumulation type distinct from the input/output type. You should use CombineFn if the combine 
+function requires a more sophisticated accumulator, must perform additional pre- or post-processing, 
+might change the output type, or takes the key into account.
+
+**Kata:** Implement the average of numbers using 
+[Combine.CombineFn](https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Combine.CombineFn.html).
+
+<div class="hint">
+  Extend the
+  <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Combine.CombineFn.html">
+    Combine.CombineFn</a> class that counts the average of the number.
+</div>
+
+<div class="hint">
+  Refer to the Beam Programming Guide
+  <a href="https://beam.apache.org/documentation/programming-guide/#advanced-combines">
+    "Advanced combinations using CombineFn"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Combine/CombineFn/test/org/apache/beam/learning/katas/coretransforms/combine/combinefn/TaskTest.kt b/learning/katas/kotlin/Core Transforms/Combine/CombineFn/test/org/apache/beam/learning/katas/coretransforms/combine/combinefn/TaskTest.kt
new file mode 100644
index 0000000..7a612d5
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/CombineFn/test/org/apache/beam/learning/katas/coretransforms/combine/combinefn/TaskTest.kt	
@@ -0,0 +1,43 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.combine.combinefn
+
+import org.apache.beam.learning.katas.coretransforms.combine.combinefn.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun core_transforms_combine_combinefn() {
+    val values = Create.of(10, 20, 50, 70, 90)
+    val numbers = testPipeline.apply(values)
+
+    val results = applyTransform(numbers)
+
+    PAssert.that(results).containsInAnyOrder(48.0)
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Combine/Simple Function/src/org/apache/beam/learning/katas/coretransforms/combine/simple/Task.kt b/learning/katas/kotlin/Core Transforms/Combine/Simple Function/src/org/apache/beam/learning/katas/coretransforms/combine/simple/Task.kt
new file mode 100644
index 0000000..98a2103
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/Simple Function/src/org/apache/beam/learning/katas/coretransforms/combine/simple/Task.kt	
@@ -0,0 +1,53 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.combine.simple
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Combine
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.SerializableFunction
+import org.apache.beam.sdk.values.PCollection
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val numbers = pipeline.apply(Create.of(10, 30, 50, 70, 90))
+
+    val output = applyTransform(numbers)
+
+    output.apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun applyTransform(input: PCollection<Int>): PCollection<Int> {
+    return input.apply(Combine.globally(SumIntegerFn()))
+  }
+
+  internal class SumIntegerFn : SerializableFunction<Iterable<Int>, Int> {
+    override fun apply(input: Iterable<Int>): Int {
+      return input.sum()
+    }
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Combine/Simple Function/task-info.yaml b/learning/katas/kotlin/Core Transforms/Combine/Simple Function/task-info.yaml
new file mode 100644
index 0000000..38c1766
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/Simple Function/task-info.yaml	
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/combine/simple/Task.kt
+  visible: true
+  placeholders:
+  - offset: 1786
+    length: 78
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/combine/simple/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Core Transforms/Combine/Simple Function/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Combine/Simple Function/task-remote-info.yaml
new file mode 100644
index 0000000..5162bbd
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/Simple Function/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326878
+update_date: Sat, 30 May 2020 18:48:15 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Combine/Simple Function/task.md b/learning/katas/kotlin/Core Transforms/Combine/Simple Function/task.md
new file mode 100644
index 0000000..b20fb9d
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/Simple Function/task.md	
@@ -0,0 +1,44 @@
+<!--
+  ~  Licensed to the Apache Software Foundation (ASF) under one
+  ~  or more contributor license agreements.  See the NOTICE file
+  ~  distributed with this work for additional information
+  ~  regarding copyright ownership.  The ASF licenses this file
+  ~  to you 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.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  -->
+
+Combine - Simple Function
+-------------------------
+
+Combine is a Beam transform for combining collections of elements or values in your data. When you 
+apply a Combine transform, you must provide the function that contains the logic for combining the 
+elements or values. The combining function should be commutative and associative, as the function 
+is not necessarily invoked exactly once on all values with a given key. Because the input data 
+(including the value collection) may be distributed across multiple workers, the combining function 
+might be called multiple times to perform partial combining on subsets of the value collection.
+
+Simple combine operations, such as sums, can usually be implemented as a simple function.
+
+**Kata:** Implement the summation of numbers using 
+[Combine.globally(SerializableFunction)](https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/SerializableFunction.html).
+
+<div class="hint">
+  Implement the
+  <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/SerializableFunction.html#apply-InputT-">
+    SerializableFunction.apply</a> method that performs the summation of the Iterable.
+</div>
+
+<div class="hint">
+  Refer to the Beam Programming Guide
+  <a href="https://beam.apache.org/documentation/programming-guide/#simple-combines">
+    "Simple combinations using simple functions"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Combine/Simple Function/test/org/apache/beam/learning/katas/coretransforms/combine/simple/TaskTest.kt b/learning/katas/kotlin/Core Transforms/Combine/Simple Function/test/org/apache/beam/learning/katas/coretransforms/combine/simple/TaskTest.kt
new file mode 100644
index 0000000..0a0a2fd
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/Simple Function/test/org/apache/beam/learning/katas/coretransforms/combine/simple/TaskTest.kt	
@@ -0,0 +1,43 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.combine.simple
+
+import org.apache.beam.learning.katas.coretransforms.combine.simple.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun core_transforms_combine_simple_function() {
+    val values = Create.of(10, 30, 50, 70, 90)
+    val numbers = testPipeline.apply(values)
+
+    val results = applyTransform(numbers)
+
+    PAssert.that(results).containsInAnyOrder(250)
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Combine/lesson-info.yaml b/learning/katas/kotlin/Core Transforms/Combine/lesson-info.yaml
new file mode 100644
index 0000000..b275018
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/lesson-info.yaml	
@@ -0,0 +1,25 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Simple Function
+- CombineFn
+- BinaryCombineFn
+- BinaryCombineFn Lambda
+- Combine PerKey
diff --git a/learning/katas/kotlin/Core Transforms/Combine/lesson-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Combine/lesson-remote-info.yaml
new file mode 100644
index 0000000..8faec31
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Combine/lesson-remote-info.yaml	
@@ -0,0 +1,3 @@
+id: 358524
+update_date: Wed, 20 May 2020 20:27:36 UTC
+unit: 342725
diff --git a/learning/katas/kotlin/Core Transforms/Composite Transform/Composite Transform/src/org/apache/beam/learning/katas/coretransforms/composite/Task.kt b/learning/katas/kotlin/Core Transforms/Composite Transform/Composite Transform/src/org/apache/beam/learning/katas/coretransforms/composite/Task.kt
new file mode 100644
index 0000000..6e103cd
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Composite Transform/Composite Transform/src/org/apache/beam/learning/katas/coretransforms/composite/Task.kt	
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.composite
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.*
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.TypeDescriptors
+import java.util.*
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    pipeline
+      .apply(Create.of("1,2,3,4,5", "6,7,8,9,10"))
+      .apply(ExtractAndMultiplyNumbers())
+      .apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  internal class ExtractAndMultiplyNumbers : PTransform<PCollection<String>, PCollection<Int>>() {
+    override fun expand(input: PCollection<String>): PCollection<Int> {
+      return input
+        .apply(ParDo.of(object : DoFn<String, Int>() {
+          @ProcessElement
+          fun processElement(@Element numbers: String, out: OutputReceiver<Int>) {
+            Arrays.stream(
+              numbers.split(",")
+                .toTypedArray()
+            )
+              .forEach { numStr: String -> out.output(numStr.toInt()) }
+          }
+        }))
+        .apply(
+          MapElements
+            .into(TypeDescriptors.integers())
+            .via(SerializableFunction { number: Int -> number * 10 })
+        )
+    }
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Composite Transform/Composite Transform/task-info.yaml b/learning/katas/kotlin/Core Transforms/Composite Transform/Composite Transform/task-info.yaml
new file mode 100644
index 0000000..8a0f9f6
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Composite Transform/Composite Transform/task-info.yaml	
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/composite/Task.kt
+  visible: true
+  placeholders:
+  - offset: 1605
+    length: 622
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/composite/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Core Transforms/Composite Transform/Composite Transform/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Composite Transform/Composite Transform/task-remote-info.yaml
new file mode 100644
index 0000000..cf842b9
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Composite Transform/Composite Transform/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326887
+update_date: Sat, 30 May 2020 18:50:17 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Composite Transform/Composite Transform/task.md b/learning/katas/kotlin/Core Transforms/Composite Transform/Composite Transform/task.md
new file mode 100644
index 0000000..45854bf
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Composite Transform/Composite Transform/task.md	
@@ -0,0 +1,47 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you 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.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+Composite Transform
+-------------------
+
+Transforms can have a nested structure, where a complex transform performs multiple simpler 
+transforms (such as more than one ParDo, Combine, GroupByKey, or even other composite transforms). 
+These transforms are called composite transforms. Nesting multiple transforms inside a single 
+composite transform can make your code more modular and easier to understand.
+
+To create your own composite transform, create a subclass of the PTransform class and override the 
+expand method to specify the actual processing logic. You can then use this transform just as you 
+would a built-in transform from the Beam SDK. For the PTransform class type parameters, you pass 
+the PCollection types that your transform takes as input, and produces as output. Within your 
+PTransform subclass, you’ll need to override the expand method. The expand method is where you add 
+the processing logic for the PTransform. Your override of expand must accept the appropriate type 
+of input PCollection as a parameter, and specify the output PCollection as the return value.
+
+**Kata:** Please implement a composite transform "ExtractAndMultiplyNumbers" that extracts numbers 
+from comma separated line and then multiplies each number by 10.
+
+<div class="hint">
+  Refer to <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/PTransform.html">
+  PTransform</a>.
+</div>
+
+<div class="hint">
+  Refer to the Beam Programming Guide
+  <a href="https://beam.apache.org/documentation/programming-guide/#composite-transforms">
+    "Composite transforms"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Composite Transform/Composite Transform/test/org/apache/beam/learning/katas/coretransforms/composite/TaskTest.kt b/learning/katas/kotlin/Core Transforms/Composite Transform/Composite Transform/test/org/apache/beam/learning/katas/coretransforms/composite/TaskTest.kt
new file mode 100644
index 0000000..dbc7d6f
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Composite Transform/Composite Transform/test/org/apache/beam/learning/katas/coretransforms/composite/TaskTest.kt	
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.composite
+
+import org.apache.beam.learning.katas.coretransforms.composite.Task.ExtractAndMultiplyNumbers
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun core_transforms_composite_transform_composite_transform() {
+    val values = Create.of("1,2,3,4,5", "6,7,8,9,10")
+
+    val results = testPipeline
+      .apply(values)
+      .apply(ExtractAndMultiplyNumbers())
+
+    PAssert.that(results).containsInAnyOrder(10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Composite Transform/lesson-info.yaml b/learning/katas/kotlin/Core Transforms/Composite Transform/lesson-info.yaml
new file mode 100644
index 0000000..177eab1
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Composite Transform/lesson-info.yaml	
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Composite Transform
diff --git a/learning/katas/kotlin/Core Transforms/Composite Transform/lesson-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Composite Transform/lesson-remote-info.yaml
new file mode 100644
index 0000000..4f61026
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Composite Transform/lesson-remote-info.yaml	
@@ -0,0 +1,3 @@
+id: 358530
+update_date: Wed, 20 May 2020 20:28:14 UTC
+unit: 342731
diff --git a/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/DoFn Additional Parameters/src/org/apache/beam/learning/katas/coretransforms/dofnadditionalparams/Task.kt b/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/DoFn Additional Parameters/src/org/apache/beam/learning/katas/coretransforms/dofnadditionalparams/Task.kt
new file mode 100644
index 0000000..553abad
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/DoFn Additional Parameters/src/org/apache/beam/learning/katas/coretransforms/dofnadditionalparams/Task.kt	
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.dofnadditionalparams
+
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    pipeline.run()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/DoFn Additional Parameters/task-info.yaml b/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/DoFn Additional Parameters/task-info.yaml
new file mode 100644
index 0000000..a00ae43
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/DoFn Additional Parameters/task-info.yaml	
@@ -0,0 +1,25 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/dofnadditionalparams/Task.kt
+  visible: true
+- name: test/org/apache/beam/learning/katas/coretransforms/dofnadditionalparams/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/DoFn Additional Parameters/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/DoFn Additional Parameters/task-remote-info.yaml
new file mode 100644
index 0000000..1ce2f88
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/DoFn Additional Parameters/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326888
+update_date: Sat, 30 May 2020 18:48:38 UTC
diff --git a/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/DoFn Additional Parameters/task.md b/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/DoFn Additional Parameters/task.md
new file mode 100644
index 0000000..32657dc
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/DoFn Additional Parameters/task.md	
@@ -0,0 +1,38 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you 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.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+DoFn Additional Parameters
+--------------------------
+
+In addition to the element and the OutputReceiver, Beam will populate other parameters to your 
+DoFn’s @ProcessElement method. Any combination of these parameters can be added to your process 
+method in any order.
+
+*   **Timestamp**: To access the timestamp of an input element, add a parameter annotated with 
+@Timestamp of type Instant
+*   **Window**: To access the window an input element falls into, add a parameter of the type of 
+the window used for the input PCollection.
+*   **PaneInfo**: When triggers are used, Beam provides a PaneInfo object that contains information 
+about the current firing. Using PaneInfo you can determine whether this is an early or a late 
+firing, and how many times this window has already fired for this key.
+*   **PipelineOptions**: The PipelineOptions for the current pipeline can always be accessed in a 
+process method by adding it as a parameter.
+
+Refer to the Beam Programming Guide
+["Accessing additional parameters in your DoFn"](https://beam.apache.org/documentation/programming-guide/#other-dofn-parameters) 
+section for more information.
diff --git a/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/DoFn Additional Parameters/test/org/apache/beam/learning/katas/coretransforms/dofnadditionalparams/TaskTest.kt b/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/DoFn Additional Parameters/test/org/apache/beam/learning/katas/coretransforms/dofnadditionalparams/TaskTest.kt
new file mode 100644
index 0000000..f20e39f
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/DoFn Additional Parameters/test/org/apache/beam/learning/katas/coretransforms/dofnadditionalparams/TaskTest.kt	
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.dofnadditionalparams
+
+class TaskTest
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/lesson-info.yaml b/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/lesson-info.yaml
new file mode 100644
index 0000000..1a41bfb
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/lesson-info.yaml	
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- DoFn Additional Parameters
diff --git a/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/lesson-remote-info.yaml b/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/lesson-remote-info.yaml
new file mode 100644
index 0000000..e79ba35
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/DoFn Additional Parameters/lesson-remote-info.yaml	
@@ -0,0 +1,3 @@
+id: 358531
+update_date: Wed, 20 May 2020 20:28:20 UTC
+unit: 342732
diff --git a/learning/katas/kotlin/Core Transforms/Flatten/Flatten/src/org/apache/beam/learning/katas/coretransforms/flatten/Task.kt b/learning/katas/kotlin/Core Transforms/Flatten/Flatten/src/org/apache/beam/learning/katas/coretransforms/flatten/Task.kt
new file mode 100644
index 0000000..466df99
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Flatten/Flatten/src/org/apache/beam/learning/katas/coretransforms/flatten/Task.kt	
@@ -0,0 +1,58 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.flatten
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.Flatten
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.PCollectionList
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val wordsStartingWithA = pipeline.apply(
+      "Words starting with A",
+      Create.of("apple", "ant", "arrow")
+    )
+
+    val wordsStartingWithB = pipeline.apply(
+      "Words starting with B",
+      Create.of("ball", "book", "bow")
+    )
+
+    val output = applyTransform(wordsStartingWithA, wordsStartingWithB)
+
+    output.apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun applyTransform(words1: PCollection<String>, words2: PCollection<String>): PCollection<String> {
+    return PCollectionList
+      .of(words1)
+      .and(words2)
+      .apply(Flatten.pCollections())
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Flatten/Flatten/task-info.yaml b/learning/katas/kotlin/Core Transforms/Flatten/Flatten/task-info.yaml
new file mode 100644
index 0000000..7b1dc84
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Flatten/Flatten/task-info.yaml	
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/flatten/Task.kt
+  visible: true
+  placeholders:
+  - offset: 1888
+    length: 89
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/flatten/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Core Transforms/Flatten/Flatten/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Flatten/Flatten/task-remote-info.yaml
new file mode 100644
index 0000000..7aeed74
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Flatten/Flatten/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326882
+update_date: Sat, 30 May 2020 18:48:25 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Flatten/Flatten/task.md b/learning/katas/kotlin/Core Transforms/Flatten/Flatten/task.md
new file mode 100644
index 0000000..5bf19ba
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Flatten/Flatten/task.md	
@@ -0,0 +1,39 @@
+<!--
+  ~  Licensed to the Apache Software Foundation (ASF) under one
+  ~  or more contributor license agreements.  See the NOTICE file
+  ~  distributed with this work for additional information
+  ~  regarding copyright ownership.  The ASF licenses this file
+  ~  to you 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.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  -->
+
+Flatten
+-------
+
+Flatten is a Beam transform for PCollection objects that store the same data type. Flatten merges 
+multiple PCollection objects into a single logical PCollection.
+
+**Kata:** Implement a 
+[Flatten](https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Flatten.html) 
+transform that merges two PCollection of words into a single PCollection.
+
+<div class="hint">
+  Refer to
+  <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Flatten.html">
+    Flatten</a> to solve this problem.
+</div>
+
+<div class="hint">
+  Refer to the Beam Programming Guide
+  <a href="https://beam.apache.org/documentation/programming-guide/#flatten">
+    "Flatten"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Flatten/Flatten/test/org/apache/beam/learning/katas/coretransforms/flatten/TaskTest.kt b/learning/katas/kotlin/Core Transforms/Flatten/Flatten/test/org/apache/beam/learning/katas/coretransforms/flatten/TaskTest.kt
new file mode 100644
index 0000000..acbad01
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Flatten/Flatten/test/org/apache/beam/learning/katas/coretransforms/flatten/TaskTest.kt	
@@ -0,0 +1,49 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.flatten
+
+import org.apache.beam.learning.katas.coretransforms.flatten.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun core_transforms_flatten_flatten() {
+    val wordsStartingWithA = testPipeline.apply(
+      "Words starting with A",
+      Create.of("apple", "ant", "arrow")
+    )
+    val wordsStartingWithB = testPipeline.apply(
+      "Words starting with B",
+      Create.of("ball", "book", "bow")
+    )
+
+    val results = applyTransform(wordsStartingWithA, wordsStartingWithB)
+
+    PAssert.that(results).containsInAnyOrder("apple", "ant", "arrow", "ball", "book", "bow")
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Flatten/lesson-info.yaml b/learning/katas/kotlin/Core Transforms/Flatten/lesson-info.yaml
new file mode 100644
index 0000000..fd01c86
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Flatten/lesson-info.yaml	
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Flatten
diff --git a/learning/katas/kotlin/Core Transforms/Flatten/lesson-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Flatten/lesson-remote-info.yaml
new file mode 100644
index 0000000..66bfb18
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Flatten/lesson-remote-info.yaml	
@@ -0,0 +1,3 @@
+id: 358525
+update_date: Wed, 20 May 2020 20:27:47 UTC
+unit: 342726
diff --git a/learning/katas/kotlin/Core Transforms/GroupByKey/GroupByKey/src/org/apache/beam/learning/katas/coretransforms/groupbykey/Task.kt b/learning/katas/kotlin/Core Transforms/GroupByKey/GroupByKey/src/org/apache/beam/learning/katas/coretransforms/groupbykey/Task.kt
new file mode 100644
index 0000000..9a55ee7
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/GroupByKey/GroupByKey/src/org/apache/beam/learning/katas/coretransforms/groupbykey/Task.kt	
@@ -0,0 +1,58 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.groupbykey
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.GroupByKey
+import org.apache.beam.sdk.transforms.MapElements
+import org.apache.beam.sdk.transforms.SerializableFunction
+import org.apache.beam.sdk.values.KV
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.TypeDescriptors
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val words = pipeline.apply(
+      Create.of("apple", "ball", "car", "bear", "cheetah", "ant")
+    )
+
+    val output = applyTransform(words)
+
+    output.apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun applyTransform(input: PCollection<String>): PCollection<KV<String, Iterable<String>>> {
+    return input
+      .apply(
+        MapElements
+          .into(TypeDescriptors.kvs(TypeDescriptors.strings(), TypeDescriptors.strings()))
+          .via(SerializableFunction { word: String -> KV.of(word.substring(0, 1), word) })
+      )
+      .apply(GroupByKey.create())
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/GroupByKey/GroupByKey/task-info.yaml b/learning/katas/kotlin/Core Transforms/GroupByKey/GroupByKey/task-info.yaml
new file mode 100644
index 0000000..b22c4e9
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/GroupByKey/GroupByKey/task-info.yaml	
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/groupbykey/Task.kt
+  visible: true
+  placeholders:
+  - offset: 1858
+    length: 263
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/groupbykey/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Core Transforms/GroupByKey/GroupByKey/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/GroupByKey/GroupByKey/task-remote-info.yaml
new file mode 100644
index 0000000..1ee3f72
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/GroupByKey/GroupByKey/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326876
+update_date: Sat, 30 May 2020 18:48:11 UTC
diff --git a/learning/katas/kotlin/Core Transforms/GroupByKey/GroupByKey/task.md b/learning/katas/kotlin/Core Transforms/GroupByKey/GroupByKey/task.md
new file mode 100644
index 0000000..cfaa2eb
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/GroupByKey/GroupByKey/task.md	
@@ -0,0 +1,43 @@
+<!--
+  ~  Licensed to the Apache Software Foundation (ASF) under one
+  ~  or more contributor license agreements.  See the NOTICE file
+  ~  distributed with this work for additional information
+  ~  regarding copyright ownership.  The ASF licenses this file
+  ~  to you 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.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  -->
+
+GroupByKey
+----------
+
+GroupByKey is a Beam transform for processing collections of key/value pairs. It’s a parallel 
+reduction operation, analogous to the Shuffle phase of a Map/Shuffle/Reduce-style algorithm. The 
+input to GroupByKey is a collection of key/value pairs that represents a multimap, where the 
+collection contains multiple pairs that have the same key, but different values. Given such a 
+collection, you use GroupByKey to collect all of the values associated with each unique key.
+
+**Kata:** Implement a 
+[GroupByKey](https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/GroupByKey.html) 
+transform that groups words by its first letter.
+
+<div class="hint">
+  Refer to <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/values/KV.html">
+  KV</a> and
+  <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/GroupByKey.html">
+    GroupByKey</a> to solve this problem.
+</div>
+
+<div class="hint">
+  Refer to the Beam Programming Guide
+  <a href="https://beam.apache.org/documentation/programming-guide/#groupbykey">
+    "GroupByKey"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/GroupByKey/GroupByKey/test/org/apache/beam/learning/katas/coretransforms/groupbykey/TaskTest.kt b/learning/katas/kotlin/Core Transforms/GroupByKey/GroupByKey/test/org/apache/beam/learning/katas/coretransforms/groupbykey/TaskTest.kt
new file mode 100644
index 0000000..5a7dea9
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/GroupByKey/GroupByKey/test/org/apache/beam/learning/katas/coretransforms/groupbykey/TaskTest.kt	
@@ -0,0 +1,52 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.groupbykey
+
+import com.google.common.collect.ImmutableList
+import org.apache.beam.learning.katas.coretransforms.groupbykey.Task.applyTransform
+import org.apache.beam.learning.katas.util.ContainsKvs
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.values.KV
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun core_transforms_groupbykey_groupbykey() {
+    val values = Create.of("apple", "ball", "car", "bear", "cheetah", "ant")
+    val numbers = testPipeline.apply(values)
+
+    val results = applyTransform(numbers)
+
+    PAssert.that(results).satisfies(
+      ContainsKvs.containsKvs(
+        KV.of("a", ImmutableList.of("apple", "ant")),
+        KV.of("b", ImmutableList.of("ball", "bear")),
+        KV.of("c", ImmutableList.of("car", "cheetah"))
+      )
+    )
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/GroupByKey/lesson-info.yaml b/learning/katas/kotlin/Core Transforms/GroupByKey/lesson-info.yaml
new file mode 100644
index 0000000..5de9eb6
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/GroupByKey/lesson-info.yaml	
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- GroupByKey
diff --git a/learning/katas/kotlin/Core Transforms/GroupByKey/lesson-remote-info.yaml b/learning/katas/kotlin/Core Transforms/GroupByKey/lesson-remote-info.yaml
new file mode 100644
index 0000000..83166a3
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/GroupByKey/lesson-remote-info.yaml	
@@ -0,0 +1,3 @@
+id: 358522
+update_date: Wed, 20 May 2020 20:27:23 UTC
+unit: 342723
diff --git a/learning/katas/kotlin/Core Transforms/Map/FlatMapElements/src/org/apache/beam/learning/katas/coretransforms/map/flatmapelements/Task.kt b/learning/katas/kotlin/Core Transforms/Map/FlatMapElements/src/org/apache/beam/learning/katas/coretransforms/map/flatmapelements/Task.kt
new file mode 100644
index 0000000..65c0c55
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/FlatMapElements/src/org/apache/beam/learning/katas/coretransforms/map/flatmapelements/Task.kt	
@@ -0,0 +1,54 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.map.flatmapelements
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.FlatMapElements
+import org.apache.beam.sdk.transforms.SerializableFunction
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.TypeDescriptors
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val sentences = pipeline.apply(Create.of("Apache Beam", "Unified Batch and Streaming"))
+
+    val output = applyTransform(sentences)
+
+    output.apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun applyTransform(input: PCollection<String>): PCollection<String> {
+    return input.apply(
+      FlatMapElements
+        .into(TypeDescriptors.strings())
+        .via(SerializableFunction<String, Iterable<String>> { sentence: String ->
+          sentence.split(" ")
+        })
+    )
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Map/FlatMapElements/task-info.yaml b/learning/katas/kotlin/Core Transforms/Map/FlatMapElements/task-info.yaml
new file mode 100644
index 0000000..59f135d
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/FlatMapElements/task-info.yaml	
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/map/flatmapelements/Task.kt
+  visible: true
+  placeholders:
+  - offset: 1755
+    length: 204
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/map/flatmapelements/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Core Transforms/Map/FlatMapElements/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Map/FlatMapElements/task-remote-info.yaml
new file mode 100644
index 0000000..97f4df9
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/FlatMapElements/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326875
+update_date: Sun, 31 May 2020 13:45:16 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Map/FlatMapElements/task.md b/learning/katas/kotlin/Core Transforms/Map/FlatMapElements/task.md
new file mode 100644
index 0000000..8eb555c
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/FlatMapElements/task.md	
@@ -0,0 +1,39 @@
+<!--
+  ~  Licensed to the Apache Software Foundation (ASF) under one
+  ~  or more contributor license agreements.  See the NOTICE file
+  ~  distributed with this work for additional information
+  ~  regarding copyright ownership.  The ASF licenses this file
+  ~  to you 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.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  -->
+
+FlatMapElements
+---------------
+
+The Beam SDKs provide language-specific ways to simplify how you provide your DoFn implementation.
+
+FlatMapElements can be used to simplify a DoFn that maps an element to multiple elements (one to 
+many).
+
+**Kata:** Implement a function that maps each input sentence into words tokenized by whitespace 
+(" ") using [FlatMapElements.into(...).via(...)](https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/FlatMapElements.html).
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/FlatMapElements.html">
+  FlatMapElements.into(...).via(...)</a>.
+</div>
+
+<div class="hint">
+  Refer to the Beam Programming Guide
+  <a href="https://beam.apache.org/documentation/programming-guide/#lightweight-dofns">
+    "Lightweight DoFns and other abstractions"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Map/FlatMapElements/test/org/apache/beam/learning/katas/coretransforms/map/flatmapelements/TaskTest.kt b/learning/katas/kotlin/Core Transforms/Map/FlatMapElements/test/org/apache/beam/learning/katas/coretransforms/map/flatmapelements/TaskTest.kt
new file mode 100644
index 0000000..efebb11
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/FlatMapElements/test/org/apache/beam/learning/katas/coretransforms/map/flatmapelements/TaskTest.kt	
@@ -0,0 +1,44 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.map.flatmapelements
+
+import org.apache.beam.learning.katas.coretransforms.map.flatmapelements.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun core_transforms_map_flatmapelements() {
+    val values = Create.of("Apache Beam", "Unified Batch and Streaming")
+    val numbers = testPipeline.apply(values)
+
+    val results = applyTransform(numbers)
+
+    PAssert.that(results).containsInAnyOrder(
+      "Apache", "Beam", "Unified", "Batch", "and", "Streaming"
+    )
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Map/MapElements/src/org/apache/beam/learning/katas/coretransforms/map/mapelements/Task.kt b/learning/katas/kotlin/Core Transforms/Map/MapElements/src/org/apache/beam/learning/katas/coretransforms/map/mapelements/Task.kt
new file mode 100644
index 0000000..5d040be
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/MapElements/src/org/apache/beam/learning/katas/coretransforms/map/mapelements/Task.kt	
@@ -0,0 +1,52 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.map.mapelements
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.MapElements
+import org.apache.beam.sdk.transforms.SerializableFunction
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.TypeDescriptors
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val numbers = pipeline.apply(Create.of(10, 20, 30, 40, 50))
+
+    val output = applyTransform(numbers)
+
+    output.apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun applyTransform(input: PCollection<Int>): PCollection<Int> {
+    return input.apply(
+      MapElements
+        .into(TypeDescriptors.integers())
+        .via(SerializableFunction { number: Int -> number * 5 })
+    )
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Map/MapElements/task-info.yaml b/learning/katas/kotlin/Core Transforms/Map/MapElements/task-info.yaml
new file mode 100644
index 0000000..384850b
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/MapElements/task-info.yaml	
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/map/mapelements/Task.kt
+  visible: true
+  placeholders:
+  - offset: 1711
+    length: 143
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/map/mapelements/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Core Transforms/Map/MapElements/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Map/MapElements/task-remote-info.yaml
new file mode 100644
index 0000000..6ba2aae
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/MapElements/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326874
+update_date: Sun, 31 May 2020 13:43:53 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Map/MapElements/task.md b/learning/katas/kotlin/Core Transforms/Map/MapElements/task.md
new file mode 100644
index 0000000..05b77f8
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/MapElements/task.md	
@@ -0,0 +1,38 @@
+<!--
+  ~  Licensed to the Apache Software Foundation (ASF) under one
+  ~  or more contributor license agreements.  See the NOTICE file
+  ~  distributed with this work for additional information
+  ~  regarding copyright ownership.  The ASF licenses this file
+  ~  to you 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.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  -->
+
+MapElements
+-----------
+
+The Beam SDKs provide language-specific ways to simplify how you provide your DoFn implementation.
+
+MapElements can be used to simplify a DoFn that maps an element to another element (one to one).
+
+**Kata:** Implement a simple map function that multiplies all input elements by 5 using 
+[MapElements.into(...).via(...)](https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/MapElements.html).
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/MapElements.html">
+  MapElements.into(...).via(...)</a>.
+</div>
+
+<div class="hint">
+  Refer to the Beam Programming Guide
+  <a href="https://beam.apache.org/documentation/programming-guide/#lightweight-dofns">
+    "Lightweight DoFns and other abstractions"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Map/MapElements/test/org/apache/beam/learning/katas/coretransforms/map/mapelements/TaskTest.kt b/learning/katas/kotlin/Core Transforms/Map/MapElements/test/org/apache/beam/learning/katas/coretransforms/map/mapelements/TaskTest.kt
new file mode 100644
index 0000000..f97c3d1
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/MapElements/test/org/apache/beam/learning/katas/coretransforms/map/mapelements/TaskTest.kt	
@@ -0,0 +1,43 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.map.mapelements
+
+import org.apache.beam.learning.katas.coretransforms.map.mapelements.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun core_transforms_map_mapelements() {
+    val values = Create.of(10, 20, 30, 40, 50)
+    val numbers = testPipeline.apply(values)
+
+    val results = applyTransform(numbers)
+
+    PAssert.that(results).containsInAnyOrder(50, 100, 150, 200, 250)
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Map/ParDo OneToMany/src/org/apache/beam/learning/katas/coretransforms/map/pardoonetomany/Task.kt b/learning/katas/kotlin/Core Transforms/Map/ParDo OneToMany/src/org/apache/beam/learning/katas/coretransforms/map/pardoonetomany/Task.kt
new file mode 100644
index 0000000..3784687
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/ParDo OneToMany/src/org/apache/beam/learning/katas/coretransforms/map/pardoonetomany/Task.kt	
@@ -0,0 +1,55 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.map.pardoonetomany
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.DoFn
+import org.apache.beam.sdk.transforms.ParDo
+import org.apache.beam.sdk.values.PCollection
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val sentences = pipeline.apply(Create.of("Hello Beam", "It is awesome"))
+
+    val output = applyTransform(sentences)
+
+    output.apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun applyTransform(input: PCollection<String>): PCollection<String> {
+    return input.apply(ParDo.of(object : DoFn<String, String>() {
+      @ProcessElement
+      fun processElement(@Element sentence: String, out: OutputReceiver<String?>) {
+        val words = sentence.split(" ")
+        for (word in words) {
+          out.output(word)
+        }
+      }
+    }))
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Map/ParDo OneToMany/task-info.yaml b/learning/katas/kotlin/Core Transforms/Map/ParDo OneToMany/task-info.yaml
new file mode 100644
index 0000000..e85d53d
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/ParDo OneToMany/task-info.yaml	
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/map/pardoonetomany/Task.kt
+  visible: true
+  placeholders:
+  - offset: 1663
+    length: 283
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/map/pardoonetomany/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Core Transforms/Map/ParDo OneToMany/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Map/ParDo OneToMany/task-remote-info.yaml
new file mode 100644
index 0000000..1fa612f
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/ParDo OneToMany/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326914
+update_date: Sun, 31 May 2020 13:43:51 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Map/ParDo OneToMany/task.md b/learning/katas/kotlin/Core Transforms/Map/ParDo OneToMany/task.md
new file mode 100644
index 0000000..013ef1d
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/ParDo OneToMany/task.md	
@@ -0,0 +1,37 @@
+<!--
+  ~  Licensed to the Apache Software Foundation (ASF) under one
+  ~  or more contributor license agreements.  See the NOTICE file
+  ~  distributed with this work for additional information
+  ~  regarding copyright ownership.  The ASF licenses this file
+  ~  to you 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.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  -->
+
+ParDo OneToMany
+---------------
+
+**Kata:** Please write a ParDo that maps each input sentence into words tokenized by whitespace 
+(" ").
+
+<div class="hint">
+  You can call <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/DoFn.OutputReceiver.html">
+  OutputReceiver</a> multiple times in a
+  <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/ParDo.html">
+  ParDo</a>.
+</div>
+
+<div class="hint">
+  If you're using Beam version before v2.5.0, you can call
+  <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/DoFn.WindowedContext.html#output-OutputT-">
+  DoFn.ProcessContext.output(..)</a> multiple times in a
+  <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/ParDo.html">ParDo</a>.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Map/ParDo OneToMany/test/org/apache/beam/learning/katas/coretransforms/map/pardoonetomany/TaskTest.kt b/learning/katas/kotlin/Core Transforms/Map/ParDo OneToMany/test/org/apache/beam/learning/katas/coretransforms/map/pardoonetomany/TaskTest.kt
new file mode 100644
index 0000000..d890a91
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/ParDo OneToMany/test/org/apache/beam/learning/katas/coretransforms/map/pardoonetomany/TaskTest.kt	
@@ -0,0 +1,41 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.map.pardoonetomany
+
+import org.apache.beam.learning.katas.coretransforms.map.pardoonetomany.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun core_transforms_map_pardo_onetomany() {
+    val values = Create.of("Hello Beam", "It is awesome")
+    val numbers = testPipeline.apply(values)
+    val results = applyTransform(numbers)
+
+    PAssert.that(results).containsInAnyOrder("Hello", "Beam", "It", "is", "awesome")
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Map/ParDo/src/org/apache/beam/learning/katas/coretransforms/map/pardo/Task.kt b/learning/katas/kotlin/Core Transforms/Map/ParDo/src/org/apache/beam/learning/katas/coretransforms/map/pardo/Task.kt
new file mode 100644
index 0000000..f11df16
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/ParDo/src/org/apache/beam/learning/katas/coretransforms/map/pardo/Task.kt	
@@ -0,0 +1,54 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.map.pardo
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.DoFn
+import org.apache.beam.sdk.transforms.ParDo
+import org.apache.beam.sdk.values.PCollection
+
+object Task {
+
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val numbers = pipeline.apply(Create.of(1, 2, 3, 4, 5))
+
+    val output = applyTransform(numbers)
+
+    output.apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun applyTransform(input: PCollection<Int>): PCollection<Int> {
+    return input.apply(ParDo.of(object : DoFn<Int, Int>() {
+      @ProcessElement
+      fun processElement(context: ProcessContext, out: OutputReceiver<Int>) {
+        val number = context.element()
+        out.output(number * 10)
+      }
+    }))
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Map/ParDo/task-info.yaml b/learning/katas/kotlin/Core Transforms/Map/ParDo/task-info.yaml
new file mode 100644
index 0000000..8dd9409
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/ParDo/task-info.yaml	
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/map/pardo/Task.kt
+  visible: true
+  placeholders:
+  - offset: 1629
+    length: 235
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/map/pardo/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Core Transforms/Map/ParDo/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Map/ParDo/task-remote-info.yaml
new file mode 100644
index 0000000..15825c8
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/ParDo/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326916
+update_date: Sun, 31 May 2020 13:43:48 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Map/ParDo/task.md b/learning/katas/kotlin/Core Transforms/Map/ParDo/task.md
new file mode 100644
index 0000000..bfcb16f
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/ParDo/task.md	
@@ -0,0 +1,40 @@
+<!--
+  ~  Licensed to the Apache Software Foundation (ASF) under one
+  ~  or more contributor license agreements.  See the NOTICE file
+  ~  distributed with this work for additional information
+  ~  regarding copyright ownership.  The ASF licenses this file
+  ~  to you 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.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  -->
+
+ParDo
+-----
+
+ParDo is a Beam transform for generic parallel processing. The ParDo processing paradigm is similar 
+to the “Map” phase of a Map/Shuffle/Reduce-style algorithm: a ParDo transform considers each 
+element in the input PCollection, performs some processing function (your user code) on that 
+element, and emits zero, one, or multiple elements to an output PCollection.
+
+**Kata:** Please write a simple ParDo that maps the input element by multiplying it by 10.
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/ParDo.html">
+  ParDo</a>
+  with <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/DoFn.html">
+  DoFn</a>.
+</div>
+
+<div class="hint">
+  Refer to the Beam Programming Guide
+  <a href="https://beam.apache.org/documentation/programming-guide/#pardo">"ParDo"</a> section for
+  more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Map/ParDo/test/org/apache/beam/learning/katas/coretransforms/map/pardo/TaskTest.kt b/learning/katas/kotlin/Core Transforms/Map/ParDo/test/org/apache/beam/learning/katas/coretransforms/map/pardo/TaskTest.kt
new file mode 100644
index 0000000..9fbf7fd
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/ParDo/test/org/apache/beam/learning/katas/coretransforms/map/pardo/TaskTest.kt	
@@ -0,0 +1,44 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.map.pardo
+
+import org.apache.beam.learning.katas.coretransforms.map.pardo.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun core_transforms_map_pardo() {
+    val values = Create.of(1, 2, 3, 4, 5)
+    val numbers = testPipeline.apply(values)
+
+    val results = applyTransform(numbers)
+
+    PAssert.that(results).containsInAnyOrder(10, 20, 30, 40, 50)
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Map/lesson-info.yaml b/learning/katas/kotlin/Core Transforms/Map/lesson-info.yaml
new file mode 100644
index 0000000..ad6558f
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/lesson-info.yaml	
@@ -0,0 +1,24 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- ParDo
+- ParDo OneToMany
+- MapElements
+- FlatMapElements
diff --git a/learning/katas/kotlin/Core Transforms/Map/lesson-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Map/lesson-remote-info.yaml
new file mode 100644
index 0000000..9086cc1
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Map/lesson-remote-info.yaml	
@@ -0,0 +1,3 @@
+id: 358521
+update_date: Wed, 20 May 2020 20:27:14 UTC
+unit: 342722
diff --git a/learning/katas/kotlin/Core Transforms/Partition/Partition/src/org/apache/beam/learning/katas/coretransforms/partition/Task.kt b/learning/katas/kotlin/Core Transforms/Partition/Partition/src/org/apache/beam/learning/katas/coretransforms/partition/Task.kt
new file mode 100644
index 0000000..a706565
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Partition/Partition/src/org/apache/beam/learning/katas/coretransforms/partition/Task.kt	
@@ -0,0 +1,57 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.partition
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.Partition
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.PCollectionList
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val numbers = pipeline.apply(
+      Create.of(1, 2, 3, 4, 5, 100, 110, 150, 250)
+    )
+
+    val partition = applyTransform(numbers)
+
+    partition[0].apply(Log.ofElements("Number > 100: "))
+    partition[1].apply(Log.ofElements("Number <= 100: "))
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun applyTransform(input: PCollection<Int>): PCollectionList<Int> {
+    return input
+      .apply(Partition.of(2) { number: Int, numPartitions: Int ->
+        if (number > 100) {
+          0
+        } else {
+          1
+        }
+      })
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Partition/Partition/task-info.yaml b/learning/katas/kotlin/Core Transforms/Partition/Partition/task-info.yaml
new file mode 100644
index 0000000..000f725
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Partition/Partition/task-info.yaml	
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/partition/Task.kt
+  visible: true
+  placeholders:
+  - offset: 1758
+    length: 159
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/partition/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Core Transforms/Partition/Partition/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Partition/Partition/task-remote-info.yaml
new file mode 100644
index 0000000..2d0bcc1
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Partition/Partition/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326883
+update_date: Sat, 30 May 2020 18:50:11 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Partition/Partition/task.md b/learning/katas/kotlin/Core Transforms/Partition/Partition/task.md
new file mode 100644
index 0000000..e254afd
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Partition/Partition/task.md	
@@ -0,0 +1,44 @@
+<!--
+  ~  Licensed to the Apache Software Foundation (ASF) under one
+  ~  or more contributor license agreements.  See the NOTICE file
+  ~  distributed with this work for additional information
+  ~  regarding copyright ownership.  The ASF licenses this file
+  ~  to you 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.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  -->
+
+Partition
+---------
+
+Partition is a Beam transform for PCollection objects that store the same data type. Partition 
+splits a single PCollection into a fixed number of smaller collections.
+
+Partition divides the elements of a PCollection according to a partitioning function that you 
+provide. The partitioning function contains the logic that determines how to split up the elements 
+of the input PCollection into each resulting partition PCollection.
+
+**Kata:** Implement a 
+[Partition](https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Partition.html) 
+transform that splits a PCollection of numbers into two PCollections. The first PCollection 
+contains numbers greater than 100, and the second PCollection contains the remaining numbers.
+
+<div class="hint">
+  Refer to
+  <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Partition.html">
+    Partition</a> to solve this problem.
+</div>
+
+<div class="hint">
+  Refer to the Beam Programming Guide
+  <a href="https://beam.apache.org/documentation/programming-guide/#partition">
+    "Partition"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Partition/Partition/test/org/apache/beam/learning/katas/coretransforms/partition/TaskTest.kt b/learning/katas/kotlin/Core Transforms/Partition/Partition/test/org/apache/beam/learning/katas/coretransforms/partition/TaskTest.kt
new file mode 100644
index 0000000..2785c60
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Partition/Partition/test/org/apache/beam/learning/katas/coretransforms/partition/TaskTest.kt	
@@ -0,0 +1,44 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.partition
+
+import org.apache.beam.learning.katas.coretransforms.partition.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun core_transforms_partition_partition() {
+    val numbers = testPipeline.apply(Create.of(1, 2, 3, 4, 5, 100, 110, 150, 250))
+
+    val results = applyTransform(numbers)
+
+    PAssert.that(results[0]).containsInAnyOrder(110, 150, 250)
+
+    PAssert.that(results[1]).containsInAnyOrder(1, 2, 3, 4, 5, 100)
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Partition/lesson-info.yaml b/learning/katas/kotlin/Core Transforms/Partition/lesson-info.yaml
new file mode 100644
index 0000000..c15773b
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Partition/lesson-info.yaml	
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Partition
diff --git a/learning/katas/kotlin/Core Transforms/Partition/lesson-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Partition/lesson-remote-info.yaml
new file mode 100644
index 0000000..eb19f96
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Partition/lesson-remote-info.yaml	
@@ -0,0 +1,3 @@
+id: 358526
+update_date: Wed, 20 May 2020 20:27:52 UTC
+unit: 342727
diff --git a/learning/katas/kotlin/Core Transforms/Side Input/Side Input/src/org/apache/beam/learning/katas/coretransforms/sideinput/Person.kt b/learning/katas/kotlin/Core Transforms/Side Input/Side Input/src/org/apache/beam/learning/katas/coretransforms/sideinput/Person.kt
new file mode 100644
index 0000000..8e16b90
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Input/Side Input/src/org/apache/beam/learning/katas/coretransforms/sideinput/Person.kt	
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.sideinput
+
+import java.io.Serializable
+
+data class Person(val name: String?, val city: String?, private val country: String? = null) : Serializable
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Side Input/Side Input/src/org/apache/beam/learning/katas/coretransforms/sideinput/Task.kt b/learning/katas/kotlin/Core Transforms/Side Input/Side Input/src/org/apache/beam/learning/katas/coretransforms/sideinput/Task.kt
new file mode 100644
index 0000000..527ca2d
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Input/Side Input/src/org/apache/beam/learning/katas/coretransforms/sideinput/Task.kt	
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.sideinput
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.DoFn
+import org.apache.beam.sdk.transforms.ParDo
+import org.apache.beam.sdk.transforms.View
+import org.apache.beam.sdk.values.KV
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.PCollectionView
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val citiesToCountries = pipeline.apply(
+      "Cities and Countries",
+      Create.of(
+        KV.of("Beijing", "China"),
+        KV.of("London", "United Kingdom"),
+        KV.of("San Francisco", "United States"),
+        KV.of("Singapore", "Singapore"),
+        KV.of("Sydney", "Australia")
+      )
+    )
+
+    val citiesToCountriesView = createView(citiesToCountries)
+
+    val persons = pipeline.apply(
+      "Persons",
+      Create.of(
+        Person("Henry", "Singapore"),
+        Person("Jane", "San Francisco"),
+        Person("Lee", "Beijing"),
+        Person("John", "Sydney"),
+        Person("Alfred", "London")
+      )
+    )
+
+    val output = applyTransform(persons, citiesToCountriesView)
+
+    output.apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun createView(citiesToCountries: PCollection<KV<String, String>>): PCollectionView<Map<String, String>> {
+    return citiesToCountries.apply(View.asMap())
+  }
+
+  @JvmStatic
+  fun applyTransform(
+    persons: PCollection<Person>,
+    citiesToCountriesView: PCollectionView<Map<String, String>>
+  ): PCollection<Person> {
+
+    return persons.apply(ParDo.of(object : DoFn<Person, Person>() {
+      @ProcessElement
+      fun processElement(@Element person: Person, out: OutputReceiver<Person>, context: ProcessContext) {
+        val citiesToCountries: Map<String, String> = context.sideInput(citiesToCountriesView)
+        val city = person.city
+        val country = citiesToCountries[city]
+
+        out.output(Person(person.name, city, country))
+      }
+    }).withSideInputs(citiesToCountriesView))
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Side Input/Side Input/src/task.md b/learning/katas/kotlin/Core Transforms/Side Input/Side Input/src/task.md
new file mode 100644
index 0000000..6ebde27
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Input/Side Input/src/task.md	
@@ -0,0 +1,52 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you 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.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+Side Input
+----------
+
+In addition to the main input PCollection, you can provide additional inputs to a ParDo transform 
+in the form of side inputs. A side input is an additional input that your DoFn can access each time 
+it processes an element in the input PCollection. When you specify a side input, you create a view 
+of some other data that can be read from within the ParDo transform’s DoFn while processing each 
+element.
+
+Side inputs are useful if your ParDo needs to inject additional data when processing each element 
+in the input PCollection, but the additional data needs to be determined at runtime (and not 
+hard-coded). Such values might be determined by the input data, or depend on a different branch of 
+your pipeline.
+
+**Kata:** Please enrich each Person with the country based on the city he/she lives in.
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/View.html">
+  View</a> to create PCollectionView of citiesToCountries.
+</div>
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/ParDo.html">
+  ParDo</a> with <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/DoFn.html">
+  DoFn</a> that accepts
+  <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/ParDo.SingleOutput.html#withSideInputs-org.apache.beam.sdk.values.PCollectionView...-">
+  side input</a>.
+</div>
+
+<div class="hint">
+  Refer to the Beam Programming Guide
+  <a href="https://beam.apache.org/documentation/programming-guide/#side-inputs">"Side inputs"</a>
+  section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Side Input/Side Input/task-info.yaml b/learning/katas/kotlin/Core Transforms/Side Input/Side Input/task-info.yaml
new file mode 100644
index 0000000..bdfed39
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Input/Side Input/task-info.yaml	
@@ -0,0 +1,34 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/sideinput/Person.kt
+  visible: true
+- name: src/org/apache/beam/learning/katas/coretransforms/sideinput/Task.kt
+  visible: true
+  placeholders:
+  - offset: 2390
+    length: 37
+    placeholder_text: TODO()
+  - offset: 2605
+    length: 465
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/sideinput/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Core Transforms/Side Input/Side Input/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Side Input/Side Input/task-remote-info.yaml
new file mode 100644
index 0000000..897f640
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Input/Side Input/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326884
+update_date: Sat, 30 May 2020 18:48:28 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Side Input/Side Input/task.md b/learning/katas/kotlin/Core Transforms/Side Input/Side Input/task.md
new file mode 100644
index 0000000..6ebde27
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Input/Side Input/task.md	
@@ -0,0 +1,52 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you 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.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+Side Input
+----------
+
+In addition to the main input PCollection, you can provide additional inputs to a ParDo transform 
+in the form of side inputs. A side input is an additional input that your DoFn can access each time 
+it processes an element in the input PCollection. When you specify a side input, you create a view 
+of some other data that can be read from within the ParDo transform’s DoFn while processing each 
+element.
+
+Side inputs are useful if your ParDo needs to inject additional data when processing each element 
+in the input PCollection, but the additional data needs to be determined at runtime (and not 
+hard-coded). Such values might be determined by the input data, or depend on a different branch of 
+your pipeline.
+
+**Kata:** Please enrich each Person with the country based on the city he/she lives in.
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/View.html">
+  View</a> to create PCollectionView of citiesToCountries.
+</div>
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/ParDo.html">
+  ParDo</a> with <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/DoFn.html">
+  DoFn</a> that accepts
+  <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/ParDo.SingleOutput.html#withSideInputs-org.apache.beam.sdk.values.PCollectionView...-">
+  side input</a>.
+</div>
+
+<div class="hint">
+  Refer to the Beam Programming Guide
+  <a href="https://beam.apache.org/documentation/programming-guide/#side-inputs">"Side inputs"</a>
+  section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Side Input/Side Input/test/org/apache/beam/learning/katas/coretransforms/sideinput/TaskTest.kt b/learning/katas/kotlin/Core Transforms/Side Input/Side Input/test/org/apache/beam/learning/katas/coretransforms/sideinput/TaskTest.kt
new file mode 100644
index 0000000..5b011e2
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Input/Side Input/test/org/apache/beam/learning/katas/coretransforms/sideinput/TaskTest.kt	
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.sideinput
+
+import org.apache.beam.learning.katas.coretransforms.sideinput.Task.applyTransform
+import org.apache.beam.learning.katas.coretransforms.sideinput.Task.createView
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.values.KV
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun core_transforms_side_input_side_input() {
+    val citiesToCountries = testPipeline.apply(
+      "Cities and Countries",
+      Create.of(
+        KV.of("Beijing", "China"),
+        KV.of("London", "United Kingdom"),
+        KV.of("San Francisco", "United States"),
+        KV.of("Singapore", "Singapore"),
+        KV.of("Sydney", "Australia")
+      )
+    )
+
+    val citiesToCountriesView = createView(citiesToCountries)
+
+    val persons = testPipeline.apply(
+      "Persons",
+      Create.of(
+        Person("Henry", "Singapore"),
+        Person("Jane", "San Francisco"),
+        Person("Lee", "Beijing"),
+        Person("John", "Sydney"),
+        Person("Alfred", "London")
+      )
+    )
+
+    val results = applyTransform(persons, citiesToCountriesView)
+
+    PAssert.that(results).containsInAnyOrder(
+      Person("Henry", "Singapore", "Singapore"),
+      Person("Jane", "San Francisco", "United States"),
+      Person("Lee", "Beijing", "China"),
+      Person("John", "Sydney", "Australia"),
+      Person("Alfred", "London", "United Kingdom")
+    )
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Side Input/lesson-info.yaml b/learning/katas/kotlin/Core Transforms/Side Input/lesson-info.yaml
new file mode 100644
index 0000000..210e3b0
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Input/lesson-info.yaml	
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Side Input
diff --git a/learning/katas/kotlin/Core Transforms/Side Input/lesson-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Side Input/lesson-remote-info.yaml
new file mode 100644
index 0000000..f96f0bd
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Input/lesson-remote-info.yaml	
@@ -0,0 +1,3 @@
+id: 358527
+update_date: Wed, 20 May 2020 20:27:56 UTC
+unit: 342728
diff --git a/learning/katas/kotlin/Core Transforms/Side Output/Side Output/src/org/apache/beam/learning/katas/coretransforms/sideoutput/Task.kt b/learning/katas/kotlin/Core Transforms/Side Output/Side Output/src/org/apache/beam/learning/katas/coretransforms/sideoutput/Task.kt
new file mode 100644
index 0000000..659e218
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Output/Side Output/src/org/apache/beam/learning/katas/coretransforms/sideoutput/Task.kt	
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.sideoutput
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.DoFn
+import org.apache.beam.sdk.transforms.ParDo
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.PCollectionTuple
+import org.apache.beam.sdk.values.TupleTag
+import org.apache.beam.sdk.values.TupleTagList
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val numbers = pipeline.apply(Create.of(10, 50, 120, 20, 200, 0))
+
+    val numBelow100Tag = object : TupleTag<Int>() {}
+    val numAbove100Tag = object : TupleTag<Int>() {}
+    val outputTuple = applyTransform(numbers, numBelow100Tag, numAbove100Tag)
+
+    outputTuple.get(numBelow100Tag).apply(Log.ofElements("Number <= 100: "))
+    outputTuple.get(numAbove100Tag).apply(Log.ofElements("Number > 100: "))
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun applyTransform(
+    numbers: PCollection<Int>,
+    numBelow100Tag: TupleTag<Int>,
+    numAbove100Tag: TupleTag<Int>
+  ): PCollectionTuple {
+
+    return numbers.apply(ParDo.of(object : DoFn<Int, Int>() {
+      @ProcessElement
+      fun processElement(context: ProcessContext, out: MultiOutputReceiver) {
+        val number = context.element()
+        if (number <= 100) {
+          out.get(numBelow100Tag).output(number)
+        } else {
+          out.get(numAbove100Tag).output(number)
+        }
+      }
+    }).withOutputTags(numBelow100Tag, TupleTagList.of(numAbove100Tag)))
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Side Output/Side Output/src/task.md b/learning/katas/kotlin/Core Transforms/Side Output/Side Output/src/task.md
new file mode 100644
index 0000000..d690244
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Output/Side Output/src/task.md	
@@ -0,0 +1,42 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you 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.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+Side Output
+-----------
+
+While ParDo always produces a main output PCollection (as the return value from apply), you can 
+also have your ParDo produce any number of additional output PCollections. If you choose to have 
+multiple outputs, your ParDo returns all of the output PCollections (including the main output) 
+bundled together.
+
+**Kata:** Implement additional output to your ParDo for numbers bigger than 100.
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/DoFn.MultiOutputReceiver.html">
+  MultiOutputReceiver</a> and
+  <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/ParDo.SingleOutput.html#withOutputTags-org.apache.beam.sdk.values.TupleTag-org.apache.beam.sdk.values.TupleTagList-">
+  .withOutputTags</a> to output multiple tagged-outputs in a
+  <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/ParDo.html">
+  ParDo.</a>
+</div>
+
+<div class="hint">
+  Refer to the Beam Programming Guide
+  <a href="https://beam.apache.org/documentation/programming-guide/#additional-outputs">
+  "Additional outputs"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Side Output/Side Output/task-info.yaml b/learning/katas/kotlin/Core Transforms/Side Output/Side Output/task-info.yaml
new file mode 100644
index 0000000..d3d89c3
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Output/Side Output/task-info.yaml	
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/coretransforms/sideoutput/Task.kt
+  visible: true
+  placeholders:
+  - offset: 2109
+    length: 423
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/coretransforms/sideoutput/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Core Transforms/Side Output/Side Output/task-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Side Output/Side Output/task-remote-info.yaml
new file mode 100644
index 0000000..309a6c0
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Output/Side Output/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326885
+update_date: Sat, 30 May 2020 18:48:30 UTC
diff --git a/learning/katas/kotlin/Core Transforms/Side Output/Side Output/task.md b/learning/katas/kotlin/Core Transforms/Side Output/Side Output/task.md
new file mode 100644
index 0000000..d690244
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Output/Side Output/task.md	
@@ -0,0 +1,42 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you 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.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+Side Output
+-----------
+
+While ParDo always produces a main output PCollection (as the return value from apply), you can 
+also have your ParDo produce any number of additional output PCollections. If you choose to have 
+multiple outputs, your ParDo returns all of the output PCollections (including the main output) 
+bundled together.
+
+**Kata:** Implement additional output to your ParDo for numbers bigger than 100.
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/DoFn.MultiOutputReceiver.html">
+  MultiOutputReceiver</a> and
+  <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/ParDo.SingleOutput.html#withOutputTags-org.apache.beam.sdk.values.TupleTag-org.apache.beam.sdk.values.TupleTagList-">
+  .withOutputTags</a> to output multiple tagged-outputs in a
+  <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/ParDo.html">
+  ParDo.</a>
+</div>
+
+<div class="hint">
+  Refer to the Beam Programming Guide
+  <a href="https://beam.apache.org/documentation/programming-guide/#additional-outputs">
+  "Additional outputs"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Core Transforms/Side Output/Side Output/test/org/apache/beam/learning/katas/coretransforms/sideoutput/TaskTest.kt b/learning/katas/kotlin/Core Transforms/Side Output/Side Output/test/org/apache/beam/learning/katas/coretransforms/sideoutput/TaskTest.kt
new file mode 100644
index 0000000..46afa1e
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Output/Side Output/test/org/apache/beam/learning/katas/coretransforms/sideoutput/TaskTest.kt	
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.coretransforms.sideoutput
+
+import org.apache.beam.learning.katas.coretransforms.sideoutput.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.values.TupleTag
+import org.junit.Rule
+import org.junit.Test
+import java.io.Serializable
+
+class TaskTest : Serializable {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun core_transforms_side_output_side_output() {
+    val numbers = testPipeline.apply(Create.of(10, 50, 120, 20, 200, 0))
+
+    val numBelow100Tag = object : TupleTag<Int>() {}
+    val numAbove100Tag = object : TupleTag<Int>() {}
+
+    val resultsTuple = applyTransform(numbers, numBelow100Tag, numAbove100Tag)
+
+    PAssert.that(resultsTuple.get(numBelow100Tag)).containsInAnyOrder(0, 10, 20, 50)
+
+    PAssert.that(resultsTuple.get(numAbove100Tag)).containsInAnyOrder(120, 200)
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Core Transforms/Side Output/lesson-info.yaml b/learning/katas/kotlin/Core Transforms/Side Output/lesson-info.yaml
new file mode 100644
index 0000000..e9096c9
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Output/lesson-info.yaml	
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Side Output
diff --git a/learning/katas/kotlin/Core Transforms/Side Output/lesson-remote-info.yaml b/learning/katas/kotlin/Core Transforms/Side Output/lesson-remote-info.yaml
new file mode 100644
index 0000000..b9af67a
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/Side Output/lesson-remote-info.yaml	
@@ -0,0 +1,3 @@
+id: 358528
+update_date: Wed, 20 May 2020 20:28:03 UTC
+unit: 342729
diff --git a/learning/katas/kotlin/Core Transforms/section-info.yaml b/learning/katas/kotlin/Core Transforms/section-info.yaml
new file mode 100644
index 0000000..7a9eda8
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/section-info.yaml	
@@ -0,0 +1,31 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Map
+- GroupByKey
+- CoGroupByKey
+- Combine
+- Flatten
+- Partition
+- Side Input
+- Side Output
+- Branching
+- Composite Transform
+- DoFn Additional Parameters
diff --git a/learning/katas/kotlin/Core Transforms/section-remote-info.yaml b/learning/katas/kotlin/Core Transforms/section-remote-info.yaml
new file mode 100644
index 0000000..965b247
--- /dev/null
+++ b/learning/katas/kotlin/Core Transforms/section-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 133888
+update_date: Wed, 20 May 2020 20:27:13 UTC
diff --git a/learning/katas/kotlin/Examples/Word Count/Word Count/src/org/apache/beam/learning/katas/examples/wordcount/Task.kt b/learning/katas/kotlin/Examples/Word Count/Word Count/src/org/apache/beam/learning/katas/examples/wordcount/Task.kt
new file mode 100644
index 0000000..67e2afc
--- /dev/null
+++ b/learning/katas/kotlin/Examples/Word Count/Word Count/src/org/apache/beam/learning/katas/examples/wordcount/Task.kt	
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.examples.wordcount
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.*
+import org.apache.beam.sdk.values.KV
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.TypeDescriptors
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val lines = arrayOf(
+      "apple orange grape banana apple banana",
+      "banana orange banana papaya"
+    )
+
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val wordCounts = pipeline.apply(Create.of(listOf(*lines)))
+
+    val output = applyTransform(wordCounts)
+
+    output.apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun applyTransform(input: PCollection<String>): PCollection<String> {
+    return input
+      .apply(
+        FlatMapElements
+          .into(TypeDescriptors.strings())
+          .via(SerializableFunction<String, Iterable<String>> { line: String ->
+            line.split(" ")
+          })
+      )
+      .apply(Count.perElement())
+      .apply(ParDo.of(object : DoFn<KV<String, Long>, String>() {
+        @ProcessElement
+        fun processElement(@Element element: KV<String, Long>, out: OutputReceiver<String>) {
+          out.output(element.key.toString() + ":" + element.value)
+        }
+      }))
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Examples/Word Count/Word Count/task-info.yaml b/learning/katas/kotlin/Examples/Word Count/Word Count/task-info.yaml
new file mode 100644
index 0000000..8807028
--- /dev/null
+++ b/learning/katas/kotlin/Examples/Word Count/Word Count/task-info.yaml	
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/examples/wordcount/Task.kt
+  visible: true
+  placeholders:
+  - offset: 1733
+    length: 519
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/examples/wordcount/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Examples/Word Count/Word Count/task-remote-info.yaml b/learning/katas/kotlin/Examples/Word Count/Word Count/task-remote-info.yaml
new file mode 100644
index 0000000..a70cf74
--- /dev/null
+++ b/learning/katas/kotlin/Examples/Word Count/Word Count/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326909
+update_date: Sat, 30 May 2020 18:49:17 UTC
diff --git a/learning/katas/kotlin/Examples/Word Count/Word Count/task.md b/learning/katas/kotlin/Examples/Word Count/Word Count/task.md
new file mode 100644
index 0000000..d8dbdff
--- /dev/null
+++ b/learning/katas/kotlin/Examples/Word Count/Word Count/task.md	
@@ -0,0 +1,33 @@
+<!--
+  ~  Licensed to the Apache Software Foundation (ASF) under one
+  ~  or more contributor license agreements.  See the NOTICE file
+  ~  distributed with this work for additional information
+  ~  regarding copyright ownership.  The ASF licenses this file
+  ~  to you 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.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  -->
+
+Word Count Pipeline
+-------------------
+
+**Kata:** Create a pipeline that counts the number of words.
+
+Please output the count of each word in the following format:
+```text
+word:count
+ball:5
+book:3
+```
+
+<div class="hint">
+  Refer to your katas above.
+</div>
diff --git a/learning/katas/kotlin/Examples/Word Count/Word Count/test/org/apache/beam/learning/katas/examples/wordcount/TaskTest.kt b/learning/katas/kotlin/Examples/Word Count/Word Count/test/org/apache/beam/learning/katas/examples/wordcount/TaskTest.kt
new file mode 100644
index 0000000..48858ba
--- /dev/null
+++ b/learning/katas/kotlin/Examples/Word Count/Word Count/test/org/apache/beam/learning/katas/examples/wordcount/TaskTest.kt	
@@ -0,0 +1,53 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.examples.wordcount
+
+import org.apache.beam.learning.katas.examples.wordcount.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun examples_word_count_word_count() {
+    val lines = Create.of(
+      "apple orange grape banana apple banana",
+      "banana orange banana papaya"
+    )
+
+    val linesPColl = testPipeline.apply(lines)
+
+    val results = applyTransform(linesPColl)
+
+    PAssert.that(results).containsInAnyOrder(
+      "apple:2",
+      "banana:4",
+      "grape:1",
+      "orange:2",
+      "papaya:1"
+    )
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Examples/Word Count/lesson-info.yaml b/learning/katas/kotlin/Examples/Word Count/lesson-info.yaml
new file mode 100644
index 0000000..cbe1d6f
--- /dev/null
+++ b/learning/katas/kotlin/Examples/Word Count/lesson-info.yaml	
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Word Count
diff --git a/learning/katas/kotlin/Examples/Word Count/lesson-remote-info.yaml b/learning/katas/kotlin/Examples/Word Count/lesson-remote-info.yaml
new file mode 100644
index 0000000..649768a
--- /dev/null
+++ b/learning/katas/kotlin/Examples/Word Count/lesson-remote-info.yaml	
@@ -0,0 +1,3 @@
+id: 358542
+update_date: Wed, 20 May 2020 20:29:29 UTC
+unit: 342743
diff --git a/learning/katas/kotlin/Examples/section-info.yaml b/learning/katas/kotlin/Examples/section-info.yaml
new file mode 100644
index 0000000..cbe1d6f
--- /dev/null
+++ b/learning/katas/kotlin/Examples/section-info.yaml
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Word Count
diff --git a/learning/katas/kotlin/Examples/section-remote-info.yaml b/learning/katas/kotlin/Examples/section-remote-info.yaml
new file mode 100644
index 0000000..1dd0468
--- /dev/null
+++ b/learning/katas/kotlin/Examples/section-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 133893
+update_date: Wed, 20 May 2020 20:29:28 UTC
diff --git a/learning/katas/kotlin/IO/Built-in IOs/Built-in IOs/src/org/apache/beam/learning/katas/io/builtinios/Task.kt b/learning/katas/kotlin/IO/Built-in IOs/Built-in IOs/src/org/apache/beam/learning/katas/io/builtinios/Task.kt
new file mode 100644
index 0000000..42e5b4b
--- /dev/null
+++ b/learning/katas/kotlin/IO/Built-in IOs/Built-in IOs/src/org/apache/beam/learning/katas/io/builtinios/Task.kt	
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.io.builtinios
+
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    pipeline.run()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/IO/Built-in IOs/Built-in IOs/task-info.yaml b/learning/katas/kotlin/IO/Built-in IOs/Built-in IOs/task-info.yaml
new file mode 100644
index 0000000..c684624
--- /dev/null
+++ b/learning/katas/kotlin/IO/Built-in IOs/Built-in IOs/task-info.yaml	
@@ -0,0 +1,25 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: theory
+files:
+- name: src/org/apache/beam/learning/katas/io/builtinios/Task.kt
+  visible: true
+- name: test/org/apache/beam/learning/katas/io/builtinios/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/IO/Built-in IOs/Built-in IOs/task-remote-info.yaml b/learning/katas/kotlin/IO/Built-in IOs/Built-in IOs/task-remote-info.yaml
new file mode 100644
index 0000000..6148789
--- /dev/null
+++ b/learning/katas/kotlin/IO/Built-in IOs/Built-in IOs/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326902
+update_date: Sat, 30 May 2020 18:49:02 UTC
diff --git a/learning/katas/kotlin/IO/Built-in IOs/Built-in IOs/task.md b/learning/katas/kotlin/IO/Built-in IOs/Built-in IOs/task.md
new file mode 100644
index 0000000..b083c73
--- /dev/null
+++ b/learning/katas/kotlin/IO/Built-in IOs/Built-in IOs/task.md	
@@ -0,0 +1,29 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you 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.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+Built-in I/Os
+-------------
+
+Beam SDKs provide many out of the box I/O transforms that can be used to read from many different 
+sources and write to many different sinks.
+
+See the [Beam-provided I/O Transforms](https://beam.apache.org/documentation/io/built-in/) page for 
+a list of the currently available I/O transforms.
+
+**Note:** There is no kata for this task. Please click the "Check" button and proceed to the next 
+task.
\ No newline at end of file
diff --git a/learning/katas/kotlin/IO/Built-in IOs/Built-in IOs/test/org/apache/beam/learning/katas/io/builtinios/TaskTest.kt b/learning/katas/kotlin/IO/Built-in IOs/Built-in IOs/test/org/apache/beam/learning/katas/io/builtinios/TaskTest.kt
new file mode 100644
index 0000000..68ef12c
--- /dev/null
+++ b/learning/katas/kotlin/IO/Built-in IOs/Built-in IOs/test/org/apache/beam/learning/katas/io/builtinios/TaskTest.kt	
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.io.builtinios
+
+class TaskTest
\ No newline at end of file
diff --git a/learning/katas/kotlin/IO/Built-in IOs/lesson-info.yaml b/learning/katas/kotlin/IO/Built-in IOs/lesson-info.yaml
new file mode 100644
index 0000000..af969f1
--- /dev/null
+++ b/learning/katas/kotlin/IO/Built-in IOs/lesson-info.yaml	
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Built-in IOs
diff --git a/learning/katas/kotlin/IO/Built-in IOs/lesson-remote-info.yaml b/learning/katas/kotlin/IO/Built-in IOs/lesson-remote-info.yaml
new file mode 100644
index 0000000..22f4247
--- /dev/null
+++ b/learning/katas/kotlin/IO/Built-in IOs/lesson-remote-info.yaml	
@@ -0,0 +1,3 @@
+id: 358536
+update_date: Wed, 20 May 2020 20:28:54 UTC
+unit: 342737
diff --git a/learning/katas/kotlin/IO/TextIO/TextIO Read/countries.txt b/learning/katas/kotlin/IO/TextIO/TextIO Read/countries.txt
new file mode 100644
index 0000000..9d6848f
--- /dev/null
+++ b/learning/katas/kotlin/IO/TextIO/TextIO Read/countries.txt	
@@ -0,0 +1,10 @@
+Singapore
+United States
+Australia
+England
+France
+China
+Indonesia
+Mexico
+Germany
+Japan
diff --git a/learning/katas/kotlin/IO/TextIO/TextIO Read/src/org/apache/beam/learning/katas/io/textio/read/Task.kt b/learning/katas/kotlin/IO/TextIO/TextIO Read/src/org/apache/beam/learning/katas/io/textio/read/Task.kt
new file mode 100644
index 0000000..69a499c
--- /dev/null
+++ b/learning/katas/kotlin/IO/TextIO/TextIO Read/src/org/apache/beam/learning/katas/io/textio/read/Task.kt	
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.io.textio.read
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.io.TextIO
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.MapElements
+import org.apache.beam.sdk.transforms.SerializableFunction
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.TypeDescriptors
+
+object Task {
+  private const val FILE_PATH = "IO/TextIO/TextIO Read/countries.txt"
+
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val countries = pipeline.apply("Read Countries", TextIO.read().from(FILE_PATH))
+
+    val output = applyTransform(countries)
+
+    output.apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun applyTransform(input: PCollection<String>): PCollection<String> {
+    return input.apply(
+      MapElements
+        .into(TypeDescriptors.strings())
+        .via(SerializableFunction(String::toUpperCase))
+    )
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/IO/TextIO/TextIO Read/task-info.yaml b/learning/katas/kotlin/IO/TextIO/TextIO Read/task-info.yaml
new file mode 100644
index 0000000..92d392f
--- /dev/null
+++ b/learning/katas/kotlin/IO/TextIO/TextIO Read/task-info.yaml	
@@ -0,0 +1,34 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: countries.txt
+  visible: true
+- name: src/org/apache/beam/learning/katas/io/textio/read/Task.kt
+  visible: true
+  placeholders:
+  - offset: 1541
+    length: 29
+    placeholder_text: TODO()
+  - offset: 1773
+    length: 133
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/io/textio/read/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/IO/TextIO/TextIO Read/task-remote-info.yaml b/learning/katas/kotlin/IO/TextIO/TextIO Read/task-remote-info.yaml
new file mode 100644
index 0000000..1c29b22
--- /dev/null
+++ b/learning/katas/kotlin/IO/TextIO/TextIO Read/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326901
+update_date: Sat, 30 May 2020 18:50:19 UTC
diff --git a/learning/katas/kotlin/IO/TextIO/TextIO Read/task.md b/learning/katas/kotlin/IO/TextIO/TextIO Read/task.md
new file mode 100644
index 0000000..23dd394
--- /dev/null
+++ b/learning/katas/kotlin/IO/TextIO/TextIO Read/task.md	
@@ -0,0 +1,44 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you 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.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+TextIO Read
+-----------
+
+When you create a pipeline, you often need to read data from some external source, such as a file 
+or a database. Likewise, you may want your pipeline to output its result data to an external 
+storage system. Beam provides read and write transforms for a number of common data storage types. 
+If you want your pipeline to read from or write to a data storage format that isn’t supported by 
+the built-in transforms, you can implement your own read and write transforms.
+
+To read a PCollection from one or more text files, use TextIO.read() to instantiate a transform 
+and use TextIO.Read.from(String) to specify the path of the file(s) to be read.
+
+**Kata:** Read the 'countries.txt' file and convert each country name into uppercase.
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/io/TextIO.html">
+  TextIO</a> and its corresponding
+  <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/io/TextIO.html#read--">
+    TextIO.read()</a> method.
+</div>
+
+<div class="hint">
+  Refer to the Beam Programming Guide
+  <a href="https://beam.apache.org/documentation/programming-guide/#pipeline-io-reading-data">
+    "Reading input data"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/IO/TextIO/TextIO Read/test/org/apache/beam/learning/katas/io/textio/read/TaskTest.kt b/learning/katas/kotlin/IO/TextIO/TextIO Read/test/org/apache/beam/learning/katas/io/textio/read/TaskTest.kt
new file mode 100644
index 0000000..62bb832
--- /dev/null
+++ b/learning/katas/kotlin/IO/TextIO/TextIO Read/test/org/apache/beam/learning/katas/io/textio/read/TaskTest.kt	
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.io.textio.read
+
+import org.apache.beam.learning.katas.io.textio.read.Task.applyTransform
+import org.apache.beam.sdk.io.TextIO
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun io_textio_textio_read() {
+    val countries = testPipeline.apply(TextIO.read().from("countries.txt"))
+
+    val results = applyTransform(countries)
+
+    PAssert.that(results).containsInAnyOrder(
+      "AUSTRALIA",
+      "CHINA",
+      "ENGLAND",
+      "FRANCE",
+      "GERMANY",
+      "INDONESIA",
+      "JAPAN",
+      "MEXICO",
+      "SINGAPORE",
+      "UNITED STATES"
+    )
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/IO/TextIO/lesson-info.yaml b/learning/katas/kotlin/IO/TextIO/lesson-info.yaml
new file mode 100644
index 0000000..e671ddc
--- /dev/null
+++ b/learning/katas/kotlin/IO/TextIO/lesson-info.yaml
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- TextIO Read
diff --git a/learning/katas/kotlin/IO/TextIO/lesson-remote-info.yaml b/learning/katas/kotlin/IO/TextIO/lesson-remote-info.yaml
new file mode 100644
index 0000000..d8716cb
--- /dev/null
+++ b/learning/katas/kotlin/IO/TextIO/lesson-remote-info.yaml
@@ -0,0 +1,3 @@
+id: 358535
+update_date: Wed, 20 May 2020 20:28:49 UTC
+unit: 342736
diff --git a/learning/katas/kotlin/IO/section-info.yaml b/learning/katas/kotlin/IO/section-info.yaml
new file mode 100644
index 0000000..1d93752
--- /dev/null
+++ b/learning/katas/kotlin/IO/section-info.yaml
@@ -0,0 +1,22 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- TextIO
+- Built-in IOs
diff --git a/learning/katas/kotlin/IO/section-remote-info.yaml b/learning/katas/kotlin/IO/section-remote-info.yaml
new file mode 100644
index 0000000..d299c8a
--- /dev/null
+++ b/learning/katas/kotlin/IO/section-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 133890
+update_date: Wed, 20 May 2020 20:28:48 UTC
diff --git a/learning/katas/kotlin/Introduction/Hello Beam/Hello Beam/src/org/apache/beam/learning/katas/intro/hello/Task.kt b/learning/katas/kotlin/Introduction/Hello Beam/Hello Beam/src/org/apache/beam/learning/katas/intro/hello/Task.kt
new file mode 100644
index 0000000..857b663
--- /dev/null
+++ b/learning/katas/kotlin/Introduction/Hello Beam/Hello Beam/src/org/apache/beam/learning/katas/intro/hello/Task.kt	
@@ -0,0 +1,43 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.intro.hello
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.values.PCollection
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val output = setupPipeline(pipeline)
+
+    output.apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun setupPipeline(pipeline: Pipeline): PCollection<String> {
+    return pipeline.apply(Create.of("Hello Beam"))
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Introduction/Hello Beam/Hello Beam/task-info.yaml b/learning/katas/kotlin/Introduction/Hello Beam/Hello Beam/task-info.yaml
new file mode 100644
index 0000000..d2d8f64
--- /dev/null
+++ b/learning/katas/kotlin/Introduction/Hello Beam/Hello Beam/task-info.yaml	
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/intro/hello/Task.kt
+  visible: true
+  placeholders:
+  - offset: 1465
+    length: 39
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/intro/hello/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Introduction/Hello Beam/Hello Beam/task-remote-info.yaml b/learning/katas/kotlin/Introduction/Hello Beam/Hello Beam/task-remote-info.yaml
new file mode 100644
index 0000000..32361a0
--- /dev/null
+++ b/learning/katas/kotlin/Introduction/Hello Beam/Hello Beam/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326913
+update_date: Sat, 30 May 2020 18:48:01 UTC
diff --git a/learning/katas/java/Introduction/Hello Beam/Hello Beam/task.md b/learning/katas/kotlin/Introduction/Hello Beam/Hello Beam/task.md
similarity index 100%
rename from learning/katas/java/Introduction/Hello Beam/Hello Beam/task.md
rename to learning/katas/kotlin/Introduction/Hello Beam/Hello Beam/task.md
diff --git a/learning/katas/kotlin/Introduction/Hello Beam/Hello Beam/test/org/apache/beam/learning/katas/intro/hello/TaskTest.kt b/learning/katas/kotlin/Introduction/Hello Beam/Hello Beam/test/org/apache/beam/learning/katas/intro/hello/TaskTest.kt
new file mode 100644
index 0000000..dff0346
--- /dev/null
+++ b/learning/katas/kotlin/Introduction/Hello Beam/Hello Beam/test/org/apache/beam/learning/katas/intro/hello/TaskTest.kt	
@@ -0,0 +1,40 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.beam.learning.katas.intro.hello
+
+import org.apache.beam.learning.katas.intro.hello.Task.setupPipeline
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.junit.Rule
+import org.junit.Test
+import java.io.Serializable
+
+class TaskTest : Serializable {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun introduction_hello_beam_hello_beam() {
+    val results = setupPipeline(testPipeline)
+
+    PAssert.that(results).containsInAnyOrder("Hello Beam")
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Introduction/Hello Beam/lesson-info.yaml b/learning/katas/kotlin/Introduction/Hello Beam/lesson-info.yaml
new file mode 100644
index 0000000..040e0ac
--- /dev/null
+++ b/learning/katas/kotlin/Introduction/Hello Beam/lesson-info.yaml	
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Hello Beam
diff --git a/learning/katas/kotlin/Introduction/Hello Beam/lesson-remote-info.yaml b/learning/katas/kotlin/Introduction/Hello Beam/lesson-remote-info.yaml
new file mode 100644
index 0000000..b2b8037
--- /dev/null
+++ b/learning/katas/kotlin/Introduction/Hello Beam/lesson-remote-info.yaml	
@@ -0,0 +1,3 @@
+id: 358520
+update_date: Wed, 20 May 2020 20:27:07 UTC
+unit: 342721
diff --git a/learning/katas/kotlin/Introduction/section-info.yaml b/learning/katas/kotlin/Introduction/section-info.yaml
new file mode 100644
index 0000000..040e0ac
--- /dev/null
+++ b/learning/katas/kotlin/Introduction/section-info.yaml
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Hello Beam
diff --git a/learning/katas/kotlin/Introduction/section-remote-info.yaml b/learning/katas/kotlin/Introduction/section-remote-info.yaml
new file mode 100644
index 0000000..8c26adf
--- /dev/null
+++ b/learning/katas/kotlin/Introduction/section-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 133887
+update_date: Wed, 20 May 2020 20:27:05 UTC
diff --git a/learning/katas/kotlin/README.md b/learning/katas/kotlin/README.md
new file mode 100644
index 0000000..5343cc6
--- /dev/null
+++ b/learning/katas/kotlin/README.md
@@ -0,0 +1,31 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you 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.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+-->
+
+### How to Setup
+Please follow the below steps in order to setup the project properly:
+* Using IntelliJ Education (or IntelliJ with EduTools plugin), select "Open" and select this 
+directory (learning/katas/kotlin)
+* "Import Gradle project" when prompted, and configure the Gradle setup
+* Wait for Gradle build to finish
+* Open "Project Structure" and setup the project SDK (e.g. JDK 8)
+* Open the "Project" tool window, and select the "Course" view
+* Your project is ready
+
+For further instructions on how the IntelliJ Education works, you can refer 
+[here](https://www.jetbrains.com/help/education/educator-start-guide.html?section=Kotlin).
diff --git a/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/src/org/apache/beam/learning/katas/triggers/earlytriggers/GenerateEvent.kt b/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/src/org/apache/beam/learning/katas/triggers/earlytriggers/GenerateEvent.kt
new file mode 100644
index 0000000..ab49dc0
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/src/org/apache/beam/learning/katas/triggers/earlytriggers/GenerateEvent.kt	
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.triggers.earlytriggers
+
+import org.apache.beam.sdk.io.GenerateSequence
+import org.apache.beam.sdk.transforms.MapElements
+import org.apache.beam.sdk.transforms.PTransform
+import org.apache.beam.sdk.transforms.SerializableFunction
+import org.apache.beam.sdk.values.PBegin
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.TypeDescriptors
+import org.joda.time.Duration
+
+class GenerateEvent : PTransform<PBegin, PCollection<String>>() {
+  companion object {
+    fun everySecond(): GenerateEvent {
+      return GenerateEvent()
+    }
+  }
+
+  override fun expand(input: PBegin): PCollection<String> {
+    return input
+      .apply(GenerateSequence.from(1).withRate(1, Duration.standardSeconds(1)))
+      .apply(MapElements.into(TypeDescriptors.strings()).via(SerializableFunction { "event" }))
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/src/org/apache/beam/learning/katas/triggers/earlytriggers/Task.kt b/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/src/org/apache/beam/learning/katas/triggers/earlytriggers/Task.kt
new file mode 100644
index 0000000..df427e6
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/src/org/apache/beam/learning/katas/triggers/earlytriggers/Task.kt	
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.triggers.earlytriggers
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Combine
+import org.apache.beam.sdk.transforms.Count
+import org.apache.beam.sdk.transforms.windowing.AfterProcessingTime
+import org.apache.beam.sdk.transforms.windowing.AfterWatermark
+import org.apache.beam.sdk.transforms.windowing.FixedWindows
+import org.apache.beam.sdk.transforms.windowing.Window
+import org.apache.beam.sdk.values.PCollection
+import org.joda.time.Duration
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val events = pipeline.apply(GenerateEvent.everySecond())
+
+    val output = applyTransform(events)
+
+    output.apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun applyTransform(events: PCollection<String>): PCollection<Long> {
+    return events
+      .apply(
+        Window.into<String>(FixedWindows.of(Duration.standardDays(1)))
+          .triggering(
+            AfterWatermark
+              .pastEndOfWindow()
+              .withEarlyFirings(AfterProcessingTime.pastFirstElementInPane())
+          )
+          .withAllowedLateness(Duration.ZERO)
+          .discardingFiredPanes()
+      )
+      .apply(Combine.globally(Count.combineFn<String>()).withoutDefaults())
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/task-info.yaml b/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/task-info.yaml
new file mode 100644
index 0000000..fcccec6
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/task-info.yaml	
@@ -0,0 +1,31 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/triggers/earlytriggers/GenerateEvent.kt
+  visible: true
+- name: src/org/apache/beam/learning/katas/triggers/earlytriggers/Task.kt
+  visible: true
+  placeholders:
+  - offset: 1854
+    length: 428
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/triggers/earlytriggers/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/task-remote-info.yaml b/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/task-remote-info.yaml
new file mode 100644
index 0000000..6b5bc11
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326907
+update_date: Sat, 30 May 2020 18:49:13 UTC
diff --git a/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/task.md b/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/task.md
new file mode 100644
index 0000000..12d579f
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/task.md	
@@ -0,0 +1,60 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you 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.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+Early Triggers
+--------------
+
+Triggers allow Beam to emit early results, before all the data in a given window has arrived. For 
+example, emitting after a certain amount of time elapses, or after a certain number of elements 
+arrives.
+
+**Kata:** Given that events are being generated every second and a fixed window of 1-day duration, 
+please implement an early trigger that emits the number of events count immediately after new 
+element is processed.
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/windowing/AfterWatermark.AfterWatermarkEarlyAndLate.html#withEarlyFirings-org.apache.beam.sdk.transforms.windowing.Trigger.OnceTrigger-">
+  withEarlyFirings</a> to set early firing triggers.
+</div>
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/windowing/FixedWindows.html">
+  FixedWindows</a> with 1-day duration using
+  <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/windowing/AfterWatermark.html#pastEndOfWindow--">
+    AfterWatermark.pastEndOfWindow()</a> trigger.
+</div>
+
+<div class="hint">
+  Set the <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/windowing/Window.html#withAllowedLateness-org.joda.time.Duration-">
+  allowed lateness</a> to 0 with
+  <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/windowing/Window.html#discardingFiredPanes--">
+    discarding accumulation mode</a>.
+</div>
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Combine.html#globally-org.apache.beam.sdk.transforms.CombineFnBase.GlobalCombineFn-">
+  Combine.globally</a> and
+  <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Count.html#combineFn--">
+    Count.combineFn</a> to calculate the count of events.
+</div>
+
+<div class="hint">
+  Refer to the Beam Programming Guide
+  <a href="https://beam.apache.org/documentation/programming-guide/#event-time-triggers">
+    "Event time triggers"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/test/org/apache/beam/learning/katas/triggers/earlytriggers/TaskTest.kt b/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/test/org/apache/beam/learning/katas/triggers/earlytriggers/TaskTest.kt
new file mode 100644
index 0000000..8f6e527
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Early Triggers/Early Triggers/test/org/apache/beam/learning/katas/triggers/earlytriggers/TaskTest.kt	
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.triggers.earlytriggers
+
+import org.apache.beam.learning.katas.triggers.earlytriggers.Task.applyTransform
+import org.apache.beam.sdk.coders.SerializableCoder
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.testing.TestStream
+import org.apache.beam.sdk.transforms.windowing.IntervalWindow
+import org.apache.beam.sdk.values.TimestampedValue
+import org.joda.time.Duration
+import org.joda.time.Instant
+import org.junit.Rule
+import org.junit.Test
+import java.io.Serializable
+
+class TaskTest : Serializable {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun triggers_early_triggers_early_triggers() {
+    val testStream = TestStream.create(SerializableCoder.of(String::class.java))
+      .addElements(TimestampedValue.of("event", Instant.ofEpochSecond(0)))
+      .advanceProcessingTime(Duration.standardSeconds(1))
+      .addElements(TimestampedValue.of("event", Instant.ofEpochSecond(1)))
+      .addElements(TimestampedValue.of("event", Instant.ofEpochSecond(2)))
+      .addElements(TimestampedValue.of("event", Instant.ofEpochSecond(3)))
+      .addElements(TimestampedValue.of("event", Instant.ofEpochSecond(4)))
+      .advanceProcessingTime(Duration.standardSeconds(1))
+      .addElements(TimestampedValue.of("event", Instant.ofEpochSecond(5)))
+      .addElements(TimestampedValue.of("event", Instant.ofEpochSecond(6)))
+      .advanceWatermarkToInfinity()
+
+    val eventsPColl = testPipeline.apply(testStream)
+
+    val results = applyTransform(eventsPColl)
+
+    PAssert.that(results)
+      .inEarlyPane(IntervalWindow(Instant.EPOCH, Instant.parse("1970-01-02T00:00:00+00:00")))
+      .containsInAnyOrder(1L, 4L)
+      .inFinalPane(IntervalWindow(Instant.EPOCH, Instant.parse("1970-01-02T00:00:00+00:00")))
+      .containsInAnyOrder(2L)
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Triggers/Early Triggers/lesson-info.yaml b/learning/katas/kotlin/Triggers/Early Triggers/lesson-info.yaml
new file mode 100644
index 0000000..184f82e
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Early Triggers/lesson-info.yaml	
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Early Triggers
diff --git a/learning/katas/kotlin/Triggers/Early Triggers/lesson-remote-info.yaml b/learning/katas/kotlin/Triggers/Early Triggers/lesson-remote-info.yaml
new file mode 100644
index 0000000..2a41ac1
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Early Triggers/lesson-remote-info.yaml	
@@ -0,0 +1,3 @@
+id: 358540
+update_date: Wed, 20 May 2020 20:29:18 UTC
+unit: 342741
diff --git a/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/src/org/apache/beam/learning/katas/triggers/eventtimetriggers/GenerateEvent.kt b/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/src/org/apache/beam/learning/katas/triggers/eventtimetriggers/GenerateEvent.kt
new file mode 100644
index 0000000..617df70
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/src/org/apache/beam/learning/katas/triggers/eventtimetriggers/GenerateEvent.kt	
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.triggers.eventtimetriggers
+
+import org.apache.beam.sdk.io.GenerateSequence
+import org.apache.beam.sdk.transforms.MapElements
+import org.apache.beam.sdk.transforms.PTransform
+import org.apache.beam.sdk.transforms.SerializableFunction
+import org.apache.beam.sdk.values.PBegin
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.TypeDescriptors
+import org.joda.time.Duration
+
+class GenerateEvent : PTransform<PBegin, PCollection<String>>() {
+  companion object {
+    fun everySecond(): GenerateEvent {
+      return GenerateEvent()
+    }
+  }
+
+  override fun expand(input: PBegin): PCollection<String> {
+    return input
+      .apply(GenerateSequence.from(1).withRate(1, Duration.standardSeconds(1)))
+      .apply(MapElements.into(TypeDescriptors.strings()).via(SerializableFunction { "event" }))
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/src/org/apache/beam/learning/katas/triggers/eventtimetriggers/Task.kt b/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/src/org/apache/beam/learning/katas/triggers/eventtimetriggers/Task.kt
new file mode 100644
index 0000000..587448c
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/src/org/apache/beam/learning/katas/triggers/eventtimetriggers/Task.kt	
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.triggers.eventtimetriggers
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Combine
+import org.apache.beam.sdk.transforms.Count
+import org.apache.beam.sdk.transforms.windowing.AfterWatermark
+import org.apache.beam.sdk.transforms.windowing.FixedWindows
+import org.apache.beam.sdk.transforms.windowing.Window
+import org.apache.beam.sdk.values.PCollection
+import org.joda.time.Duration
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val events = pipeline.apply(GenerateEvent.everySecond())
+
+    val output = applyTransform(events)
+
+    output.apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun applyTransform(events: PCollection<String>): PCollection<Long> {
+    return events
+      .apply(
+        Window.into<String>(FixedWindows.of(Duration.standardSeconds(5)))
+          .triggering(AfterWatermark.pastEndOfWindow())
+          .withAllowedLateness(Duration.ZERO)
+          .discardingFiredPanes()
+      )
+      .apply(Combine.globally(Count.combineFn<String>()).withoutDefaults())
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/task-info.yaml b/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/task-info.yaml
new file mode 100644
index 0000000..c56d17c
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/task-info.yaml	
@@ -0,0 +1,31 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/triggers/eventtimetriggers/GenerateEvent.kt
+  visible: true
+- name: src/org/apache/beam/learning/katas/triggers/eventtimetriggers/Task.kt
+  visible: true
+  placeholders:
+  - offset: 1790
+    length: 314
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/triggers/eventtimetriggers/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/task-remote-info.yaml b/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/task-remote-info.yaml
new file mode 100644
index 0000000..4429fbd
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326906
+update_date: Sat, 30 May 2020 18:49:10 UTC
diff --git a/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/task.md b/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/task.md
new file mode 100644
index 0000000..273ac8f
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/task.md	
@@ -0,0 +1,72 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you 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.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+Event Time Triggers
+-------------------
+
+When collecting and grouping data into windows, Beam uses triggers to determine when to emit the 
+aggregated results of each window (referred to as a pane). If you use Beam’s default windowing 
+configuration and default trigger, Beam outputs the aggregated result when it estimates all data 
+has arrived, and discards all subsequent data for that window.
+
+You can set triggers for your PCollections to change this default behavior. Beam provides a number 
+of pre-built triggers that you can set:
+
+*   Event time triggers
+*   Processing time triggers
+*   Data-driven triggers
+*   Composite triggers
+
+Event time triggers operate on the event time, as indicated by the timestamp on each data element. 
+Beam’s default trigger is event time-based.
+
+The AfterWatermark trigger operates on event time. The AfterWatermark trigger emits the contents 
+of a window after the watermark passes the end of the window, based on the timestamps attached to 
+the data elements. The watermark is a global progress metric, and is Beam’s notion of input 
+completeness within your pipeline at any given point. AfterWatermark.pastEndOfWindow() only fires 
+when the watermark passes the end of the window.
+
+**Kata:** Given that events are being generated every second, please implement a trigger that emits 
+the number of events count within a fixed window of 5-second duration.
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/windowing/FixedWindows.html">
+  FixedWindows</a> with 5-second duration using
+  <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/windowing/AfterWatermark.html#pastEndOfWindow--">
+  AfterWatermark.pastEndOfWindow()</a> trigger.
+</div>
+
+<div class="hint">
+  Set the <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/windowing/Window.html#withAllowedLateness-org.joda.time.Duration-">
+  allowed lateness</a> to 0 with
+  <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/windowing/Window.html#discardingFiredPanes--">
+    discarding accumulation mode</a>.
+</div>
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Combine.html#globally-org.apache.beam.sdk.transforms.CombineFnBase.GlobalCombineFn-">
+  Combine.globally</a> and
+  <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Count.html#combineFn--">
+    Count.combineFn</a> to calculate the count of events.
+</div>
+
+<div class="hint">
+  Refer to the Beam Programming Guide
+  <a href="https://beam.apache.org/documentation/programming-guide/#event-time-triggers">
+    "Event time triggers"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/test/org/apache/beam/learning/katas/triggers/eventtimetriggers/TaskTest.kt b/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/test/org/apache/beam/learning/katas/triggers/eventtimetriggers/TaskTest.kt
new file mode 100644
index 0000000..23f9ae5
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Event Time Triggers/Event Time Triggers/test/org/apache/beam/learning/katas/triggers/eventtimetriggers/TaskTest.kt	
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.triggers.eventtimetriggers
+
+import org.apache.beam.learning.katas.triggers.eventtimetriggers.Task.applyTransform
+import org.apache.beam.sdk.coders.SerializableCoder
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.testing.TestStream
+import org.apache.beam.sdk.transforms.windowing.IntervalWindow
+import org.apache.beam.sdk.values.TimestampedValue
+import org.joda.time.Instant
+import org.junit.Rule
+import org.junit.Test
+
+class TaskTest {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun triggers_event_time_triggers_event_time_triggers() {
+    val testStream = TestStream.create(SerializableCoder.of(String::class.java))
+      .addElements(TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:00+00:00")))
+      .addElements(TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:01+00:00")))
+      .addElements(TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:02+00:00")))
+      .addElements(TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:03+00:00")))
+      .addElements(TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:04+00:00")))
+      .advanceWatermarkTo(Instant.parse("2019-06-01T00:00:05+00:00"))
+      .addElements(TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:05+00:00")))
+      .addElements(TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:06+00:00")))
+      .addElements(TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:07+00:00")))
+      .advanceWatermarkTo(Instant.parse("2019-06-01T00:00:10+00:00"))
+      .advanceWatermarkToInfinity()
+
+    val eventsPColl = testPipeline.apply(testStream)
+
+    val results = applyTransform(eventsPColl)
+
+    PAssert.that(results)
+      .inWindow(createIntervalWindow("2019-06-01T00:00:00+00:00", "2019-06-01T00:00:05+00:00"))
+      .containsInAnyOrder(5L)
+      .inWindow(createIntervalWindow("2019-06-01T00:00:05+00:00", "2019-06-01T00:00:10+00:00"))
+      .containsInAnyOrder(3L)
+
+    testPipeline.run().waitUntilFinish()
+  }
+
+  private fun createIntervalWindow(startStr: String, endStr: String): IntervalWindow {
+    return IntervalWindow(Instant.parse(startStr), Instant.parse(endStr))
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Triggers/Event Time Triggers/lesson-info.yaml b/learning/katas/kotlin/Triggers/Event Time Triggers/lesson-info.yaml
new file mode 100644
index 0000000..e423635
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Event Time Triggers/lesson-info.yaml	
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Event Time Triggers
diff --git a/learning/katas/kotlin/Triggers/Event Time Triggers/lesson-remote-info.yaml b/learning/katas/kotlin/Triggers/Event Time Triggers/lesson-remote-info.yaml
new file mode 100644
index 0000000..cac0151
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Event Time Triggers/lesson-remote-info.yaml	
@@ -0,0 +1,3 @@
+id: 358539
+update_date: Wed, 20 May 2020 20:29:13 UTC
+unit: 342740
diff --git a/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/src/org/apache/beam/learning/katas/triggers/windowaccummode/GenerateEvent.kt b/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/src/org/apache/beam/learning/katas/triggers/windowaccummode/GenerateEvent.kt
new file mode 100644
index 0000000..5288a4f
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/src/org/apache/beam/learning/katas/triggers/windowaccummode/GenerateEvent.kt	
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.triggers.windowaccummode
+
+import org.apache.beam.sdk.io.GenerateSequence
+import org.apache.beam.sdk.transforms.MapElements
+import org.apache.beam.sdk.transforms.PTransform
+import org.apache.beam.sdk.transforms.SerializableFunction
+import org.apache.beam.sdk.values.PBegin
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.TypeDescriptors
+import org.joda.time.Duration
+
+class GenerateEvent : PTransform<PBegin, PCollection<String>>() {
+  companion object {
+    fun everySecond(): GenerateEvent {
+      return GenerateEvent()
+    }
+  }
+
+  override fun expand(input: PBegin): PCollection<String> {
+    return input
+      .apply(GenerateSequence.from(1).withRate(1, Duration.standardSeconds(1)))
+      .apply(MapElements.into(TypeDescriptors.strings()).via(SerializableFunction { "event" }))
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/src/org/apache/beam/learning/katas/triggers/windowaccummode/Task.kt b/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/src/org/apache/beam/learning/katas/triggers/windowaccummode/Task.kt
new file mode 100644
index 0000000..db3bf68
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/src/org/apache/beam/learning/katas/triggers/windowaccummode/Task.kt	
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.triggers.windowaccummode
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Combine
+import org.apache.beam.sdk.transforms.Count
+import org.apache.beam.sdk.transforms.windowing.AfterProcessingTime
+import org.apache.beam.sdk.transforms.windowing.AfterWatermark
+import org.apache.beam.sdk.transforms.windowing.FixedWindows
+import org.apache.beam.sdk.transforms.windowing.Window
+import org.apache.beam.sdk.values.PCollection
+import org.joda.time.Duration
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val events = pipeline.apply(GenerateEvent.everySecond())
+
+    val output = applyTransform(events)
+
+    output.apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun applyTransform(events: PCollection<String>): PCollection<Long> {
+    return events
+      .apply(
+        Window.into<String>(FixedWindows.of(Duration.standardDays(1)))
+          .triggering(
+            AfterWatermark
+              .pastEndOfWindow()
+              .withEarlyFirings(AfterProcessingTime.pastFirstElementInPane())
+          )
+          .withAllowedLateness(Duration.ZERO)
+          .accumulatingFiredPanes()
+      )
+      .apply(Combine.globally(Count.combineFn<String>()).withoutDefaults())
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/task-info.yaml b/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/task-info.yaml
new file mode 100644
index 0000000..89b48d1
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/task-info.yaml	
@@ -0,0 +1,31 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/triggers/windowaccummode/GenerateEvent.kt
+  visible: true
+- name: src/org/apache/beam/learning/katas/triggers/windowaccummode/Task.kt
+  visible: true
+  placeholders:
+  - offset: 1856
+    length: 430
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/triggers/windowaccummode/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/task-remote-info.yaml b/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/task-remote-info.yaml
new file mode 100644
index 0000000..8be1ca3
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326908
+update_date: Sat, 30 May 2020 18:49:15 UTC
diff --git a/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/task.md b/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/task.md
new file mode 100644
index 0000000..90f4486
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/task.md	
@@ -0,0 +1,65 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you 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.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+Window Accumulation Mode
+------------------------
+
+When you specify a trigger, you must also set the the window’s accumulation mode. When a trigger 
+fires, it emits the current contents of the window as a pane. Since a trigger can fire multiple 
+times, the accumulation mode determines whether the system accumulates the window panes as the 
+trigger fires, or discards them.
+
+**Kata:** Given that events are being generated every second and a fixed window of 1-day duration, 
+please implement an early trigger that emits the number of events count immediately after new 
+element is processed in accumulating mode.
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/2.13.0/org/apache/beam/sdk/transforms/windowing/Window.html#accumulatingFiredPanes--">
+  accumulatingFiredPanes()</a> to set a window to accumulate the panes that are produced when the
+  trigger fires.
+</div>
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/windowing/AfterWatermark.AfterWatermarkEarlyAndLate.html#withEarlyFirings-org.apache.beam.sdk.transforms.windowing.Trigger.OnceTrigger-">
+  withEarlyFirings</a> to set early firing triggers.
+</div>
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/windowing/FixedWindows.html">
+  FixedWindows</a> with 1-day duration using
+  <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/windowing/AfterWatermark.html#pastEndOfWindow--">
+    AfterWatermark.pastEndOfWindow()</a> trigger.
+</div>
+
+<div class="hint">
+  Set the <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/windowing/Window.html#withAllowedLateness-org.joda.time.Duration-">
+  allowed lateness</a> to 0.
+</div>
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Combine.html#globally-org.apache.beam.sdk.transforms.CombineFnBase.GlobalCombineFn-">
+  Combine.globally</a> and
+  <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/Count.html#combineFn--">
+    Count.combineFn</a> to calculate the count of events.
+</div>
+
+<div class="hint">
+  Refer to the Beam Programming Guide
+  <a href="https://beam.apache.org/documentation/programming-guide/#event-time-triggers">
+    "Event time triggers"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/test/org/apache/beam/learning/katas/triggers/windowaccummode/TaskTest.kt b/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/test/org/apache/beam/learning/katas/triggers/windowaccummode/TaskTest.kt
new file mode 100644
index 0000000..7e06c36
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Window Accumulation Mode/Window Accumulation Mode/test/org/apache/beam/learning/katas/triggers/windowaccummode/TaskTest.kt	
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.triggers.windowaccummode
+
+import org.apache.beam.learning.katas.triggers.windowaccummode.Task.applyTransform
+import org.apache.beam.sdk.coders.SerializableCoder
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.testing.TestStream
+import org.apache.beam.sdk.transforms.windowing.IntervalWindow
+import org.apache.beam.sdk.values.TimestampedValue
+import org.joda.time.Duration
+import org.joda.time.Instant
+import org.junit.Rule
+import org.junit.Test
+import java.io.Serializable
+
+class TaskTest : Serializable {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun triggers_window_accumulation_mode_window_accumulation_mode() {
+    val testStream = TestStream.create(SerializableCoder.of(String::class.java))
+      .addElements(TimestampedValue.of("event", Instant.ofEpochSecond(0)))
+      .advanceProcessingTime(Duration.standardSeconds(1))
+      .addElements(TimestampedValue.of("event", Instant.ofEpochSecond(1)))
+      .addElements(TimestampedValue.of("event", Instant.ofEpochSecond(2)))
+      .addElements(TimestampedValue.of("event", Instant.ofEpochSecond(3)))
+      .addElements(TimestampedValue.of("event", Instant.ofEpochSecond(4)))
+      .advanceProcessingTime(Duration.standardSeconds(1))
+      .addElements(TimestampedValue.of("event", Instant.ofEpochSecond(5)))
+      .addElements(TimestampedValue.of("event", Instant.ofEpochSecond(6)))
+      .advanceWatermarkToInfinity()
+
+    val eventsPColl = testPipeline.apply(testStream)
+
+    val results = applyTransform(eventsPColl)
+
+    PAssert.that(results)
+      .inEarlyPane(IntervalWindow(Instant.EPOCH, Instant.parse("1970-01-02T00:00:00+00:00")))
+      .containsInAnyOrder(1L, 5L)
+      .inFinalPane(IntervalWindow(Instant.EPOCH, Instant.parse("1970-01-02T00:00:00+00:00")))
+      .containsInAnyOrder(7L)
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Triggers/Window Accumulation Mode/lesson-info.yaml b/learning/katas/kotlin/Triggers/Window Accumulation Mode/lesson-info.yaml
new file mode 100644
index 0000000..8a260af
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Window Accumulation Mode/lesson-info.yaml	
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Window Accumulation Mode
diff --git a/learning/katas/kotlin/Triggers/Window Accumulation Mode/lesson-remote-info.yaml b/learning/katas/kotlin/Triggers/Window Accumulation Mode/lesson-remote-info.yaml
new file mode 100644
index 0000000..9d9fa65
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/Window Accumulation Mode/lesson-remote-info.yaml	
@@ -0,0 +1,3 @@
+id: 358541
+update_date: Wed, 20 May 2020 20:29:23 UTC
+unit: 342742
diff --git a/learning/katas/kotlin/Triggers/section-info.yaml b/learning/katas/kotlin/Triggers/section-info.yaml
new file mode 100644
index 0000000..f62f316
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/section-info.yaml
@@ -0,0 +1,23 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Event Time Triggers
+- Early Triggers
+- Window Accumulation Mode
diff --git a/learning/katas/kotlin/Triggers/section-remote-info.yaml b/learning/katas/kotlin/Triggers/section-remote-info.yaml
new file mode 100644
index 0000000..1e0f31d
--- /dev/null
+++ b/learning/katas/kotlin/Triggers/section-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 133892
+update_date: Wed, 20 May 2020 20:29:12 UTC
diff --git a/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/src/org/apache/beam/learning/katas/windowing/addingtimestamp/pardo/Event.kt b/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/src/org/apache/beam/learning/katas/windowing/addingtimestamp/pardo/Event.kt
new file mode 100644
index 0000000..03d79e1
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/src/org/apache/beam/learning/katas/windowing/addingtimestamp/pardo/Event.kt	
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.windowing.addingtimestamp.pardo
+
+import org.joda.time.DateTime
+import java.io.Serializable
+
+data class Event(private var id: String, private var event: String, var date: DateTime) : Serializable
\ No newline at end of file
diff --git a/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/src/org/apache/beam/learning/katas/windowing/addingtimestamp/pardo/Task.kt b/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/src/org/apache/beam/learning/katas/windowing/addingtimestamp/pardo/Task.kt
new file mode 100644
index 0000000..7e73d95
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/src/org/apache/beam/learning/katas/windowing/addingtimestamp/pardo/Task.kt	
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.windowing.addingtimestamp.pardo
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.DoFn
+import org.apache.beam.sdk.transforms.ParDo
+import org.apache.beam.sdk.values.PCollection
+import org.joda.time.DateTime
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val events = pipeline.apply(
+      Create.of(
+        Event("1", "book-order", DateTime.parse("2019-06-01T00:00:00+00:00")),
+        Event("2", "pencil-order", DateTime.parse("2019-06-02T00:00:00+00:00")),
+        Event("3", "paper-order", DateTime.parse("2019-06-03T00:00:00+00:00")),
+        Event("4", "pencil-order", DateTime.parse("2019-06-04T00:00:00+00:00")),
+        Event("5", "book-order", DateTime.parse("2019-06-05T00:00:00+00:00"))
+      )
+    )
+
+    val output = applyTransform(events)
+
+    output.apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun applyTransform(events: PCollection<Event>): PCollection<Event> {
+    return events.apply(ParDo.of(object : DoFn<Event, Event>() {
+      @ProcessElement
+      fun processElement(@Element event: Event, out: OutputReceiver<Event>) {
+        out.outputWithTimestamp(event, event.date.toInstant())
+      }
+    }))
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/task-info.yaml b/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/task-info.yaml
new file mode 100644
index 0000000..5814cab
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/task-info.yaml	
@@ -0,0 +1,31 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/windowing/addingtimestamp/pardo/Event.kt
+  visible: true
+- name: src/org/apache/beam/learning/katas/windowing/addingtimestamp/pardo/Task.kt
+  visible: true
+  placeholders:
+  - offset: 2060
+    length: 232
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/windowing/addingtimestamp/pardo/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/task-remote-info.yaml b/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/task-remote-info.yaml
new file mode 100644
index 0000000..eff63cb
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326903
+update_date: Sat, 30 May 2020 18:49:04 UTC
diff --git a/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/task.md b/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/task.md
new file mode 100644
index 0000000..2da4912
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/task.md	
@@ -0,0 +1,46 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you 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.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+Adding Timestamp - ParDo
+------------------------
+
+Bounded sources (such as a file from TextIO) do not provide timestamps for elements. If you need 
+timestamps, you must add them to your PCollection’s elements.
+
+You can assign new timestamps to the elements of a PCollection by applying a ParDo transform that 
+outputs new elements with timestamps that you set.
+
+**Kata:** Please assign each element a timestamp based on the the `Event.date`.
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/ParDo.html">
+  ParDo</a>
+  with <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/DoFn.html">
+  DoFn</a>.
+</div>
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/DoFn.OutputReceiver.html#outputWithTimestamp-T-org.joda.time.Instant-">
+  OutputReceiver.outputWithTimestamp</a> method to assign timestamp to the element.
+</div>
+
+<div class="hint">
+  Refer to the Beam Programming Guide
+  <a href="https://beam.apache.org/documentation/programming-guide/#adding-timestamps-to-a-pcollections-elements">
+    "Adding timestamps to a PCollection’s elements"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/test/org/apache/beam/learning/katas/windowing/addingtimestamp/pardo/TaskTest.kt b/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/test/org/apache/beam/learning/katas/windowing/addingtimestamp/pardo/TaskTest.kt
new file mode 100644
index 0000000..2386ca5
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Adding Timestamp/ParDo/test/org/apache/beam/learning/katas/windowing/addingtimestamp/pardo/TaskTest.kt	
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.windowing.addingtimestamp.pardo
+
+import org.apache.beam.learning.katas.windowing.addingtimestamp.pardo.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.DoFn
+import org.apache.beam.sdk.transforms.ParDo
+import org.apache.beam.sdk.values.KV
+import org.joda.time.DateTime
+import org.joda.time.Instant
+import org.junit.Rule
+import org.junit.Test
+import java.io.Serializable
+
+class TaskTest : Serializable {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun windowing_adding_timestamp_pardo() {
+    val events = listOf(
+      Event("1", "book-order", DateTime.parse("2019-06-01T00:00:00+00:00")),
+      Event("2", "pencil-order", DateTime.parse("2019-06-02T00:00:00+00:00")),
+      Event("3", "paper-order", DateTime.parse("2019-06-03T00:00:00+00:00")),
+      Event("4", "pencil-order", DateTime.parse("2019-06-04T00:00:00+00:00")),
+      Event("5", "book-order", DateTime.parse("2019-06-05T00:00:00+00:00"))
+    )
+
+    val eventsPColl = testPipeline.apply(Create.of(events))
+
+    val results = applyTransform(eventsPColl)
+
+    val timestampedResults = results.apply(
+      "KV<Event, Instant>",
+      ParDo.of(object : DoFn<Event, KV<Event, Instant>>() {
+
+        @ProcessElement
+        fun processElement(context: ProcessContext, out: OutputReceiver<KV<Event, Instant>>) {
+          val event = context.element()
+          out.output(KV.of(event, context.timestamp()))
+        }
+
+      })
+    )
+
+    PAssert.that(results).containsInAnyOrder(events)
+
+    PAssert.that(timestampedResults).containsInAnyOrder(
+      KV.of(events[0], events[0].date.toInstant()),
+      KV.of(events[1], events[1].date.toInstant()),
+      KV.of(events[2], events[2].date.toInstant()),
+      KV.of(events[3], events[3].date.toInstant()),
+      KV.of(events[4], events[4].date.toInstant())
+    )
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/src/org/apache/beam/learning/katas/windowing/addingtimestamp/withtimestamps/Event.kt b/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/src/org/apache/beam/learning/katas/windowing/addingtimestamp/withtimestamps/Event.kt
new file mode 100644
index 0000000..2016f1f
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/src/org/apache/beam/learning/katas/windowing/addingtimestamp/withtimestamps/Event.kt	
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.windowing.addingtimestamp.withtimestamps
+
+import org.joda.time.DateTime
+import java.io.Serializable
+
+data class Event(private var id: String, private var event: String, var date: DateTime) : Serializable
\ No newline at end of file
diff --git a/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/src/org/apache/beam/learning/katas/windowing/addingtimestamp/withtimestamps/Task.kt b/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/src/org/apache/beam/learning/katas/windowing/addingtimestamp/withtimestamps/Task.kt
new file mode 100644
index 0000000..40ccb2d
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/src/org/apache/beam/learning/katas/windowing/addingtimestamp/withtimestamps/Task.kt	
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.windowing.addingtimestamp.withtimestamps
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.WithTimestamps
+import org.apache.beam.sdk.values.PCollection
+import org.joda.time.DateTime
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val events = pipeline.apply(
+      Create.of(
+        Event("1", "book-order", DateTime.parse("2019-06-01T00:00:00+00:00")),
+        Event("2", "pencil-order", DateTime.parse("2019-06-02T00:00:00+00:00")),
+        Event("3", "paper-order", DateTime.parse("2019-06-03T00:00:00+00:00")),
+        Event("4", "pencil-order", DateTime.parse("2019-06-04T00:00:00+00:00")),
+        Event("5", "book-order", DateTime.parse("2019-06-05T00:00:00+00:00"))
+      )
+    )
+
+    val output = applyTransform(events)
+
+    output.apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  @JvmStatic
+  fun applyTransform(events: PCollection<Event>): PCollection<Event> {
+    return events.apply(WithTimestamps.of { event: Event -> event.date.toInstant() })
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/task-info.yaml b/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/task-info.yaml
new file mode 100644
index 0000000..058c723
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/task-info.yaml	
@@ -0,0 +1,31 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/windowing/addingtimestamp/withtimestamps/Event.kt
+  visible: true
+- name: src/org/apache/beam/learning/katas/windowing/addingtimestamp/withtimestamps/Task.kt
+  visible: true
+  placeholders:
+  - offset: 2035
+    length: 74
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/windowing/addingtimestamp/withtimestamps/TaskTest.kt
+  visible: false
diff --git a/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/task-remote-info.yaml b/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/task-remote-info.yaml
new file mode 100644
index 0000000..a34be18
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326904
+update_date: Sat, 30 May 2020 18:50:21 UTC
diff --git a/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/task.md b/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/task.md
new file mode 100644
index 0000000..d5616e5
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/task.md	
@@ -0,0 +1,39 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you 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.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+Adding Timestamp - WithTimestamps
+---------------------------------
+
+Bounded sources (such as a file from TextIO) do not provide timestamps for elements. If you need 
+timestamps, you must add them to your PCollection’s elements.
+
+You can assign new timestamps to the elements of a PCollection by applying a ParDo transform that 
+outputs new elements with timestamps that you set.
+
+**Kata:** Please assign each element a timestamp based on the the `Event.date`.
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/WithTimestamps.html">
+  WithTimestamps</a>.
+</div>
+
+<div class="hint">
+  Refer to the Beam Programming Guide
+  <a href="https://beam.apache.org/documentation/programming-guide/#adding-timestamps-to-a-pcollections-elements">
+    "Adding timestamps to a PCollection’s elements"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/test/org/apache/beam/learning/katas/windowing/addingtimestamp/withtimestamps/TaskTest.kt b/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/test/org/apache/beam/learning/katas/windowing/addingtimestamp/withtimestamps/TaskTest.kt
new file mode 100644
index 0000000..ade7966
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Adding Timestamp/WithTimestamps/test/org/apache/beam/learning/katas/windowing/addingtimestamp/withtimestamps/TaskTest.kt	
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.windowing.addingtimestamp.withtimestamps
+
+import org.apache.beam.learning.katas.windowing.addingtimestamp.withtimestamps.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.DoFn
+import org.apache.beam.sdk.transforms.ParDo
+import org.apache.beam.sdk.values.KV
+import org.joda.time.DateTime
+import org.joda.time.Instant
+import org.junit.Rule
+import org.junit.Test
+import java.io.Serializable
+
+class TaskTest : Serializable {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun windowing_adding_timestamp_withtimestamps() {
+    val events = listOf(
+      Event("1", "book-order", DateTime.parse("2019-06-01T00:00:00+00:00")),
+      Event("2", "pencil-order", DateTime.parse("2019-06-02T00:00:00+00:00")),
+      Event("3", "paper-order", DateTime.parse("2019-06-03T00:00:00+00:00")),
+      Event("4", "pencil-order", DateTime.parse("2019-06-04T00:00:00+00:00")),
+      Event("5", "book-order", DateTime.parse("2019-06-05T00:00:00+00:00"))
+    )
+
+    val eventsPColl = testPipeline.apply(Create.of(events))
+
+    val results = applyTransform(eventsPColl)
+
+    val timestampedResults = results.apply(
+      "KV<Event, Instant>",
+      ParDo.of(object : DoFn<Event, KV<Event, Instant>>() {
+        @ProcessElement
+        fun processElement(context: ProcessContext, out: OutputReceiver<KV<Event, Instant>>) {
+          val event = context.element()
+          out.output(KV.of(event, context.timestamp()))
+        }
+      })
+    )
+
+    PAssert.that(results).containsInAnyOrder(events)
+
+    PAssert.that(timestampedResults).containsInAnyOrder(
+      KV.of(events[0], events[0].date.toInstant()),
+      KV.of(events[1], events[1].date.toInstant()),
+      KV.of(events[2], events[2].date.toInstant()),
+      KV.of(events[3], events[3].date.toInstant()),
+      KV.of(events[4], events[4].date.toInstant())
+    )
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Windowing/Adding Timestamp/lesson-info.yaml b/learning/katas/kotlin/Windowing/Adding Timestamp/lesson-info.yaml
new file mode 100644
index 0000000..c6a234c
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Adding Timestamp/lesson-info.yaml	
@@ -0,0 +1,22 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- ParDo
+- WithTimestamps
diff --git a/learning/katas/kotlin/Windowing/Adding Timestamp/lesson-remote-info.yaml b/learning/katas/kotlin/Windowing/Adding Timestamp/lesson-remote-info.yaml
new file mode 100644
index 0000000..752baef
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Adding Timestamp/lesson-remote-info.yaml	
@@ -0,0 +1,3 @@
+id: 358537
+update_date: Wed, 20 May 2020 20:29:00 UTC
+unit: 342738
diff --git a/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/src/org/apache/beam/learning/katas/windowing/fixedwindow/Task.kt b/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/src/org/apache/beam/learning/katas/windowing/fixedwindow/Task.kt
new file mode 100644
index 0000000..c56605d
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/src/org/apache/beam/learning/katas/windowing/fixedwindow/Task.kt	
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.windowing.fixedwindow
+
+import org.apache.beam.learning.katas.util.Log
+import org.apache.beam.sdk.Pipeline
+import org.apache.beam.sdk.options.PipelineOptionsFactory
+import org.apache.beam.sdk.transforms.Count
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.windowing.FixedWindows
+import org.apache.beam.sdk.transforms.windowing.Window
+import org.apache.beam.sdk.values.KV
+import org.apache.beam.sdk.values.PCollection
+import org.apache.beam.sdk.values.TimestampedValue
+import org.joda.time.Duration
+import org.joda.time.Instant
+
+object Task {
+  @JvmStatic
+  fun main(args: Array<String>) {
+    val options = PipelineOptionsFactory.fromArgs(*args).create()
+    val pipeline = Pipeline.create(options)
+
+    val events = pipeline.apply(
+      Create.timestamped(
+        TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:00+00:00")),
+        TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:00+00:00")),
+        TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:00+00:00")),
+        TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:00+00:00")),
+        TimestampedValue.of("event", Instant.parse("2019-06-05T00:00:00+00:00")),
+        TimestampedValue.of("event", Instant.parse("2019-06-05T00:00:00+00:00")),
+        TimestampedValue.of("event", Instant.parse("2019-06-08T00:00:00+00:00")),
+        TimestampedValue.of("event", Instant.parse("2019-06-08T00:00:00+00:00")),
+        TimestampedValue.of("event", Instant.parse("2019-06-08T00:00:00+00:00")),
+        TimestampedValue.of("event", Instant.parse("2019-06-10T00:00:00+00:00"))
+      )
+    )
+
+    val output = applyTransform(events)
+
+    output.apply(Log.ofElements())
+
+    pipeline.run()
+  }
+
+  fun applyTransform(events: PCollection<String>): PCollection<KV<String, Long>> {
+    return events
+      .apply(Window.into<String>(FixedWindows.of(Duration.standardDays(1))))
+      .apply(Count.perElement())
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/task-info.yaml b/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/task-info.yaml
new file mode 100644
index 0000000..02deae9
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/task-info.yaml	
@@ -0,0 +1,31 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+type: edu
+files:
+- name: src/org/apache/beam/learning/katas/windowing/fixedwindow/Task.kt
+  visible: true
+  placeholders:
+  - offset: 2668
+    length: 116
+    placeholder_text: TODO()
+- name: test/org/apache/beam/learning/katas/windowing/fixedwindow/TaskTest.kt
+  visible: false
+- name: test/org/apache/beam/learning/katas/windowing/fixedwindow/WindowedEvent.kt
+  visible: false
diff --git a/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/task-remote-info.yaml b/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/task-remote-info.yaml
new file mode 100644
index 0000000..16d8396
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/task-remote-info.yaml	
@@ -0,0 +1,2 @@
+id: 1326905
+update_date: Sat, 30 May 2020 18:49:07 UTC
diff --git a/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/task.md b/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/task.md
new file mode 100644
index 0000000..ff4c19c
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/task.md	
@@ -0,0 +1,53 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you 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.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+Fixed Time Window
+-----------------
+
+Windowing subdivides a PCollection according to the timestamps of its individual elements. 
+Transforms that aggregate multiple elements, such as GroupByKey and Combine, work implicitly on a 
+per-window basis — they process each PCollection as a succession of multiple, finite windows, 
+though the entire collection itself may be of unbounded size.
+
+In the Beam model, any PCollection (including unbounded PCollections) can be subdivided into 
+logical windows. Each element in a PCollection is assigned to one or more windows according to the 
+PCollection’s windowing function, and each individual window contains a finite number of elements. 
+Grouping transforms then consider each PCollection’s elements on a per-window basis. GroupByKey, 
+for example, implicitly groups the elements of a PCollection by key and window.
+
+Beam provides several windowing functions, including:
+*   Fixed Time Windows
+*   Sliding Time Windows
+*   Per-Session Windows
+*   Single Global Window
+
+The simplest form of windowing is using fixed time windows. A fixed time window represents a 
+consistent duration, non overlapping time interval in the data stream.
+
+**Kata:** Please count the number of events that happened based on fixed window with 1-day duration.
+
+<div class="hint">
+  Use <a href="https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/transforms/windowing/FixedWindows.html">
+  FixedWindows</a> with 1-day duration.
+</div>
+
+<div class="hint">
+  Refer to the Beam Programming Guide
+  <a href="https://beam.apache.org/documentation/programming-guide/#fixed-time-windows">
+    "Fixed time windows"</a> section for more information.
+</div>
diff --git a/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/test/org/apache/beam/learning/katas/windowing/fixedwindow/TaskTest.kt b/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/test/org/apache/beam/learning/katas/windowing/fixedwindow/TaskTest.kt
new file mode 100644
index 0000000..569c491
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/test/org/apache/beam/learning/katas/windowing/fixedwindow/TaskTest.kt	
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.windowing.fixedwindow
+
+import org.apache.beam.learning.katas.windowing.fixedwindow.Task.applyTransform
+import org.apache.beam.sdk.testing.PAssert
+import org.apache.beam.sdk.testing.TestPipeline
+import org.apache.beam.sdk.transforms.Create
+import org.apache.beam.sdk.transforms.DoFn
+import org.apache.beam.sdk.transforms.ParDo
+import org.apache.beam.sdk.transforms.windowing.BoundedWindow
+import org.apache.beam.sdk.values.KV
+import org.apache.beam.sdk.values.TimestampedValue
+import org.joda.time.Instant
+import org.junit.Rule
+import org.junit.Test
+import java.io.Serializable
+
+class TaskTest : Serializable {
+  @get:Rule
+  @Transient
+  val testPipeline: TestPipeline = TestPipeline.create()
+
+  @Test
+  fun windowing_fixed_window_time_fixed_window_time() {
+    val eventsPColl = testPipeline.apply(
+      Create.timestamped(
+        TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:00+00:00")),
+        TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:00+00:00")),
+        TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:00+00:00")),
+        TimestampedValue.of("event", Instant.parse("2019-06-01T00:00:00+00:00")),
+        TimestampedValue.of("event", Instant.parse("2019-06-05T00:00:00+00:00")),
+        TimestampedValue.of("event", Instant.parse("2019-06-05T00:00:00+00:00")),
+        TimestampedValue.of("event", Instant.parse("2019-06-08T00:00:00+00:00")),
+        TimestampedValue.of("event", Instant.parse("2019-06-08T00:00:00+00:00")),
+        TimestampedValue.of("event", Instant.parse("2019-06-08T00:00:00+00:00")),
+        TimestampedValue.of("event", Instant.parse("2019-06-10T00:00:00+00:00"))
+      )
+    )
+
+    val results = applyTransform(eventsPColl)
+
+    val windowedResults = results.apply(
+      "WindowedEvent",
+      ParDo.of(object : DoFn<KV<String, Long>, WindowedEvent>() {
+        @ProcessElement
+        fun processElement(
+          @Element element: KV<String, Long>,
+          window: BoundedWindow, out: OutputReceiver<WindowedEvent>
+        ) {
+
+          out.output(WindowedEvent(element.key, element.value, window.toString()))
+        }
+      })
+    )
+
+    PAssert.that(windowedResults).containsInAnyOrder(
+      WindowedEvent("event", 4L, "[2019-06-01T00:00:00.000Z..2019-06-02T00:00:00.000Z)"),
+      WindowedEvent("event", 2L, "[2019-06-05T00:00:00.000Z..2019-06-06T00:00:00.000Z)"),
+      WindowedEvent("event", 3L, "[2019-06-08T00:00:00.000Z..2019-06-09T00:00:00.000Z)"),
+      WindowedEvent("event", 1L, "[2019-06-10T00:00:00.000Z..2019-06-11T00:00:00.000Z)")
+    )
+
+    testPipeline.run().waitUntilFinish()
+  }
+}
\ No newline at end of file
diff --git a/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/test/org/apache/beam/learning/katas/windowing/fixedwindow/WindowedEvent.kt b/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/test/org/apache/beam/learning/katas/windowing/fixedwindow/WindowedEvent.kt
new file mode 100644
index 0000000..cf3a300
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Fixed Time Window/Fixed Time Window/test/org/apache/beam/learning/katas/windowing/fixedwindow/WindowedEvent.kt	
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.learning.katas.windowing.fixedwindow
+
+import java.io.Serializable
+
+data class WindowedEvent(private val event: String?, private val count: Long, private val window: String) : Serializable
\ No newline at end of file
diff --git a/learning/katas/kotlin/Windowing/Fixed Time Window/lesson-info.yaml b/learning/katas/kotlin/Windowing/Fixed Time Window/lesson-info.yaml
new file mode 100644
index 0000000..9f65c8a
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Fixed Time Window/lesson-info.yaml	
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Fixed Time Window
diff --git a/learning/katas/kotlin/Windowing/Fixed Time Window/lesson-remote-info.yaml b/learning/katas/kotlin/Windowing/Fixed Time Window/lesson-remote-info.yaml
new file mode 100644
index 0000000..ec71e4a
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/Fixed Time Window/lesson-remote-info.yaml	
@@ -0,0 +1,3 @@
+id: 358538
+update_date: Wed, 20 May 2020 20:29:06 UTC
+unit: 342739
diff --git a/learning/katas/kotlin/Windowing/section-info.yaml b/learning/katas/kotlin/Windowing/section-info.yaml
new file mode 100644
index 0000000..e5121f4
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/section-info.yaml
@@ -0,0 +1,22 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+content:
+- Adding Timestamp
+- Fixed Time Window
diff --git a/learning/katas/kotlin/Windowing/section-remote-info.yaml b/learning/katas/kotlin/Windowing/section-remote-info.yaml
new file mode 100644
index 0000000..c0ae8e3
--- /dev/null
+++ b/learning/katas/kotlin/Windowing/section-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 133891
+update_date: Wed, 20 May 2020 20:28:59 UTC
diff --git a/learning/katas/kotlin/build.gradle b/learning/katas/kotlin/build.gradle
new file mode 100644
index 0000000..cb49f0d
--- /dev/null
+++ b/learning/katas/kotlin/build.gradle
@@ -0,0 +1,134 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+buildscript {
+  ext {
+    beamVersion = '2.19.0'
+    guavaVersion = '28.1-jre'
+    jodaTimeVersion = '2.10.4'
+    slf4jVersion = '1.7.28'
+    log4jSlf4jImpl = '2.12.1'
+    kotlinVersion = '1.3.72'
+
+    assertjVersion = '3.13.2'
+    hamcrestVersion = '2.1'
+    junitVersion = '4.12'
+  }
+  
+  repositories {
+    mavenCentral()
+  }
+
+  dependencies {
+    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
+  }
+}
+
+def printOutput(def output) {
+  return tasks.create("printOutput") {
+    for (line in output.toString().readLines()) {
+      println "#educational_plugin" + line
+    }
+  }
+}
+
+subprojects {
+  apply plugin: 'application'
+  apply plugin: 'java'
+  apply plugin: 'kotlin'
+
+  sourceCompatibility = 1.8
+
+  repositories {
+    mavenCentral()
+  }
+
+  dependencies {
+    compile "org.apache.beam:beam-sdks-java-core:$beamVersion"
+    compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
+    runtime "org.apache.beam:beam-runners-direct-java:$beamVersion"
+
+    compile "joda-time:joda-time:$jodaTimeVersion"
+    compile "org.slf4j:slf4j-api:$slf4jVersion"
+    compile "org.apache.logging.log4j:log4j-slf4j-impl:$log4jSlf4jImpl"
+    compile "com.google.guava:guava:$guavaVersion"
+
+    testCompile "junit:junit:$junitVersion"
+    testCompile "org.hamcrest:hamcrest-core:$hamcrestVersion"
+    testCompile "org.hamcrest:hamcrest-library:$hamcrestVersion"
+    testCompile "org.assertj:assertj-core:$assertjVersion"
+  }
+
+  compileKotlin.destinationDir = compileJava.destinationDir
+
+  compileKotlin {
+    kotlinOptions.jvmTarget = "1.8"
+  }
+  compileTestKotlin {
+    kotlinOptions.jvmTarget = "1.8"
+  }
+
+  sourceSets {
+    main {
+      java.srcDir 'src'
+      resources.srcDir 'resources'
+    }
+    test {
+      java.srcDir 'test'
+    }
+  }
+
+  mainClassName = project.hasProperty("mainClass") ? project.getProperty("mainClass") : ""
+
+  test {
+    outputs.upToDateWhen { false }
+    afterTest { TestDescriptor test, TestResult result ->
+      if (result.resultType == TestResult.ResultType.FAILURE) {
+        def message = result.exception?.message ?: "Wrong answer"
+        def lines = message.readLines()
+        println "#educational_plugin FAILED + " + lines[0]
+        lines[1..-1].forEach { line ->
+          println "#educational_plugin" + line
+        }
+        // we need this to separate output of different tests
+        println
+      }
+    }
+  }
+
+  def runOutput = new ByteArrayOutputStream()
+  tasks.run.setStandardOutput(runOutput)
+  tasks.run.doLast { printOutput(runOutput) }
+}
+
+project(':util') {
+  dependencies {
+    compile "junit:junit:$junitVersion"
+  }
+}
+
+configure(subprojects.findAll { it.name != 'util' }) {
+  dependencies {
+    compile project(':util').sourceSets.main.output
+    testCompile project(':util').sourceSets.test.output
+  }
+}
+
+wrapper {
+  gradleVersion = '5.0'
+}
diff --git a/learning/katas/kotlin/course-info.yaml b/learning/katas/kotlin/course-info.yaml
new file mode 100644
index 0000000..f090fc9
--- /dev/null
+++ b/learning/katas/kotlin/course-info.yaml
@@ -0,0 +1,32 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+title: Beam Katas - Kotlin
+language: English
+summary: "This course provides a series of katas to get familiar with Apache Beam using Kotlin"
+programming_language: Kotlin
+programming_language_version: 1.3
+content:
+- Introduction
+- Core Transforms
+- Common Transforms
+- IO
+- Windowing
+- Triggers
+- Examples
diff --git a/learning/katas/kotlin/course-remote-info.yaml b/learning/katas/kotlin/course-remote-info.yaml
new file mode 100644
index 0000000..fe6bd8d
--- /dev/null
+++ b/learning/katas/kotlin/course-remote-info.yaml
@@ -0,0 +1,2 @@
+id: 72488
+update_date: Sat, 30 May 2020 18:51:41 UTC
diff --git a/learning/katas/kotlin/gradle/wrapper/gradle-wrapper.jar b/learning/katas/kotlin/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..87b738c
Binary files /dev/null and b/learning/katas/kotlin/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/learning/katas/kotlin/gradle/wrapper/gradle-wrapper.properties b/learning/katas/kotlin/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..f71c9f7
--- /dev/null
+++ b/learning/katas/kotlin/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,23 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-all.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/learning/katas/kotlin/gradlew b/learning/katas/kotlin/gradlew
new file mode 100755
index 0000000..9e22af6
--- /dev/null
+++ b/learning/katas/kotlin/gradlew
@@ -0,0 +1,190 @@
+#!/usr/bin/env sh
+
+################################################################################
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you 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.
+#  See the License for the specific language governing permissions and
+# limitations under the License.
+################################################################################
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+    echo "$*"
+}
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Escape application args
+save () {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+    echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+  cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/learning/katas/kotlin/gradlew.bat b/learning/katas/kotlin/gradlew.bat
new file mode 100644
index 0000000..582415f
--- /dev/null
+++ b/learning/katas/kotlin/gradlew.bat
@@ -0,0 +1,102 @@
+@rem ################################################################################
+@rem #  Licensed to the Apache Software Foundation (ASF) under one
+@rem #  or more contributor license agreements.  See the NOTICE file
+@rem #  distributed with this work for additional information
+@rem #  regarding copyright ownership.  The ASF licenses this file
+@rem #  to you under the Apache License, Version 2.0 (the
+@rem #  "License"); you may not use this file except in compliance
+@rem #  with the License.  You may obtain a copy of the License at
+@rem #
+@rem #      http://www.apache.org/licenses/LICENSE-2.0
+@rem #
+@rem #  Unless required by applicable law or agreed to in writing, software
+@rem #  distributed under the License is distributed on an "AS IS" BASIS,
+@rem #  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem #  See the License for the specific language governing permissions and
+@rem # limitations under the License.
+@rem ################################################################################
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
... 304 lines suppressed ...