You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@beam.apache.org by re...@apache.org on 2019/05/14 20:35:13 UTC
[beam] branch master updated: Merge pull request #8358: Beam Kata
for Java and Python SDKs
This is an automated email from the ASF dual-hosted git repository.
reuvenlax 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 238659b Merge pull request #8358: Beam Kata for Java and Python SDKs
238659b is described below
commit 238659bce8043e6a64619a959ab44453dbe22dff
Author: Henry Suryawirawan <hs...@google.com>
AuthorDate: Wed May 15 04:35:00 2019 +0800
Merge pull request #8358: Beam Kata for Java and Python SDKs
---
.gitignore | 4 +
learning/katas/README.md | 24 +
learning/katas/java/.idea/study_project.xml | 1740 ++++++++++++++++++++
.../Aggregation/Count/src/Task.java | 46 +
.../Common Transforms/Aggregation/Count/task.html | 25 +
.../Aggregation/Count/test/TaskTest.java | 44 +
.../Aggregation/Max/src/Task.java | 46 +
.../Common Transforms/Aggregation/Max/task.html | 25 +
.../Aggregation/Max/test/TaskTest.java | 44 +
.../Aggregation/Mean/src/Task.java | 46 +
.../Common Transforms/Aggregation/Mean/task.html | 25 +
.../Aggregation/Mean/test/TaskTest.java | 44 +
.../Aggregation/Min/src/Task.java | 46 +
.../Common Transforms/Aggregation/Min/task.html | 25 +
.../Aggregation/Min/test/TaskTest.java | 44 +
.../Aggregation/Sum/src/Task.java | 46 +
.../Common Transforms/Aggregation/Sum/task.html | 25 +
.../Aggregation/Sum/test/TaskTest.java | 44 +
.../Common Transforms/Filter/Filter/src/Task.java | 47 +
.../java/Common Transforms/Filter/Filter/task.html | 29 +
.../Filter/Filter/test/TaskTest.java | 44 +
.../Common Transforms/Filter/ParDo/src/Task.java | 57 +
.../java/Common Transforms/Filter/ParDo/task.html | 30 +
.../Filter/ParDo/test/TaskTest.java | 44 +
.../CoGroupByKey/CoGroupByKey/src/Task.java | 98 ++
.../CoGroupByKey/src/WordsAlphabet.java | 40 +
.../CoGroupByKey/CoGroupByKey/task.html | 32 +
.../CoGroupByKey/CoGroupByKey/test/TaskTest.java | 55 +
.../Combine/BinaryCombineFn/src/Task.java | 62 +
.../Combine/BinaryCombineFn/task.html | 38 +
.../Combine/BinaryCombineFn/test/TaskTest.java | 48 +
.../Combine/Combine PerKey/src/Task.java | 66 +
.../Combine/Combine PerKey/task.html | 36 +
.../Combine/Combine PerKey/test/TaskTest.java | 51 +
.../Combine/CombineFn/src/Task.java | 106 ++
.../Core Transforms/Combine/CombineFn/task.html | 41 +
.../Combine/CombineFn/test/TaskTest.java | 44 +
.../Combine/Simple Function/src/Task.java | 62 +
.../Combine/Simple Function/task.html | 38 +
.../Combine/Simple Function/test/TaskTest.java | 44 +
.../Core Transforms/Flatten/Flatten/src/Task.java | 58 +
.../java/Core Transforms/Flatten/Flatten/task.html | 32 +
.../Flatten/Flatten/test/TaskTest.java | 48 +
.../GroupByKey/GroupByKey/src/Task.java | 58 +
.../GroupByKey/GroupByKey/task.html | 35 +
.../GroupByKey/GroupByKey/test/TaskTest.java | 54 +
.../Map/FlatMapElements/src/Task.java | 52 +
.../Core Transforms/Map/FlatMapElements/task.html | 32 +
.../Map/FlatMapElements/test/TaskTest.java | 44 +
.../Core Transforms/Map/MapElements/src/Task.java | 51 +
.../java/Core Transforms/Map/MapElements/task.html | 30 +
.../Map/MapElements/test/TaskTest.java | 44 +
.../Map/ParDo OneToMany/src/Task.java | 59 +
.../Core Transforms/Map/ParDo OneToMany/task.html | 27 +
.../Map/ParDo OneToMany/test/TaskTest.java | 44 +
.../java/Core Transforms/Map/ParDo/src/Task.java | 55 +
.../katas/java/Core Transforms/Map/ParDo/task.html | 30 +
.../Core Transforms/Map/ParDo/test/TaskTest.java | 44 +
.../Partition/Partition/src/Task.java | 60 +
.../Core Transforms/Partition/Partition/task.html | 38 +
.../Partition/Partition/test/TaskTest.java | 50 +
.../Examples/Word Count/Word Count/src/Task.java | 74 +
.../java/Examples/Word Count/Word Count/task.html | 32 +
.../Word Count/Word Count/test/TaskTest.java | 54 +
.../Hello Beam/Hello Beam/src/Task.java | 43 +
.../Introduction/Hello Beam/Hello Beam/task.html | 27 +
.../Hello Beam/Hello Beam/test/TaskTest.java | 41 +
learning/katas/java/build.gradle | 116 ++
.../katas/java/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54413 bytes
.../java/gradle/wrapper/gradle-wrapper.properties | 23 +
learning/katas/java/gradlew | 190 +++
learning/katas/java/gradlew.bat | 102 ++
learning/katas/java/settings.gradle | 43 +
learning/katas/java/util/src/util/Log.java | 71 +
.../java/util/test/test/util/ContainsKvs.java | 61 +
.../katas/java/util/test/test/util/KvMatcher.java | 56 +
learning/katas/python/.idea/study_project.xml | 1723 +++++++++++++++++++
.../Common Transforms/Aggregation/Count/task.html | 27 +
.../Common Transforms/Aggregation/Count/task.py | 27 +
.../Common Transforms/Aggregation/Count/tests.py | 33 +
.../Aggregation/Largest/task.html | 27 +
.../Common Transforms/Aggregation/Largest/task.py | 27 +
.../Common Transforms/Aggregation/Largest/tests.py | 33 +
.../Common Transforms/Aggregation/Mean/task.html | 26 +
.../Common Transforms/Aggregation/Mean/task.py | 27 +
.../Common Transforms/Aggregation/Mean/tests.py | 33 +
.../Aggregation/Smallest/task.html | 27 +
.../Common Transforms/Aggregation/Smallest/task.py | 27 +
.../Aggregation/Smallest/tests.py | 33 +
.../Common Transforms/Aggregation/Sum/task.html | 28 +
.../Common Transforms/Aggregation/Sum/task.py | 27 +
.../Common Transforms/Aggregation/Sum/tests.py | 33 +
.../Common Transforms/Filter/Filter/task.html | 31 +
.../python/Common Transforms/Filter/Filter/task.py | 27 +
.../Common Transforms/Filter/Filter/tests.py | 44 +
.../Common Transforms/Filter/ParDo/task.html | 30 +
.../python/Common Transforms/Filter/ParDo/task.py | 35 +
.../python/Common Transforms/Filter/ParDo/tests.py | 33 +
.../CoGroupByKey/CoGroupByKey/task.html | 33 +
.../CoGroupByKey/CoGroupByKey/task.py | 57 +
.../CoGroupByKey/CoGroupByKey/tests.py | 37 +
.../Combine/Combine PerKey/task.html | 35 +
.../Core Transforms/Combine/Combine PerKey/task.py | 32 +
.../Combine/Combine PerKey/tests.py | 49 +
.../Core Transforms/Combine/CombineFn/task.html | 42 +
.../Core Transforms/Combine/CombineFn/task.py | 46 +
.../Core Transforms/Combine/CombineFn/tests.py | 44 +
.../Combine/Simple Function/task.html | 38 +
.../Combine/Simple Function/task.py | 37 +
.../Combine/Simple Function/tests.py | 44 +
.../Core Transforms/Flatten/Flatten/task.html | 33 +
.../python/Core Transforms/Flatten/Flatten/task.py | 33 +
.../Core Transforms/Flatten/Flatten/tests.py | 44 +
.../GroupByKey/GroupByKey/task.html | 36 +
.../Core Transforms/GroupByKey/GroupByKey/task.py | 28 +
.../Core Transforms/GroupByKey/GroupByKey/tests.py | 35 +
.../python/Core Transforms/Map/FlatMap/task.html | 32 +
.../python/Core Transforms/Map/FlatMap/task.py | 27 +
.../python/Core Transforms/Map/FlatMap/tests.py | 44 +
.../katas/python/Core Transforms/Map/Map/task.html | 31 +
.../katas/python/Core Transforms/Map/Map/task.py | 27 +
.../katas/python/Core Transforms/Map/Map/tests.py | 44 +
.../Core Transforms/Map/ParDo OneToMany/task.html | 29 +
.../Core Transforms/Map/ParDo OneToMany/task.py | 34 +
.../Core Transforms/Map/ParDo OneToMany/tests.py | 55 +
.../python/Core Transforms/Map/ParDo/task.html | 29 +
.../katas/python/Core Transforms/Map/ParDo/task.py | 34 +
.../python/Core Transforms/Map/ParDo/tests.py | 55 +
.../Core Transforms/Partition/Partition/task.html | 38 +
.../Core Transforms/Partition/Partition/task.py | 38 +
.../Core Transforms/Partition/Partition/tests.py | 53 +
.../Examples/Word Count/Word Count/task.html | 32 +
.../python/Examples/Word Count/Word Count/task.py | 36 +
.../python/Examples/Word Count/Word Count/tests.py | 39 +
.../Introduction/Hello Beam/Hello Beam/task.html | 26 +
.../Introduction/Hello Beam/Hello Beam/task.py | 26 +
.../Introduction/Hello Beam/Hello Beam/tests.py | 41 +
learning/katas/python/log_elements.py | 37 +
learning/katas/python/requirements.txt | 18 +
learning/katas/python/test_helper.py | 240 +++
140 files changed, 9459 insertions(+)
diff --git a/.gitignore b/.gitignore
index 385b99f..900989d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -83,3 +83,7 @@ sdks/python/postcommit_requirements.txt
# NOTE: if you modify this file, you probably need to modify the file set that
# is an input to 'maven-assembly-plugin' that generates source distribution.
# This is typically in files named 'src.xml' throughout this repository.
+
+# JetBrains Education files
+!**/study_project.xml
+**/.coursecreator/**/*
diff --git a/learning/katas/README.md b/learning/katas/README.md
new file mode 100644
index 0000000..167edc3
--- /dev/null
+++ b/learning/katas/README.md
@@ -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.
+-->
+
+# Beam Kata
+Beam Kata is a set of interactive Beam coding exercises (i.e. code kata) that aids in learning Beam programming hands-on. It is built based on [JetBrains Educational Products](https://www.jetbrains.com/education/).
+
+## Objective
+The objective of Beam Kata is to provide a structured hands-on learning experience for people to learn about Beam and its SDK by solving focused mini problems with gradually increasing complexity (e.g. SDK, common transforms, common use-case patterns, common problems like word count, etc).
diff --git a/learning/katas/java/.idea/study_project.xml b/learning/katas/java/.idea/study_project.xml
new file mode 100644
index 0000000..82cb98c
--- /dev/null
+++ b/learning/katas/java/.idea/study_project.xml
@@ -0,0 +1,1740 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="StudySettings">
+ <StudyTaskManager>
+ <option name="VERSION" value="14" />
+ <option name="myUserTests">
+ <map />
+ </option>
+ <option name="course">
+ <EduCourse>
+ <option name="authors">
+ <list>
+ <StepikUserInfo>
+ <option name="firstName" value="Henry" />
+ <option name="id" value="48485817" />
+ <option name="lastName" value="Suryawirawan" />
+ </StepikUserInfo>
+ </list>
+ </option>
+ <option name="compatible" value="true" />
+ <option name="courseMode" value="Course Creator" />
+ <option name="createDate" value="1557823043901" />
+ <option name="customPresentableName" />
+ <option name="description" value="This course provides a series of kata to get familiar with Apache Beam. Apache Beam website – https://beam.apache.org/" />
+ <option name="environment" value="" />
+ <option name="fromZip" value="false" />
+ <option name="id" value="54530" />
+ <option name="index" value="-1" />
+ <option name="instructors">
+ <list>
+ <option value="48485817" />
+ </list>
+ </option>
+ <option name="language" value="JAVA" />
+ <option name="languageCode" value="en" />
+ <option name="name" value="Beam Kata - Java" />
+ <option name="public" value="false" />
+ <option name="sectionIds">
+ <list />
+ </option>
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="type" value="pycharm11 JAVA" />
+ <option name="updateDate" value="1557823043000" />
+ <option name="items">
+ <list>
+ <Section>
+ <option name="courseId" value="54530" />
+ <option name="customPresentableName" />
+ <option name="id" value="85639" />
+ <option name="index" value="1" />
+ <option name="name" value="Introduction" />
+ <option name="position" value="0" />
+ <option name="stepikChangeStatus" value="Content changed" />
+ <option name="updateDate" value="1557823047000" />
+ <option name="items">
+ <list>
+ <Lesson>
+ <option name="customPresentableName" />
+ <option name="id" value="229506" />
+ <option name="index" value="1" />
+ <option name="name" value="Hello Beam" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="updateDate" value="1557823051000" />
+ <option name="unitId" value="202031" />
+ <option name="items">
+ <list>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713723" />
+ <option name="index" value="1" />
+ <option name="name" value="Hello Beam" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="src/Task.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="1461" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="pipeline.apply(Create.of("Hello Beam"))" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="src/Task.java" />
+ <option name="text" value="class Task { //put your task here }" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="test/TaskTest.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="test/TaskTest.java" />
+ <option name="text" value="public class Test { // put your test here }" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557823053000" />
+ </EduTask>
+ </list>
+ </option>
+ </Lesson>
+ </list>
+ </option>
+ </Section>
+ <Section>
+ <option name="courseId" value="54530" />
+ <option name="customPresentableName" />
+ <option name="id" value="85640" />
+ <option name="index" value="2" />
+ <option name="name" value="Core Transforms" />
+ <option name="position" value="0" />
+ <option name="stepikChangeStatus" value="Content changed" />
+ <option name="updateDate" value="1557823054000" />
+ <option name="items">
+ <list>
+ <Lesson>
+ <option name="customPresentableName" />
+ <option name="id" value="229507" />
+ <option name="index" value="1" />
+ <option name="name" value="Map" />
+ <option name="stepikChangeStatus" value="Content changed" />
+ <option name="updateDate" value="1557823058000" />
+ <option name="unitId" value="202032" />
+ <option name="items">
+ <list>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713724" />
+ <option name="index" value="1" />
+ <option name="name" value="ParDo" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="src/Task.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="1648" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="input.apply(ParDo.of(new DoFn<Integer, Integer>() { @ProcessElement public void processElement(@Element Integer number, OutputReceiver<Integer> out) { out.output(number * 10); } }))" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="src/Task.java" />
+ <option name="text" value="class Task { //put your task here }" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="test/TaskTest.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="test/TaskTest.java" />
+ <option name="text" value="public class Test { // put your test here }" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557823060000" />
+ </EduTask>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713725" />
+ <option name="index" value="2" />
+ <option name="name" value="ParDo OneToMany" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="src/Task.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="1664" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="input.apply(ParDo.of(new DoFn<String, String>() { @ProcessElement public void processElement(@Element String sentence, OutputReceiver<String> out) { String[] words = sentence.split(" "); for (String word : words) { out.output(word); } } }))" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="src/Task.java" />
+ <option name="text" value="class Task { //put your task here }" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="test/TaskTest.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="test/TaskTest.java" />
+ <option name="text" value="public class Test { // put your test here }" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557823062000" />
+ </EduTask>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713726" />
+ <option name="index" value="3" />
+ <option name="name" value="MapElements" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="src/Task.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="1666" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="input.apply( MapElements.into(TypeDescriptors.integers()) .via(number -> number * 5) )" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="src/Task.java" />
+ <option name="text" value="" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="test/TaskTest.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="test/TaskTest.java" />
+ <option name="text" value="" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557823065000" />
+ </EduTask>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713727" />
+ <option name="index" value="4" />
+ <option name="name" value="FlatMapElements" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="src/Task.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="1721" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="input.apply( FlatMapElements.into(TypeDescriptors.strings()) .via(sentence -> Arrays.asList(sentence.split(" "))) )" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="src/Task.java" />
+ <option name="text" value="" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="test/TaskTest.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="test/TaskTest.java" />
+ <option name="text" value="" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557823067000" />
+ </EduTask>
+ </list>
+ </option>
+ </Lesson>
+ <Lesson>
+ <option name="customPresentableName" />
+ <option name="id" value="229508" />
+ <option name="index" value="2" />
+ <option name="name" value="GroupByKey" />
+ <option name="stepikChangeStatus" value="Content changed" />
+ <option name="updateDate" value="1557823071000" />
+ <option name="unitId" value="202033" />
+ <option name="items">
+ <list>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713728" />
+ <option name="index" value="1" />
+ <option name="name" value="GroupByKey" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="src/Task.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="1920" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="input .apply(MapElements.into(kvs(strings(), strings())) .via(word -> KV.of(word.substring(0, 1), word))) .apply(GroupByKey.create())" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="src/Task.java" />
+ <option name="text" value="" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="test/TaskTest.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="test/TaskTest.java" />
+ <option name="text" value="" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557823073000" />
+ </EduTask>
+ </list>
+ </option>
+ </Lesson>
+ <Lesson>
+ <option name="customPresentableName" />
+ <option name="id" value="229509" />
+ <option name="index" value="3" />
+ <option name="name" value="CoGroupByKey" />
+ <option name="stepikChangeStatus" value="Content changed" />
+ <option name="updateDate" value="1557823076000" />
+ <option name="unitId" value="202034" />
+ <option name="items">
+ <list>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713729" />
+ <option name="index" value="1" />
+ <option name="name" value="CoGroupByKey" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="src/Task.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="2290" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="TupleTag<String> fruitsTag = new TupleTag<>(); TupleTag<String> countriesTag = new TupleTag<>(); MapElements<String, KV<String, String>> mapToAlphabetKv = MapElements.into(kvs(strings(), strings())) .via(word -> KV.of(word.substring(0, 1), word)); PCollection<KV<String, String>> fruitsPColl = frui [...]
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="src/Task.java" />
+ <option name="text" value="" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="src/WordsAlphabet.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="src/WordsAlphabet.java" />
+ <option name="text" value="" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="test/TaskTest.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="test/TaskTest.java" />
+ <option name="text" value="" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557823078000" />
+ </EduTask>
+ </list>
+ </option>
+ </Lesson>
+ <Lesson>
+ <option name="customPresentableName" />
+ <option name="id" value="229510" />
+ <option name="index" value="4" />
+ <option name="name" value="Combine" />
+ <option name="stepikChangeStatus" value="Content changed" />
+ <option name="updateDate" value="1557823081000" />
+ <option name="unitId" value="202035" />
+ <option name="items">
+ <list>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713730" />
+ <option name="index" value="1" />
+ <option name="name" value="Simple Function" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="src/Task.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="1814" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="@Override public Integer apply(Iterable<Integer> input) { int sum = 0; for (int item : input) { sum += item; } return sum; }" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="src/Task.java" />
+ <option name="text" value="class Task { //put your task here }" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="test/TaskTest.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="test/TaskTest.java" />
+ <option name="text" value="public class Test { // put your test here }" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557823083000" />
+ </EduTask>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713731" />
+ <option name="index" value="2" />
+ <option name="name" value="CombineFn" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="src/Task.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="1850" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="class Accum implements Serializable { int sum = 0; int count = 0; @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Accum accum = (Accum) o; return sum == accum.sum &&&# [...]
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="src/Task.java" />
+ <option name="text" value="class Task { //put your task here }" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="test/TaskTest.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="test/TaskTest.java" />
+ <option name="text" value="public class Test { // put your test here }" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557823086000" />
+ </EduTask>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713732" />
+ <option name="index" value="3" />
+ <option name="name" value="BinaryCombineFn" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Content changed" />
+ <option name="files">
+ <map>
+ <entry key="src/Task.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="2007" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="@Override public BigInteger apply(BigInteger left, BigInteger right) { return left.add(right); }" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="src/Task.java" />
+ <option name="text" value="class Task { //put your task here }" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="test/TaskTest.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="test/TaskTest.java" />
+ <option name="text" value="public class Test { // put your test here }" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557823088000" />
+ </EduTask>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713733" />
+ <option name="index" value="4" />
+ <option name="name" value="Combine PerKey" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Content changed" />
+ <option name="files">
+ <map>
+ <entry key="src/Task.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="2039" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="input.apply(Combine.perKey(new SumIntBinaryCombineFn()))" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="1" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="2179" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="@Override public Integer apply(Integer left, Integer right) { return left + right; }" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="src/Task.java" />
+ <option name="text" value="class Task { //put your task here }" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="test/TaskTest.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="test/TaskTest.java" />
+ <option name="text" value="public class Test { // put your test here }" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557823090000" />
+ </EduTask>
+ </list>
+ </option>
+ </Lesson>
+ <Lesson>
+ <option name="customPresentableName" />
+ <option name="id" value="229511" />
+ <option name="index" value="5" />
+ <option name="name" value="Flatten" />
+ <option name="stepikChangeStatus" value="Content changed" />
+ <option name="updateDate" value="1557823093000" />
+ <option name="unitId" value="202036" />
+ <option name="items">
+ <list>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713734" />
+ <option name="index" value="1" />
+ <option name="name" value="Flatten" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="src/Task.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="1938" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="PCollectionList.of(words1).and(words2) .apply(Flatten.pCollections())" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="src/Task.java" />
+ <option name="text" value="class Task { //put your task here }" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="test/TaskTest.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="test/TaskTest.java" />
+ <option name="text" value="public class Test { // put your test here }" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557823095000" />
+ </EduTask>
+ </list>
+ </option>
+ </Lesson>
+ <Lesson>
+ <option name="customPresentableName" />
+ <option name="id" value="229512" />
+ <option name="index" value="6" />
+ <option name="name" value="Partition" />
+ <option name="stepikChangeStatus" value="Content changed" />
+ <option name="updateDate" value="1557823098000" />
+ <option name="unitId" value="202037" />
+ <option name="items">
+ <list>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713735" />
+ <option name="index" value="1" />
+ <option name="name" value="Partition" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="src/Task.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="1862" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="input .apply(Partition.of(2, (PartitionFn<Integer>) (number, numPartitions) -> { if (number > 100) { return 0; } else { return 1; } }))" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="src/Task.java" />
+ <option name="text" value="class Task { //put your task here }" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="test/TaskTest.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="test/TaskTest.java" />
+ <option name="text" value="public class Test { // put your test here }" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557823100000" />
+ </EduTask>
+ </list>
+ </option>
+ </Lesson>
+ </list>
+ </option>
+ </Section>
+ <Section>
+ <option name="courseId" value="54530" />
+ <option name="customPresentableName" />
+ <option name="id" value="85641" />
+ <option name="index" value="3" />
+ <option name="name" value="Common Transforms" />
+ <option name="position" value="0" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="updateDate" value="1557823101000" />
+ <option name="items">
+ <list>
+ <Lesson>
+ <option name="customPresentableName" />
+ <option name="id" value="229513" />
+ <option name="index" value="1" />
+ <option name="name" value="Filter" />
+ <option name="stepikChangeStatus" value="Content changed" />
+ <option name="updateDate" value="1557823104000" />
+ <option name="unitId" value="202038" />
+ <option name="items">
+ <list>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713736" />
+ <option name="index" value="1" />
+ <option name="name" value="ParDo" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="src/Task.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="1656" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="input.apply(ParDo.of( new DoFn<Integer, Integer>() { @ProcessElement public void processElement(@Element Integer number, OutputReceiver<Integer> out) { if (number % 2 == 1) { out.output(number); } } }) )" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="src/Task.java" />
+ <option name="text" value="" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="test/TaskTest.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="test/TaskTest.java" />
+ <option name="text" value="" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557823106000" />
+ </EduTask>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713737" />
+ <option name="index" value="2" />
+ <option name="name" value="Filter" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="src/Task.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="1621" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="input.apply(Filter.by(number -> number % 2 == 0))" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="src/Task.java" />
+ <option name="text" value="" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="test/TaskTest.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="test/TaskTest.java" />
+ <option name="text" value="" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557823108000" />
+ </EduTask>
+ </list>
+ </option>
+ </Lesson>
+ <Lesson>
+ <option name="customPresentableName" />
+ <option name="id" value="229514" />
+ <option name="index" value="2" />
+ <option name="name" value="Aggregation" />
+ <option name="stepikChangeStatus" value="Content changed" />
+ <option name="updateDate" value="1557823111000" />
+ <option name="unitId" value="202039" />
+ <option name="items">
+ <list>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713738" />
+ <option name="index" value="1" />
+ <option name="name" value="Count" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="src/Task.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="1606" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="input.apply(Count.globally())" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="src/Task.java" />
+ <option name="text" value="" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="test/TaskTest.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="test/TaskTest.java" />
+ <option name="text" value="" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557823113000" />
+ </EduTask>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713739" />
+ <option name="index" value="2" />
+ <option name="name" value="Sum" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="src/Task.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="1610" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="input.apply(Sum.integersGlobally())" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="src/Task.java" />
+ <option name="text" value="" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="test/TaskTest.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="test/TaskTest.java" />
+ <option name="text" value="" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557823115000" />
+ </EduTask>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713740" />
+ <option name="index" value="3" />
+ <option name="name" value="Mean" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="src/Task.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="1609" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="input.apply(Mean.globally())" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="src/Task.java" />
+ <option name="text" value="" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="test/TaskTest.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="test/TaskTest.java" />
+ <option name="text" value="" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557823117000" />
+ </EduTask>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713741" />
+ <option name="index" value="4" />
+ <option name="name" value="Min" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="src/Task.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="1610" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="input.apply(Min.integersGlobally())" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="src/Task.java" />
+ <option name="text" value="class Task { //put your task here }" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="test/TaskTest.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="test/TaskTest.java" />
+ <option name="text" value="public class Test { // put your test here }" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557823119000" />
+ </EduTask>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713742" />
+ <option name="index" value="5" />
+ <option name="name" value="Max" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="src/Task.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="1610" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="input.apply(Max.integersGlobally())" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="src/Task.java" />
+ <option name="text" value="class Task { //put your task here }" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="test/TaskTest.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="test/TaskTest.java" />
+ <option name="text" value="public class Test { // put your test here }" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557823121000" />
+ </EduTask>
+ </list>
+ </option>
+ </Lesson>
+ </list>
+ </option>
+ </Section>
+ <Section>
+ <option name="courseId" value="54530" />
+ <option name="customPresentableName" />
+ <option name="id" value="85642" />
+ <option name="index" value="4" />
+ <option name="name" value="Examples" />
+ <option name="position" value="0" />
+ <option name="stepikChangeStatus" value="Content changed" />
+ <option name="updateDate" value="1557823123000" />
+ <option name="items">
+ <list>
+ <Lesson>
+ <option name="customPresentableName" />
+ <option name="id" value="229515" />
+ <option name="index" value="1" />
+ <option name="name" value="Word Count" />
+ <option name="stepikChangeStatus" value="Content changed" />
+ <option name="updateDate" value="1557823126000" />
+ <option name="unitId" value="202040" />
+ <option name="items">
+ <list>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713743" />
+ <option name="index" value="1" />
+ <option name="name" value="Word Count" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="src/Task.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="1990" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="input .apply(FlatMapElements.into(TypeDescriptors.strings()) .via(line -> Arrays.asList(line.split(" ")))) .apply(Count.perElement()) .apply(ParDo.of(new DoFn<KV<String, Long>, String>() { @ProcessElement public void processElement( @Element KV<String, Long> ele [...]
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="src/Task.java" />
+ <option name="text" value="class Task { //put your task here }" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="test/TaskTest.java">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="test/TaskTest.java" />
+ <option name="text" value="public class Test { // put your test here }" />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557823128000" />
+ </EduTask>
+ </list>
+ </option>
+ </Lesson>
+ </list>
+ </option>
+ </Section>
+ </list>
+ </option>
+ </EduCourse>
+ </option>
+ </StudyTaskManager>
+ </component>
+</project>
\ No newline at end of file
diff --git a/learning/katas/java/Common Transforms/Aggregation/Count/src/Task.java b/learning/katas/java/Common Transforms/Aggregation/Count/src/Task.java
new file mode 100644
index 0000000..c15c928
--- /dev/null
+++ b/learning/katas/java/Common Transforms/Aggregation/Count/src/Task.java
@@ -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.
+ */
+
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.options.PipelineOptions;
+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;
+import util.Log;
+
+class Task {
+
+ public static void main(String[] args) {
+ PipelineOptions options = PipelineOptionsFactory.fromArgs(args).create();
+ Pipeline pipeline = Pipeline.create(options);
+
+ PCollection<Integer> numbers = pipeline.apply(Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
+
+ PCollection<Long> output = applyTransform(numbers);
+
+ output.apply(Log.ofElements());
+
+ pipeline.run();
+ }
+
+ static PCollection<Long> applyTransform(PCollection<Integer> input) {
+ return input.apply(Count.globally());
+ }
+
+}
\ No newline at end of file
diff --git a/learning/katas/java/Common Transforms/Aggregation/Count/task.html b/learning/katas/java/Common Transforms/Aggregation/Count/task.html
new file mode 100644
index 0000000..ac96243
--- /dev/null
+++ b/learning/katas/java/Common Transforms/Aggregation/Count/task.html
@@ -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.
+ -->
+
+<html>
+<h2>Aggregation - Count</h2>
+<p>In this task, we are going to count the number of elements from an input.</p>
+<br>
+<br>
+<div class='hint'>Use <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/Count.html">Count</a></div>
+</html>
\ No newline at end of file
diff --git a/learning/katas/java/Common Transforms/Aggregation/Count/test/TaskTest.java b/learning/katas/java/Common Transforms/Aggregation/Count/test/TaskTest.java
new file mode 100644
index 0000000..16f8a66
--- /dev/null
+++ b/learning/katas/java/Common Transforms/Aggregation/Count/test/TaskTest.java
@@ -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.
+ */
+
+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.PCollection;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class TaskTest {
+
+ @Rule
+ public TestPipeline testPipeline = TestPipeline.create();
+
+ @Test
+ public void count() {
+ Create.Values<Integer> values = Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ PCollection<Integer> numbers = testPipeline.apply(values);
+
+ PCollection<Long> results = Task.applyTransform(numbers);
+
+ PAssert.that(results)
+ .containsInAnyOrder(10L);
+
+ testPipeline.run().waitUntilFinish();
+ }
+
+}
\ No newline at end of file
diff --git a/learning/katas/java/Common Transforms/Aggregation/Max/src/Task.java b/learning/katas/java/Common Transforms/Aggregation/Max/src/Task.java
new file mode 100644
index 0000000..d1081eb
--- /dev/null
+++ b/learning/katas/java/Common Transforms/Aggregation/Max/src/Task.java
@@ -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.
+ */
+
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.options.PipelineOptions;
+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;
+import util.Log;
+
+class Task {
+
+ public static void main(String[] args) {
+ PipelineOptions options = PipelineOptionsFactory.fromArgs(args).create();
+ Pipeline pipeline = Pipeline.create(options);
+
+ PCollection<Integer> numbers = pipeline.apply(Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
+
+ PCollection<Integer> output = applyTransform(numbers);
+
+ output.apply(Log.ofElements());
+
+ pipeline.run();
+ }
+
+ static PCollection<Integer> applyTransform(PCollection<Integer> input) {
+ return input.apply(Max.integersGlobally());
+ }
+
+}
\ No newline at end of file
diff --git a/learning/katas/java/Common Transforms/Aggregation/Max/task.html b/learning/katas/java/Common Transforms/Aggregation/Max/task.html
new file mode 100644
index 0000000..98b399e
--- /dev/null
+++ b/learning/katas/java/Common Transforms/Aggregation/Max/task.html
@@ -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.
+ -->
+
+<html>
+<h2>Aggregation - Max</h2>
+<p>In this task, we are going to compute the maximum of the elements from an input.</p>
+<br>
+<br>
+<div class='hint'>Use <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/Max.html">Max</a></div>
+</html>
\ No newline at end of file
diff --git a/learning/katas/java/Common Transforms/Aggregation/Max/test/TaskTest.java b/learning/katas/java/Common Transforms/Aggregation/Max/test/TaskTest.java
new file mode 100644
index 0000000..0852d60
--- /dev/null
+++ b/learning/katas/java/Common Transforms/Aggregation/Max/test/TaskTest.java
@@ -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.
+ */
+
+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.PCollection;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class TaskTest {
+
+ @Rule
+ public TestPipeline testPipeline = TestPipeline.create();
+
+ @Test
+ public void max() {
+ Create.Values<Integer> values = Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ PCollection<Integer> numbers = testPipeline.apply(values);
+
+ PCollection<Integer> results = Task.applyTransform(numbers);
+
+ PAssert.that(results)
+ .containsInAnyOrder(10);
+
+ testPipeline.run().waitUntilFinish();
+ }
+
+}
\ No newline at end of file
diff --git a/learning/katas/java/Common Transforms/Aggregation/Mean/src/Task.java b/learning/katas/java/Common Transforms/Aggregation/Mean/src/Task.java
new file mode 100644
index 0000000..f184d2b
--- /dev/null
+++ b/learning/katas/java/Common Transforms/Aggregation/Mean/src/Task.java
@@ -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.
+ */
+
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.options.PipelineOptions;
+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;
+import util.Log;
+
+class Task {
+
+ public static void main(String[] args) {
+ PipelineOptions options = PipelineOptionsFactory.fromArgs(args).create();
+ Pipeline pipeline = Pipeline.create(options);
+
+ PCollection<Integer> numbers = pipeline.apply(Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
+
+ PCollection<Double> output = applyTransform(numbers);
+
+ output.apply(Log.ofElements());
+
+ pipeline.run();
+ }
+
+ static PCollection<Double> applyTransform(PCollection<Integer> input) {
+ return input.apply(Mean.globally());
+ }
+
+}
\ No newline at end of file
diff --git a/learning/katas/java/Common Transforms/Aggregation/Mean/task.html b/learning/katas/java/Common Transforms/Aggregation/Mean/task.html
new file mode 100644
index 0000000..39348b7
--- /dev/null
+++ b/learning/katas/java/Common Transforms/Aggregation/Mean/task.html
@@ -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.
+ -->
+
+<html>
+<h2>Aggregation - Mean</h2>
+<p>In this task, we are going to compute the mean/average of all elements from an input.</p>
+<br>
+<br>
+<div class='hint'>Use <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/Mean.html">Mean</a></div>
+</html>
\ No newline at end of file
diff --git a/learning/katas/java/Common Transforms/Aggregation/Mean/test/TaskTest.java b/learning/katas/java/Common Transforms/Aggregation/Mean/test/TaskTest.java
new file mode 100644
index 0000000..9c77105
--- /dev/null
+++ b/learning/katas/java/Common Transforms/Aggregation/Mean/test/TaskTest.java
@@ -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.
+ */
+
+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.PCollection;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class TaskTest {
+
+ @Rule
+ public TestPipeline testPipeline = TestPipeline.create();
+
+ @Test
+ public void mean() {
+ Create.Values<Integer> values = Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ PCollection<Integer> numbers = testPipeline.apply(values);
+
+ PCollection<Double> results = Task.applyTransform(numbers);
+
+ PAssert.that(results)
+ .containsInAnyOrder(5.5);
+
+ testPipeline.run().waitUntilFinish();
+ }
+
+}
\ No newline at end of file
diff --git a/learning/katas/java/Common Transforms/Aggregation/Min/src/Task.java b/learning/katas/java/Common Transforms/Aggregation/Min/src/Task.java
new file mode 100644
index 0000000..54c4238
--- /dev/null
+++ b/learning/katas/java/Common Transforms/Aggregation/Min/src/Task.java
@@ -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.
+ */
+
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.options.PipelineOptions;
+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;
+import util.Log;
+
+class Task {
+
+ public static void main(String[] args) {
+ PipelineOptions options = PipelineOptionsFactory.fromArgs(args).create();
+ Pipeline pipeline = Pipeline.create(options);
+
+ PCollection<Integer> numbers = pipeline.apply(Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
+
+ PCollection<Integer> output = applyTransform(numbers);
+
+ output.apply(Log.ofElements());
+
+ pipeline.run();
+ }
+
+ static PCollection<Integer> applyTransform(PCollection<Integer> input) {
+ return input.apply(Min.integersGlobally());
+ }
+
+}
\ No newline at end of file
diff --git a/learning/katas/java/Common Transforms/Aggregation/Min/task.html b/learning/katas/java/Common Transforms/Aggregation/Min/task.html
new file mode 100644
index 0000000..1ec26be
--- /dev/null
+++ b/learning/katas/java/Common Transforms/Aggregation/Min/task.html
@@ -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.
+ -->
+
+<html>
+<h2>Aggregation - Min</h2>
+<p>In this task, we are going to compute the minimum of the elements from an input.</p>
+<br>
+<br>
+<div class='hint'>Use <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/Min.html">Min</a></div>
+</html>
\ No newline at end of file
diff --git a/learning/katas/java/Common Transforms/Aggregation/Min/test/TaskTest.java b/learning/katas/java/Common Transforms/Aggregation/Min/test/TaskTest.java
new file mode 100644
index 0000000..8814308
--- /dev/null
+++ b/learning/katas/java/Common Transforms/Aggregation/Min/test/TaskTest.java
@@ -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.
+ */
+
+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.PCollection;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class TaskTest {
+
+ @Rule
+ public TestPipeline testPipeline = TestPipeline.create();
+
+ @Test
+ public void min() {
+ Create.Values<Integer> values = Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ PCollection<Integer> numbers = testPipeline.apply(values);
+
+ PCollection<Integer> results = Task.applyTransform(numbers);
+
+ PAssert.that(results)
+ .containsInAnyOrder(1);
+
+ testPipeline.run().waitUntilFinish();
+ }
+
+}
\ No newline at end of file
diff --git a/learning/katas/java/Common Transforms/Aggregation/Sum/src/Task.java b/learning/katas/java/Common Transforms/Aggregation/Sum/src/Task.java
new file mode 100644
index 0000000..ead1ffa
--- /dev/null
+++ b/learning/katas/java/Common Transforms/Aggregation/Sum/src/Task.java
@@ -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.
+ */
+
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.options.PipelineOptions;
+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;
+import util.Log;
+
+class Task {
+
+ public static void main(String[] args) {
+ PipelineOptions options = PipelineOptionsFactory.fromArgs(args).create();
+ Pipeline pipeline = Pipeline.create(options);
+
+ PCollection<Integer> numbers = pipeline.apply(Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
+
+ PCollection<Integer> output = applyTransform(numbers);
+
+ output.apply(Log.ofElements());
+
+ pipeline.run();
+ }
+
+ static PCollection<Integer> applyTransform(PCollection<Integer> input) {
+ return input.apply(Sum.integersGlobally());
+ }
+
+}
\ No newline at end of file
diff --git a/learning/katas/java/Common Transforms/Aggregation/Sum/task.html b/learning/katas/java/Common Transforms/Aggregation/Sum/task.html
new file mode 100644
index 0000000..55692b9
--- /dev/null
+++ b/learning/katas/java/Common Transforms/Aggregation/Sum/task.html
@@ -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.
+ -->
+
+<html>
+<h2>Aggregation - Sum</h2>
+<p>In this task, we are going to compute the sum of all elements from an input.</p>
+<br>
+<br>
+<div class='hint'>Use <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/Sum.html">Sum</a></div>
+</html>
\ No newline at end of file
diff --git a/learning/katas/java/Common Transforms/Aggregation/Sum/test/TaskTest.java b/learning/katas/java/Common Transforms/Aggregation/Sum/test/TaskTest.java
new file mode 100644
index 0000000..99f4b8e
--- /dev/null
+++ b/learning/katas/java/Common Transforms/Aggregation/Sum/test/TaskTest.java
@@ -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.
+ */
+
+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.PCollection;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class TaskTest {
+
+ @Rule
+ public TestPipeline testPipeline = TestPipeline.create();
+
+ @Test
+ public void sum() {
+ Create.Values<Integer> values = Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ PCollection<Integer> numbers = testPipeline.apply(values);
+
+ PCollection<Integer> results = Task.applyTransform(numbers);
+
+ PAssert.that(results)
+ .containsInAnyOrder(55);
+
+ testPipeline.run().waitUntilFinish();
+ }
+
+}
\ No newline at end of file
diff --git a/learning/katas/java/Common Transforms/Filter/Filter/src/Task.java b/learning/katas/java/Common Transforms/Filter/Filter/src/Task.java
new file mode 100644
index 0000000..c567f5b
--- /dev/null
+++ b/learning/katas/java/Common Transforms/Filter/Filter/src/Task.java
@@ -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.
+ */
+
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.options.PipelineOptions;
+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.values.PCollection;
+import util.Log;
+
+class Task {
+
+ public static void main(String[] args) {
+ PipelineOptions options = PipelineOptionsFactory.fromArgs(args).create();
+ Pipeline pipeline = Pipeline.create(options);
+
+ PCollection<Integer> numbers =
+ pipeline.apply(Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
+
+ PCollection<Integer> output = applyTransform(numbers);
+
+ output.apply(Log.ofElements());
+
+ pipeline.run();
+ }
+
+ static PCollection<Integer> applyTransform(PCollection<Integer> input) {
+ return input.apply(Filter.by(number -> number % 2 == 0));
+ }
+
+}
\ No newline at end of file
diff --git a/learning/katas/java/Common Transforms/Filter/Filter/task.html b/learning/katas/java/Common Transforms/Filter/Filter/task.html
new file mode 100644
index 0000000..02ed9d9
--- /dev/null
+++ b/learning/katas/java/Common Transforms/Filter/Filter/task.html
@@ -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.
+ -->
+
+<html>
+<h2>Filter</h2>
+<p>The Beam SDKs provide language-specific ways to simplify how you provide your DoFn implementation.</p>
+<p>In this task, we are going to implement a filter function that filters out the odd numbers by using
+ <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/Filter.html">
+ Filter</a>.
+</p>
+<br>
+<br>
+<div class='hint'>Use <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/Filter.html">Filter.by(...)</a></div>
+</html>
\ No newline at end of file
diff --git a/learning/katas/java/Common Transforms/Filter/Filter/test/TaskTest.java b/learning/katas/java/Common Transforms/Filter/Filter/test/TaskTest.java
new file mode 100644
index 0000000..ccf1bab
--- /dev/null
+++ b/learning/katas/java/Common Transforms/Filter/Filter/test/TaskTest.java
@@ -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.
+ */
+
+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.PCollection;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class TaskTest {
+
+ @Rule
+ public TestPipeline testPipeline = TestPipeline.create();
+
+ @Test
+ public void filter() {
+ Create.Values<Integer> values = Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ PCollection<Integer> numbers = testPipeline.apply(values);
+
+ PCollection<Integer> results = Task.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/java/Common Transforms/Filter/ParDo/src/Task.java b/learning/katas/java/Common Transforms/Filter/ParDo/src/Task.java
new file mode 100644
index 0000000..7b3cb3f
--- /dev/null
+++ b/learning/katas/java/Common Transforms/Filter/ParDo/src/Task.java
@@ -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.
+ */
+
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.options.PipelineOptions;
+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 util.Log;
+
+class Task {
+
+ public static void main(String[] args) {
+ PipelineOptions options = PipelineOptionsFactory.fromArgs(args).create();
+ Pipeline pipeline = Pipeline.create(options);
+
+ PCollection<Integer> numbers = pipeline.apply(Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
+
+ PCollection<Integer> output = applyTransform(numbers);
+
+ output.apply(Log.ofElements());
+
+ pipeline.run();
+ }
+
+ static PCollection<Integer> applyTransform(PCollection<Integer> input) {
+ return input.apply(ParDo.of(
+ new DoFn<Integer, Integer>() {
+
+ @ProcessElement
+ public void processElement(@Element Integer number, OutputReceiver<Integer> out) {
+ if (number % 2 == 1) {
+ out.output(number);
+ }
+ }
+ })
+ );
+ }
+
+}
diff --git a/learning/katas/java/Common Transforms/Filter/ParDo/task.html b/learning/katas/java/Common Transforms/Filter/ParDo/task.html
new file mode 100644
index 0000000..af3cb62
--- /dev/null
+++ b/learning/katas/java/Common Transforms/Filter/ParDo/task.html
@@ -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.
+ -->
+
+<html>
+<h2>Filter using ParDo</h2>
+<p>In this task, we are going to implement a filter function that filters out the even numbers by using
+ <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/DoFn.html">
+ DoFn</a>.
+</p>
+<br>
+<br>
+<div class='hint'>Use <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/ParDo.html">ParDo</a>
+ with <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/DoFn.html">DoFn</a>
+ and only output the intended element.</div>
+</html>
\ No newline at end of file
diff --git a/learning/katas/java/Common Transforms/Filter/ParDo/test/TaskTest.java b/learning/katas/java/Common Transforms/Filter/ParDo/test/TaskTest.java
new file mode 100644
index 0000000..d92d0ae
--- /dev/null
+++ b/learning/katas/java/Common Transforms/Filter/ParDo/test/TaskTest.java
@@ -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.
+ */
+
+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.PCollection;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class TaskTest {
+
+ @Rule
+ public TestPipeline testPipeline = TestPipeline.create();
+
+ @Test
+ public void filter_parDo() {
+ Create.Values<Integer> values = Create.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ PCollection<Integer> numbers = testPipeline.apply(values);
+
+ PCollection<Integer> results = Task.applyTransform(numbers);
+
+ PAssert.that(results)
+ .containsInAnyOrder(1, 3, 5, 7, 9);
+
+ testPipeline.run().waitUntilFinish();
+ }
+
+}
diff --git a/learning/katas/java/Core Transforms/CoGroupByKey/CoGroupByKey/src/Task.java b/learning/katas/java/Core Transforms/CoGroupByKey/CoGroupByKey/src/Task.java
new file mode 100644
index 0000000..01ec78f
--- /dev/null
+++ b/learning/katas/java/Core Transforms/CoGroupByKey/CoGroupByKey/src/Task.java
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+import static org.apache.beam.sdk.values.TypeDescriptors.kvs;
+import static org.apache.beam.sdk.values.TypeDescriptors.strings;
+
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.options.PipelineOptions;
+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.MapElements;
+import org.apache.beam.sdk.transforms.ParDo;
+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 util.Log;
+
+class Task {
+
+ public static void main(String[] args) {
+ PipelineOptions options = PipelineOptionsFactory.fromArgs(args).create();
+ Pipeline pipeline = Pipeline.create(options);
+
+ PCollection<String> fruits =
+ pipeline.apply(
+ Create.of("apple", "banana", "cherry")
+ );
+
+ PCollection<String> countries =
+ pipeline.apply(
+ Create.of("australia", "brazil", "canada")
+ );
+
+ PCollection<String> output = applyTransform(fruits, countries);
+
+ output.apply(Log.ofElements());
+
+ pipeline.run();
+ }
+
+ static PCollection<String> applyTransform(
+ PCollection<String> fruits, PCollection<String> countries) {
+
+ TupleTag<String> fruitsTag = new TupleTag<>();
+ TupleTag<String> countriesTag = new TupleTag<>();
+
+ MapElements<String, KV<String, String>> mapToAlphabetKv =
+ MapElements.into(kvs(strings(), strings()))
+ .via(word -> KV.of(word.substring(0, 1), word));
+
+ PCollection<KV<String, String>> fruitsPColl = fruits.apply("Fruit to KV", mapToAlphabetKv);
+ PCollection<KV<String, String>> countriesPColl = countries
+ .apply("Country to KV", mapToAlphabetKv);
+
+ return KeyedPCollectionTuple
+ .of(fruitsTag, fruitsPColl)
+ .and(countriesTag, countriesPColl)
+
+ .apply(CoGroupByKey.create())
+
+ .apply(ParDo.of(new DoFn<KV<String, CoGbkResult>, String>() {
+
+ @ProcessElement
+ public void processElement(
+ @Element KV<String, CoGbkResult> element, OutputReceiver<String> out) {
+
+ String alphabet = element.getKey();
+ CoGbkResult coGbkResult = element.getValue();
+
+ String fruit = coGbkResult.getOnly(fruitsTag);
+ String country = coGbkResult.getOnly(countriesTag);
+
+ out.output(new WordsAlphabet(alphabet, fruit, country).toString());
+ }
+
+ }));
+ }
+
+}
\ No newline at end of file
diff --git a/learning/katas/java/Core Transforms/CoGroupByKey/CoGroupByKey/src/WordsAlphabet.java b/learning/katas/java/Core Transforms/CoGroupByKey/CoGroupByKey/src/WordsAlphabet.java
new file mode 100644
index 0000000..3870642
--- /dev/null
+++ b/learning/katas/java/Core Transforms/CoGroupByKey/CoGroupByKey/src/WordsAlphabet.java
@@ -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.
+ */
+
+public class WordsAlphabet {
+
+ private String alphabet;
+ private String fruit;
+ private String country;
+
+ public WordsAlphabet(String alphabet, String fruit, String country) {
+ this.alphabet = alphabet;
+ this.fruit = fruit;
+ this.country = country;
+ }
+
+ @Override
+ public String toString() {
+ return "WordsAlphabet{" +
+ "alphabet='" + alphabet + '\'' +
+ ", fruit='" + fruit + '\'' +
+ ", country='" + country + '\'' +
+ '}';
+ }
+
+}
diff --git a/learning/katas/java/Core Transforms/CoGroupByKey/CoGroupByKey/task.html b/learning/katas/java/Core Transforms/CoGroupByKey/CoGroupByKey/task.html
new file mode 100644
index 0000000..a6c29a8
--- /dev/null
+++ b/learning/katas/java/Core Transforms/CoGroupByKey/CoGroupByKey/task.html
@@ -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.
+ -->
+
+<html>
+<h2>CoGroupByKey</h2>
+<p>CoGroupByKey performs a relational join of two or more key/value PCollections that have the same key type.</p>
+<p>In this task, we are going to implement a
+ <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/join/CoGroupByKey.html">
+ CoGroupByKey</a> transform that join words by its first alphabetical letter, and then produces the toString()
+ representation of the WordsAlphabet model.
+</p>
+<br>
+<br>
+<div class='hint'>Refer to <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/join/CoGroupByKey.html">CoGroupByKey</a>,
+ <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/values/TupleTag.html">TupleTag</a>,
+ and <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/join/CoGbkResult.html">CoGbkResult</a>.</div>
+</html>
\ No newline at end of file
diff --git a/learning/katas/java/Core Transforms/CoGroupByKey/CoGroupByKey/test/TaskTest.java b/learning/katas/java/Core Transforms/CoGroupByKey/CoGroupByKey/test/TaskTest.java
new file mode 100644
index 0000000..08d8ab9
--- /dev/null
+++ b/learning/katas/java/Core Transforms/CoGroupByKey/CoGroupByKey/test/TaskTest.java
@@ -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.
+ */
+
+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.PCollection;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class TaskTest {
+
+ @Rule
+ public TestPipeline testPipeline = TestPipeline.create();
+
+ @Test
+ public void coGroupByKey() {
+ PCollection<String> fruits =
+ testPipeline.apply("Fruits",
+ Create.of("apple", "banana", "cherry")
+ );
+
+ PCollection<String> countries =
+ testPipeline.apply("Countries",
+ Create.of("australia", "brazil", "canada")
+ );
+
+ PCollection<String> results = Task.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/java/Core Transforms/Combine/BinaryCombineFn/src/Task.java b/learning/katas/java/Core Transforms/Combine/BinaryCombineFn/src/Task.java
new file mode 100644
index 0000000..c3c9ac2
--- /dev/null
+++ b/learning/katas/java/Core Transforms/Combine/BinaryCombineFn/src/Task.java
@@ -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.
+ */
+
+import java.math.BigInteger;
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.options.PipelineOptions;
+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 util.Log;
+
+class Task {
+
+ public static void main(String[] args) {
+ PipelineOptions options = PipelineOptionsFactory.fromArgs(args).create();
+ Pipeline pipeline = Pipeline.create(options);
+
+ PCollection<BigInteger> numbers =
+ pipeline.apply(
+ Create.of(
+ BigInteger.valueOf(10), BigInteger.valueOf(20), BigInteger.valueOf(30),
+ BigInteger.valueOf(40), BigInteger.valueOf(50)
+ ));
+
+ PCollection<BigInteger> output = applyTransform(numbers);
+
+ output.apply(Log.ofElements());
+
+ pipeline.run();
+ }
+
+ static PCollection<BigInteger> applyTransform(PCollection<BigInteger> input) {
+ return input.apply(Combine.globally(new SumBigIntegerFn()));
+ }
+
+ static class SumBigIntegerFn extends BinaryCombineFn<BigInteger> {
+
+ @Override
+ public BigInteger apply(BigInteger left, BigInteger right) {
+ return left.add(right);
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/learning/katas/java/Core Transforms/Combine/BinaryCombineFn/task.html b/learning/katas/java/Core Transforms/Combine/BinaryCombineFn/task.html
new file mode 100644
index 0000000..ee8db27
--- /dev/null
+++ b/learning/katas/java/Core Transforms/Combine/BinaryCombineFn/task.html
@@ -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.
+ -->
+
+<html>
+<h2>Combine - BinaryCombineFn</h2>
+<p>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.</p>
+<p>BinaryCombineFn is used for implementing combiners that are more easily expressed as binary operations.</p>
+<p>In this task, we are going to implement the summation of BigInteger using
+ <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/Combine.BinaryCombineFn.html">
+ Combine.BinaryCombineFn</a>.
+</p>
+<br>
+<br>
+<div class='hint'>Extend the
+ <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/Combine.BinaryCombineFn.html">Combine.BinaryCombineFn</a>
+ class that counts the sum of the number.</div>
+</html>
\ No newline at end of file
diff --git a/learning/katas/java/Core Transforms/Combine/BinaryCombineFn/test/TaskTest.java b/learning/katas/java/Core Transforms/Combine/BinaryCombineFn/test/TaskTest.java
new file mode 100644
index 0000000..d4e4f42
--- /dev/null
+++ b/learning/katas/java/Core Transforms/Combine/BinaryCombineFn/test/TaskTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+import java.math.BigInteger;
+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.PCollection;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class TaskTest {
+
+ @Rule
+ public TestPipeline testPipeline = TestPipeline.create();
+
+ @Test
+ public void combine_binaryCombineFn() {
+ Create.Values<BigInteger> values = Create.of(
+ BigInteger.valueOf(10), BigInteger.valueOf(20), BigInteger.valueOf(30),
+ BigInteger.valueOf(40), BigInteger.valueOf(50)
+ );
+ PCollection<BigInteger> numbers = testPipeline.apply(values);
+
+ PCollection<BigInteger> results = Task.applyTransform(numbers);
+
+ PAssert.that(results)
+ .containsInAnyOrder(BigInteger.valueOf(150));
+
+ testPipeline.run().waitUntilFinish();
+ }
+
+}
\ No newline at end of file
diff --git a/learning/katas/java/Core Transforms/Combine/Combine PerKey/src/Task.java b/learning/katas/java/Core Transforms/Combine/Combine PerKey/src/Task.java
new file mode 100644
index 0000000..16ca7c5
--- /dev/null
+++ b/learning/katas/java/Core Transforms/Combine/Combine PerKey/src/Task.java
@@ -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.
+ */
+
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.options.PipelineOptions;
+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;
+import util.Log;
+
+class Task {
+
+ static final String PLAYER_1 = "Player 1";
+ static final String PLAYER_2 = "Player 2";
+ static final String PLAYER_3 = "Player 3";
+
+ public static void main(String[] args) {
+ PipelineOptions options = PipelineOptionsFactory.fromArgs(args).create();
+ Pipeline pipeline = Pipeline.create(options);
+
+ PCollection<KV<String, Integer>> 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)
+ ));
+
+ PCollection<KV<String, Integer>> output = applyTransform(scores);
+
+ output.apply(Log.ofElements());
+
+ pipeline.run();
+ }
+
+ static PCollection<KV<String, Integer>> applyTransform(PCollection<KV<String, Integer>> input) {
+ return input.apply(Combine.perKey(new SumIntBinaryCombineFn()));
+ }
+
+ static class SumIntBinaryCombineFn extends BinaryCombineFn<Integer> {
+
+ @Override
+ public Integer apply(Integer left, Integer right) {
+ return left + right;
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/learning/katas/java/Core Transforms/Combine/Combine PerKey/task.html b/learning/katas/java/Core Transforms/Combine/Combine PerKey/task.html
new file mode 100644
index 0000000..76a591a
--- /dev/null
+++ b/learning/katas/java/Core Transforms/Combine/Combine PerKey/task.html
@@ -0,0 +1,36 @@
+<!--
+ ~ 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.
+ -->
+
+<html>
+<h2>Combine - Combine PerKey</h2>
+<p>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.</p>
+<p>In this task, we are going to implement the sum of scores per player using
+ <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/CombineFnBase.GlobalCombineFn.html">
+ Combine.perKey</a>.
+</p>
+<br>
+<br>
+<div class='hint'>Use <a href="https://beam.apache.org/releases/javadoc/2.11.0/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/2.11.0/org/apache/beam/sdk/transforms/Combine.BinaryCombineFn.html">Combine.BinaryCombineFn</a>
+ class that counts the sum of the number.</div>
+</html>
\ No newline at end of file
diff --git a/learning/katas/java/Core Transforms/Combine/Combine PerKey/test/TaskTest.java b/learning/katas/java/Core Transforms/Combine/Combine PerKey/test/TaskTest.java
new file mode 100644
index 0000000..ff5df4d
--- /dev/null
+++ b/learning/katas/java/Core Transforms/Combine/Combine PerKey/test/TaskTest.java
@@ -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.
+ */
+
+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.apache.beam.sdk.values.PCollection;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class TaskTest {
+
+ @Rule
+ public TestPipeline testPipeline = TestPipeline.create();
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void combine_combineFn() {
+ Create.Values<KV<String, Integer>> 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)
+ );
+ PCollection<KV<String, Integer>> numbers = testPipeline.apply(values);
+
+ PCollection<KV<String, Integer>> results = Task.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/java/Core Transforms/Combine/CombineFn/src/Task.java b/learning/katas/java/Core Transforms/Combine/CombineFn/src/Task.java
new file mode 100644
index 0000000..fa2d226
--- /dev/null
+++ b/learning/katas/java/Core Transforms/Combine/CombineFn/src/Task.java
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ */
+
+import java.io.Serializable;
+import java.util.Objects;
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.options.PipelineOptions;
+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 util.Log;
+
+class Task {
+
+ public static void main(String[] args) {
+ PipelineOptions options = PipelineOptionsFactory.fromArgs(args).create();
+ Pipeline pipeline = Pipeline.create(options);
+
+ PCollection<Integer> numbers = pipeline.apply(Create.of(10, 20, 50, 70, 90));
+
+ PCollection<Double> output = applyTransform(numbers);
+
+ output.apply(Log.ofElements());
+
+ pipeline.run();
+ }
+
+ static PCollection<Double> applyTransform(PCollection<Integer> input) {
+ return input.apply(Combine.globally(new AverageFn()));
+ }
+
+ static class AverageFn extends CombineFn<Integer, AverageFn.Accum, Double> {
+
+ class Accum implements Serializable {
+ int sum = 0;
+ int count = 0;
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Accum accum = (Accum) o;
+ return sum == accum.sum &&
+ count == accum.count;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(sum, count);
+ }
+ }
+
+ @Override
+ public Accum createAccumulator() {
+ return new Accum();
+ }
+
+ @Override
+ public Accum addInput(Accum accumulator, Integer input) {
+ accumulator.sum += input;
+ accumulator.count++;
+
+ return accumulator;
+ }
+
+ @Override
+ public Accum mergeAccumulators(Iterable<Accum> accumulators) {
+ Accum merged = createAccumulator();
+
+ for (Accum accumulator : accumulators) {
+ merged.sum += accumulator.sum;
+ merged.count += accumulator.count;
+ }
+
+ return merged;
+ }
+
+ @Override
+ public Double extractOutput(Accum accumulator) {
+ return ((double) accumulator.sum) / accumulator.count;
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/learning/katas/java/Core Transforms/Combine/CombineFn/task.html b/learning/katas/java/Core Transforms/Combine/CombineFn/task.html
new file mode 100644
index 0000000..2a31de3
--- /dev/null
+++ b/learning/katas/java/Core Transforms/Combine/CombineFn/task.html
@@ -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.
+ -->
+
+<html>
+<h2>Combine - CombineFn</h2>
+<p>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.</p>
+<p>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.</p>
+<p>In this task, we are going to implement the average of numbers using
+ <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/Combine.CombineFn.html">
+ Combine.CombineFn</a>.
+</p>
+<br>
+<br>
+<div class='hint'>Extend the
+ <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/Combine.CombineFn.html">Combine.CombineFn</a>
+ class that counts the average of the number.</div>
+</html>
\ No newline at end of file
diff --git a/learning/katas/java/Core Transforms/Combine/CombineFn/test/TaskTest.java b/learning/katas/java/Core Transforms/Combine/CombineFn/test/TaskTest.java
new file mode 100644
index 0000000..a6631e4
--- /dev/null
+++ b/learning/katas/java/Core Transforms/Combine/CombineFn/test/TaskTest.java
@@ -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.
+ */
+
+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.PCollection;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class TaskTest {
+
+ @Rule
+ public TestPipeline testPipeline = TestPipeline.create();
+
+ @Test
+ public void combine_combineFn() {
+ Create.Values<Integer> values = Create.of(10, 20, 50, 70, 90);
+ PCollection<Integer> numbers = testPipeline.apply(values);
+
+ PCollection<Double> results = Task.applyTransform(numbers);
+
+ PAssert.that(results)
+ .containsInAnyOrder(48.0);
+
+ testPipeline.run().waitUntilFinish();
+ }
+
+}
\ No newline at end of file
diff --git a/learning/katas/java/Core Transforms/Combine/Simple Function/src/Task.java b/learning/katas/java/Core Transforms/Combine/Simple Function/src/Task.java
new file mode 100644
index 0000000..5b4591f
--- /dev/null
+++ b/learning/katas/java/Core Transforms/Combine/Simple Function/src/Task.java
@@ -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.
+ */
+
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.options.PipelineOptions;
+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;
+import util.Log;
+
+class Task {
+
+ public static void main(String[] args) {
+ PipelineOptions options = PipelineOptionsFactory.fromArgs(args).create();
+ Pipeline pipeline = Pipeline.create(options);
+
+ PCollection<Integer> numbers = pipeline.apply(Create.of(10, 30, 50, 70, 90));
+
+ PCollection<Integer> output = applyTransform(numbers);
+
+ output.apply(Log.ofElements());
+
+ pipeline.run();
+ }
+
+ static PCollection<Integer> applyTransform(PCollection<Integer> input) {
+ return input.apply(Combine.globally(new SumIntegerFn()));
+ }
+
+ static class SumIntegerFn implements SerializableFunction<Iterable<Integer>, Integer> {
+
+ @Override
+ public Integer apply(Iterable<Integer> input) {
+ int sum = 0;
+
+ for (int item : input) {
+ sum += item;
+ }
+
+ return sum;
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/learning/katas/java/Core Transforms/Combine/Simple Function/task.html b/learning/katas/java/Core Transforms/Combine/Simple Function/task.html
new file mode 100644
index 0000000..0006a87
--- /dev/null
+++ b/learning/katas/java/Core Transforms/Combine/Simple Function/task.html
@@ -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.
+ -->
+
+<html>
+<h2>Combine - Simple Function</h2>
+<p>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.</p>
+<p>Simple combine operations, such as sums, can usually be implemented as a simple function.</p>
+<p>In this task, we are going to implement the summation of numbers using
+ <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/SerializableFunction.html">
+ Combine.globally(SerializableFunction)</a>.
+</p>
+<br>
+<br>
+<div class='hint'>Implement the
+ <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/SerializableFunction.html#apply-InputT-">SerializableFunction.apply</a>
+ method that performs the summation of the Iterable.</div>
+</html>
\ No newline at end of file
diff --git a/learning/katas/java/Core Transforms/Combine/Simple Function/test/TaskTest.java b/learning/katas/java/Core Transforms/Combine/Simple Function/test/TaskTest.java
new file mode 100644
index 0000000..85cfcae
--- /dev/null
+++ b/learning/katas/java/Core Transforms/Combine/Simple Function/test/TaskTest.java
@@ -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.
+ */
+
+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.PCollection;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class TaskTest {
+
+ @Rule
+ public TestPipeline testPipeline = TestPipeline.create();
+
+ @Test
+ public void combine_simpleFn() {
+ Create.Values<Integer> values = Create.of(10, 30, 50, 70, 90);
+ PCollection<Integer> numbers = testPipeline.apply(values);
+
+ PCollection<Integer> results = Task.applyTransform(numbers);
+
+ PAssert.that(results)
+ .containsInAnyOrder(250);
+
+ testPipeline.run().waitUntilFinish();
+ }
+
+}
\ No newline at end of file
diff --git a/learning/katas/java/Core Transforms/Flatten/Flatten/src/Task.java b/learning/katas/java/Core Transforms/Flatten/Flatten/src/Task.java
new file mode 100644
index 0000000..1d36f22
--- /dev/null
+++ b/learning/katas/java/Core Transforms/Flatten/Flatten/src/Task.java
@@ -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.
+ */
+
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.options.PipelineOptions;
+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;
+import util.Log;
+
+class Task {
+
+ public static void main(String[] args) {
+ PipelineOptions options = PipelineOptionsFactory.fromArgs(args).create();
+ Pipeline pipeline = Pipeline.create(options);
+
+ PCollection<String> wordsStartingWithA =
+ pipeline.apply("Words starting with A",
+ Create.of("apple", "ant", "arrow")
+ );
+
+ PCollection<String> wordsStartingWithB =
+ pipeline.apply("Words starting with B",
+ Create.of("ball", "book", "bow")
+ );
+
+ PCollection<String> output = applyTransform(wordsStartingWithA, wordsStartingWithB);
+
+ output.apply(Log.ofElements());
+
+ pipeline.run();
+ }
+
+ static PCollection<String> applyTransform(
+ PCollection<String> words1, PCollection<String> words2) {
+
+ return PCollectionList.of(words1).and(words2)
+ .apply(Flatten.pCollections());
+ }
+
+}
\ No newline at end of file
diff --git a/learning/katas/java/Core Transforms/Flatten/Flatten/task.html b/learning/katas/java/Core Transforms/Flatten/Flatten/task.html
new file mode 100644
index 0000000..3bef763
--- /dev/null
+++ b/learning/katas/java/Core Transforms/Flatten/Flatten/task.html
@@ -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.
+ -->
+
+<html>
+<h2>Flatten</h2>
+<p>Flatten is a Beam transform for PCollection objects that store the same data type.
+ Flatten merges multiple PCollection objects into a single logical PCollection.</p>
+<p>In this task, we are going to implement a
+ <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/Flatten.html">
+ Flatten</a> transform that merges two PCollection of words into a single PCollection.
+</p>
+<br>
+<br>
+<div class='hint'>Refer to
+ <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/Flatten.html">Flatten</a>
+ to solve this problem.</div>
+</html>
\ No newline at end of file
diff --git a/learning/katas/java/Core Transforms/Flatten/Flatten/test/TaskTest.java b/learning/katas/java/Core Transforms/Flatten/Flatten/test/TaskTest.java
new file mode 100644
index 0000000..d6df982
--- /dev/null
+++ b/learning/katas/java/Core Transforms/Flatten/Flatten/test/TaskTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+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.PCollection;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class TaskTest {
+
+ @Rule
+ public TestPipeline testPipeline = TestPipeline.create();
+
+ @Test
+ public void flatten() {
+ PCollection<String> wordsStartingWithA =
+ testPipeline.apply("Words starting with A",
+ Create.of("apple", "ant", "arrow"));
+ PCollection<String> wordsStartingWithB =
+ testPipeline.apply("Words starting with B",
+ Create.of("ball", "book", "bow"));
+
+ PCollection<String> results = Task.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/java/Core Transforms/GroupByKey/GroupByKey/src/Task.java b/learning/katas/java/Core Transforms/GroupByKey/GroupByKey/src/Task.java
new file mode 100644
index 0000000..548fd1c
--- /dev/null
+++ b/learning/katas/java/Core Transforms/GroupByKey/GroupByKey/src/Task.java
@@ -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.
+ */
+
+import static org.apache.beam.sdk.values.TypeDescriptors.kvs;
+import static org.apache.beam.sdk.values.TypeDescriptors.strings;
+
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.options.PipelineOptions;
+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.values.KV;
+import org.apache.beam.sdk.values.PCollection;
+import util.Log;
+
+class Task {
+
+ public static void main(String[] args) {
+ PipelineOptions options = PipelineOptionsFactory.fromArgs(args).create();
+ Pipeline pipeline = Pipeline.create(options);
+
+ PCollection<String> words =
+ pipeline.apply(
+ Create.of("apple", "ball", "car", "bear", "cheetah", "ant")
+ );
+
+ PCollection<KV<String, Iterable<String>>> output = applyTransform(words);
+
+ output.apply(Log.ofElements());
+
+ pipeline.run();
+ }
+
+ static PCollection<KV<String, Iterable<String>>> applyTransform(PCollection<String> input) {
+ return input
+ .apply(MapElements.into(kvs(strings(), strings()))
+ .via(word -> KV.of(word.substring(0, 1), word)))
+
+ .apply(GroupByKey.create());
+ }
+
+}
\ No newline at end of file
diff --git a/learning/katas/java/Core Transforms/GroupByKey/GroupByKey/task.html b/learning/katas/java/Core Transforms/GroupByKey/GroupByKey/task.html
new file mode 100644
index 0000000..05469eb
--- /dev/null
+++ b/learning/katas/java/Core Transforms/GroupByKey/GroupByKey/task.html
@@ -0,0 +1,35 @@
+<!--
+ ~ 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.
+ -->
+
+<html>
+<h2>GroupByKey</h2>
+<p>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.</p>
+<p>In this task, we are going to implement a
+ <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/GroupByKey.html">
+ GroupByKey</a> transform that groups words by its first letter.
+</p>
+<br>
+<br>
+<div class='hint'>Refer to <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/values/KV.html">KV</a>
+ and <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/GroupByKey.html">GroupByKey</a>
+ to solve this problem.</div>
+</html>
\ No newline at end of file
diff --git a/learning/katas/java/Core Transforms/GroupByKey/GroupByKey/test/TaskTest.java b/learning/katas/java/Core Transforms/GroupByKey/GroupByKey/test/TaskTest.java
new file mode 100644
index 0000000..15cf69e
--- /dev/null
+++ b/learning/katas/java/Core Transforms/GroupByKey/GroupByKey/test/TaskTest.java
@@ -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.
+ */
+
+import static test.util.ContainsKvs.containsKvs;
+
+import com.google.common.collect.ImmutableList;
+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.apache.beam.sdk.values.PCollection;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class TaskTest {
+
+ @Rule
+ public TestPipeline testPipeline = TestPipeline.create();
+
+ @Test
+ public void groupByKey() {
+ Create.Values<String> values = Create.of("apple", "ball", "car", "bear", "cheetah", "ant");
+ PCollection<String> numbers = testPipeline.apply(values);
+
+ PCollection<KV<String, Iterable<String>>> results = Task.applyTransform(numbers);
+
+ PAssert.that(results)
+ .satisfies(
+ 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/java/Core Transforms/Map/FlatMapElements/src/Task.java b/learning/katas/java/Core Transforms/Map/FlatMapElements/src/Task.java
new file mode 100644
index 0000000..cf442d8
--- /dev/null
+++ b/learning/katas/java/Core Transforms/Map/FlatMapElements/src/Task.java
@@ -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.
+ */
+
+import java.util.Arrays;
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.options.PipelineOptions;
+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.values.PCollection;
+import org.apache.beam.sdk.values.TypeDescriptors;
+import util.Log;
+
+class Task {
+
+ public static void main(String[] args) {
+ PipelineOptions options = PipelineOptionsFactory.fromArgs(args).create();
+ Pipeline pipeline = Pipeline.create(options);
+
+ PCollection<String> sentences =
+ pipeline.apply(Create.of("Apache Beam", "Unified Batch and Streaming"));
+
+ PCollection<String> output = applyTransform(sentences);
+
+ output.apply(Log.ofElements());
+
+ pipeline.run();
+ }
+
+ static PCollection<String> applyTransform(PCollection<String> input) {
+ return input.apply(
+ FlatMapElements.into(TypeDescriptors.strings())
+ .via(sentence -> Arrays.asList(sentence.split(" ")))
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/learning/katas/java/Core Transforms/Map/FlatMapElements/task.html b/learning/katas/java/Core Transforms/Map/FlatMapElements/task.html
new file mode 100644
index 0000000..1572a8e
--- /dev/null
+++ b/learning/katas/java/Core Transforms/Map/FlatMapElements/task.html
@@ -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.
+ -->
+
+<html>
+<h2>FlatMapElements</h2>
+<p>The Beam SDKs provide language-specific ways to simplify how you provide your DoFn implementation.</p>
+<p>FlatMapElements can be used to simplify DoFn that maps an element to multiple elements (one to many).</p>
+<p>In this task, we are going to implement a function that maps each input sentence into words tokenized by whitespace (" ") using
+ <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/FlatMapElements.html">
+ FlatMapElements.into(...).via(...)</a>.
+</p>
+<br>
+<br>
+<div class='hint'>Use
+ <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/FlatMapElements.html">FlatMapElements.into(...).via(...)</a>
+</div>
+</html>
\ No newline at end of file
diff --git a/learning/katas/java/Core Transforms/Map/FlatMapElements/test/TaskTest.java b/learning/katas/java/Core Transforms/Map/FlatMapElements/test/TaskTest.java
new file mode 100644
index 0000000..db5de38
--- /dev/null
+++ b/learning/katas/java/Core Transforms/Map/FlatMapElements/test/TaskTest.java
@@ -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.
+ */
+
+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.PCollection;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class TaskTest {
+
+ @Rule
+ public TestPipeline testPipeline = TestPipeline.create();
+
+ @Test
+ public void flatMapElements() {
+ Create.Values<String> values = Create.of("Apache Beam", "Unified Batch and Streaming");
+ PCollection<String> numbers = testPipeline.apply(values);
+
+ PCollection<String> results = Task.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/java/Core Transforms/Map/MapElements/src/Task.java b/learning/katas/java/Core Transforms/Map/MapElements/src/Task.java
new file mode 100644
index 0000000..4a1b49c
--- /dev/null
+++ b/learning/katas/java/Core Transforms/Map/MapElements/src/Task.java
@@ -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.
+ */
+
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.options.PipelineOptions;
+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.values.PCollection;
+import org.apache.beam.sdk.values.TypeDescriptors;
+import util.Log;
+
+class Task {
+
+ public static void main(String[] args) {
+ PipelineOptions options = PipelineOptionsFactory.fromArgs(args).create();
+ Pipeline pipeline = Pipeline.create(options);
+
+ PCollection<Integer> numbers =
+ pipeline.apply(Create.of(10, 20, 30, 40, 50));
+
+ PCollection<Integer> output = applyTransform(numbers);
+
+ output.apply(Log.ofElements());
+
+ pipeline.run();
+ }
+
+ static PCollection<Integer> applyTransform(PCollection<Integer> input) {
+ return input.apply(
+ MapElements.into(TypeDescriptors.integers())
+ .via(number -> number * 5)
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/learning/katas/java/Core Transforms/Map/MapElements/task.html b/learning/katas/java/Core Transforms/Map/MapElements/task.html
new file mode 100644
index 0000000..8fbfa97
--- /dev/null
+++ b/learning/katas/java/Core Transforms/Map/MapElements/task.html
@@ -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.
+ -->
+
+<html>
+<h2>MapElements</h2>
+<p>The Beam SDKs provide language-specific ways to simplify how you provide your DoFn implementation.</p>
+<p>MapElements can be used to simplify DoFn that maps an element to another element (one to one).</p>
+<p>In this task, we are going to implement a simple map function that multiplies all input elements by 5 using
+ <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/MapElements.html">
+ MapElements.into(...).via(...)</a>.
+</p>
+<br>
+<br>
+<div class='hint'>Use <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/MapElements.html">MapElements.into(...).via(...)</a></div>
+</html>
\ No newline at end of file
diff --git a/learning/katas/java/Core Transforms/Map/MapElements/test/TaskTest.java b/learning/katas/java/Core Transforms/Map/MapElements/test/TaskTest.java
new file mode 100644
index 0000000..9d713a7
--- /dev/null
+++ b/learning/katas/java/Core Transforms/Map/MapElements/test/TaskTest.java
@@ -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.
+ */
+
+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.PCollection;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class TaskTest {
+
+ @Rule
+ public TestPipeline testPipeline = TestPipeline.create();
+
+ @Test
+ public void mapElements() {
+ Create.Values<Integer> values = Create.of(10, 20, 30, 40, 50);
+ PCollection<Integer> numbers = testPipeline.apply(values);
+
+ PCollection<Integer> results = Task.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/java/Core Transforms/Map/ParDo OneToMany/src/Task.java b/learning/katas/java/Core Transforms/Map/ParDo OneToMany/src/Task.java
new file mode 100644
index 0000000..9e52ca6
--- /dev/null
+++ b/learning/katas/java/Core Transforms/Map/ParDo OneToMany/src/Task.java
@@ -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.
+ */
+
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.options.PipelineOptions;
+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 util.Log;
+
+class Task {
+
+ public static void main(String[] args) {
+ PipelineOptions options = PipelineOptionsFactory.fromArgs(args).create();
+ Pipeline pipeline = Pipeline.create(options);
+
+ PCollection<String> sentences =
+ pipeline.apply(Create.of("Hello Beam", "It is awesome"));
+
+ PCollection<String> output = applyTransform(sentences);
+
+ output.apply(Log.ofElements());
+
+ pipeline.run();
+ }
+
+ static PCollection<String> applyTransform(PCollection<String> input) {
+ return input.apply(ParDo.of(new DoFn<String, String>() {
+
+ @ProcessElement
+ public void processElement(@Element String sentence, OutputReceiver<String> out) {
+ String[] words = sentence.split(" ");
+
+ for (String word : words) {
+ out.output(word);
+ }
+ }
+
+ }));
+ }
+
+}
\ No newline at end of file
diff --git a/learning/katas/java/Core Transforms/Map/ParDo OneToMany/task.html b/learning/katas/java/Core Transforms/Map/ParDo OneToMany/task.html
new file mode 100644
index 0000000..02167e0
--- /dev/null
+++ b/learning/katas/java/Core Transforms/Map/ParDo OneToMany/task.html
@@ -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.
+ -->
+
+<html>
+<h2>ParDo OneToMany</h2>
+<p>For this task, please write a ParDo that maps each input sentence into words tokenized by whitespace (" ").</p>
+<br>
+<br>
+<div class='hint'>Hint: You can call DoFn.ProcessContext.output(..) multiple times in a
+ <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/ParDo.html">ParDo</a>.
+</div>
+</html>
\ No newline at end of file
diff --git a/learning/katas/java/Core Transforms/Map/ParDo OneToMany/test/TaskTest.java b/learning/katas/java/Core Transforms/Map/ParDo OneToMany/test/TaskTest.java
new file mode 100644
index 0000000..eecf2da
--- /dev/null
+++ b/learning/katas/java/Core Transforms/Map/ParDo OneToMany/test/TaskTest.java
@@ -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.
+ */
+
+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.PCollection;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class TaskTest {
+
+ @Rule
+ public TestPipeline testPipeline = TestPipeline.create();
+
+ @Test
+ public void parDo_oneToMany() {
+ Create.Values<String> values = Create.of("Hello Beam", "It is awesome");
+ PCollection<String> numbers = testPipeline.apply(values);
+
+ PCollection<String> results = Task.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/java/Core Transforms/Map/ParDo/src/Task.java b/learning/katas/java/Core Transforms/Map/ParDo/src/Task.java
new file mode 100644
index 0000000..ad9a039
--- /dev/null
+++ b/learning/katas/java/Core Transforms/Map/ParDo/src/Task.java
@@ -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.
+ */
+
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.options.PipelineOptions;
+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 util.Log;
+
+class Task {
+
+ public static void main(String[] args) {
+ PipelineOptions options = PipelineOptionsFactory.fromArgs(args).create();
+ Pipeline pipeline = Pipeline.create(options);
+
+ PCollection<Integer> numbers =
+ pipeline.apply(Create.of(1, 2, 3, 4, 5));
+
+ PCollection<Integer> output = applyTransform(numbers);
+
+ output.apply(Log.ofElements());
+
+ pipeline.run();
+ }
+
+ static PCollection<Integer> applyTransform(PCollection<Integer> input) {
+ return input.apply(ParDo.of(new DoFn<Integer, Integer>() {
+
+ @ProcessElement
+ public void processElement(@Element Integer number, OutputReceiver<Integer> out) {
+ out.output(number * 10);
+ }
+
+ }));
+ }
+
+}
\ No newline at end of file
diff --git a/learning/katas/java/Core Transforms/Map/ParDo/task.html b/learning/katas/java/Core Transforms/Map/ParDo/task.html
new file mode 100644
index 0000000..06673dd
--- /dev/null
+++ b/learning/katas/java/Core Transforms/Map/ParDo/task.html
@@ -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.
+ -->
+
+<html>
+<h2>ParDo</h2>
+<p>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.</p>
+<p>For this task, please write a simple ParDo that maps the input element by multiplying it by 10.</p>
+<br>
+<br>
+<div class='hint'>Use <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/ParDo.html">ParDo</a>
+ with <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/DoFn.html">DoFn</a></div>
+</html>
\ No newline at end of file
diff --git a/learning/katas/java/Core Transforms/Map/ParDo/test/TaskTest.java b/learning/katas/java/Core Transforms/Map/ParDo/test/TaskTest.java
new file mode 100644
index 0000000..d9b44bd
--- /dev/null
+++ b/learning/katas/java/Core Transforms/Map/ParDo/test/TaskTest.java
@@ -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.
+ */
+
+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.PCollection;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class TaskTest {
+
+ @Rule
+ public TestPipeline testPipeline = TestPipeline.create();
+
+ @Test
+ public void parDo() {
+ Create.Values<Integer> values = Create.of(1, 2, 3, 4, 5);
+ PCollection<Integer> numbers = testPipeline.apply(values);
+
+ PCollection<Integer> results = Task.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/java/Core Transforms/Partition/Partition/src/Task.java b/learning/katas/java/Core Transforms/Partition/Partition/src/Task.java
new file mode 100644
index 0000000..339f30d
--- /dev/null
+++ b/learning/katas/java/Core Transforms/Partition/Partition/src/Task.java
@@ -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.
+ */
+
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.options.PipelineOptions;
+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.transforms.Partition.PartitionFn;
+import org.apache.beam.sdk.values.PCollection;
+import org.apache.beam.sdk.values.PCollectionList;
+import util.Log;
+
+class Task {
+
+ public static void main(String[] args) {
+ PipelineOptions options = PipelineOptionsFactory.fromArgs(args).create();
+ Pipeline pipeline = Pipeline.create(options);
+
+ PCollection<Integer> numbers =
+ pipeline.apply(
+ Create.of(1, 2, 3, 4, 5, 100, 110, 150, 250)
+ );
+
+ PCollectionList<Integer> partition = applyTransform(numbers);
+
+ partition.get(0).apply(Log.ofElements("Number > 100: "));
+ partition.get(1).apply(Log.ofElements("Number <= 100: "));
+
+ pipeline.run();
+ }
+
+ static PCollectionList<Integer> applyTransform(PCollection<Integer> input) {
+ return input
+ .apply(Partition.of(2,
+ (PartitionFn<Integer>) (number, numPartitions) -> {
+ if (number > 100) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }));
+ }
+
+}
\ No newline at end of file
diff --git a/learning/katas/java/Core Transforms/Partition/Partition/task.html b/learning/katas/java/Core Transforms/Partition/Partition/task.html
new file mode 100644
index 0000000..18d7bce
--- /dev/null
+++ b/learning/katas/java/Core Transforms/Partition/Partition/task.html
@@ -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.
+ -->
+
+<html>
+<h2>Partition</h2>
+<p>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.</p>
+<p>In this task, we are going to implement a
+ <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/Partition.html">
+ Partition</a> 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.
+</p>
+<br>
+<br>
+<div class='hint'>Refer to
+ <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/Partition.html">Partition</a>
+ to solve this problem.
+</div>
+</html>
\ No newline at end of file
diff --git a/learning/katas/java/Core Transforms/Partition/Partition/test/TaskTest.java b/learning/katas/java/Core Transforms/Partition/Partition/test/TaskTest.java
new file mode 100644
index 0000000..cf38042
--- /dev/null
+++ b/learning/katas/java/Core Transforms/Partition/Partition/test/TaskTest.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+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.PCollection;
+import org.apache.beam.sdk.values.PCollectionList;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class TaskTest {
+
+ @Rule
+ public TestPipeline testPipeline = TestPipeline.create();
+
+ @Test
+ public void groupByKey() {
+ PCollection<Integer> numbers =
+ testPipeline.apply(
+ Create.of(1, 2, 3, 4, 5, 100, 110, 150, 250)
+ );
+
+ PCollectionList<Integer> results = Task.applyTransform(numbers);
+
+ PAssert.that(results.get(0))
+ .containsInAnyOrder(110, 150, 250);
+
+ PAssert.that(results.get(1))
+ .containsInAnyOrder(1, 2, 3, 4, 5, 100);
+
+ testPipeline.run().waitUntilFinish();
+ }
+
+}
\ No newline at end of file
diff --git a/learning/katas/java/Examples/Word Count/Word Count/src/Task.java b/learning/katas/java/Examples/Word Count/Word Count/src/Task.java
new file mode 100644
index 0000000..fcfbdf4
--- /dev/null
+++ b/learning/katas/java/Examples/Word Count/Word Count/src/Task.java
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+import java.util.Arrays;
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.options.PipelineOptions;
+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.DoFn;
+import org.apache.beam.sdk.transforms.FlatMapElements;
+import org.apache.beam.sdk.transforms.ParDo;
+import org.apache.beam.sdk.values.KV;
+import org.apache.beam.sdk.values.PCollection;
+import org.apache.beam.sdk.values.TypeDescriptors;
+import util.Log;
+
+class Task {
+
+ public static void main(String[] args) {
+ String[] lines = {
+ "apple orange grape banana apple banana",
+ "banana orange banana papaya"
+ };
+
+ PipelineOptions options = PipelineOptionsFactory.fromArgs(args).create();
+ Pipeline pipeline = Pipeline.create(options);
+
+ PCollection<String> wordCounts =
+ pipeline.apply(Create.of(Arrays.asList(lines)));
+
+ PCollection<String> output = applyTransform(wordCounts);
+
+ output.apply(Log.ofElements());
+
+ pipeline.run();
+ }
+
+ static PCollection<String> applyTransform(PCollection<String> input) {
+ return input
+
+ .apply(FlatMapElements.into(TypeDescriptors.strings())
+ .via(line -> Arrays.asList(line.split(" "))))
+
+ .apply(Count.perElement())
+
+ .apply(ParDo.of(new DoFn<KV<String, Long>, String>() {
+
+ @ProcessElement
+ public void processElement(
+ @Element KV<String, Long> element, OutputReceiver<String> out) {
+
+ out.output(element.getKey() + ":" + element.getValue());
+ }
+
+ }));
+ }
+
+}
\ No newline at end of file
diff --git a/learning/katas/java/Examples/Word Count/Word Count/task.html b/learning/katas/java/Examples/Word Count/Word Count/task.html
new file mode 100644
index 0000000..6ba9d1b
--- /dev/null
+++ b/learning/katas/java/Examples/Word Count/Word Count/task.html
@@ -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.
+ -->
+
+<html>
+<h2>Word Count Pipeline</h2>
+<p>This kata is to create a pipeline that counts the number of words.</p>
+<p>For this task, please output the count of each word in the following format:<br/>
+ <pre>
+ word:count
+ ball:5
+ book:3
+ </pre>
+</p>
+<br>
+<br>
+<div class='hint'>Refer to your lessons above.</div>
+</html>
\ No newline at end of file
diff --git a/learning/katas/java/Examples/Word Count/Word Count/test/TaskTest.java b/learning/katas/java/Examples/Word Count/Word Count/test/TaskTest.java
new file mode 100644
index 0000000..06c057c
--- /dev/null
+++ b/learning/katas/java/Examples/Word Count/Word Count/test/TaskTest.java
@@ -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.
+ */
+
+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.PCollection;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class TaskTest {
+
+ @Rule
+ public TestPipeline testPipeline = TestPipeline.create();
+
+ @Test
+ public void parDo() {
+ Create.Values<String> lines =
+ Create.of(
+ "apple orange grape banana apple banana",
+ "banana orange banana papaya");
+
+ PCollection<String> linesPColl = testPipeline.apply(lines);
+
+ PCollection<String> results = Task.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/java/Introduction/Hello Beam/Hello Beam/src/Task.java b/learning/katas/java/Introduction/Hello Beam/Hello Beam/src/Task.java
new file mode 100644
index 0000000..bed1a67
--- /dev/null
+++ b/learning/katas/java/Introduction/Hello Beam/Hello Beam/src/Task.java
@@ -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.
+ */
+
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.options.PipelineOptions;
+import org.apache.beam.sdk.options.PipelineOptionsFactory;
+import org.apache.beam.sdk.transforms.Create;
+import org.apache.beam.sdk.values.PCollection;
+import util.Log;
+
+class Task {
+
+ public static void main(String[] args) {
+ PipelineOptions options = PipelineOptionsFactory.fromArgs(args).create();
+ Pipeline pipeline = Pipeline.create(options);
+
+ PCollection<String> output = setupPipeline(pipeline);
+
+ output.apply(Log.ofElements());
+
+ pipeline.run();
+ }
+
+ static PCollection<String> setupPipeline(Pipeline pipeline) {
+ return pipeline.apply(Create.of("Hello Beam"));
+ }
+
+}
\ No newline at end of file
diff --git a/learning/katas/java/Introduction/Hello Beam/Hello Beam/task.html b/learning/katas/java/Introduction/Hello Beam/Hello Beam/task.html
new file mode 100644
index 0000000..5d6928b
--- /dev/null
+++ b/learning/katas/java/Introduction/Hello Beam/Hello Beam/task.html
@@ -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.
+ -->
+
+<html>
+<h2>Hello Beam Pipeline</h2>
+<p>This kata is to create a simple pipeline that takes a hardcoded input element "Hello Beam"</p>
+<br>
+<br>
+<div class='hint'>Hardcoded input can be created using
+ <a href="https://beam.apache.org/releases/javadoc/2.11.0/org/apache/beam/sdk/transforms/Create.html">Create</a>
+</div>
+</html>
\ No newline at end of file
diff --git a/learning/katas/java/Introduction/Hello Beam/Hello Beam/test/TaskTest.java b/learning/katas/java/Introduction/Hello Beam/Hello Beam/test/TaskTest.java
new file mode 100644
index 0000000..6dd0e0b
--- /dev/null
+++ b/learning/katas/java/Introduction/Hello Beam/Hello Beam/test/TaskTest.java
@@ -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.
+ */
+
+import java.io.Serializable;
+import org.apache.beam.sdk.testing.PAssert;
+import org.apache.beam.sdk.testing.TestPipeline;
+import org.apache.beam.sdk.values.PCollection;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class TaskTest implements Serializable {
+
+ @Rule
+ public final transient TestPipeline testPipeline = TestPipeline.create();
+
+ @Test
+ public void helloWorld() {
+ PCollection<String> results = Task.setupPipeline(testPipeline);
+
+ PAssert.that(results)
+ .containsInAnyOrder("Hello Beam");
+
+ testPipeline.run().waitUntilFinish();
+ }
+
+}
\ No newline at end of file
diff --git a/learning/katas/java/build.gradle b/learning/katas/java/build.gradle
new file mode 100644
index 0000000..35ccb2f
--- /dev/null
+++ b/learning/katas/java/build.gradle
@@ -0,0 +1,116 @@
+/*
+ * 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.11.0'
+ guavaVersion = '27.0-jre'
+ jodaTimeVersion = '2.10.1'
+ slf4jVersion = '1.7.25'
+
+ assertjVersion = '3.11.1'
+ hamcrestVersion = '1.3'
+ junitVersion = '4.12'
+ }
+
+ repositories {
+ mavenCentral()
+ }
+}
+
+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'
+
+ sourceCompatibility = 1.8
+
+ repositories {
+ mavenCentral()
+ }
+
+ dependencies {
+ compile "org.apache.beam:beam-sdks-java-core:$beamVersion"
+ runtime "org.apache.beam:beam-runners-direct-java:$beamVersion"
+
+ compile "joda-time:joda-time:$jodaTimeVersion"
+ compile "org.slf4j:slf4j-api:$slf4jVersion"
+ compile "org.slf4j:slf4j-jdk14:$slf4jVersion"
+ 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"
+ }
+
+ sourceSets {
+ main {
+ java.srcDir 'src'
+ }
+ 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
+ }
+}
+
+task wrapper(type: Wrapper) {
+ gradleVersion = '4.8'
+}
diff --git a/learning/katas/java/gradle/wrapper/gradle-wrapper.jar b/learning/katas/java/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..1948b90
Binary files /dev/null and b/learning/katas/java/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/learning/katas/java/gradle/wrapper/gradle-wrapper.properties b/learning/katas/java/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..afd2df2
--- /dev/null
+++ b/learning/katas/java/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
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.8-all.zip
diff --git a/learning/katas/java/gradlew b/learning/katas/java/gradlew
new file mode 100755
index 0000000..9e22af6
--- /dev/null
+++ b/learning/katas/java/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/java/gradlew.bat b/learning/katas/java/gradlew.bat
new file mode 100644
index 0000000..582415f
--- /dev/null
+++ b/learning/katas/java/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
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/learning/katas/java/settings.gradle b/learning/katas/java/settings.gradle
new file mode 100644
index 0000000..6100c4e
--- /dev/null
+++ b/learning/katas/java/settings.gradle
@@ -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.
+ */
+
+static String sanitizeName(String name) {
+ return name.replaceAll("[ /\\\\:<>\"?*|]", "_")
+}
+
+rootProject.name = sanitizeName('Beam Kata')
+
+rootProject.projectDir.eachDirRecurse {
+ if (!isTaskDir(it) || it.path.contains(".idea")) {
+ return
+ }
+ def taskRelativePath = rootDir.toPath().relativize(it.toPath())
+ def parts = []
+ for (name in taskRelativePath) {
+ parts.add(sanitizeName(name.toString()))
+ }
+ def moduleName = parts.join("-")
+ include "$moduleName"
+ project(":$moduleName").projectDir = it
+}
+
+def isTaskDir(File dir) {
+ return new File(dir, "src").exists()
+}
+
+include 'util'
\ No newline at end of file
diff --git a/learning/katas/java/util/src/util/Log.java b/learning/katas/java/util/src/util/Log.java
new file mode 100644
index 0000000..69624af
--- /dev/null
+++ b/learning/katas/java/util/src/util/Log.java
@@ -0,0 +1,71 @@
+/*
+ * 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 util;
+
+import org.apache.beam.sdk.transforms.DoFn;
+import org.apache.beam.sdk.transforms.PTransform;
+import org.apache.beam.sdk.transforms.ParDo;
+import org.apache.beam.sdk.values.PCollection;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Log {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(Log.class);
+
+ private Log() {
+ }
+
+ public static <T> PTransform<PCollection<T>, PCollection<T>> ofElements() {
+ return new LoggingTransform<>();
+ }
+
+ public static <T> PTransform<PCollection<T>, PCollection<T>> ofElements(String prefix) {
+ return new LoggingTransform<>(prefix);
+ }
+
+ private static class LoggingTransform<T> extends PTransform<PCollection<T>, PCollection<T>> {
+
+ private String prefix;
+
+ private LoggingTransform() {
+ prefix = "";
+ }
+
+ private LoggingTransform(String prefix) {
+ this.prefix = prefix;
+ }
+
+ @Override
+ public PCollection<T> expand(PCollection<T> input) {
+ return input.apply(ParDo.of(new DoFn<T, T>() {
+
+ @ProcessElement
+ public void processElement(@Element T element, OutputReceiver<T> out) {
+ LOGGER.info(prefix + element.toString());
+
+ out.output(element);
+ }
+
+ }));
+ }
+
+ }
+
+}
diff --git a/learning/katas/java/util/test/test/util/ContainsKvs.java b/learning/katas/java/util/test/test/util/ContainsKvs.java
new file mode 100644
index 0000000..1540bf7
--- /dev/null
+++ b/learning/katas/java/util/test/test/util/ContainsKvs.java
@@ -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 test.util;
+
+import static com.google.common.collect.Iterables.toArray;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
+import static org.junit.Assert.assertThat;
+import static test.util.KvMatcher.isKv;
+
+import com.google.common.collect.ImmutableList;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.beam.sdk.transforms.SerializableFunction;
+import org.apache.beam.sdk.values.KV;
+import org.hamcrest.Matcher;
+
+public class ContainsKvs implements
+ SerializableFunction<Iterable<KV<String, Iterable<String>>>, Void> {
+
+ private final List<KV<String, Iterable<String>>> expectedKvs;
+
+ private ContainsKvs(List<KV<String, Iterable<String>>> expectedKvs) {
+ this.expectedKvs = expectedKvs;
+ }
+
+ @SafeVarargs
+ public static SerializableFunction<Iterable<KV<String, Iterable<String>>>, Void> containsKvs(
+ KV<String, Iterable<String>>... kvs) {
+ return new ContainsKvs(ImmutableList.copyOf(kvs));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Void apply(Iterable<KV<String, Iterable<String>>> input) {
+ List<Matcher<? super KV<String, Iterable<String>>>> matchers = new ArrayList<>();
+ for (KV<String, Iterable<String>> expected : expectedKvs) {
+ String[] values = toArray(expected.getValue(), String.class);
+ matchers.add(isKv(equalTo(expected.getKey()), containsInAnyOrder(values)));
+ }
+ assertThat(input, containsInAnyOrder(toArray(matchers, Matcher.class)));
+ return null;
+ }
+
+}
diff --git a/learning/katas/java/util/test/test/util/KvMatcher.java b/learning/katas/java/util/test/test/util/KvMatcher.java
new file mode 100644
index 0000000..ecbff08
--- /dev/null
+++ b/learning/katas/java/util/test/test/util/KvMatcher.java
@@ -0,0 +1,56 @@
+/*
+ * 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 test.util;
+
+import org.apache.beam.sdk.values.KV;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+
+public class KvMatcher<K, V> extends TypeSafeMatcher<KV<? extends K, ? extends V>> {
+
+ private final Matcher<? super K> keyMatcher;
+ private final Matcher<? super V> valueMatcher;
+
+ public KvMatcher(Matcher<? super K> keyMatcher,
+ Matcher<? super V> valueMatcher) {
+ this.keyMatcher = keyMatcher;
+ this.valueMatcher = valueMatcher;
+ }
+
+ public static <K, V> KvMatcher<K, V> isKv(Matcher<K> keyMatcher,
+ Matcher<V> valueMatcher) {
+ return new KvMatcher<>(keyMatcher, valueMatcher);
+ }
+
+ @Override
+ public boolean matchesSafely(KV<? extends K, ? extends V> kv) {
+ return keyMatcher.matches(kv.getKey())
+ && valueMatcher.matches(kv.getValue());
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description
+ .appendText("a KV(").appendValue(keyMatcher)
+ .appendText(", ").appendValue(valueMatcher)
+ .appendText(")");
+ }
+
+}
diff --git a/learning/katas/python/.idea/study_project.xml b/learning/katas/python/.idea/study_project.xml
new file mode 100644
index 0000000..d2ea075
--- /dev/null
+++ b/learning/katas/python/.idea/study_project.xml
@@ -0,0 +1,1723 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="StudySettings">
+ <StudyTaskManager>
+ <option name="VERSION" value="14" />
+ <option name="myUserTests">
+ <map />
+ </option>
+ <option name="course">
+ <EduCourse>
+ <option name="authors">
+ <list>
+ <StepikUserInfo>
+ <option name="firstName" value="Henry" />
+ <option name="id" value="48485817" />
+ <option name="lastName" value="Suryawirawan" />
+ </StepikUserInfo>
+ </list>
+ </option>
+ <option name="compatible" value="true" />
+ <option name="courseMode" value="Course Creator" />
+ <option name="createDate" value="1557824500323" />
+ <option name="customPresentableName" />
+ <option name="description" value="This course provides a series of kata to get familiar with Apache Beam. Apache Beam website – https://beam.apache.org/" />
+ <option name="environment" value="" />
+ <option name="fromZip" value="false" />
+ <option name="id" value="54532" />
+ <option name="index" value="-1" />
+ <option name="instructors">
+ <list>
+ <option value="48485817" />
+ </list>
+ </option>
+ <option name="language" value="Python 2.7" />
+ <option name="languageCode" value="en" />
+ <option name="name" value="Beam Kata - Python" />
+ <option name="public" value="false" />
+ <option name="sectionIds">
+ <list />
+ </option>
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="type" value="pycharm11 Python 2.7" />
+ <option name="updateDate" value="1557824500000" />
+ <option name="items">
+ <list>
+ <Section>
+ <option name="courseId" value="54532" />
+ <option name="customPresentableName" />
+ <option name="id" value="85644" />
+ <option name="index" value="1" />
+ <option name="name" value="Introduction" />
+ <option name="position" value="0" />
+ <option name="stepikChangeStatus" value="Content changed" />
+ <option name="updateDate" value="1557824504000" />
+ <option name="items">
+ <list>
+ <Lesson>
+ <option name="customPresentableName" />
+ <option name="id" value="229517" />
+ <option name="index" value="1" />
+ <option name="name" value="Hello Beam" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="updateDate" value="1557824508000" />
+ <option name="unitId" value="202042" />
+ <option name="items">
+ <list>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713750" />
+ <option name="index" value="1" />
+ <option name="name" value="Hello Beam" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="task.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="903" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="beam.Create(['Hello Beam'])" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="task.py" />
+ <option name="text" value="# TODO: type solution here " />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="tests.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="tests.py" />
+ <option name="text" value="from test_helper import run_common_tests, failed, passed, get_answer_placeholders def test_answer_placeholders(): placeholders = get_answer_placeholders() placeholder = placeholders[0] if placeholder == "": # TODO: your condition here passed() else: failed() if __name__ == '__main__': run_common_tests() # test [...]
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557824510000" />
+ </EduTask>
+ </list>
+ </option>
+ </Lesson>
+ </list>
+ </option>
+ </Section>
+ <Section>
+ <option name="courseId" value="54532" />
+ <option name="customPresentableName" />
+ <option name="id" value="85645" />
+ <option name="index" value="2" />
+ <option name="name" value="Core Transforms" />
+ <option name="position" value="0" />
+ <option name="stepikChangeStatus" value="Content changed" />
+ <option name="updateDate" value="1557824511000" />
+ <option name="items">
+ <list>
+ <Lesson>
+ <option name="customPresentableName" />
+ <option name="id" value="229518" />
+ <option name="index" value="1" />
+ <option name="name" value="Map" />
+ <option name="stepikChangeStatus" value="Content changed" />
+ <option name="updateDate" value="1557824515000" />
+ <option name="unitId" value="202043" />
+ <option name="items">
+ <list>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713751" />
+ <option name="index" value="1" />
+ <option name="name" value="ParDo" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="task.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="919" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="def process(self, element): yield element * 10" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="1" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="1036" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="beam.ParDo(MultiplyByTenDoFn())" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="task.py" />
+ <option name="text" value="# TODO: type solution here " />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="tests.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="tests.py" />
+ <option name="text" value="from test_helper import run_common_tests, failed, passed, get_answer_placeholders def test_answer_placeholders(): placeholders = get_answer_placeholders() placeholder = placeholders[0] if placeholder == "": # TODO: your condition here passed() else: failed() if __name__ == '__main__': run_common_tests() # test [...]
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557824517000" />
+ </EduTask>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713752" />
+ <option name="index" value="2" />
+ <option name="name" value="ParDo OneToMany" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="task.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="920" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="def process(self, element): return element.split()" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="1" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="1057" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="beam.ParDo(BreakIntoWordsDoFn())" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="task.py" />
+ <option name="text" value="# TODO: type solution here " />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="tests.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="tests.py" />
+ <option name="text" value="from test_helper import run_common_tests, failed, passed, get_answer_placeholders def test_answer_placeholders(): placeholders = get_answer_placeholders() placeholder = placeholders[0] if placeholder == "": # TODO: your condition here passed() else: failed() if __name__ == '__main__': run_common_tests() # test [...]
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557824519000" />
+ </EduTask>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713753" />
+ <option name="index" value="3" />
+ <option name="name" value="Map" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="task.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="942" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="beam.Map(lambda num: num * 5)" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="task.py" />
+ <option name="text" value="# TODO: type solution here " />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="tests.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="tests.py" />
+ <option name="text" value="from test_helper import run_common_tests, failed, passed, get_answer_placeholders def test_answer_placeholders(): placeholders = get_answer_placeholders() placeholder = placeholders[0] if placeholder == "": # TODO: your condition here passed() else: failed() if __name__ == '__main__': run_common_tests() # test [...]
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557824521000" />
+ </EduTask>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713754" />
+ <option name="index" value="4" />
+ <option name="name" value="FlatMap" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="task.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="968" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="beam.FlatMap(lambda sentence: sentence.split())" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="task.py" />
+ <option name="text" value="# TODO: type solution here " />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="tests.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="tests.py" />
+ <option name="text" value="from test_helper import run_common_tests, failed, passed, get_answer_placeholders def test_answer_placeholders(): placeholders = get_answer_placeholders() placeholder = placeholders[0] if placeholder == "": # TODO: your condition here passed() else: failed() if __name__ == '__main__': run_common_tests() # test [...]
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557824523000" />
+ </EduTask>
+ </list>
+ </option>
+ </Lesson>
+ <Lesson>
+ <option name="customPresentableName" />
+ <option name="id" value="229519" />
+ <option name="index" value="2" />
+ <option name="name" value="GroupByKey" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="updateDate" value="1557824527000" />
+ <option name="unitId" value="202044" />
+ <option name="items">
+ <list>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713756" />
+ <option name="index" value="1" />
+ <option name="name" value="GroupByKey" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="task.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="8" />
+ <option name="offset" value="970" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="| TODO()" />
+ <option name="possibleAnswer" value="| beam.Map(lambda word: (word[0], word)) | beam.GroupByKey()" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="task.py" />
+ <option name="text" value="# TODO: type solution here " />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="tests.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="tests.py" />
+ <option name="text" value="from test_helper import run_common_tests, failed, passed, get_answer_placeholders def test_answer_placeholders(): placeholders = get_answer_placeholders() placeholder = placeholders[0] if placeholder == "": # TODO: your condition here passed() else: failed() if __name__ == '__main__': run_common_tests() # test [...]
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557824529000" />
+ </EduTask>
+ </list>
+ </option>
+ </Lesson>
+ <Lesson>
+ <option name="customPresentableName" />
+ <option name="id" value="229520" />
+ <option name="index" value="3" />
+ <option name="name" value="CoGroupByKey" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="updateDate" value="1557824533000" />
+ <option name="unitId" value="202045" />
+ <option name="items">
+ <list>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713757" />
+ <option name="index" value="1" />
+ <option name="name" value="CoGroupByKey" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="task.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="1228" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="def map_to_alphabet_kv(word): return (word[0], word) def cogbk_result_to_wordsalphabet(cgbk_result): (alphabet, words) = cgbk_result return WordsAlphabet(alphabet, words['fruits'][0], words['countries'][0]) fruits_kv = (fruits | 'Fruit to KV' >> beam.Map(map_to_alphabet_kv)) countries_kv = (countries | 'Country to KV' >> beam.M [...]
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="task.py" />
+ <option name="text" value="# TODO: type solution here " />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="tests.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="tests.py" />
+ <option name="text" value="from test_helper import run_common_tests, failed, passed, get_answer_placeholders def test_answer_placeholders(): placeholders = get_answer_placeholders() placeholder = placeholders[0] if placeholder == "": # TODO: your condition here passed() else: failed() if __name__ == '__main__': run_common_tests() # test [...]
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557824535000" />
+ </EduTask>
+ </list>
+ </option>
+ </Lesson>
+ <Lesson>
+ <option name="customPresentableName" />
+ <option name="id" value="229521" />
+ <option name="index" value="4" />
+ <option name="name" value="Combine" />
+ <option name="stepikChangeStatus" value="Content changed" />
+ <option name="updateDate" value="1557824539000" />
+ <option name="unitId" value="202046" />
+ <option name="items">
+ <list>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713758" />
+ <option name="index" value="1" />
+ <option name="name" value="Simple Function" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="task.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="900" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="total = 0 for num in numbers: total += num return total" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="1" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="1036" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="beam.CombineGlobally(sum)" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="task.py" />
+ <option name="text" value="# TODO: type solution here " />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="tests.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="tests.py" />
+ <option name="text" value="from test_helper import run_common_tests, failed, passed, get_answer_placeholders def test_answer_placeholders(): placeholders = get_answer_placeholders() placeholder = placeholders[0] if placeholder == "": # TODO: your condition here passed() else: failed() if __name__ == '__main__': run_common_tests() # test [...]
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557824541000" />
+ </EduTask>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713759" />
+ <option name="index" value="2" />
+ <option name="name" value="CombineFn" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="task.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="916" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="def create_accumulator(self): return 0.0, 0 def add_input(self, accumulator, element): (sum, count) = accumulator return sum + element, count + 1 def merge_accumulators(self, accumulators): sums, counts = zip(*accumulators) return sum(sums), sum(counts) def extract_output(self, accumulator): (sum, c [...]
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="1" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="1420" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="beam.CombineGlobally(AverageFn())" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="task.py" />
+ <option name="text" value="# TODO: type solution here " />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="tests.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="tests.py" />
+ <option name="text" value="from test_helper import run_common_tests, failed, passed, get_answer_placeholders def test_answer_placeholders(): placeholders = get_answer_placeholders() placeholder = placeholders[0] if placeholder == "": # TODO: your condition here passed() else: failed() if __name__ == '__main__': run_common_tests() # test [...]
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557824543000" />
+ </EduTask>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713760" />
+ <option name="index" value="3" />
+ <option name="name" value="Combine PerKey" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="task.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="1088" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="beam.CombinePerKey(sum)" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="task.py" />
+ <option name="text" value="# TODO: type solution here " />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="tests.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="tests.py" />
+ <option name="text" value="from test_helper import run_common_tests, failed, passed, get_answer_placeholders def test_answer_placeholders(): placeholders = get_answer_placeholders() placeholder = placeholders[0] if placeholder == "": # TODO: your condition here passed() else: failed() if __name__ == '__main__': run_common_tests() # test [...]
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557824546000" />
+ </EduTask>
+ </list>
+ </option>
+ </Lesson>
+ <Lesson>
+ <option name="customPresentableName" />
+ <option name="id" value="229522" />
+ <option name="index" value="5" />
+ <option name="name" value="Flatten" />
+ <option name="stepikChangeStatus" value="Content changed" />
+ <option name="updateDate" value="1557824550000" />
+ <option name="unitId" value="202047" />
+ <option name="items">
+ <list>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713761" />
+ <option name="index" value="1" />
+ <option name="name" value="Flatten" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="task.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="1140" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="beam.Flatten()" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="task.py" />
+ <option name="text" value="# TODO: type solution here " />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="tests.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="tests.py" />
+ <option name="text" value="from test_helper import run_common_tests, failed, passed, get_answer_placeholders def test_answer_placeholders(): placeholders = get_answer_placeholders() placeholder = placeholders[0] if placeholder == "": # TODO: your condition here passed() else: failed() if __name__ == '__main__': run_common_tests() # test [...]
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557824553000" />
+ </EduTask>
+ </list>
+ </option>
+ </Lesson>
+ <Lesson>
+ <option name="customPresentableName" />
+ <option name="id" value="229523" />
+ <option name="index" value="6" />
+ <option name="name" value="Partition" />
+ <option name="stepikChangeStatus" value="Content changed" />
+ <option name="updateDate" value="1557824556000" />
+ <option name="unitId" value="202048" />
+ <option name="items">
+ <list>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713762" />
+ <option name="index" value="1" />
+ <option name="name" value="Partition" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="task.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="924" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="if number > 100: return 0 else: return 1" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="1" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="1087" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="beam.Partition(partition_fn, 2)" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="task.py" />
+ <option name="text" value="# TODO: type solution here " />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="tests.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="tests.py" />
+ <option name="text" value="from test_helper import run_common_tests, failed, passed, get_answer_placeholders def test_answer_placeholders(): placeholders = get_answer_placeholders() placeholder = placeholders[0] if placeholder == "": # TODO: your condition here passed() else: failed() if __name__ == '__main__': run_common_tests() # test [...]
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557824558000" />
+ </EduTask>
+ </list>
+ </option>
+ </Lesson>
+ </list>
+ </option>
+ </Section>
+ <Section>
+ <option name="courseId" value="54532" />
+ <option name="customPresentableName" />
+ <option name="id" value="85646" />
+ <option name="index" value="3" />
+ <option name="name" value="Common Transforms" />
+ <option name="position" value="0" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="updateDate" value="1557824560000" />
+ <option name="items">
+ <list>
+ <Lesson>
+ <option name="customPresentableName" />
+ <option name="id" value="229524" />
+ <option name="index" value="1" />
+ <option name="name" value="Filter" />
+ <option name="stepikChangeStatus" value="Content changed" />
+ <option name="updateDate" value="1557824563000" />
+ <option name="unitId" value="202049" />
+ <option name="items">
+ <list>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713763" />
+ <option name="index" value="1" />
+ <option name="name" value="ParDo" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="task.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="942" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="def process(self, element): if element % 2 == 1: yield element" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="task.py" />
+ <option name="text" value="# TODO: type solution here " />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="tests.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="tests.py" />
+ <option name="text" value="from test_helper import run_common_tests, failed, passed, get_answer_placeholders def test_answer_placeholders(): placeholders = get_answer_placeholders() placeholder = placeholders[0] if placeholder == "": # TODO: your condition here passed() else: failed() if __name__ == '__main__': run_common_tests() # test [...]
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557824566000" />
+ </EduTask>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713764" />
+ <option name="index" value="2" />
+ <option name="name" value="Filter" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="task.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="934" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="beam.Filter(lambda num: num % 2 == 0)" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="task.py" />
+ <option name="text" value="# TODO: type solution here " />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="tests.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="tests.py" />
+ <option name="text" value="from test_helper import run_common_tests, failed, passed, get_answer_placeholders def test_answer_placeholders(): placeholders = get_answer_placeholders() placeholder = placeholders[0] if placeholder == "": # TODO: your condition here passed() else: failed() if __name__ == '__main__': run_common_tests() # test [...]
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557824567000" />
+ </EduTask>
+ </list>
+ </option>
+ </Lesson>
+ <Lesson>
+ <option name="customPresentableName" />
+ <option name="id" value="229525" />
+ <option name="index" value="2" />
+ <option name="name" value="Aggregation" />
+ <option name="stepikChangeStatus" value="Content changed" />
+ <option name="updateDate" value="1557824571000" />
+ <option name="unitId" value="202050" />
+ <option name="items">
+ <list>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713765" />
+ <option name="index" value="1" />
+ <option name="name" value="Count" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="task.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="934" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="beam.combiners.Count.Globally()" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="task.py" />
+ <option name="text" value="# TODO: type solution here " />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="tests.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="tests.py" />
+ <option name="text" value="from test_helper import run_common_tests, failed, passed, get_answer_placeholders def test_answer_placeholders(): placeholders = get_answer_placeholders() placeholder = placeholders[0] if placeholder == "": # TODO: your condition here passed() else: failed() if __name__ == '__main__': run_common_tests() # test [...]
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557824574000" />
+ </EduTask>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713766" />
+ <option name="index" value="2" />
+ <option name="name" value="Sum" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="task.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="934" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="beam.CombineGlobally(sum)" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="task.py" />
+ <option name="text" value="# TODO: type solution here " />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="tests.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="tests.py" />
+ <option name="text" value="from test_helper import run_common_tests, failed, passed, get_answer_placeholders def test_answer_placeholders(): placeholders = get_answer_placeholders() placeholder = placeholders[0] if placeholder == "": # TODO: your condition here passed() else: failed() if __name__ == '__main__': run_common_tests() # test [...]
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557824575000" />
+ </EduTask>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713767" />
+ <option name="index" value="3" />
+ <option name="name" value="Mean" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="task.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="934" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="beam.combiners.Mean.Globally()" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="task.py" />
+ <option name="text" value="# TODO: type solution here " />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="tests.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="tests.py" />
+ <option name="text" value="from test_helper import run_common_tests, failed, passed, get_answer_placeholders def test_answer_placeholders(): placeholders = get_answer_placeholders() placeholder = placeholders[0] if placeholder == "": # TODO: your condition here passed() else: failed() if __name__ == '__main__': run_common_tests() # test [...]
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557824578000" />
+ </EduTask>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713768" />
+ <option name="index" value="4" />
+ <option name="name" value="Smallest" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="task.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="934" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="beam.combiners.Top.Smallest(1)" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="task.py" />
+ <option name="text" value="# TODO: type solution here " />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="tests.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="tests.py" />
+ <option name="text" value="from test_helper import run_common_tests, failed, passed, get_answer_placeholders def test_answer_placeholders(): placeholders = get_answer_placeholders() placeholder = placeholders[0] if placeholder == "": # TODO: your condition here passed() else: failed() if __name__ == '__main__': run_common_tests() # test [...]
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557824580000" />
+ </EduTask>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713769" />
+ <option name="index" value="5" />
+ <option name="name" value="Largest" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="task.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="934" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="beam.combiners.Top.Largest(1)" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="task.py" />
+ <option name="text" value="# TODO: type solution here " />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="tests.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="tests.py" />
+ <option name="text" value="from test_helper import run_common_tests, failed, passed, get_answer_placeholders def test_answer_placeholders(): placeholders = get_answer_placeholders() placeholder = placeholders[0] if placeholder == "": # TODO: your condition here passed() else: failed() if __name__ == '__main__': run_common_tests() # test [...]
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557824582000" />
+ </EduTask>
+ </list>
+ </option>
+ </Lesson>
+ </list>
+ </option>
+ </Section>
+ <Section>
+ <option name="courseId" value="54532" />
+ <option name="customPresentableName" />
+ <option name="id" value="85647" />
+ <option name="index" value="4" />
+ <option name="name" value="Examples" />
+ <option name="position" value="0" />
+ <option name="stepikChangeStatus" value="Content changed" />
+ <option name="updateDate" value="1557824583000" />
+ <option name="items">
+ <list>
+ <Lesson>
+ <option name="customPresentableName" />
+ <option name="id" value="229526" />
+ <option name="index" value="1" />
+ <option name="name" value="Word Count" />
+ <option name="stepikChangeStatus" value="Content changed" />
+ <option name="updateDate" value="1557824587000" />
+ <option name="unitId" value="202051" />
+ <option name="items">
+ <list>
+ <EduTask>
+ <option name="customPresentableName" />
+ <option name="descriptionFormat" value="HTML" />
+ <option name="descriptionText" value="<!-- ~ 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 ~ wit [...]
+ <option name="feedbackLink">
+ <FeedbackLink>
+ <option name="link" />
+ <option name="type" value="STEPIK" />
+ </FeedbackLink>
+ </option>
+ <option name="id" value="713770" />
+ <option name="index" value="1" />
+ <option name="name" value="Word Count" />
+ <option name="record" value="-1" />
+ <option name="status" value="Unchecked" />
+ <option name="stepikChangeStatus" value="Up to date" />
+ <option name="files">
+ <map>
+ <entry key="task.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list>
+ <AnswerPlaceholder>
+ <option name="hints">
+ <list />
+ </option>
+ <option name="index" value="0" />
+ <option name="initialState" />
+ <option name="initializedFromDependency" value="false" />
+ <option name="length" value="6" />
+ <option name="offset" value="1021" />
+ <option name="placeholderDependency" />
+ <option name="placeholderText" value="TODO()" />
+ <option name="possibleAnswer" value="beam.FlatMap(lambda sentence: sentence.split()) | beam.combiners.Count.PerElement() | beam.Map(lambda (k, v): k + ":" + str(v))" />
+ <option name="selected" value="false" />
+ <option name="status" value="Unchecked" />
+ <option name="studentAnswer" />
+ <option name="useLength" value="false" />
+ </AnswerPlaceholder>
+ </list>
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="task.py" />
+ <option name="text" value="# TODO: type solution here " />
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="true" />
+ </TaskFile>
+ </value>
+ </entry>
+ <entry key="tests.py">
+ <value>
+ <TaskFile>
+ <option name="answerPlaceholders">
+ <list />
+ </option>
+ <option name="highlightErrors" value="true" />
+ <option name="name" value="tests.py" />
+ <option name="text" value="from test_helper import run_common_tests, failed, passed, get_answer_placeholders def test_answer_placeholders(): placeholders = get_answer_placeholders() placeholder = placeholders[0] if placeholder == "": # TODO: your condition here passed() else: failed() if __name__ == '__main__': run_common_tests() # test [...]
+ <option name="trackChanges" value="true" />
+ <option name="trackLengths" value="true" />
+ <option name="visible" value="false" />
+ </TaskFile>
+ </value>
+ </entry>
+ </map>
+ </option>
+ <option name="updateDate" value="1557824590000" />
+ </EduTask>
+ </list>
+ </option>
+ </Lesson>
+ </list>
+ </option>
+ </Section>
+ </list>
+ </option>
+ </EduCourse>
+ </option>
+ </StudyTaskManager>
+ </component>
+</project>
\ No newline at end of file
diff --git a/learning/katas/python/Common Transforms/Aggregation/Count/task.html b/learning/katas/python/Common Transforms/Aggregation/Count/task.html
new file mode 100644
index 0000000..b7ff9d6
--- /dev/null
+++ b/learning/katas/python/Common Transforms/Aggregation/Count/task.html
@@ -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.
+ -->
+
+<html>
+<h2>Aggregation - Count</h2>
+<p>
+ In this task, we are going to count the number of elements from an input.</p>
+<br>
+<br>
+<div class='hint'>Use <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.combiners.html#apache_beam.transforms.combiners.Count">Count</a></div>
+</html>
+
diff --git a/learning/katas/python/Common Transforms/Aggregation/Count/task.py b/learning/katas/python/Common Transforms/Aggregation/Count/task.py
new file mode 100644
index 0000000..1c34f05
--- /dev/null
+++ b/learning/katas/python/Common Transforms/Aggregation/Count/task.py
@@ -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.
+
+import apache_beam as beam
+
+from log_elements import LogElements
+
+p = beam.Pipeline()
+
+(p | beam.Create(range(1, 11))
+ | beam.combiners.Count.Globally()
+ | LogElements())
+
+p.run()
diff --git a/learning/katas/python/Common Transforms/Aggregation/Count/tests.py b/learning/katas/python/Common Transforms/Aggregation/Count/tests.py
new file mode 100644
index 0000000..a63ecd4
--- /dev/null
+++ b/learning/katas/python/Common Transforms/Aggregation/Count/tests.py
@@ -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.
+
+from test_helper import run_common_tests, failed, passed, get_file_output
+
+
+def test_output():
+ output = get_file_output()
+
+ answers = ['10']
+
+ if all(num in output for num in answers):
+ passed()
+ else:
+ failed("Incorrect output. Use Count.")
+
+
+if __name__ == '__main__':
+ run_common_tests()
+ test_output()
diff --git a/learning/katas/python/Common Transforms/Aggregation/Largest/task.html b/learning/katas/python/Common Transforms/Aggregation/Largest/task.html
new file mode 100644
index 0000000..ec2fcbb
--- /dev/null
+++ b/learning/katas/python/Common Transforms/Aggregation/Largest/task.html
@@ -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.
+ -->
+
+<html>
+<h2>Aggregation - Largest</h2>
+<p>In this task, we are going to compute the largest of the elements from an input.</p>
+<br>
+<br>
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.combiners.html#apache_beam.transforms.combiners.Top.Largest">Top.Largest</a>
+</div>
+</html>
diff --git a/learning/katas/python/Common Transforms/Aggregation/Largest/task.py b/learning/katas/python/Common Transforms/Aggregation/Largest/task.py
new file mode 100644
index 0000000..32627c8
--- /dev/null
+++ b/learning/katas/python/Common Transforms/Aggregation/Largest/task.py
@@ -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.
+
+import apache_beam as beam
+
+from log_elements import LogElements
+
+p = beam.Pipeline()
+
+(p | beam.Create(range(1, 11))
+ | beam.combiners.Top.Largest(1)
+ | LogElements())
+
+p.run()
diff --git a/learning/katas/python/Common Transforms/Aggregation/Largest/tests.py b/learning/katas/python/Common Transforms/Aggregation/Largest/tests.py
new file mode 100644
index 0000000..1a89b9d
--- /dev/null
+++ b/learning/katas/python/Common Transforms/Aggregation/Largest/tests.py
@@ -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.
+
+from test_helper import run_common_tests, failed, passed, get_file_output
+
+
+def test_output():
+ output = get_file_output()
+
+ answers = ['[10]']
+
+ if all(num in output for num in answers):
+ passed()
+ else:
+ failed("Incorrect output. Calculate the largest of all elements.")
+
+
+if __name__ == '__main__':
+ run_common_tests()
+ test_output()
diff --git a/learning/katas/python/Common Transforms/Aggregation/Mean/task.html b/learning/katas/python/Common Transforms/Aggregation/Mean/task.html
new file mode 100644
index 0000000..e3013ca
--- /dev/null
+++ b/learning/katas/python/Common Transforms/Aggregation/Mean/task.html
@@ -0,0 +1,26 @@
+<!--
+ ~ 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.
+ -->
+
+<html>
+<h2>Aggregation - Mean</h2>
+<p>In this task, we are going to compute the mean/average of all elements from an input.</p>
+<br>
+<br>
+<div class='hint'>Use <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.combiners.html#apache_beam.transforms.combiners.Mean">Mean</a></div>
+</html>
+
diff --git a/learning/katas/python/Common Transforms/Aggregation/Mean/task.py b/learning/katas/python/Common Transforms/Aggregation/Mean/task.py
new file mode 100644
index 0000000..79f6f53
--- /dev/null
+++ b/learning/katas/python/Common Transforms/Aggregation/Mean/task.py
@@ -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.
+
+import apache_beam as beam
+
+from log_elements import LogElements
+
+p = beam.Pipeline()
+
+(p | beam.Create(range(1, 11))
+ | beam.combiners.Mean.Globally()
+ | LogElements())
+
+p.run()
diff --git a/learning/katas/python/Common Transforms/Aggregation/Mean/tests.py b/learning/katas/python/Common Transforms/Aggregation/Mean/tests.py
new file mode 100644
index 0000000..cba3205
--- /dev/null
+++ b/learning/katas/python/Common Transforms/Aggregation/Mean/tests.py
@@ -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.
+
+from test_helper import run_common_tests, failed, passed, get_file_output
+
+
+def test_output():
+ output = get_file_output()
+
+ answers = ['5.5']
+
+ if all(num in output for num in answers):
+ passed()
+ else:
+ failed("Incorrect output. Calculate the mean of all elements.")
+
+
+if __name__ == '__main__':
+ run_common_tests()
+ test_output()
diff --git a/learning/katas/python/Common Transforms/Aggregation/Smallest/task.html b/learning/katas/python/Common Transforms/Aggregation/Smallest/task.html
new file mode 100644
index 0000000..5eac49e
--- /dev/null
+++ b/learning/katas/python/Common Transforms/Aggregation/Smallest/task.html
@@ -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.
+ -->
+
+<html>
+<h2>Aggregation - Smallest</h2>
+<p>In this task, we are going to compute the smallest of the elements from an input.</p>
+<br>
+<br>
+<div class="hint">
+ Use <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.combiners.html#apache_beam.transforms.combiners.Top.Smallest">Top.Smallest</a>
+</div>
+</html>
diff --git a/learning/katas/python/Common Transforms/Aggregation/Smallest/task.py b/learning/katas/python/Common Transforms/Aggregation/Smallest/task.py
new file mode 100644
index 0000000..871ebaf
--- /dev/null
+++ b/learning/katas/python/Common Transforms/Aggregation/Smallest/task.py
@@ -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.
+
+import apache_beam as beam
+
+from log_elements import LogElements
+
+p = beam.Pipeline()
+
+(p | beam.Create(range(1, 11))
+ | beam.combiners.Top.Smallest(1)
+ | LogElements())
+
+p.run()
diff --git a/learning/katas/python/Common Transforms/Aggregation/Smallest/tests.py b/learning/katas/python/Common Transforms/Aggregation/Smallest/tests.py
new file mode 100644
index 0000000..90d1223
--- /dev/null
+++ b/learning/katas/python/Common Transforms/Aggregation/Smallest/tests.py
@@ -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.
+
+from test_helper import run_common_tests, failed, passed, get_file_output
+
+
+def test_output():
+ output = get_file_output()
+
+ answers = ['[1]']
+
+ if all(num in output for num in answers):
+ passed()
+ else:
+ failed("Incorrect output. Calculate the smallest of all elements.")
+
+
+if __name__ == '__main__':
+ run_common_tests()
+ test_output()
diff --git a/learning/katas/python/Common Transforms/Aggregation/Sum/task.html b/learning/katas/python/Common Transforms/Aggregation/Sum/task.html
new file mode 100644
index 0000000..fa57f37
--- /dev/null
+++ b/learning/katas/python/Common Transforms/Aggregation/Sum/task.html
@@ -0,0 +1,28 @@
+<!--
+ ~ 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.
+ -->
+
+<html>
+<h2>Aggregation - Sum</h2>
+<p>
+ In this task, we are going to compute the sum of all elements from an input.</p>
+<br>
+<br>
+<div class='hint'>Use <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.core.html#apache_beam.transforms.core.CombineGlobally">CombineGlobally</a>
+ and Python built-in <a href="https://docs.python.org/2/library/functions.html#sum">sum</a></div>
+</html>
+
diff --git a/learning/katas/python/Common Transforms/Aggregation/Sum/task.py b/learning/katas/python/Common Transforms/Aggregation/Sum/task.py
new file mode 100644
index 0000000..9509993
--- /dev/null
+++ b/learning/katas/python/Common Transforms/Aggregation/Sum/task.py
@@ -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.
+
+import apache_beam as beam
+
+from log_elements import LogElements
+
+p = beam.Pipeline()
+
+(p | beam.Create(range(1, 11))
+ | beam.CombineGlobally(sum)
+ | LogElements())
+
+p.run()
diff --git a/learning/katas/python/Common Transforms/Aggregation/Sum/tests.py b/learning/katas/python/Common Transforms/Aggregation/Sum/tests.py
new file mode 100644
index 0000000..9756b6d
--- /dev/null
+++ b/learning/katas/python/Common Transforms/Aggregation/Sum/tests.py
@@ -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.
+
+from test_helper import run_common_tests, failed, passed, get_file_output
+
+
+def test_output():
+ output = get_file_output()
+
+ answers = ['55']
+
+ if all(num in output for num in answers):
+ passed()
+ else:
+ failed("Incorrect output. Calculate the sum of all elements.")
+
+
+if __name__ == '__main__':
+ run_common_tests()
+ test_output()
diff --git a/learning/katas/python/Common Transforms/Filter/Filter/task.html b/learning/katas/python/Common Transforms/Filter/Filter/task.html
new file mode 100644
index 0000000..2de6da8
--- /dev/null
+++ b/learning/katas/python/Common Transforms/Filter/Filter/task.html
@@ -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.
+ -->
+
+<html>
+<h2>Filter</h2>
+<p>The Beam SDKs provide language-specific ways to simplify how you provide your DoFn implementation.</p>
+<p>In this task, we are going to implement a filter function that filters out the odd numbers by using
+ <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.core.html#apache_beam.transforms.core.Filter">
+ Filter</a>.
+</p>
+<br>
+<br>
+<div class='hint'>Use <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.core.html#apache_beam.transforms.core.Filter">Filter</a>
+ with a lambda.</div>
+</html>
+
diff --git a/learning/katas/python/Common Transforms/Filter/Filter/task.py b/learning/katas/python/Common Transforms/Filter/Filter/task.py
new file mode 100644
index 0000000..57a5486
--- /dev/null
+++ b/learning/katas/python/Common Transforms/Filter/Filter/task.py
@@ -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.
+
+import apache_beam as beam
+
+from log_elements import LogElements
+
+p = beam.Pipeline()
+
+(p | beam.Create(range(1, 11))
+ | beam.Filter(lambda num: num % 2 == 0)
+ | LogElements())
+
+p.run()
diff --git a/learning/katas/python/Common Transforms/Filter/Filter/tests.py b/learning/katas/python/Common Transforms/Filter/Filter/tests.py
new file mode 100644
index 0000000..40e7837
--- /dev/null
+++ b/learning/katas/python/Common Transforms/Filter/Filter/tests.py
@@ -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.
+
+from test_helper import run_common_tests, failed, passed, get_answer_placeholders, get_file_output
+
+
+def test_filter():
+ placeholders = get_answer_placeholders()
+ placeholder = placeholders[0]
+
+ if 'beam.Filter' in placeholder:
+ passed()
+ else:
+ failed('Use beam.Filter')
+
+
+def test_output():
+ output = get_file_output()
+
+ answers = ['2', '4', '6', '8', '10']
+
+ if all(num in output for num in answers):
+ passed()
+ else:
+ failed("Incorrect output. Filter out the odd numbers.")
+
+
+if __name__ == '__main__':
+ run_common_tests()
+ test_filter()
+ test_output()
diff --git a/learning/katas/python/Common Transforms/Filter/ParDo/task.html b/learning/katas/python/Common Transforms/Filter/ParDo/task.html
new file mode 100644
index 0000000..628f63f
--- /dev/null
+++ b/learning/katas/python/Common Transforms/Filter/ParDo/task.html
@@ -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.
+ -->
+
+<html>
+<h2>Filter using ParDo</h2>
+<p>In this task, we are going to implement a filter function that filters out the even numbers by using
+ <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.core.html#apache_beam.transforms.core.ParDo">
+ ParDo</a>.
+</p>
+<br>
+<br>
+<div class='hint'>Override <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.core.html#apache_beam.transforms.core.DoFn.process">process</a>
+ method. You can use "yield" for each intended element.</div>
+</html>
+
diff --git a/learning/katas/python/Common Transforms/Filter/ParDo/task.py b/learning/katas/python/Common Transforms/Filter/ParDo/task.py
new file mode 100644
index 0000000..58fb267
--- /dev/null
+++ b/learning/katas/python/Common Transforms/Filter/ParDo/task.py
@@ -0,0 +1,35 @@
+# 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.
+
+import apache_beam as beam
+
+from log_elements import LogElements
+
+p = beam.Pipeline()
+
+
+class FilterOutEvenNumber(beam.DoFn):
+
+ def process(self, element):
+ if element % 2 == 1:
+ yield element
+
+
+(p | beam.Create(range(1, 11))
+ | beam.ParDo(FilterOutEvenNumber())
+ | LogElements())
+
+p.run()
diff --git a/learning/katas/python/Common Transforms/Filter/ParDo/tests.py b/learning/katas/python/Common Transforms/Filter/ParDo/tests.py
new file mode 100644
index 0000000..a91e9bc
--- /dev/null
+++ b/learning/katas/python/Common Transforms/Filter/ParDo/tests.py
@@ -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.
+
+from test_helper import run_common_tests, failed, passed, get_file_output
+
+
+def test_output():
+ output = get_file_output()
+
+ answers = ['1', '3', '5', '7', '9']
+
+ if all(num in output for num in answers):
+ passed()
+ else:
+ failed("Incorrect output. Filter out the even numbers.")
+
+
+if __name__ == '__main__':
+ run_common_tests()
+ test_output()
diff --git a/learning/katas/python/Core Transforms/CoGroupByKey/CoGroupByKey/task.html b/learning/katas/python/Core Transforms/CoGroupByKey/CoGroupByKey/task.html
new file mode 100644
index 0000000..48f2f97
--- /dev/null
+++ b/learning/katas/python/Core Transforms/CoGroupByKey/CoGroupByKey/task.html
@@ -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.
+ -->
+
+<html>
+<h2>CoGroupByKey</h2>
+<p>CoGroupByKey performs a relational join of two or more key/value PCollections that have the same key type.</p>
+<p>In this task, we are going to implement a
+ <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.util.html#apache_beam.transforms.util.CoGroupByKey">
+ CoGroupByKey</a> transform that join words by its first alphabetical letter, and then produces the string
+ representation of the WordsAlphabet model.
+</p>
+<br>
+<br>
+<div class='hint'>Refer to
+ <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.util.html#apache_beam.transforms.util.CoGroupByKey">CoGroupByKey</a>
+ to solve this problem</div>
+</html>
+
diff --git a/learning/katas/python/Core Transforms/CoGroupByKey/CoGroupByKey/task.py b/learning/katas/python/Core Transforms/CoGroupByKey/CoGroupByKey/task.py
new file mode 100644
index 0000000..f76002b
--- /dev/null
+++ b/learning/katas/python/Core Transforms/CoGroupByKey/CoGroupByKey/task.py
@@ -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.
+
+import apache_beam as beam
+
+from log_elements import LogElements
+
+
+class WordsAlphabet:
+
+ def __init__(self, alphabet, fruit, country):
+ self.alphabet = alphabet
+ self.fruit = fruit
+ self.country = country
+
+ def __str__(self):
+ return "WordsAlphabet(alphabet:'%s', fruit='%s', country='%s')" % (self.alphabet, self.fruit, self.country)
+
+
+def apply_transforms(fruits, countries):
+ def map_to_alphabet_kv(word):
+ return (word[0], word)
+
+ def cogbk_result_to_wordsalphabet(cgbk_result):
+ (alphabet, words) = cgbk_result
+ return WordsAlphabet(alphabet, words['fruits'][0], words['countries'][0])
+
+ fruits_kv = (fruits | 'Fruit to KV' >> beam.Map(map_to_alphabet_kv))
+ countries_kv = (countries | 'Country to KV' >> beam.Map(map_to_alphabet_kv))
+
+ return ({'fruits': fruits_kv, 'countries': countries_kv}
+ | beam.CoGroupByKey()
+ | beam.Map(cogbk_result_to_wordsalphabet))
+
+
+p = beam.Pipeline()
+
+fruits = p | 'Fruits' >> beam.Create(['apple', 'banana', 'cherry'])
+countries = p | 'Countries' >> beam.Create(['australia', 'brazil', 'canada'])
+
+(apply_transforms(fruits, countries)
+ | LogElements())
+
+p.run()
diff --git a/learning/katas/python/Core Transforms/CoGroupByKey/CoGroupByKey/tests.py b/learning/katas/python/Core Transforms/CoGroupByKey/CoGroupByKey/tests.py
new file mode 100644
index 0000000..59c8515
--- /dev/null
+++ b/learning/katas/python/Core Transforms/CoGroupByKey/CoGroupByKey/tests.py
@@ -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.
+
+from test_helper import run_common_tests, failed, passed, get_file_output
+
+
+def test_output():
+ output = get_file_output()
+
+ answers = [
+ "WordsAlphabet(alphabet:'a', fruit='apple', country='australia')",
+ "WordsAlphabet(alphabet:'b', fruit='banana', country='brazil')",
+ "WordsAlphabet(alphabet:'c', fruit='cherry', country='canada')"
+ ]
+
+ if all(num in output for num in answers):
+ passed()
+ else:
+ failed("Incorrect output. Use CoGroupByKey.")
+
+
+if __name__ == '__main__':
+ run_common_tests()
+ test_output()
diff --git a/learning/katas/python/Core Transforms/Combine/Combine PerKey/task.html b/learning/katas/python/Core Transforms/Combine/Combine PerKey/task.html
new file mode 100644
index 0000000..523857a
--- /dev/null
+++ b/learning/katas/python/Core Transforms/Combine/Combine PerKey/task.html
@@ -0,0 +1,35 @@
+<!--
+ ~ 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.
+ -->
+
+<html>
+<h2>Combine - Combine PerKey</h2>
+<p>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.</p>
+<p>In this task, we are going to implement the sum of scores per player using
+ <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.core.html#apache_beam.transforms.core.CombinePerKey">
+ CombinePerKey</a>.
+</p>
+<br>
+<br>
+<div class='hint'>Use <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.core.html#apache_beam.transforms.core.CombinePerKey">CombinePerKey(CombineFn)</a>.</div>
+<div class='hint'>Extend the <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.core.html#apache_beam.transforms.core.CombineFn">CombineFn</a>
+ class that counts the sum of the number.</div>
+</html>
diff --git a/learning/katas/python/Core Transforms/Combine/Combine PerKey/task.py b/learning/katas/python/Core Transforms/Combine/Combine PerKey/task.py
new file mode 100644
index 0000000..c9167f7
--- /dev/null
+++ b/learning/katas/python/Core Transforms/Combine/Combine PerKey/task.py
@@ -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.
+
+import apache_beam as beam
+
+from log_elements import LogElements
+
+PLAYER_1 = 'Player 1'
+PLAYER_2 = 'Player 2'
+PLAYER_3 = 'Player 3'
+
+p = beam.Pipeline()
+
+(p | beam.Create([(PLAYER_1, 15), (PLAYER_2, 10), (PLAYER_1, 100),
+ (PLAYER_3, 25), (PLAYER_2, 75)])
+ | beam.CombinePerKey(sum)
+ | LogElements())
+
+p.run()
diff --git a/learning/katas/python/Core Transforms/Combine/Combine PerKey/tests.py b/learning/katas/python/Core Transforms/Combine/Combine PerKey/tests.py
new file mode 100644
index 0000000..7890e0a
--- /dev/null
+++ b/learning/katas/python/Core Transforms/Combine/Combine PerKey/tests.py
@@ -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.
+
+from test_helper import run_common_tests, failed, passed, get_answer_placeholders, get_file_output
+
+
+def test_combine_placeholders():
+ placeholders = get_answer_placeholders()
+ placeholder = placeholders[0]
+
+ if 'beam.CombinePerKey' in placeholder:
+ passed()
+ else:
+ failed('Use beam.CombinePerKey')
+
+
+def test_output():
+ output = get_file_output()
+
+ PLAYER_1 = 'Player 1'
+ PLAYER_2 = 'Player 2'
+ PLAYER_3 = 'Player 3'
+
+ answers = [str((PLAYER_1, 115)), str((PLAYER_2, 85)), str((PLAYER_3, 25))]
+ print answers
+
+ if all(num in output for num in answers):
+ passed()
+ else:
+ failed("Incorrect output. Sum all the scores per player.")
+
+
+if __name__ == '__main__':
+ run_common_tests()
+ test_combine_placeholders()
+ test_output()
diff --git a/learning/katas/python/Core Transforms/Combine/CombineFn/task.html b/learning/katas/python/Core Transforms/Combine/CombineFn/task.html
new file mode 100644
index 0000000..9918d1b
--- /dev/null
+++ b/learning/katas/python/Core Transforms/Combine/CombineFn/task.html
@@ -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.
+ -->
+
+<html>
+<h2>Combine - CombineFn</h2>
+<p>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.</p>
+<p>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.</p>
+<p>In this task, we are going to implement the average of numbers using
+ <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.core.html#apache_beam.transforms.core.CombineFn">
+ Combine.CombineFn</a>.
+</p>
+<br>
+<br>
+<div class="hint">
+ Extend the <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.core.html#apache_beam.transforms.core.CombineFn">CombineFn</a>
+ class that counts the average of the number.
+</div>
+</html>
diff --git a/learning/katas/python/Core Transforms/Combine/CombineFn/task.py b/learning/katas/python/Core Transforms/Combine/CombineFn/task.py
new file mode 100644
index 0000000..ce7b4db
--- /dev/null
+++ b/learning/katas/python/Core Transforms/Combine/CombineFn/task.py
@@ -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.
+
+import apache_beam as beam
+
+from log_elements import LogElements
+
+
+class AverageFn(beam.CombineFn):
+
+ def create_accumulator(self):
+ return 0.0, 0
+
+ def add_input(self, accumulator, element):
+ (sum, count) = accumulator
+ return sum + element, count + 1
+
+ def merge_accumulators(self, accumulators):
+ sums, counts = zip(*accumulators)
+ return sum(sums), sum(counts)
+
+ def extract_output(self, accumulator):
+ (sum, count) = accumulator
+ return sum / count if count else float('NaN')
+
+
+p = beam.Pipeline()
+
+(p | beam.Create([10, 20, 50, 70, 90])
+ | beam.CombineGlobally(AverageFn())
+ | LogElements())
+
+p.run()
diff --git a/learning/katas/python/Core Transforms/Combine/CombineFn/tests.py b/learning/katas/python/Core Transforms/Combine/CombineFn/tests.py
new file mode 100644
index 0000000..6e8ff93
--- /dev/null
+++ b/learning/katas/python/Core Transforms/Combine/CombineFn/tests.py
@@ -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.
+
+from test_helper import run_common_tests, failed, passed, get_answer_placeholders, get_file_output
+
+
+def test_combine_placeholders():
+ placeholders = get_answer_placeholders()
+ placeholder = placeholders[1]
+
+ if 'beam.CombineGlobally' in placeholder:
+ passed()
+ else:
+ failed('Use beam.CombineGlobally')
+
+
+def test_output():
+ output = get_file_output()
+
+ answers = ['48.0']
+
+ if all(num in output for num in answers):
+ passed()
+ else:
+ failed("Incorrect output. Average all the numbers.")
+
+
+if __name__ == '__main__':
+ run_common_tests()
+ test_combine_placeholders()
+ test_output()
diff --git a/learning/katas/python/Core Transforms/Combine/Simple Function/task.html b/learning/katas/python/Core Transforms/Combine/Simple Function/task.html
new file mode 100644
index 0000000..cb3e79c
--- /dev/null
+++ b/learning/katas/python/Core Transforms/Combine/Simple Function/task.html
@@ -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.
+ -->
+
+<html>
+<h2>Combine - Simple Function</h2>
+<p>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.</p>
+<p>Simple combine operations, such as sums, can usually be implemented as a simple function.</p>
+<p>In this task, we are going to implement the summation of numbers using
+ <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.core.html#apache_beam.transforms.core.CombineGlobally">
+ CombineGlobally</a>.
+</p>
+<br>
+<br>
+<div class="hint">
+ Implement a simple Python function that performs the summation of the values.
+</div>
+</html>
diff --git a/learning/katas/python/Core Transforms/Combine/Simple Function/task.py b/learning/katas/python/Core Transforms/Combine/Simple Function/task.py
new file mode 100644
index 0000000..a3c29cf
--- /dev/null
+++ b/learning/katas/python/Core Transforms/Combine/Simple Function/task.py
@@ -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.
+
+import apache_beam as beam
+
+from log_elements import LogElements
+
+
+def sum(numbers):
+ total = 0
+
+ for num in numbers:
+ total += num
+
+ return total
+
+
+p = beam.Pipeline()
+
+(p | beam.Create([1, 2, 3, 4, 5])
+ | beam.CombineGlobally(sum)
+ | LogElements())
+
+p.run()
diff --git a/learning/katas/python/Core Transforms/Combine/Simple Function/tests.py b/learning/katas/python/Core Transforms/Combine/Simple Function/tests.py
new file mode 100644
index 0000000..70cb7f6
--- /dev/null
+++ b/learning/katas/python/Core Transforms/Combine/Simple Function/tests.py
@@ -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.
+
+from test_helper import run_common_tests, failed, passed, get_answer_placeholders, get_file_output
+
+
+def test_combine_placeholders():
+ placeholders = get_answer_placeholders()
+ placeholder = placeholders[1]
+
+ if 'beam.CombineGlobally' in placeholder:
+ passed()
+ else:
+ failed('Use beam.CombineGlobally')
+
+
+def test_output():
+ output = get_file_output()
+
+ answers = ['15']
+
+ if all(num in output for num in answers):
+ passed()
+ else:
+ failed("Incorrect output. Sum all the numbers.")
+
+
+if __name__ == '__main__':
+ run_common_tests()
+ test_combine_placeholders()
+ test_output()
diff --git a/learning/katas/python/Core Transforms/Flatten/Flatten/task.html b/learning/katas/python/Core Transforms/Flatten/Flatten/task.html
new file mode 100644
index 0000000..e7225ef
--- /dev/null
+++ b/learning/katas/python/Core Transforms/Flatten/Flatten/task.html
@@ -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.
+ -->
+
+<html>
+<h2>Flatten</h2>
+<p>Flatten is a Beam transform for PCollection objects that store the same data type.
+ Flatten merges multiple PCollection objects into a single logical PCollection.</p>
+<p>In this task, we are going to implement a
+ <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.core.html#apache_beam.transforms.core.Flatten">
+ Flatten</a> transform that merges two PCollection of words into a single PCollection.
+</p>
+<br>
+<br>
+<div class="hint">
+ Refer to <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.core.html#apache_beam.transforms.core.Flatten">Flatten</a>
+ to solve this problem.
+</div>
+</html>
diff --git a/learning/katas/python/Core Transforms/Flatten/Flatten/task.py b/learning/katas/python/Core Transforms/Flatten/Flatten/task.py
new file mode 100644
index 0000000..c4c3b6e
--- /dev/null
+++ b/learning/katas/python/Core Transforms/Flatten/Flatten/task.py
@@ -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.
+
+import apache_beam as beam
+
+from log_elements import LogElements
+
+p = beam.Pipeline()
+
+wordsStartingWithA = \
+ p | 'Words starting with A' >> beam.Create(['apple', 'ant', 'arrow'])
+
+wordsStartingWithB = \
+ p | 'Words starting with B' >> beam.Create(['ball', 'book', 'bow'])
+
+((wordsStartingWithA, wordsStartingWithB)
+ | beam.Flatten()
+ | LogElements())
+
+p.run()
diff --git a/learning/katas/python/Core Transforms/Flatten/Flatten/tests.py b/learning/katas/python/Core Transforms/Flatten/Flatten/tests.py
new file mode 100644
index 0000000..285dc48
--- /dev/null
+++ b/learning/katas/python/Core Transforms/Flatten/Flatten/tests.py
@@ -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.
+
+from test_helper import run_common_tests, failed, passed, get_answer_placeholders, get_file_output
+
+
+def test_flatten():
+ placeholders = get_answer_placeholders()
+ placeholder = placeholders[0]
+
+ if 'beam.Flatten' in placeholder:
+ passed()
+ else:
+ failed('Use beam.Flatten')
+
+
+def test_output():
+ output = get_file_output()
+
+ answers = ['ball', 'book', 'bow', 'apple', 'ant', 'arrow']
+
+ if all(num in output for num in answers):
+ passed()
+ else:
+ failed("Incorrect output. Flatten both PCollection into one.")
+
+
+if __name__ == '__main__':
+ run_common_tests()
+ test_flatten()
+ test_output()
diff --git a/learning/katas/python/Core Transforms/GroupByKey/GroupByKey/task.html b/learning/katas/python/Core Transforms/GroupByKey/GroupByKey/task.html
new file mode 100644
index 0000000..f5b6d06
--- /dev/null
+++ b/learning/katas/python/Core Transforms/GroupByKey/GroupByKey/task.html
@@ -0,0 +1,36 @@
+<!--
+ ~ 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.
+ -->
+
+<html>
+<h2>GroupByKey</h2>
+<p>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.</p>
+<p>In this task, we are going to implement a
+ <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.core.html#apache_beam.transforms.core.GroupByKey">
+ GroupByKey</a> transform that groups words by its first letter.
+</p>
+<br>
+<br>
+<div class='hint'>Refer to
+ <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.core.html#apache_beam.transforms.core.GroupByKey">GroupByKey</a>
+ to solve this problem</div>
+</html>
+
diff --git a/learning/katas/python/Core Transforms/GroupByKey/GroupByKey/task.py b/learning/katas/python/Core Transforms/GroupByKey/GroupByKey/task.py
new file mode 100644
index 0000000..f65ffa1
--- /dev/null
+++ b/learning/katas/python/Core Transforms/GroupByKey/GroupByKey/task.py
@@ -0,0 +1,28 @@
+# 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.
+
+import apache_beam as beam
+
+from log_elements import LogElements
+
+p = beam.Pipeline()
+
+(p | beam.Create(['apple', 'ball', 'car', 'bear', 'cheetah', 'ant'])
+ | beam.Map(lambda word: (word[0], word))
+ | beam.GroupByKey()
+ | LogElements())
+
+p.run()
diff --git a/learning/katas/python/Core Transforms/GroupByKey/GroupByKey/tests.py b/learning/katas/python/Core Transforms/GroupByKey/GroupByKey/tests.py
new file mode 100644
index 0000000..afc8e36
--- /dev/null
+++ b/learning/katas/python/Core Transforms/GroupByKey/GroupByKey/tests.py
@@ -0,0 +1,35 @@
+# 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.
+
+from test_helper import run_common_tests, failed, passed, get_file_output
+
+
+def test_output():
+ output = get_file_output()
+
+ answers = ["('a', ['apple', 'ant'])",
+ "('b', ['ball', 'bear'])",
+ "('c', ['car', 'cheetah'])"]
+
+ if all(num in output for num in answers):
+ passed()
+ else:
+ failed("Incorrect output. Use GroupByKey.")
+
+
+if __name__ == '__main__':
+ run_common_tests()
+ test_output()
diff --git a/learning/katas/python/Core Transforms/Map/FlatMap/task.html b/learning/katas/python/Core Transforms/Map/FlatMap/task.html
new file mode 100644
index 0000000..3a4f51b
--- /dev/null
+++ b/learning/katas/python/Core Transforms/Map/FlatMap/task.html
@@ -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.
+ -->
+
+<html>
+<h2>FlatMapElements</h2>
+<p>The Beam SDKs provide language-specific ways to simplify how you provide your DoFn implementation.</p>
+<p>FlatMap can be used to simplify DoFn that maps an element to multiple elements (one to many).</p>
+<p>In this task, we are going to implement a function that maps each input sentence into words tokenized by whitespace (" ") using
+ <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.core.html#apache_beam.transforms.core.FlatMap">
+ FlatMap</a>.
+</p>
+<br>
+<br>
+<div class='hint'>Use <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.core.html#apache_beam.transforms.core.FlatMap">FlatMap</a>
+ with a lambda.</div>
+</html>
+
diff --git a/learning/katas/python/Core Transforms/Map/FlatMap/task.py b/learning/katas/python/Core Transforms/Map/FlatMap/task.py
new file mode 100644
index 0000000..ba4c0d8
--- /dev/null
+++ b/learning/katas/python/Core Transforms/Map/FlatMap/task.py
@@ -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.
+
+import apache_beam as beam
+
+from log_elements import LogElements
+
+p = beam.Pipeline()
+
+(p | beam.Create(['Apache Beam', 'Unified Batch and Streaming'])
+ | beam.FlatMap(lambda sentence: sentence.split())
+ | LogElements())
+
+p.run()
diff --git a/learning/katas/python/Core Transforms/Map/FlatMap/tests.py b/learning/katas/python/Core Transforms/Map/FlatMap/tests.py
new file mode 100644
index 0000000..55bd104
--- /dev/null
+++ b/learning/katas/python/Core Transforms/Map/FlatMap/tests.py
@@ -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.
+
+from test_helper import run_common_tests, failed, passed, get_answer_placeholders, get_file_output
+
+
+def test_flatmap():
+ placeholders = get_answer_placeholders()
+ placeholder = placeholders[0]
+
+ if 'beam.FlatMap' in placeholder:
+ passed()
+ else:
+ failed('Use beam.FlatMap')
+
+
+def test_output():
+ output = get_file_output()
+
+ answers = ['Apache', 'Beam', 'Unified', 'Batch', 'and', 'Streaming']
+
+ if all(num in output for num in answers):
+ passed()
+ else:
+ failed("Incorrect output. Break each sentence into words.")
+
+
+if __name__ == '__main__':
+ run_common_tests()
+ test_flatmap()
+ test_output()
diff --git a/learning/katas/python/Core Transforms/Map/Map/task.html b/learning/katas/python/Core Transforms/Map/Map/task.html
new file mode 100644
index 0000000..d0cf0a7
--- /dev/null
+++ b/learning/katas/python/Core Transforms/Map/Map/task.html
@@ -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.
+ -->
+
+<html>
+<h2>MapElements</h2>
+<p>The Beam SDKs provide language-specific ways to simplify how you provide your DoFn implementation.</p>
+<p>In this task, we are going to implement a simple map function that multiplies all input elements by 5 using
+ <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.core.html#apache_beam.transforms.core.Map">
+ Map</a>.
+</p>
+<br>
+<br>
+<div class='hint'>Use <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.core.html#apache_beam.transforms.core.Map">Map</a>
+ with a lambda.</div>
+</html>
+
diff --git a/learning/katas/python/Core Transforms/Map/Map/task.py b/learning/katas/python/Core Transforms/Map/Map/task.py
new file mode 100644
index 0000000..fac6a77
--- /dev/null
+++ b/learning/katas/python/Core Transforms/Map/Map/task.py
@@ -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.
+
+import apache_beam as beam
+
+from log_elements import LogElements
+
+p = beam.Pipeline()
+
+(p | beam.Create([10, 20, 30, 40, 50])
+ | beam.Map(lambda num: num * 5)
+ | LogElements())
+
+p.run()
diff --git a/learning/katas/python/Core Transforms/Map/Map/tests.py b/learning/katas/python/Core Transforms/Map/Map/tests.py
new file mode 100644
index 0000000..df1544f
--- /dev/null
+++ b/learning/katas/python/Core Transforms/Map/Map/tests.py
@@ -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.
+
+from test_helper import run_common_tests, failed, passed, get_answer_placeholders, get_file_output
+
+
+def test_map():
+ placeholders = get_answer_placeholders()
+ placeholder = placeholders[0]
+
+ if 'beam.Map' in placeholder:
+ passed()
+ else:
+ failed('Use beam.Map')
+
+
+def test_output():
+ output = get_file_output()
+
+ answers = ['50', '100', '150', '200', '250']
+
+ if all(num in output for num in answers):
+ passed()
+ else:
+ failed("Incorrect output. Multiply each element by 5.")
+
+
+if __name__ == '__main__':
+ run_common_tests()
+ test_map()
+ test_output()
diff --git a/learning/katas/python/Core Transforms/Map/ParDo OneToMany/task.html b/learning/katas/python/Core Transforms/Map/ParDo OneToMany/task.html
new file mode 100644
index 0000000..d797cc3
--- /dev/null
+++ b/learning/katas/python/Core Transforms/Map/ParDo OneToMany/task.html
@@ -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.
+ -->
+
+<html>
+<h2>ParDo OneToMany</h2>
+<p>For this task, please write a ParDo that maps each input sentence into words tokenized by whitespace (" ").</p>
+<br>
+<br>
+<div class='hint'>Override <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.core.html#apache_beam.transforms.core.DoFn.process">process</a> method.
+ You can return an Iterable for multiple elements or call "yield" for each element to return a generator.</div>
+<div class='hint'>Use <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.core.html#apache_beam.transforms.core.ParDo">ParDo</a>
+ with <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.core.html#apache_beam.transforms.core.DoFn">DoFn</a></div>
+</html>
+
diff --git a/learning/katas/python/Core Transforms/Map/ParDo OneToMany/task.py b/learning/katas/python/Core Transforms/Map/ParDo OneToMany/task.py
new file mode 100644
index 0000000..e93edc1
--- /dev/null
+++ b/learning/katas/python/Core Transforms/Map/ParDo OneToMany/task.py
@@ -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.
+
+import apache_beam as beam
+
+from log_elements import LogElements
+
+
+class BreakIntoWordsDoFn(beam.DoFn):
+
+ def process(self, element):
+ return element.split()
+
+
+p = beam.Pipeline()
+
+(p | beam.Create(['Hello Beam', 'It is awesome'])
+ | beam.ParDo(BreakIntoWordsDoFn())
+ | LogElements())
+
+p.run()
diff --git a/learning/katas/python/Core Transforms/Map/ParDo OneToMany/tests.py b/learning/katas/python/Core Transforms/Map/ParDo OneToMany/tests.py
new file mode 100644
index 0000000..8f9fe86
--- /dev/null
+++ b/learning/katas/python/Core Transforms/Map/ParDo OneToMany/tests.py
@@ -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.
+
+from test_helper import run_common_tests, failed, passed, get_answer_placeholders, get_file_output
+
+
+def test_dofn_process_method():
+ placeholders = get_answer_placeholders()
+ placeholder = placeholders[0]
+
+ if 'def process(self, element' in placeholder:
+ passed()
+ else:
+ failed('Override "process" method')
+
+
+def test_pardo():
+ placeholders = get_answer_placeholders()
+ placeholder = placeholders[1]
+
+ if 'beam.ParDo(BreakIntoWordsDoFn())' in placeholder:
+ passed()
+ else:
+ failed('Use beam.ParDo')
+
+
+def test_output():
+ output = get_file_output()
+
+ answers = ['Hello', 'Beam', 'It', 'is', 'awesome']
+
+ if all(num in output for num in answers):
+ passed()
+ else:
+ failed("Incorrect output. Break each sentence into words.")
+
+
+if __name__ == '__main__':
+ run_common_tests()
+ test_dofn_process_method()
+ test_pardo()
+ test_output()
diff --git a/learning/katas/python/Core Transforms/Map/ParDo/task.html b/learning/katas/python/Core Transforms/Map/ParDo/task.html
new file mode 100644
index 0000000..899c7f1
--- /dev/null
+++ b/learning/katas/python/Core Transforms/Map/ParDo/task.html
@@ -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.
+ -->
+
+<html>
+<h2>ParDo</h2>
+<p>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.</p>
+<p>For this task, please write a simple ParDo that maps the input element by multiplying it by 10.</p>
+<br>
+<br>
+<div class='hint'>Override <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.core.html#apache_beam.transforms.core.DoFn.process">process</a> method</div>
+<div class='hint'>Use <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.core.html#apache_beam.transforms.core.ParDo">ParDo</a> with
+ <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.core.html#apache_beam.transforms.core.DoFn">DoFn</a></div>
+</html>
+
diff --git a/learning/katas/python/Core Transforms/Map/ParDo/task.py b/learning/katas/python/Core Transforms/Map/ParDo/task.py
new file mode 100644
index 0000000..e0b6cff
--- /dev/null
+++ b/learning/katas/python/Core Transforms/Map/ParDo/task.py
@@ -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.
+
+import apache_beam as beam
+
+from log_elements import LogElements
+
+
+class MultiplyByTenDoFn(beam.DoFn):
+
+ def process(self, element):
+ yield element * 10
+
+
+p = beam.Pipeline()
+
+(p | beam.Create([1, 2, 3, 4, 5])
+ | beam.ParDo(MultiplyByTenDoFn())
+ | LogElements())
+
+p.run()
diff --git a/learning/katas/python/Core Transforms/Map/ParDo/tests.py b/learning/katas/python/Core Transforms/Map/ParDo/tests.py
new file mode 100644
index 0000000..f6dd859
--- /dev/null
+++ b/learning/katas/python/Core Transforms/Map/ParDo/tests.py
@@ -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.
+
+from test_helper import run_common_tests, failed, passed, get_answer_placeholders, get_file_output
+
+
+def test_dofn_process_method():
+ placeholders = get_answer_placeholders()
+ placeholder = placeholders[0]
+
+ if 'def process(self, element' in placeholder:
+ passed()
+ else:
+ failed('Override "process" method')
+
+
+def test_pardo():
+ placeholders = get_answer_placeholders()
+ placeholder = placeholders[1]
+
+ if 'beam.ParDo(MultiplyByTenDoFn())' in placeholder:
+ passed()
+ else:
+ failed('Use beam.ParDo')
+
+
+def test_output():
+ output = get_file_output()
+
+ answers = ['10', '20', '30', '40', '50']
+
+ if all(num in output for num in answers):
+ passed()
+ else:
+ failed("Incorrect output. Multiply each element by 10.")
+
+
+if __name__ == '__main__':
+ run_common_tests()
+ test_dofn_process_method()
+ test_pardo()
+ test_output()
diff --git a/learning/katas/python/Core Transforms/Partition/Partition/task.html b/learning/katas/python/Core Transforms/Partition/Partition/task.html
new file mode 100644
index 0000000..96a7510
--- /dev/null
+++ b/learning/katas/python/Core Transforms/Partition/Partition/task.html
@@ -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.
+ -->
+
+<html>
+<h2>Partition</h2>
+<p>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.</p>
+<p>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.</p>
+<p>In this task, we are going to implement a
+ <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.core.html#apache_beam.transforms.core.Partition">
+ Partition</a> 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.
+</p>
+<br>
+<br>
+<div class="hint">
+ Refer to <a href="https://beam.apache.org/releases/pydoc/2.11.0/apache_beam.transforms.core.html#apache_beam.transforms.core.Partition">Partition</a>
+ to solve this problem.
+</div>
+</html>
diff --git a/learning/katas/python/Core Transforms/Partition/Partition/task.py b/learning/katas/python/Core Transforms/Partition/Partition/task.py
new file mode 100644
index 0000000..d4ab573
--- /dev/null
+++ b/learning/katas/python/Core Transforms/Partition/Partition/task.py
@@ -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.
+
+import apache_beam as beam
+
+from log_elements import LogElements
+
+
+def partition_fn(number, num_partitions):
+ if number > 100:
+ return 0
+ else:
+ return 1
+
+
+p = beam.Pipeline()
+
+results = \
+ (p | beam.Create([1, 2, 3, 4, 5, 100, 110, 150, 250])
+ | beam.Partition(partition_fn, 2))
+
+results[0] | 'Log numbers > 100' >> LogElements(prefix='Number > 100: ')
+results[1] | 'Log numbers <= 100' >> LogElements(prefix='Number <= 100: ')
+
+p.run()
diff --git a/learning/katas/python/Core Transforms/Partition/Partition/tests.py b/learning/katas/python/Core Transforms/Partition/Partition/tests.py
new file mode 100644
index 0000000..6c5568a
--- /dev/null
+++ b/learning/katas/python/Core Transforms/Partition/Partition/tests.py
@@ -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.
+
+from test_helper import run_common_tests, failed, passed, get_answer_placeholders, get_file_output
+
+
+def test_partition():
+ placeholders = get_answer_placeholders()
+ placeholder = placeholders[1]
+
+ if 'beam.Partition' in placeholder:
+ passed()
+ else:
+ failed('Use beam.Partition')
+
+
+def test_output():
+ output = get_file_output()
+
+ numbers_greater_than_100 = ['110', '150', '250']
+ remaining_numbers = ['1', '2', '3', '4', '5', '100']
+
+ answers = []
+
+ for num in numbers_greater_than_100:
+ answers.append('Number > 100: ' + num)
+
+ for num in remaining_numbers:
+ answers.append('Number <= 100: ' + num)
+
+ if all(num in output for num in answers):
+ passed()
+ else:
+ failed("Incorrect output. Partition the numbers accordingly.")
+
+
+if __name__ == '__main__':
+ run_common_tests()
+ test_partition()
+ test_output()
diff --git a/learning/katas/python/Examples/Word Count/Word Count/task.html b/learning/katas/python/Examples/Word Count/Word Count/task.html
new file mode 100644
index 0000000..9210a56
--- /dev/null
+++ b/learning/katas/python/Examples/Word Count/Word Count/task.html
@@ -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.
+ -->
+
+<html>
+<h2>Word Count Pipeline</h2>
+<p>This kata is to create a pipeline that counts the number of words.</p>
+<p>For this task, please output the count of each word in the following format:<br/>
+ <pre>
+ word:count
+ ball:5
+ book:3
+ </pre>
+</p>
... 515 lines suppressed ...