From 6058a2a4e6ebe818849ef7bf7cae3f5426ee72da Mon Sep 17 00:00:00 2001 From: Aleksandr Minkin Date: Sun, 10 May 2026 12:04:11 +0300 Subject: [PATCH 1/2] feat: implement main page design --- app/ask/page.tsx | 12 +- app/globals.css | 7 + app/page.tsx | 446 +++++++++++++++++---------- components/home/HomeSearchForm.tsx | 51 +++ components/layout/Footer.tsx | 100 ++++-- components/layout/Header.tsx | 114 ++++--- components/layout/MobileDocsMenu.tsx | 2 +- components/search/AskStackMirea.tsx | 17 +- components/ui/ThemeToggle.tsx | 11 +- lib/home.ts | 74 +++++ public/search-index.json | 2 +- 11 files changed, 599 insertions(+), 237 deletions(-) create mode 100644 components/home/HomeSearchForm.tsx create mode 100644 lib/home.ts diff --git a/app/ask/page.tsx b/app/ask/page.tsx index 47dc85f..0ab7ad2 100644 --- a/app/ask/page.tsx +++ b/app/ask/page.tsx @@ -10,7 +10,15 @@ export const metadata: Metadata = { description: "Семантический поиск по материалам StackMIREA: темы, практики, сравнение дисциплин и быстрый вход в нужные страницы." }; -export default function AskPage() { +interface AskPageProps { + searchParams?: { + q?: string; + }; +} + +export default function AskPage({ searchParams }: AskPageProps) { + const initialQuery = typeof searchParams?.q === "string" ? searchParams.q : ""; + return (
@@ -39,7 +47,7 @@ export default function AskPage() {
- +
); diff --git a/app/globals.css b/app/globals.css index ce525b4..e903f03 100644 --- a/app/globals.css +++ b/app/globals.css @@ -22,6 +22,7 @@ --border: 210 10% 87%; --input: 210 10% 87%; --ring: 0 0% 18%; + --site-header-height: 104px; } .dark { @@ -68,6 +69,12 @@ body { hsl(var(--background)); } +@media (min-width: 768px) { + :root { + --site-header-height: 96px; + } +} + @media (prefers-reduced-motion: no-preference) { html[data-theme-transition="wave"]::view-transition-old(root), html[data-theme-transition="wave"]::view-transition-new(root) { diff --git a/app/page.tsx b/app/page.tsx index 2f68bd4..d992a82 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,191 +1,309 @@ import Link from "next/link"; -import { ArrowRight, Brain, BrainCircuit, ExternalLink, GitPullRequest, ListChecks } from "lucide-react"; +import { + ArrowRight, + Atom, + BookOpenText, + BrainCircuit, + Braces, + Boxes, + Coffee, + Database, + GitBranch, + Network, + Sigma, + SquareTerminal +} from "lucide-react"; -import { ContributorsSection } from "@/components/contributors/ContributorsSection"; -import { WhatsNewSection } from "@/components/home/WhatsNewSection"; -import { buttonVariants } from "@/components/ui/button"; -import { cn, REPO_URL } from "@/lib/utils"; -import { getContributorsOverview } from "@/lib/contributors"; +import { HomeSearchForm } from "@/components/home/HomeSearchForm"; +import { getHomePageOverview } from "@/lib/home"; +import type { TrackIconKey } from "@/lib/tracks"; +import { cn } from "@/lib/utils"; +import { formatWhatsNewDate } from "@/lib/whats-new"; export const dynamic = "force-static"; -const publicationRules = [ - { - title: "Публикуй материал в нужный трек", - description: "Размещай файл в соответствующем разделе документации и соблюдай структуру текущего трека." - }, - { - title: "Соблюдай единый формат", - description: "Используй понятную структуру: цель, шаги решения, код, результат и краткие выводы." - }, - { - title: "Оформляй кодовые примеры", - description: "Добавляй язык в код-блоки и оставляй только воспроизводимые, проверенные фрагменты." - }, - { - title: "Фиксируй контекст и источники", - description: "Если материал опирается на внешние источники, обязательно оставляй ссылки и пояснения." - }, - { - title: "Проверяй изменения перед PR", - description: "Перед публикацией запускай `npm run lint` и `npm run typecheck`, чтобы не ломать сборку." - } -]; - -const pullRequestLinks = [ - { - title: "Создать Pull Request", - href: `${REPO_URL}/compare?expand=1`, - description: "Откроет форму сравнения веток и создания PR для публикации." - }, - { - title: "Все Pull Request", - href: `${REPO_URL}/pulls`, - description: "Список открытых и закрытых PR по проекту." - }, - { - title: "Открытые Pull Request", - href: `${REPO_URL}/pulls?q=is%3Apr+is%3Aopen`, - description: "Быстрый фильтр для проверки, что уже находится на ревью." - } -]; +const displayTitleByTrackId: Record = { + algorithms: "Алгоритмы", + ai: "AI", + bigdata: "Большие данные", + java: "Java", + python: "Python", + react: "React", + "procedural-programming": "Процедурное программирование" +}; + +const accentByTrackId: Record = { + react: "#79A7FF", + bigdata: "#6C95FF", + java: "#7CA1FF", + algorithms: "#89ABFF", + ai: "#9E8BFF", + python: "#7FBAFF", + "procedural-programming": "#75A6FF" +}; + +const iconByTrackId: Partial> = { + react: Atom, + bigdata: Database, + java: Coffee, + algorithms: Sigma, + ai: BrainCircuit, + python: Braces, + "procedural-programming": SquareTerminal +}; + +const fallbackIconByKey: Record = { + bot: BrainCircuit, + brain: Boxes, + code2: SquareTerminal, + database: Database, + gitPullRequest: GitBranch, + listChecks: Network, + sigma: Sigma +}; + +const changeToneByStatus = { + new: "bg-[#dff7da] text-[#2f9557] dark:bg-emerald-500/15 dark:text-emerald-300", + updated: "bg-[#e4edff] text-[#5f84e7] dark:bg-blue-500/15 dark:text-blue-300" +} as const; + +function getHomeDisplayTitle(trackId: string, title: string) { + return displayTitleByTrackId[trackId] ?? title; +} + +function getTrackIcon(trackId: string, iconKey: TrackIconKey) { + return iconByTrackId[trackId] ?? fallbackIconByKey[iconKey]; +} + +function getTrackAccent(trackId: string) { + return accentByTrackId[trackId] ?? "#7C9FFF"; +} + +function getRecentChangeTone(isNew: boolean) { + return isNew ? changeToneByStatus.new : changeToneByStatus.updated; +} export default function HomePage() { - const { authors, productTeam, contentManagers, devTeam } = getContributorsOverview(); + const { trackCards, popularTracks, recentMaterials, featuredAuthors } = getHomePageOverview(); return ( -
-
-
-
- -
-

- - Центр документации StackMIREA -

+
+
+
+
+
-

- Практики и ноутбуки -
- в едином формате docs -

- -

- Учебные материалы StackMIREA по ключевым IT-дисциплинам. Каждая страница оформлена как техническая - документация с кодом, разбором и привязкой к исходникам. -

+
+
+

+ Практики и ноутбуки +
+ в едином формате docs +

-
- - Открыть документацию - - +

+ Учебные материалы StackMIREA по ключевым IT-дисциплинам. Каждая страница оформлена как техническая + документация с кодом, разбором и привязкой к исходникам. +

+
+ +
- - Спроси StackMIREA + + Открыть документацию
-
-
-
-

- - Бета семантического поиска -

-

Новая навигация по материалам

-

- Есть вопрос? Можешь найти ответы на него в ИИ-поиске. - Например: `где есть KNN`, `покажи материалы по pandas`, `сравни MVC и OOP`. -

-
+
+
+ {trackCards.map((track) => { + const Icon = getTrackIcon(track.id, track.iconKey); + const accentColor = getTrackAccent(track.id); - - Открыть "Спроси StackMIREA" - - + return ( + +
+
+ +
+ + + + + {track.itemsCount} материалов + +
+ +
+
+
+ +
+ +
+

+ {getHomeDisplayTitle(track.id, track.title)} +

+

{track.description}

+
+ + + Открыть трек + + + + ); + })}
- - - - -
-
-
- - Правила публикации -
-

Как публиковать материалы в StackMIREA

-
    - {publicationRules.map((rule, index) => ( -
  1. - - {index + 1} - -
    -

    {rule.title}

    -

    {rule.description}

    -
    -
  2. - ))} -
-
- -
-
- - Публикация через PR -
-

Ссылки на Pull Request

-

- Для публикации открывай PR с изменениями в документации. В описании укажи, что именно добавлено и в каком - треке лежит материал. +

+
+

ИИ-поиск по StackMIREA

+

+ Задайте вопрос своими словами, умный поиск найдёт ответ в коде и разборах.

-
- {pullRequestLinks.map((item) => ( - - - {item.title} - {item.description} - - - - ))} -
-
+ +
+
+ +
+
+

Что нового в сообществе

+

Новые решения, популярные материалы и авторы сообщества

+
+ +
+
+

Популярные

+
+ {popularTracks.map((track) => ( + +
+ + {track.itemsCount} материалов + + + {track.itemsCount} + +
+

{getHomeDisplayTitle(track.id, track.title)}

+

{track.description}

+
+ Материалы курса и раздела + + Просмотреть + + +
+ + ))} +
+
+ +
+

Изменения

+
+ {recentMaterials.map((item) => ( + +
+ + {item.sectionTitle} + + + {item.isNew ? "Новый" : "Обновлено"} + +
+

{item.title}

+

+ Последнее изменение {formatWhatsNewDate(item.updatedAt ?? item.createdAt)} +

+
+ {formatWhatsNewDate(item.updatedAt ?? item.createdAt)} + + Просмотреть + + +
+ + ))} +
+
+ +
+

Авторы

+
+ {featuredAuthors.map((author) => ( + + {`Аватар + + + @{author.github} + + {author.firstContributionAt + ? `Первая публикация ${formatWhatsNewDate(author.firstContributionAt)}` + : `${author.docsCount} публикаций в проекте`} + + + + + Просмотреть + + + ))} + + {featuredAuthors.length === 0 ? ( +
+ История авторов пока недоступна в этой сборке. +
+ ) : null} +
+
+
); diff --git a/components/home/HomeSearchForm.tsx b/components/home/HomeSearchForm.tsx new file mode 100644 index 0000000..c2f9885 --- /dev/null +++ b/components/home/HomeSearchForm.tsx @@ -0,0 +1,51 @@ +"use client"; + +import { Search } from "lucide-react"; +import { useRouter } from "next/navigation"; +import { type FormEvent, useState } from "react"; + +import { withBasePath } from "@/lib/utils"; + +interface HomeSearchFormProps { + defaultValue?: string; +} + +export function HomeSearchForm({ defaultValue = "" }: HomeSearchFormProps) { + const router = useRouter(); + const [query, setQuery] = useState(defaultValue); + + function handleSubmit(event: FormEvent) { + event.preventDefault(); + + const normalizedQuery = query.trim(); + const url = normalizedQuery ? `${withBasePath("/ask")}?q=${encodeURIComponent(normalizedQuery)}` : withBasePath("/ask"); + + router.push(url); + } + + return ( +
+
+ + + +
+
+ ); +} diff --git a/components/layout/Footer.tsx b/components/layout/Footer.tsx index 9fe2dbd..488c328 100644 --- a/components/layout/Footer.tsx +++ b/components/layout/Footer.tsx @@ -1,29 +1,91 @@ +import Image from "next/image"; import Link from "next/link"; -import { DEFAULT_BRANCH, REPO_NAME, REPO_OWNER, REPO_URL, SITE_NAME } from "@/lib/utils"; +import siteLogo from "@/public/favicon.png"; +import { DEFAULT_BRANCH, REPO_NAME, REPO_OWNER, REPO_URL, SITE_NAME, SITE_ORIGIN } from "@/lib/utils"; const CONTENT_LICENSE_URL = `${REPO_URL}/blob/${DEFAULT_BRANCH}/CC-BY-NC-SA-4.0`; +const footerGroups = [ + { + title: "Продукт", + links: [ + { label: "Сообщить об ошибках", href: `${REPO_URL}/issues/new/choose` } + ] + }, + { + title: "О нас", + links: [ + { label: "Сайт проекта", href: `${SITE_ORIGIN}/StackMIREA/` }, + { label: "README", href: `${REPO_URL}#readme` } + ] + }, + { + title: "GitHub", + links: [ + { label: `${REPO_OWNER}/${REPO_NAME}`, href: REPO_URL }, + { label: `@${REPO_OWNER}`, href: `https://github.com/${REPO_OWNER}` } + ] + }, + { + title: "Сообщество", + links: [ + { label: "CONTRIBUTING", href: `${REPO_URL}/blob/${DEFAULT_BRANCH}/CONTRIBUTING.md` }, + { label: "SUPPORT", href: `${REPO_URL}/blob/${DEFAULT_BRANCH}/SUPPORT.md` } + ] + } +] as const; export function Footer() { return ( -
-
-

{SITE_NAME} Документация

-

- Весь контент сайта защищен лицензией{" "} - - CC-BY-NC-SA-4.0 - - . -

- - {REPO_OWNER}/{REPO_NAME} - +
+
+
+
+
+ + {`Логотип + {SITE_NAME} + +
+ + {footerGroups.map((group) => ( +
+

{group.title}

+
+ {group.links.map((item) => ( + + {item.label} + + ))} +
+
+ ))} +
+ +
+
+

Упрощаем обучение

+
+ +
+ от студентов для студентов +
+ +

+ © 2026 Min's collective. Весь контент сайта защищен лицензией{" "} + + CC-BY-NC-SA-4.0 + + . +

+
+
); diff --git a/components/layout/Header.tsx b/components/layout/Header.tsx index 268cf9b..6f0310f 100644 --- a/components/layout/Header.tsx +++ b/components/layout/Header.tsx @@ -1,60 +1,86 @@ -import Link from "next/link"; +"use client"; + import Image from "next/image"; -import { BookOpenText, BrainCircuit, Github, Home } from "lucide-react"; +import Link from "next/link"; +import { BookOpen, Home, Search } from "lucide-react"; +import { usePathname } from "next/navigation"; import siteLogo from "@/public/favicon.png"; import { ThemeToggle } from "@/components/ui/ThemeToggle"; -import { REPO_URL, SITE_NAME } from "@/lib/utils"; +import { SITE_NAME, cn } from "@/lib/utils"; + +const navigation = [ + { + href: "/", + label: "Главная", + icon: Home + }, + { + href: "/docs", + label: "Документация", + icon: BookOpen + }, + { + href: "/ask", + label: "ИИ-Поиск", + icon: Search + } +] as const; export function Header() { + const pathname = usePathname(); + return ( -
-
-
- - {`Логотип - {SITE_NAME} - - - -
-
- - + +
+
+ +
diff --git a/components/layout/MobileDocsMenu.tsx b/components/layout/MobileDocsMenu.tsx index f8ca269..e5d99a1 100644 --- a/components/layout/MobileDocsMenu.tsx +++ b/components/layout/MobileDocsMenu.tsx @@ -27,7 +27,7 @@ export function MobileDocsMenu({ buildInfo, groups, currentPath }: MobileDocsMen } return ( -
+
diff --git a/lib/home.ts b/lib/home.ts new file mode 100644 index 0000000..4681145 --- /dev/null +++ b/lib/home.ts @@ -0,0 +1,74 @@ +import { getAuthorsWithSummary } from "@/lib/contributors"; +import { getPublishedDocs } from "@/lib/navigation"; +import { getTrackDefinitions, type TrackIconKey } from "@/lib/tracks"; +import { getWhatsNewOverview, type WhatsNewAuthor, type WhatsNewMaterial } from "@/lib/whats-new"; + +export interface HomeTrackCard { + id: string; + href: string; + title: string; + description: string; + iconKey: TrackIconKey; + itemsCount: number; +} + +export interface HomePopularTrack { + id: string; + href: string; + title: string; + description: string; + itemsCount: number; +} + +export interface HomePageOverview { + trackCards: HomeTrackCard[]; + popularTracks: HomePopularTrack[]; + recentMaterials: WhatsNewMaterial[]; + featuredAuthors: WhatsNewAuthor[]; +} + +function getPublishedDocsCountByTrack() { + return getPublishedDocs().reduce( + (counts, doc) => counts.set(doc.section, (counts.get(doc.section) ?? 0) + 1), + new Map() + ); +} + +export function getHomePageOverview(): HomePageOverview { + const countsByTrack = getPublishedDocsCountByTrack(); + const whatsNew = getWhatsNewOverview(); + const fallbackAuthors = getAuthorsWithSummary(); + + const sortedTracks = getTrackDefinitions() + .map((track) => ({ + id: track.id, + href: `/docs/${track.id}`, + title: track.title, + description: track.homeSubtitle, + iconKey: track.iconKey, + itemsCount: countsByTrack.get(track.id) ?? 0 + })) + .sort((left, right) => { + if (left.itemsCount !== right.itemsCount) { + return right.itemsCount - left.itemsCount; + } + + return left.title.localeCompare(right.title); + }); + + return { + trackCards: sortedTracks.slice(0, 10), + popularTracks: sortedTracks.slice(0, 3), + recentMaterials: whatsNew.materials.slice(0, 3), + featuredAuthors: + whatsNew.authors.slice(0, 3).length > 0 + ? whatsNew.authors.slice(0, 3) + : fallbackAuthors.slice(0, 3).map((author) => ({ + github: author.github, + profileUrl: author.profileUrl, + avatarUrl: author.avatarUrl, + docsCount: author.docsCount, + firstContributionAt: null + })) + }; +} diff --git a/public/search-index.json b/public/search-index.json index b31b609..d607f5d 100644 --- a/public/search-index.json +++ b/public/search-index.json @@ -1 +1 @@ -{"version":1,"generatedAt":"2026-05-05T08:47:47.095Z","docs":[{"id":"ai","href":"/docs/ai","slug":["ai"],"section":"ai","sectionTitle":"AI","title":"AI","description":"Рабочие тетради по искусственному интеллекту в формате MDX.","preview":"AI обзор Раздел объединяет 8 рабочих тетрадей по дисциплине «Искусственный интеллект», перенесенных в MDX формат. Материалы идут от базового Python и научных библиотек к классическим ML методам, нейросетям, эволюционным алгоритмам и кластеризации. Что внутри P","keywords":["notebook","python","ai","ml","данных","деревья","методы","раздел","решений","knn","mdx","numpy","pandas","алгоритмам","базового","библиотек","внутри","генетические"],"topics":["python","ai","knn","pandas","numpy","oop","algorithms","clustering","regression"],"chunks":[{"id":"chunk-0","heading":"AI обзор","text":"Раздел объединяет 8 рабочих тетрадей по дисциплине «Искусственный интеллект», перенесенных в MDX формат. Материалы идут от базового Python и научных библиотек к классическим ML методам, нейросетям, эволюционным алгоритмам и кластеризации.","keywords":["ai","mdx","mdx.","ml","python","алгоритмам","базового","библиотек","дисциплине","идут","интеллект","интеллекту"],"topics":["python","ai","oop","algorithms"]},{"id":"chunk-1","heading":"Что внутри","text":"Python, NumPy и pandas для подготовки данных; метрики расстояния, KNN и базовые техники классификации; регрессия и деревья решений; эволюционные методы, нейросети и кластеризация.","keywords":["ai","knn","mdx.","numpy","pandas","python","базовые","внутри","данных","деревья","интеллекту","искусственному"],"topics":["python","knn","pandas","numpy","oop","clustering","regression"]},{"id":"chunk-2","heading":"Ноутбуки","text":"Notebook 1 — Основа Python типы данных, условия, циклы и вводные примеры. Notebook 2 — NumPy и pandas массивы, таблицы и базовая подготовка данных. Notebook 3 — Метрики и KNN расстояния между объектами и классификация ближайших соседей. Notebook 4 — Регрессия линейные модели, аппроксимация и оценка качества. Notebook 5 — Деревья решений деревья решений и работа с классификаторами","keywords":["notebook","ai","деревья","решений","knn","mdx.","numpy","pandas","python","аппроксимация","базовая","ближайших"],"topics":["python","knn","pandas","numpy","oop","regression"]},{"id":"chunk-3","heading":"Ноутбуки","text":". Notebook 6 — Генетические и эволюционные методы оптимизация, генетические алгоритмы и отжиг. Notebook 7 — Нейронные сети персептрон, MLP и основы обучения сети. Notebook 8 — Кластеризация методы группировки данных без учителя.","keywords":["ai","notebook","генетические","методы","mdx.","mlp","алгоритмы","без","группировки","данных","интеллекту","искусственному"],"topics":["ai","algorithms","clustering"]},{"id":"chunk-4","heading":"Как читать раздел","text":"Начните с Notebook 1 и Notebook 2 , если нужно выровнять базу по Python и обработке данных. Для классического ML переходите к Notebook 3 , Notebook 4 и Notebook 5 . Темы оптимизации и более продвинутых подходов собраны в Notebook 6 , Notebook 7 и Notebook 8 .","keywords":["notebook","ai","mdx.","ml","python","базу","более","выровнять","данных.","если","интеллекту","искусственному"],"topics":["python","ai","oop"]}]},{"id":"ai/notebook-01-python-basics","href":"/docs/ai/notebook-01-python-basics","slug":["ai","notebook-01-python-basics"],"section":"ai","sectionTitle":"AI","title":"AI Notebook 1 — Основа Python","description":"Типы данных, условия, циклы и старт работы с NumPy.","preview":"Основа Python. Библиотеки. Дата 25.02.2023 1.1. Теоретический материал – Типы данных Типы данных Все типы данных в Python относятся к одной из 2 х категорий: изменяемые (mutable) и неизменяемые (immutable). Неизменяемые объекты: исловые данные (int, float), bo","keywords":["print","python","type","задача","10","elif","dev","от","plt.plot","range","данных","apple","df","if","import","rng","trapz","массива"],"topics":["python","ai","numpy","knn"],"chunks":[{"id":"chunk-0","heading":"","text":"Типы данных Все типы данных в Python относятся к одной из 2 х категорий: изменяемые (mutable) и неизменяемые (immutable). Неизменяемые объекты: исловые данные (int, float), bool, None, символьные строки (class 'str'), кортежи (tuple). Изменяемые объекты: списки (list), множества (set), словари (dict).","keywords":["ai","данных","типы","python","изменяемые","неизменяемые","объекты","bool","class","dict","float","immutable"],"topics":["python"]},{"id":"chunk-1","heading":"","text":"python x= 3+5.2 7 y= None z= 'a',5,12.345, (2,'b') df= [['Антонова Антонина',34,'ж'],['Борисов Борис',26,'м']] A={1,'title',2,'content'} print(x,' ',type(x),'\\n',y,' ',type(y),'\\n',df,' ',type(df),'\\n',A,' ',type(A),'\\n')","keywords":["type","ai","df","python","12.345","26","3+5.2","34","content","none","notebook","numpy."],"topics":["python"]},{"id":"chunk-2","heading":"","text":"code 39.4 None [['Антонова Антонина', 34, 'ж'], ['Борисов Борис', 26, 'м']] {'content', 1, 2, 'title'}","keywords":["ai","26","34","39.4","code","content","none","notebook","numpy.","python","title","антонина"],"topics":[]},{"id":"chunk-3","heading":"","text":"python x=5 =2 A={ 1,3,7,8} B={2,4,5,10,'apple'} C=A&B df= 'Антонова Антонина',34,'ж' z='type' D=[1,'title',2,'connect'] print(x,' ',type(x),'\\n',A,' ',type(A),'\\n',B,' ',type(B),'\\n',C,' ',type(C),'\\n',df,' ',type(df),'\\n',z,' ',type(z),'\\n',D,' ',type(D),'\\n')","keywords":["type","ai","df","python","10","34","apple","connect","notebook","numpy.","print","title"],"topics":["python"]},{"id":"chunk-4","heading":"","text":"text True {8, 1, 3, 7} {2, 'apple', 4, 5, 10} set() ('Антонова Антонина', 34, 'ж') type [1, 'title', 2, 'connect']","keywords":["ai","10","34","apple","connect","notebook","numpy.","python","set","text","title","true"],"topics":[]},{"id":"chunk-5","heading":"","text":"В коде часто приходится проверять выполнимость или невыполнимость каких то условий. Синтаксис:","keywords":["ai","notebook","numpy.","python","выполнимость","данных","каких","коде","невыполнимость","основа","приходится","проверять"],"topics":[]},{"id":"chunk-6","heading":"","text":"Обратите внимание, что код, который должен выполняться внутри каждого условия, записывается с отступом в 4 пробела от уровня if, elif и else: в питоне области видимости переменных обозначаются отступами.","keywords":["ai","условия","elif","else","if","notebook","numpy.","python","видимости","внимание","внутри","выполняться"],"topics":["python"]},{"id":"chunk-7","heading":"","text":"То есть, отступы позволяют понять, где начинается код, который должен выполняться при выполнении условия в if, и где заканчивается.","keywords":["ai","условия","if","notebook","numpy.","python","выполнении","выполняться","данных","должен","заканчивается.","код"],"topics":[]},{"id":"chunk-8","heading":"","text":"Задача:Вывести на экран является ли переменная х положительной, отрицательной или равна нулю.","keywords":["ai","notebook","numpy.","python","вывести","данных","задача","ли","нулю.","основа","отрицательной","переменная"],"topics":[]},{"id":"chunk-9","heading":"","text":"python x=125 if x<0: print('x отрицательный') elif x==0: print('x равен 0') else: print('x положительный')","keywords":["ai","print","python","125","elif","else","if","notebook","numpy.","данных","основа","отрицательный"],"topics":["python"]},{"id":"chunk-10","heading":"","text":"Задача: Напишите код. Задается х, напечатать какому из интервалов принадлежит: ( infinity, 5), [ 5, 5] или от (5, +infinity)","keywords":["ai","+infinity","infinity","notebook","numpy.","python","данных","задается","задача","интервалов","какому","код."],"topics":[]},{"id":"chunk-11","heading":"","text":"python x=int(input()) if x < 5: print('x пренадлежит интервалу от бесконечности до 5') elif 5