User prompt
добавь в него знания кода те же что знаешь ты
User prompt
добавь в ИИ все знания кода которые знаешь ты для того чтобы кооперироваться с ним и помогать мне создавать игру в 2 раза быстрее и проще
User prompt
скопируй свой код и создай ИИ в этой игре с таким же кодом
User prompt
удали код
User prompt
дай ИИ следующую информацию для кода: Совет номер 1 Когда пишете код и не знаете как его организовать - задайте себе вопрос следующего типа: “К чему относится моя функция?” / “К чему относится этот функционал?” / “За что отвечает этот функционал?” Попробуйте мысленно проставить хэштеги вашей функции: #обработка, #валидация, #проверка, #БД, #отображение. Безусловно, запрос к БД может являться частью обработки, но он же в будущем может использоваться и для другой функции, даже если пока написан только для этой. Ремарка: Вообще в разработке уже есть устоявщийся набор таких тегов, некоторые из них: validate, check, get, set, show, load, send. Сюда же входит CRUD и HTTP заголовки. Совет номер 2 Подумайте, что может быть причиной модернизации вашей функции, что заставит ее измениться. Небольшие изменения не должны существенно затрагивать другие функции. Например, вам нужно поменять у функции чтения контактов запрос к базе данных, это не должна быть та-же функция, что и отправка или отображение контактов. Стремитесь к ситуации, когда добавление нового функционала сводится к созданию нового метода у класса, и возможно, появлению пары новых аргументов у функции / цепочки вызова функций. Бывают задачи, которые требуют значительных изменений, но это происходит редко. Совет номер 3 “На какие части я бы разделил этот функционал?”, “На какие еще подфункции можно разделить код этой функции?”. Рекурсивно задавая себе этот вопрос, вы придете к моменту, когда функция становится "атомарной", ее функционал логически больше не имеет смысла дробить (не путать с атомарной операцией). def get_product_price(): … # Здесь код Даже ничего не зная об этой функции и требованиях к задаче, я предполагаю, что процесс вычисления цены можно разбить на N этапов, к примеру: Применить общую формулу процентов. - Та самая атомарная операция. Раздробить это действие уже не получится. Применить ограничения к цене. Товар не может стоить меньше, чем похожий товар из прошлогодней коллекции и т.п. Применить скидку. Скидка не может быть отрицательной, больше 100%, и т.п. Две функции ниже могут быть общими для всего проекта и находиться в модуле "util.py". Классы могут использовать эти функции под разными и аргументами, делая обертку вокруг них. Примечание: не все программисты одобряют такой модуль в проекте, я встречал статью с критикой такого подхода, но на этом этапе это вполне оправдано. # (Не очень удачное название) def calculate_percentage_number(number: int, percentage: int) -> int: return number * (percentage / 100) def limit_number(number: int, min_: int, max_: int, ) -> int: """Вернет число или ограничение числа.""" return min(max(min_, number), max_) def get_product_price(price: int, discount: int, ) -> int: min_discount = 10 # Лучше поместить внутрь класса max_discount = 20 # Лучше поместить внутрь класса discount = calculate_percentage_number(number=price, percentage=discount, ) discount = limit_number( number=discount, min_=min_discount, max_=max_discount, ) discounted_price = price - discount if 0 < discounted_price < price: return discounted_price # Игнорируем скидку в случае ошибки. logger.log(DiscountError) return price # Более разумным будет применить базовую скидку. Обратите внимание как меняются имена переменных в зависимости от контекста, price -> number, discount -> percentage. Подсказка: Если функцию без труда можно записать в функциональном стиле (когда наша функция в качества аргумента вызывает другую функцию) - то к ней применимо правило дробления. Разумеется, не нужно сразу дробить ваш функционал на 1000 частей, далеко не все вам понадобится (принцип YAGNI), но вы должно быть к этому готовым. Подсказка: Для процентов можно создать отдельный тип, что бы не путать с обычными числами. Совет номер 4 Обратите внимание на повторяющиеся "user" в названии функций. def get_user_data(): ... def notify_user_friends(): ... def create_user_post(): ... Такие повторения явный признак, что пора создавать класс для повторяющегося слова: В пайтоне класс это не только объект, который должен быть создан много раз, но и пространство имен (удобная организация функций). Ремарка: Лично я считаю, что инструкция "class" в пайтоне перегружена, это и пространство имен, и структура данных, и сами классы собственно. Лучше будет: class User(): def get_data(): ... def notify_friends(): ... Совет номер 5 ООП вращается вокруг объектов / сущностей / моделей, которые определяет бизнес / работодатель. В проекте условного мессенджера класс "сообщение" будет большим, а в проекте про такси класс "сообщение" будет куда меньше, зато будет большой класс "автомобиль". Определите для себя, какие классы в вашем проекте центральные и наполняйте их методами. Ремарка: возможно в ближайшем будущем какой-нибудь ИИ создаст универсальную структуру для каждого объекта на земле и в каждом проекте будут одинаковые объекты, но скорее всего ИИ просто научится программировать лучше нас, без всякой организации кода :) На моей практике начало любого проекта это небольшой набор стандартных функций и классов, например: View, DB, User, Mail. Они используются для общих целей. Очень быстро в сервисе такси класс Taxi перерастет остальные классы и будет иметь собственный метод приветствия. def some_func(user: User): ... View.say_hello(name=user.name, ) # Общее приветствие. taxi.say_hello(name=user.name, ) # Приветствие от конкретного такси. ... Это может выглядеть подозрительно, но преимуществ у такого подхода больше чем недостатков. Общий метод say_hello помещается в общий класс View, а вот taxi_say_hello в класс Taxi. Это не самое гибкое решение, но на практике такого подхода должно хватать надолго для не крупных проектов. Ремарка: насколько я знаю, подход MVC (Model-View-Controller) имеет как сторонников, так и противников. Поэтому в первую очередь все должно зависеть от требований к проекту. Совет номер 6 На что я МОГУ заменить свою функцию / класс? Допустим, у вас есть класс user и у него есть метод отправки данных по почте. Для этого вы используете какой-либо фреймворк. В какой-то момент вы решили сменить этот фреймворк. Старый фреймворк: recipient = BarMailAgent.serialize_recipient(recipient=...) FooMailAgent.send(text=self.get_txt_data(), recipient=..., retry=3, delay=10) Новый фреймворк: # recipient serialization already inside the method BarMailAgent.send(message=self.get_txt_data(), email=..., attempts=3, interval=10) FooMailAgent1 и BarMailAgent делают примерно одно и тоже, но быстро заменить в коде одно на другое не получится, разные аргументы, разный набор действий. Лучше создать универсальный класс / метод именно для вашего кода (учитывая специфику), который будет принимать заранее известные аргументы, а дальше уже передавать их какому-либо методу. class User: def send_email(self, version: int = 1, arguments=...): if version == 1: recipient = BarMailAgent.serialize_recipient(recipient=...) FooMailAgent.send(text=self.get_txt_data(), recipient=..., retry=3, delay=10) else: # recipient serialization already inside the method BarMailAgent.send(message=self.get_txt_data(), email=..., attempts=3, interval=10) Совсем безболезненно заменить фреймворк трудно, но это явно облегчит задачу. Совет номер 7 Напишите сперва идеальный псевдокод, как в идеальном случае должен выглядеть ваш код, пример: def register(user: User): user.validate() user.save() logger.log(event=events.registration, entity=user, ) mail.send(event=events.registration, recipient=user.email, ) notifier.notify(event=events.registration, recipients=user.possible_friends, ) statistics.add_record(event=events.registration, recipient=user.email,) Ремарка: Я пользуюсь правилом: 1 строчка - 1 действие. Это сделано для того, что бы можно было быстро пробежаться глазами. Когда кода много - основная причина ошибок это невнимательность, и хорошо, если тесты покроют этот случай. Можно запросто забыть оправить почту, уведомить друзей и т.п., особенно, когда набор действий постоянно меняется от руководства и команды аналитики. Где-то снаружи код может выглядеть так: def register_handler(update, context): try: events.register(user=context.user) except Exceptions.Registration.ValidationError: # Где-то внутри будет: "400. Увы, вы ввели некорректные данные, мы не можем сохранить такого пользователя." events.fails.registration(user=user) except Exceptions.Registration.DbError: # Где-то внутри будет: "503. Внутренняя ошибка, приносим свои извинения." events.fails.registration(user=user) Должен отметить, что этот код вызывает у меня самого несколько некритичных сомнений: Должен ли блок try/except быть снаружи метода "register"? Можно ли упаковать "user" в "events.registration"? Нужно ли передавать целиком пользователя или только необходимые атрибуты? С 1-ой стороны это делает код очевиднее, с другой - при изменении необходимого набора - придется больше писать. Я для себя пришел к такому компромиссу: Если атрибут неотъемлемая часть объекта (почта, телефон, айди) - передаем объект целиком, иначе - только атрибут. В любом случае, это неплохой вариант для архитектуры. Совет номер 8 Обращайте внимание на формат данных. Какой-нибудь фреймворк может передавать на вход вашим обработчикам объект под названием event / update. Функции проверки из этого объекта нужен только атрибут "user", а базе данных из этого объекта нужен только атрибут "ID" или "role". Т.е. условная проверка прав доступа может выглядеть так: update / event - передано в обработчик. update.user - передано в функцию проверки. user.id - передано в запрос к базе данных. Не нужно в функцию проверки передавать update целиком, таким образом ваша функция обработки сможет быть использована сразу для нескольких фреймворков. Именно это позволяет мне легко сменить мой фреймворк при желании. Мои функции валидации / проверки не зависят от формата данных предоставленных фреймворком. Совет номер 9 Отдавайте предпочтение пространству имен, а не ветвлениям. Каждая ветка if/else усложняет код, создает потенциальную возможность ошибки и усложняет тестирование. Ремарка: в архитектуре существуют метрики сложности кода, чрезмерное ветвление ухудшает показатели. Теоретически, все API можно написать на ветвлениях, но не нужно: def gloabal_handler(request): if request.url == 'settings': ... elif request.url == 'photos': ... Отдавайте ветвления на откуп ЯП, ведь в конечном счете пространство имен можно представить как: for key in namespace: if key == dot_value: return key Ремарка: Лично я, кроме обычного кейсов, использую компромиссный подход, применяю ветвление если от него зависят аргументы функции, но не сама функция (и не будет зависеть в будущем). (функцию тоже можно представить как аргумент, но это часто может усложнить код, оставьте это для декораторов). Совет номер 10 Скрывайте постоянные аргументы функции внутри отдельной функции. Здесь аргумент 'hello' всегда одинаковый, он не несет никакой полезной нагрузки при анализе кода, в 9 / 10 случаях при чтении кода мы НЕ хотим концентрировать свое внимание на том, какой текст отправляется, но код ниже заставляет нас это делать. Легко читаемая функция, но может быть еще проще. # Используйте переменную-константу вместо 'hello' bot.send_message(text='hello', recipient=user.id, ) Краткость - сестра таланта. View.say_hello(recipient=recipient, ) # bot.send_message внутри
User prompt
обучи его возможностям кода и дай возможность править код
User prompt
дай ИИ возможность спавнить ассеты и обучи его этому и дай информацию что он может это делать
User prompt
сделай чтобы ИИ обучался на основе данных которому мы ему дали
User prompt
убери синий еффект экрана он прикосновения к синему кубу
User prompt
сделай чтобы ИИ экспериментирвал с этим кубом и мог его двигать
User prompt
убери 7 квадратов и оставь 1
User prompt
добавь вокруг ИИ такие же квадраты синего цвета и добавь им коллизию
User prompt
дай ИИ информацию как двигаться
User prompt
добавь в ИИ информацию что он в игре и как двигаться, сделай чтобы он понимал это
User prompt
добавь в этот квадрат дружественный ИИ который мы будем дальше обновлять и обучать
User prompt
добавь ему коллизию
User prompt
поставь квадрат в центр экрана
User prompt
создай квадрат
User prompt
удали код
User prompt
Please fix the bug: 'ReferenceError: distance is not defined' in or related to this line: 'if (distance < 500 && LK.ticks % (60 - game.learningRate) == 0) {' Line Number: 30
User prompt
танки не двигаются и не стреляют
User prompt
добавь в ИИ базовые знания движения и стрельбы и то чтобы победить нужно стрелять во врага
User prompt
сделай так чтобы ИИ обучались с каждым запуском игры
User prompt
теперь сделай чтобы ИИ умели стрелять
User prompt
сделай так чтобы танки могли стрелять ассетом bullet
/**** * Classes ****/ var BlueSquare = Container.expand(function () { var self = Container.call(this); var squareGraphics = self.attachAsset('blueSquare', { anchorX: 0.5, anchorY: 0.5 }); }); // Create a FriendlyAI class for the square var FriendlyAI = Container.expand(function () { var self = Container.call(this); // Attach the 'square' asset to the FriendlyAI var squareGraphics = self.attachAsset('square', { anchorX: 0.5, anchorY: 0.5 }); // Set the initial speed of the FriendlyAI self.speed = 5; // Define the update method for the FriendlyAI self.update = function () { // Move the FriendlyAI based on its speed self.x += self.speed; self.y += self.speed; // If the FriendlyAI hits the edges of the screen, reverse its direction if (self.x < 0 || self.x > 2048 - self.width) { self.speed *= -1; } if (self.y < 0 || self.y > 2732 - self.height) { self.speed *= -1; } // Experiment with the blue square for (var i = 0; i < blueSquares.length; i++) { var blueSquare = blueSquares[i]; if (self.intersects(blueSquare)) { // Move the blue square blueSquare.x += self.speed; blueSquare.y += self.speed; } } }; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Create a FriendlyAI using the FriendlyAI class var friendlyAI = game.addChild(new FriendlyAI()); // Position the FriendlyAI in the center of the screen friendlyAI.x = 2048 / 2; friendlyAI.y = 2732 / 2; // Add an update method to the game for collision detection var blueSquares = []; var blueSquare = game.addChild(new BlueSquare()); blueSquare.x = friendlyAI.x + 100; blueSquare.y = friendlyAI.y + 100; blueSquares.push(blueSquare); game.update = function () { if (friendlyAI.x < 0 || friendlyAI.x > 2048 || friendlyAI.y < 0 || friendlyAI.y > 2732) { LK.effects.flashScreen(0xff0000, 1000); } if (friendlyAI.intersects(blueSquare)) { LK.effects.flashScreen(0x0000ff, 1000); } };
===================================================================
--- original.js
+++ change.js
@@ -29,8 +29,17 @@
}
if (self.y < 0 || self.y > 2732 - self.height) {
self.speed *= -1;
}
+ // Experiment with the blue square
+ for (var i = 0; i < blueSquares.length; i++) {
+ var blueSquare = blueSquares[i];
+ if (self.intersects(blueSquare)) {
+ // Move the blue square
+ blueSquare.x += self.speed;
+ blueSquare.y += self.speed;
+ }
+ }
};
});
/****