• 0.40

  • +0.16

  • ,

Учеба на JavaRush. Поиск работы и прохождение собеседований. Часть 2.

Добрый день! В этой части я расскажу вам о составлении резюме, портфолио, поиске работы, прохождении собеседований, а так же выполнении тестовых заданий. Первая часть

Составление резюме и портфолио. Как всем вам известно, для поиска работы нужно составлять резюме. Существует множество разных статей и советов как это делать, я же расскажу только свое мнение.

Резюме желательно составлять на английском языке и желательно формы CV (на некоторых вакансиях только такую и требуют). Вот ссылка на сайт, где это можно сделать онлайн, но не обязательно придерживаться такой формы как там). Если же будете делать на этом сайте, то убирайте логотипы с резюме (они идут как колонтитулы в ворде).

На первой странице нужно указать всю самую важную информацию, что бы hr заинтересовался вами. Я там писал знание языков, прохождение курса JavaRush и кратко что изучал, прохождение стажировки и какие там были технологии. Далее, поскольку я шел на Android Developer, то писал все технологии и библиотеки какие знал по данной платформе. Далее можно написать про паттерны проектирования, системы контроля версий, системы сборки (maven, gradle), а так же в каких средах разработки вы работали.

После этого напишите о предыдущем опыте работы, если такой присутствует (если он никак не связан с программирование, то просто кратко опишите чего вы там достигли, какие улучшение в работе сделали). Потом идет образование и в самом конце я писал о своих проектах. Так как превалирующее большинство технологий вы напишете на первой странице, то не нужно на 100% повторяться и писать, что все они присутствуют в ваших проектах – напишите только самое важное.

Поиск работы. Начал я отправлять резюме где-то в средине весны 2017. На удивление вакансий на Android Developer даже в Киеве совсем немного, если посмотреть на самых популярных сайтах поиска работы, то их наберется до 30 штук, больше половины которых хотят уровень middle/senior. Но все же они постоянно обновляются и за весь период поиска думаю до сотни резюме я отправил.

Изначально в моем портфолио был только бот в телеграмм, о котором я рассказывал в первой статье и само резюме еще было не совсем привлекательным. Никаких звонков о приглашении на собеседование я не получал.

После пары недель отправки резюме я понял, что нужно его немного переделать, а так же нужно что бы был хотя бы один проект на андроиде в портфолио. В то время как раз я начал делать свое первое андроид приложение. Продолжил отправку резюме где-то через полтора месяца (как раз уже все вакансии обновились), когда первая версия приложения была готова.

По поводу вакансий – они бывают очень разные, но меня всегда сразу отталкивали те, в которых работодатель поленился даже проверить ошибки и форматирование в тексте описания вакансии. Это сразу характеризирует компанию, и работать там не очень хочется.

После того как я немного переделал резюме и расширил портфолио мне начали поступать первые приглашения на собеседования. С самого начала на один день пригласили две компании на позицию middle. Это, конечно, было немного шоком, но все же и приятно, что мое резюме им понравилось.

Прохождении собеседований. Подготовка к первым собеседования была очень туманная. После курса JavaRush и начала изучения android я не занимался теорией вообще, а тут нужно было за пару дней повторить все, что ты знаешь и не знаешь о Java и Android. Это такие моменты, когда ты вообще не понимаешь с чего начать и что учить. Просидел я с утра до вечера читая разные статьи, даже лекции JavaRush открывал по многопоточности.

На первом собеседовании меня долго не спрашивали. Сразу поняли, что на middle я не тяну (путался даже в жизненных циклах activity) и сказали, что я не подхожу. Но в целом очень приятные впечатления сложились и то, что я не подхожу было изначально мне понятно, просто хотел получить опыт прохождения собеседований.

На втором собеседовании было очень круто. Спрашивал меня их тим лидер целый час по теории и все, что я не знал он мне объяснял. Я остался очень доволен, хоть меня туда и не взяли.

Третье собеседование было вообще не техническое, там мне руководители рассказали о проекте, сказали, что кандидат должен сам его вести и было бы неплохо, если бы еще api на php писал. После собеседования я туда идти уже перехотел и когда меня не взяли, но только обрадовался.

Четвертое собеседование по длительности было час, 80% из чего спрашивали по технической части. После собеседования сказали, что сбросят тестовое задание, но потом написали, что я не подхожу и тестовое сбросить они не готовы.

Если говорить о том, что нужно железно знать на позицию Android Developer (думаю на позицию Java Developer так же), то это ОПП. Там сразу будет понятно или ты только заучил как называются основные принципы или же ты знаешь их саму суть и можешь нормально использовать на практике. Так же нужно знать жизненные циклы активити, фрагментов. Про паттерн Observable часто спрашивают, так как он довольно часто используется и даже лежит в основе библиотеки RxJava. А вообще о чем будут спрашивать не угадаешь – могут больше уклон делать на java, а могут на android. Я, например, очень старался сделать хорошим свое портфолио, а меня о моем одном проекте спросили только на последнем собеседовании.

Каких-то алгоритмических задачек у меня на собеседованиях не было. Иногда могли попросить написать на бумажке как реализовать паттерн singleton, либо на доске написать любую сортировку массива. И знать это нужно очень четко, потому что там ты находишься в стрессовой ситуаций и с ограничением по времени.

В предыдущей статье я писал, что у меня друг работает android разработчиком. Вот недавно ему предложили работу в другой компании и так как он уходил, то на его место искали нового кандидата. Он порекомендовал провести со мной собеседование. Изначально мне прислали сделать тестовое задание и дали время 1 неделю с учетом того, что чем быстрее сделаешь, тем лучше. Сделал я задание за 4 дня (друг мне как честный человек в этом деле не помогал). После этого меня пригласили на собеседование.

На всех собеседованиях что у меня были либо сразу задают технические вопросы, либо сначала разговор с hr, а потом техническая часть. Тут же все было вперемешку, что немного сбивало. Сразу и впервые меня попросили на доске написать сортировку — я начал вспоминать какую-то статью на хабре о хорошо оптимизированной сортировке, но так как время ограничено, то написал первое, что пришло в голову.

Собеседование было по больше мене с уклоном на практическую сторону и по времени длилось час. После мне сказали, что дадут ответ в течении двух недель, так как хотят еще посмотреть других кандидатов. И вот недавно мне пришло письмо, что я приглашен на испытательный срок на позицию Android Developer – радости было не отнять:)

Если вы изучаете андроид, все задания на startandroid и других ресурсах уже прошли, то что я могу вам посоветовать попрактиковать. Есть хороший сайт. Там генерируете список json обьектов. Создайте андроид приложение в котором вы будете загружать этот список (в отдельном потоке или в сервисе или с помощью сторонних либ) и отображать его потом пользователю. Базу данных используйте либо SqlLite либо сторонние либы Realm. В списке пусть будет краткая информация, а при нажатии на эл списка – открывается фрагмент с полной информацией. Еще для усложнения задания сделайте адаптацию на планшеты – разделение на два экрана в повороте в горизонтальное положение, в вертикальном же один экран (для этого используйте фрагменты). Так же можно добавить navigation drawer и там какие-то пункты настроек (смена языка приложения, фона, шрифта и т.д.). Что-то похожее было в моем тестовом задании.

В общем, что хочется сказать всем, кому еще предстоит поиск работы – напишите хорошее резюме, так как это самое первое, что вас характеризирует. Выбирайте стажировки и вакансии только в хороших компаниях (по крайней мере в тех, кто не поленился нормально составить описание вакансии). Учите теорию – хоть иногда и кажется, что это только для собеседований, а на практике гугл всегда под рукой, но по своему опыту скажу, что со знанием всей основной теории программировать становится легче. После каждого собеседования изучайте все вопросы, на которые не знали ответа и в которых были не очень уверены – так уже после 4-5 собеседования вы будете знать ответы на все самые распространенные вопросы. Хотелось еще сказать, что бы не волновались, но это все естественно и этого не отнять – мы же не машины :)

Ссылка на все вопросы, что у меня были на собеседованиях (ответы ищете в гугле) – вопросы на собеседованиях
Всем спасибо за внимание и всем удачного трудоустройства!
  • ,

Учеба на JavaRush. Первые проекты, что Вас ждет и как лучше не делать. Часть 1.

Добрый день! Наконец-то я дождался того времени, когда готов поделиться своей историей успеха. Рассказать хочется много, поэтому разделю на две части – так сказать «первые проекты и как лучше не делать» и собственно «поиск работы и прохождение собеседований».
О себе много рассказывать не буду, скажу только, что как и почти все здесь я отучился и поработал на другой специальности, но потом решил стать программистом:)

Поговорим сразу об обучении. Начал я заниматься на JavaRush в начале 2016 года. Долго выбирал где изучать программирование и, конечно, как и все наши люди не хотел платить за обучение. Изучать хотел именно Java, так как моя мечта – программировать на Android. Курс JavaRush несколько раз попадался мне на глаза во время поиска, но я его отбрасывал, так как он условно-бесплатный. Начал заниматься по видео урокам на ютубе. Потом все же какая-то сила меня заставила попробовать порешать бесплатные задачки на JavaRush, и я настолько удивился, что после прохождения 50 видео уроков (я считал их довольно нормальными) и написанию кода за лектором, я с большим трудом и далеко не с первой попытки решал начальные задачи курса. Качество курса и то, что он мне даст, если я его пройду полностью я оценил почти сразу, потом посмотрел на форуме, что время от времени там бывают хорошие скидки на подписку решил, что буду брать полную версию.
Да, многие учащиеся злятся и негодуют насчет курса — задачи дают по материалу, который еще не рассматривали, валидатор их не понимает и много-много чего можно почитать на форуме и в комментариях. И знаете что? Я тоже таким был:) У меня до сих пор висит большая задача на 34 уровне и я перепробовал все решения, но ее не принимает валидатор. Хорошо, что в тех поддержке мне докинули черной материи и я смог до конца добить курс. В общем, как выпускник курса JavaRush скажу свое субъективное мнение, что мне понравилось и не понравилось в курсе (да простят меня админы).

Понравилось: количество задач, мгновенная проверка задач, удаленное обучение, обучение не имеет привязки к твоему рабочему графику, структурированность курса, форум учащихся, а так же цена.
Не понравилось: за время прохождения курса начинаешь подстраиваться под валидатор и потом сложно от этого отвыкать, что бы подумать и найти какие-то другие подходы(но все же такая идея и она тут реализована довольно хорошо), ошибки в некоторых задачах, сильная замысловатость в некоторых условиях задач (хорошо, что для таких случаев есть форум), так же пробовал новый интерфейс – не очень понравился, благо есть возможность переключится на старый.

Если это подытожить, то я доволен курсом и тем, что он мне дал. Вспоминаю себя год назад, как мне друг пытался объяснить что такое boolean, void, что такое методы и как они возвращают значения. Помню как долго не мог понять зачем нужно возвращать эти значения:)
Сейчас же мне часто вспоминается сцена из фильма Матрица:
Нео: Ты что научишь меня уворачиваться от пуль?
Морфиус: Когда придет время тебе это уже не понадобится.
И действительно, когда пришло время у него уже априори были эти навыки.

На 30 уровне курса я хотел попасть на стажировку, которую предлагает JavaRush. Посмотрел тестовое задание и немного ужаснулся. Очень надеялся, что поможет друг его сделать, но за неделю до дедлайна он сказал, что вот тебе Гугл, вот тут вбивай все технологии и там будет куча примеров. Я ему очень благодарен, что так получилось, так как тогда я впервые почувствовал, что значит быть программистом. За 4 полных дня я сделал задание и был невероятно рад, что попал на стажировку.

Стажировка. Стажировку я до конца не прошел, так как в это же время начал делать свой первый проект и все же он для меня оказался приоритетнее и интереснее + я не хотел работать в enterprise. Что могу сказать о самой стажировке – есть свои плюсы и минусы, но в целом довольно таки хорошо. Если планируете дальше идти в enterprise, то думаю ее стоит пройти.

Первый проект. Как и упоминал выше, что где-то на 30х уровнях я попал на стажировку и начал делать свой проект. Это был и есть бот в телеграмме. Желание создать бота было у меня еще на 20-30 уровнях курса, но я никак не мог найти подходящей либы либо инструкции how to start. И все же случайным образом мне попалась такая статья и я сразу начал пробовать. Если кому интересно – вот ссылка на статью —
How to write bot in telegram Java
Откровенно говоря, автор этой статьи мне потом еще очень сильно помог, речь о чем пойдет чуть ниже. Идея для бота была такая – мне как программисту нужно изучать Английский язык. Грамматику я знал относительно хорошо, а вот словарный запас захотел подтянуть. Подумал, что неплохо бы было иметь бота для изучения слов. Подробную информацию о боте я уже писал в статье ранее, поэтому повторятся не буду – вот ссылка Телеграм бот Words

Расскажу, с какими трудностями мне пришлось столкнуться, при его создании. Во-первых это первая работа с telegram api. Хоть многие и говорят, что это одно из простейших и наиболее лучше документированных api, но мне тогда как новичку было очень сложно. Все делал путем подбора :) Иногда на то, что бы сделать какую-то фичу, например, убрать кнопку после ее нажатия мне приходилось потратить полный день. Где-то за пол месяца удалось написать самую первую бета версию, весь код которой был в одном java классе, и хотел попробовать залить ее на сервер. Проект у меня не коммерческий, поэтому платные сервера я сразу же отбрасывал. Вспомнил о сервере heroku, который кстати используют для размещения сайта на стажировке. Пробовал этот сервер два полных дня и уже был в полном отчаянии, так как не получалось вообще ничего – все инструкции которые были относились к сайтам, а у меня бот и там нужно действовать немного по-другому. В итоге я решил написать автору статьи о боте и спросить, какой он использует сервер для размещения бота. И тут удача мне улыбнулась – автор оказался очень крутым программистом (я с ним до сих пор поддерживаю связь), и он мне предложил разместить бота у себя на Linux сервере (и если я знаю линус, то выделит мне аккаунт). На начальное изучение линукса ушло один день и, конечно, не без ошибок и сложностей бот начал крутиться на сервере. Так же между всем этим делом я добил курс JavaRush и был очень доволен :)

Базу данных для бота я выбрал MySql, пересмотрел много уроков по оптимизации таблиц, выбору движка и всего прочего. Дам совет всем, кто будет делать свой первый проект – старайтесь сразу продумать всю его структуру и строить хотя бы относительно расширяемую архитектуру. Я же свой переписывал, наверное, раза 3 из-за таких ошибок. Да, это сложно, так как очень часто ты не знаешь что захочешь следующее добавить в свой проект, но все же на минимальном уровне сделать можно. Не пишите весь код в одном классе!!! Попробуйте использовать MVC, вспомните ООП и т.д. Самое смешное, что некоторые основные принципы ООП я начал использовать в проекте, когда он уже был почти готов. До этого я даже не задумывался о них. Конечно, пользователю вообще все равно на каком языке написан продукт, какие там используются паттерны и технологии использовались, но когда вы через пару месяцев его открываете и хотите что-то туда добавить, то очень много хороших слов о себе подумаете :) Так же не забывайте делать логирование – это позволяет как отслеживать ошибки, так и смотреть какими функциями пользователи больше пользуются и что нужно дальше развивать. В телеграмме это кстати можно очень круто сделать – отправлять все логи в режиме реального времени себе в приватный канал, так сказать можно сделать некую big data :)

Если подытожить про первый проект, то времени на его создание ушло где-то 3 месяца, сейчас там более 14 тысяч зарегистрированных пользователей, много которых стали постоянными и изучают иностранные слова ежедневного.

Второй проект. Моя цель была стать Android программистом, поэтому когда более менее закончив с ботом я решил адаптировать его на Android платформу. Начал обучение с курса startandroid, так же мой лучший друг android разработчик давал мне много крутых заданий, проверял их и говорил что нужно переделать и доделать. Когда получил уже базовые навыки начал делать свое приложение. Как и с первым проектом было много разных трудностей, но если брать в целом, то немного меньше. Где-то за полтора месяца была готовая первая бета версия (пару раз пришлось переписывать весь дизайн приложения, так как я понятия не имел как он будет выглядеть). Потом я зарегистрировался как разработчик в гугл плей и залил его в маркет. Последнее время занимался оптимизацией и синхронизацией двух своих проектов. Для общей базы данных выбрал Firebase – очень хорошая документация, много уроков и для небольших проектов бесплатной версии в 1гб объема более чем достаточно.

Если кратко сказать о наибольших трудностях во втором проекте (я думаю некоторые из этих трудностей возникают и у опытных разработчиков), то это — создание многопоточности в android, много заморочек з размерами и расширениями экранов, для создания дизайна пришлось подружиться с photoshop, поддержка старых версий андроида, а так же никогда не используйте Recycler View, если у вас в списке будет анимация :) После блокировки в Украине Яндекса, а именно от туда я беру большую часть перевода и озвучки слов, пришлось добавлять дополнительные проверки в код, и просто сообщать пользвателям, что бы воспользовались vpn. Трудности даже возникли при регистрации в гугл плей – там что бы стать разработчиком нужно одноразово(в отличии от апл стора) заплатить взнос в размере 25$. У меня же при оплате стоял лимит на карточке и оплата моя зависла. Пришлось пообщаться с тех поддержкой гугла и в общем они меня посылали от одного оператора к другому, пока я не понял, что меня просто вежливо посылают :) Пришлось удалять все и заново регистрироваться (сразу бы до этого додумался).

Еще пару слов по поводу продвижения своих проектов. С ботом дела обстояли немного проще – сама идея ботов относительно новая (в самый мейнстрим я не попал, но все же нормально). Есть каталог ботов, группы вк, фб другие ресурсы. Сейчас мой бот занимает 5 место в разделе образовательных и для меня это очень хороший результат. Что бы продвигаться в каталоге ботов, нужно что бы его оценивали. Я сделал предложение для пользователя о голосовании, которое возникает всего один раз (сам не люблю навящивости), когда пользователь сыграет определенное количество игр (как бы проведет некоторое время в боте).

С андроид приложением дела обстоят намного хуже. Скажу одно – без рекламы ваше приложение никто не заметит в маркете даже по ключевым словам, так как их там миллионы. После того как я сделал синхронизацию между проэктами, то дал объявление в боте о моем приложении. После этого у меня появилось первые 14 скачиваний :)

Если кто дочитал до этого момента, то вот ссылка на приложение, если будет интересно — Android приложение Words.
Ссылка же на бота есть в статье о нем чуть выше по тексту.

Всем спасибо за внимание. О своем опыте собеседований, вопросах которые там задавали и вообще поиске работы расскажу во второй части.
  • ,

level34.lesson15.big01 Задание 10

В игре будет несколько уровней, все уровни будут храниться в текстовом файле. Сейчас мы напишем тестовую реализацию загрузчика уровней LevelLoader. Почему тестовую? Полный функционал нам пока не нужен, он довольно сложный, оставим его на потом. А пока: 10.1. Создай класс LevelLoader в пакете model. 10.2. Добавь в класс конструктор, принимающий Path levels. Параметр levels – это путь к тестовому файлу, содержащему описание уровней. 10.3. Добавь в класс LevelLoader метод GameObjects getLevel(int level). Пока не важно, что будет возвращать этот метод. Пусть он всегда возвращает набор из: одного игрока, одного дома, одного ящика и нескольких стен. Так будет проще отладить работу игры. Координаты каждого объекта должны быть не нулевые и кратны половине FIELD_SELL_SIZE (центр каждого объекта должен быть в середине ячейки поля).

import java.nio.file.Path;
import java.util.HashSet;
import java.util.Set;
public class LevelLoader {
    private Path levels;
    public LevelLoader(Path levels) {
        this.levels = levels;
    }
    public GameObjects getLevel(int level) {
        Set<Wall> walls = new HashSet<>();
        Set<Box> boxes = new HashSet<>();
        Set<Home> homes = new HashSet<>();
        Player player;
        walls.add(new Wall(200, 200));
        walls.add(new Wall(240, 240));
        walls.add(new Wall(280, 280));
        boxes.add(new Box(160, 160));
        homes.add(new Home(300, 300));
        player = new Player(100, 100);
        return new GameObjects(walls, boxes, homes, player);
    }
}


Я не пойму почему не проходит? Я уже перечитал тему тоже с обсуждением этого задания и все советы, что там были перепробовал — безрезультатно. Написано «Координаты каждого объекта должны быть не нулевые и кратны половине FIELD_SELL_SIZE». FIELD_SELL_SIZE у нас 20, половина — 10. Значит любое число с нулем кратное половине FIELD_SELL_SIZE. Подскажите куда обратить внимание.
  • ,

level27.lesson15.big01 задание 14

Уже пару дней сижу с этим заданием — перечитал все форумы, все что можно было варианты перепробовал. Может быть чего-то не замечаю — подскажите что можно поправить.

Задание 14

1. Внутри StatisticStorage создайте единственный метод void put(EventDataRow data).

2. Чтобы методом put(EventDataRow data) добавить объект data в данные карты, нужен тип события — EventType.
Будет правильно, если событие будет хранить в себе свой тип. Поэтому
2.1. в интерфейс EventDataRow добавь метод EventType getType()
2.2. реализуй этот метод в каждом классе-событии: CookedOrderEventDataRow, NoAvailableVideoEventDataRow, VideoSelectedEventDataRow

3. Сделай так, чтобы к методу void put(EventDataRow data) нельзя было доступиться за пределами класса StatisticManager.
Пользуйтесь особенностями вложенных классов.

Теперь остается растыкать вызовы StatisticManager-а в те места, которые генерируют события.

4. Зарегистрируйте событие для повара во время приготовления еды.
Добавьте геттер для поля dishes в класс Order, используйте его при создании события.

5. Зарегистрируйте событие «видео выбрано» перед его отображением.

AdvertisementManager
public class AdvertisementManager {
    private int timeSeconds;

    private final AdvertisementStorage storage = AdvertisementStorage.getInstance();

    public AdvertisementManager(int timeSeconds) {
        this.timeSeconds = timeSeconds;
    }

    public void processVideos() {
        List<Advertisement>videos = optimalVideo(powerList(storage.list()));
        int leftSec = timeSeconds;

        Collections.sort(videos, new Comparator<Advertisement>() {
            @Override
            public int compare(Advertisement o1, Advertisement o2) {
                int result = Long.compare(o1.getAmountPerOneDisplaying(), o2.getAmountPerOneDisplaying());
                if (result != 0) {
                    return -result;
                }
                long first = o1.getAmountPerOneDisplaying() * 1000 / o1.getDuration();
                long second = o2.getAmountPerOneDisplaying() * 1000 / o2.getDuration();

                return Long.compare(first, second);
            }
        });
        for (Advertisement advertisement : videos) {
            int q = advertisement.getDuration()/60;
            if (q > leftSec) {
                continue;
            }
            long sumAmount = 0;
            int sumDuration = 0;
            for(Advertisement a : videos){
                sumAmount += a.getAmountPerOneDisplaying();
                sumDuration += a.getDuration();
            }
            StatisticManager.getInstance().register(new VideoSelectedEventDataRow(videos,sumAmount,sumDuration));
            ConsoleHelper.writeMessage(String.format("%s  is displaying... %d, %d",
                    advertisement.getName(),
                    advertisement.getAmountPerOneDisplaying(),
                    advertisement.getAmountPerOneDisplaying() * 1000 / advertisement.getDuration()));

            leftSec -= q;
            advertisement.revalidate();
        }
        if(videos.size()<=0 || videos==null){
            StatisticManager.getInstance().register(new NoAvailableVideoEventDataRow(timeSeconds));
            throw new NoVideoAvailableException();
        }
    }
//поиск оптимального видео


StatisticManager
public class StatisticManager {
    private static StatisticManager ourInstance = new StatisticManager();

    private static StatisticManager.StatisticStorage storage = getInstance().new StatisticStorage();

    public static StatisticManager getInstance() {
        return ourInstance;
    }

    private StatisticManager() {

    }

    public void register(EventDataRow data){
        storage.put(data);
    }
    private class StatisticStorage{
        private Map<EventType, List<EventDataRow>> storage = new HashMap<>();

        public StatisticStorage() {
            for(EventType e : EventType.values()){
                storage.put(e, new ArrayList<EventDataRow>());
            }
        }
       private void put(EventDataRow data){
            storage.get(data.getType()).add(data);
        }
    }
}


Cook
public class Cook extends Observable implements Observer {
    private String name;
    @Override
    public void update(Observable o, Object arg) {
        Order order =(Order) arg;
        ConsoleHelper.writeMessage("Start cooking - " + arg + ", cooking time " + order.getTotalCookingTime() + "min");
        StatisticManager.getInstance().register(new CookedOrderEventDataRow(order.tablet.toString(),name,order.getTotalCookingTime()*60,order.getDishes()));
        setChanged();
        notifyObservers(arg);

    }

    public Cook(String name) {
       this.name = name;
    }

    @Override
    public String toString() {
        return name;
    }
}


CookedOrderEventDataRow
public class CookedOrderEventDataRow implements EventDataRow {
    private String tabletName;
    private String cookName;
    private int cookingTimeSeconds;
    private List<Dish> cookingDishs;
    Date currentDate;

    public CookedOrderEventDataRow(String tabletName, String cookName, int cookingTimeSeconds, List<Dish> cookingDishs) {
        this.tabletName = tabletName;
        this.cookName = cookName;
        this.cookingTimeSeconds = cookingTimeSeconds;
        this.cookingDishs = cookingDishs;
        this.currentDate = new Date();
    }
    @Override
    public EventType getType() {
        return EventType.COOKED_ORDER;
    }
}


NoAvailableVideoEventDataRow
public class NoAvailableVideoEventDataRow implements EventDataRow {
    private int totalDuration;
    Date currentDate;

    public NoAvailableVideoEventDataRow(int totalDuration) {
        this.totalDuration = totalDuration;
        this.currentDate = new Date();
    }

    @Override
    public EventType getType() {
        return EventType.NO_AVAILABLE_VIDEO;
    }
}


VideoSelectedEventDataRow
public class VideoSelectedEventDataRow implements EventDataRow {
    private List<Advertisement> optimalVideoSet;
    private long amount;
    private int totalDuration;
    Date currentDate;

    public VideoSelectedEventDataRow(List<Advertisement> optimalVideoSet, long amount, int totalDuration) {
        this.optimalVideoSet = optimalVideoSet;
        this.amount = amount;
        this.totalDuration = totalDuration;
        this.currentDate = new Date();
    }

    @Override
    public EventType getType() {
        return EventType.SELECTED_VIDEOS;
    }
}
  • ,

level20.lesson10.bonus03

Долго сидел думал над этой задачей и вроде удалось решить — вывод правильный. Создал отдельный метод для каждого прохода. Поставил даже проверку на 1 символ(хотя в условии четко сказано, что должно быть слово)- тестирование никак не проходит.
Подскажите, пожалуйста, что еще упустил и на что нужно обратить внимание.

/* Кроссворд
1. Дан двумерный массив, который содержит буквы английского алфавита в нижнем регистре.
2. Метод detectAllWords должен найти все слова из words в массиве crossword.
3. Элемент(startX, startY) должен соответствовать первой букве слова, элемент(endX, endY) — последней.
text — это само слово, располагается между начальным и конечным элементами
4. Все слова есть в массиве.
5. Слова могут быть расположены горизонтально, вертикально и по диагонали как в нормальном, так и в обратном порядке.
6. Метод main не участвует в тестировании
*/

public class Solution {
    public static void main(String[] args) {
        int[][] crossword = new int[][]{
                {'f', 'd', 'e', 'r', 'l', 'k'},
                {'u', 's', 'a', 'm', 'e', 'o'},
                {'l', 'n', 'g', 'r', 'o', 'v'},
                {'m', 'l', 'p', 'r', 'r', 'h'},
                {'p', 'o', 'e', 'e', 'j', 'j'}
        };
        detectAllWords(crossword, "home", "same","h","rrh","erl","ngr");
        /*
Ожидаемый результат
home - (5, 3) - (2, 0)
same - (1, 1) - (4, 1)
         */
    }
    public static List<Word> detectAllWords(int[][] crossword, String... words) {
        List<Word> list = new ArrayList<>();
        String name = "";
        for (String s : words) {
            name = s;
            Word w = new Word(name);
            char[] cr = name.toCharArray();
            for (int i = 0; i < crossword[0].length; i++) {
                for (int j = 0; j < crossword.length; j++) {
                    if (crossword[j][i] == cr[0]) {
                        w.setStartPoint(i, j);
                        if(cr.length==1){
                           list.add(w);
                            break;
                        }
                        if (roadUpRight(crossword, w)) {
                            list.add(w);
                            break;
                        }
                        if (roadUpLeft(crossword, w)) {
                            list.add(w);
                            break;
                        }
                        if (roadDownRight(crossword, w)) {
                            list.add(w);
                            break;
                        }
                        if (roadDownLeft(crossword, w)) {
                            list.add(w);
                            break;
                        }
                        if (roadRight(crossword, w)) {
                            list.add(w);
                            break;
                        }
                        if (roadLeft(crossword, w)) {
                            list.add(w);
                            break;
                        }
                        if (roadUp(crossword, w)) {
                            list.add(w);
                            break;
                        }
                        if (roadDown(crossword, w)) {
                            list.add(w);
                            break;
                        }
                    }
                }
            }
        }
        for (Word w : list) {
            System.out.println(w.toString());
        }
        return list;
    }

    public static boolean roadUpRight(int[][] crossword, Word word) {
        if (word.startX + 1 == crossword[0].length || word.startY - 1 == -1) {
            return false;
        }
        char[] cr = word.text.toCharArray();
        int c = 1;
        int j = word.startY - 1;
        for (int i = word.startX + 1; i < crossword[0].length; i++) {
            if (crossword[j][i] == cr[c]) {
                c++;
                word.setEndPoint(i, j);
                if (c == cr.length)
                    return true;
                if (j - 1 >= 0) {
                    j--;
                } else {
                    return false;
                }
            } else {
                return false;
            }
        }
        return false;
    }
    public static boolean roadUpLeft(int[][] crossword, Word word) {
        if (word.startX - 1 == -1 || word.startY - 1 == -1) {
            return false;
        }
        char[] cr = word.text.toCharArray();
        int c = 1;
        int j = word.startY - 1;
        for (int i = word.startX - 1; i >= 0; i--)
            if (crossword[j][i] == cr[c]) {
                c++;
                word.setEndPoint(i, j);
                if (c == cr.length)
                    return true;
                if (j - 1 >= 0) {
                    j--;
                } else {
                    return false;
                }
            } else {
                return false;
            }
        return false;
    }
    public static boolean roadDownRight(int[][] crossword, Word word) {
        if (word.startX + 1 == crossword[0].length || word.startY + 1 == crossword.length) {
            return false;
        }
        char[] cr = word.text.toCharArray();
        int c = 1;
        int j = word.startY + 1;
        for (int i = word.startX + 1; i < crossword[0].length; i++)
            if (crossword[j][i] == cr[c]) {
                c++;
                word.setEndPoint(i, j);
                if (c == cr.length)
                    return true;
                if (j < crossword.length) {
                    j++;
                } else return false;
            } else return false;
        return false;
    }
    public static boolean roadDownLeft(int[][] crossword, Word word) {
        if (word.startX - 1 == -1 || word.startY + 1 == crossword.length) {
            return false;
        }
        char[] cr = word.text.toCharArray();
        int c = 1;
        int j = word.startY + 1;
        for (int i = word.startX - 1; i >= 0; i--)
            if (crossword[j][i] == cr[c]) {
                c++;
                word.setEndPoint(i, j);
                if (c == cr.length)
                    return true;
                if (j < crossword.length) {
                    j++;
                } else return false;
            } else return false;
        return false;
    }
    public static boolean roadRight(int[][] crossword, Word word) {
        if (word.startX + 1 == crossword[0].length) {
            return false;
        }
        char[] cr = word.text.toCharArray();
        int c = 1;
        for (int i = word.startX + 1; i < crossword[0].length; i++)
            if (crossword[word.startY][i] == cr[c]) {
                c++;
                word.setEndPoint(i, word.startY);
                if (c == cr.length)
                    return true;
            }
        return false;
    }
    public static boolean roadLeft(int[][] crossword, Word word) {
        if (word.startX - 1 == -1) {
            return false;
        }
        char[] cr = word.text.toCharArray();
        int c = 1;
        for (int i = word.startX - 1; i >= 0; i--)
            if (crossword[word.startY][i] == cr[c]) {
                c++;
                word.setEndPoint(i, word.startY);
                if (c == cr.length)
                    return true;
            }
        return false;
    }
    public static boolean roadUp(int[][] crossword, Word word) {
        if (word.startY - 1 == -1) {
            return false;
        }
        char[] cr = word.text.toCharArray();
        int c = 1;
        for (int j = word.startY - 1; j >= 0; j--)
            if (crossword[j][word.startX] == cr[c]) {
                c++;
                word.setEndPoint(word.startX, j);
                if (c == cr.length)
                    return true;
            }
        return false;
    }
    public static boolean roadDown(int[][] crossword, Word word) {
        if (word.startY + 1 == crossword.length) {
            return false;
        }
        char[] cr = word.text.toCharArray();
        int c = 1;
        for (int j = word.startY + 1; j < crossword.length; j++)
            if (crossword[j][word.startX] == cr[c]) {
                c++;
                word.setEndPoint(word.startX, j);
                if (c == cr.length)
                    return true;
            }
        return false;
    }
    public static class Word {
        private String text;
        private int startX;
        private int startY;
        private int endX;
        private int endY;

        public Word(String text) {
            this.text = text;
        }
        public void setStartPoint(int i, int j) {
            startX = i;
            startY = j;
        }

        public void setEndPoint(int i, int j) {
            endX = i;
            endY = j;
        }
        @Override
        public String toString() {
            return String.format("%s - (%d, %d) - (%d, %d)", text, startX, startY, endX, endY);
        }
    }
}