commit
e0d40450d2
@ -0,0 +1,3 @@ |
||||
{ |
||||
"extends": "next/core-web-vitals" |
||||
} |
@ -0,0 +1,39 @@ |
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. |
||||
|
||||
# dependencies |
||||
/node_modules |
||||
/.pnp |
||||
.pnp.js |
||||
|
||||
# testing |
||||
/coverage |
||||
|
||||
# next.js |
||||
/.next/ |
||||
/out/ |
||||
|
||||
# production |
||||
/build |
||||
|
||||
# misc |
||||
.DS_Store |
||||
*.pem |
||||
|
||||
# debug |
||||
npm-debug.log* |
||||
yarn-debug.log* |
||||
yarn-error.log* |
||||
.pnpm-debug.log* |
||||
|
||||
# local env files |
||||
.env*.local |
||||
|
||||
# vercel |
||||
.vercel |
||||
|
||||
# typescript |
||||
*.tsbuildinfo |
||||
next-env.d.ts |
||||
|
||||
#sourse |
||||
/public/informatica |
@ -0,0 +1,45 @@ |
||||
import NextHead from 'next/head'; |
||||
import { useRouter } from 'next/router'; |
||||
import React from 'react'; |
||||
import { MetaProps } from '../types/layout'; |
||||
|
||||
export type WithYandexMetrikaProps = { |
||||
children: React.ReactNode; |
||||
} |
||||
|
||||
export const WEBSITE_HOST_URL = 'https://robotop.krasnikov.pro'; |
||||
|
||||
const Head = ({ customMeta }: { customMeta?: MetaProps }): JSX.Element => { |
||||
const router = useRouter(); |
||||
const meta: MetaProps = { |
||||
title: 'РоботТоп - робототехнический фестиваль', |
||||
description: |
||||
'РоботТОП – это робототехнические соревнования, в которых могут принять участие молодые любители робототехники, объединившись в команды.', |
||||
image: `${WEBSITE_HOST_URL}/images/site-preview.png`, |
||||
type: 'website', |
||||
...customMeta, |
||||
}; |
||||
|
||||
return ( |
||||
<NextHead> |
||||
<title>{meta.title}</title> |
||||
<meta content={meta.description} name="РоботТОП – это робототехнические соревнования, в которых могут принять участие молодые любители робототехники, объединившись в команды." /> |
||||
<meta property="og:url" content={`${WEBSITE_HOST_URL}${router.asPath}`} /> |
||||
<link rel="canonical" href={`${WEBSITE_HOST_URL}${router.asPath}`} /> |
||||
<meta property="og:type" content={meta.type} /> |
||||
<meta property="og:site_name" content="РоботТоп - робототехнический фестиваль" /> |
||||
<meta property="og:description" content={meta.description} /> |
||||
<meta property="og:title" content={meta.title} /> |
||||
<meta property="og:image" content={meta.image} /> |
||||
<meta name="twitter:card" content="summary_large_image" /> |
||||
<meta name="twitter:title" content={meta.title} /> |
||||
<meta name="twitter:description" content={meta.description} /> |
||||
<meta name="twitter:image" content={meta.image} /> |
||||
{meta.date && ( |
||||
<meta property="article:published_time" content={meta.date} /> |
||||
)} |
||||
</NextHead> |
||||
); |
||||
}; |
||||
|
||||
export default Head; |
@ -0,0 +1,45 @@ |
||||
import React from 'react'; |
||||
import { MetaProps } from '../types/layout'; |
||||
import Head from './Head'; |
||||
import Navigation from './Navigation'; |
||||
import ThemeSwitch from './ThemeSwitch'; |
||||
type LayoutProps = { |
||||
children: React.ReactNode; |
||||
customMeta?: MetaProps; |
||||
}; |
||||
|
||||
export const WEBSITE_HOST_URL = 'https://robotop.krasnikov.pro/'; |
||||
|
||||
const Layout = ({ children, customMeta }: LayoutProps): JSX.Element => { |
||||
return ( |
||||
<> |
||||
<Head customMeta={customMeta} /> |
||||
<header> |
||||
<div className="max-w-5xl px-8 mx-auto max-w"> |
||||
<div className="flex items-center justify-between py-6"> |
||||
<Navigation /> |
||||
<ThemeSwitch /> |
||||
</div> |
||||
</div> |
||||
</header> |
||||
<main> |
||||
<div className="max-w-5xl px-8 py-4 mx-auto max-w"> |
||||
{children} |
||||
</div> |
||||
</main> |
||||
<footer className="py-8"> |
||||
<div className="max-w-5xl px-8 mx-auto max-w"> |
||||
Разработано {' '} |
||||
<a |
||||
className="text-gray-900 dark:text-white" |
||||
href="https://krasnikov.pro" target='_blank' rel="noreferrer" |
||||
> |
||||
Krasnikov.pro - {(new Date()).getFullYear()} год |
||||
</a> |
||||
</div> |
||||
</footer> |
||||
</> |
||||
); |
||||
}; |
||||
|
||||
export default Layout; |
@ -0,0 +1,45 @@ |
||||
import React from 'react'; |
||||
import { MetaProps } from '../types/layout'; |
||||
import Head from './Head'; |
||||
import Navigation from './Navigation'; |
||||
import ThemeSwitch from './ThemeSwitch'; |
||||
type LayoutProps = { |
||||
children: React.ReactNode; |
||||
customMeta?: MetaProps; |
||||
}; |
||||
|
||||
export const WEBSITE_HOST_URL = 'https://robotop.krasnikov.pro/'; |
||||
|
||||
const Layout = ({ children, customMeta }: LayoutProps): JSX.Element => { |
||||
return ( |
||||
<> |
||||
<Head customMeta={customMeta} /> |
||||
<header> |
||||
<div className="max-w-5xl px-8 mx-auto max-w"> |
||||
<div className="flex items-center justify-between py-6"> |
||||
<Navigation /> |
||||
<ThemeSwitch /> |
||||
</div> |
||||
</div> |
||||
</header> |
||||
<main> |
||||
<div className="max-w-5xl px-8 py-4 mx-auto max-w"> |
||||
{children} |
||||
</div> |
||||
</main> |
||||
<footer className="py-8"> |
||||
<div className="max-w-5xl px-8 mx-auto max-w"> |
||||
Разработано {' '} |
||||
<a |
||||
className="text-gray-900 dark:text-white" |
||||
href="https://krasnikov.pro" target='_blank' rel="noreferrer" |
||||
> |
||||
Krasnikov.pro - {(new Date()).getFullYear()} год |
||||
</a> |
||||
</div> |
||||
</footer> |
||||
</> |
||||
); |
||||
}; |
||||
|
||||
export default Layout; |
@ -0,0 +1,108 @@ |
||||
import Link from 'next/link'; |
||||
import React, { useState } from 'react'; |
||||
import { MenuIcon, XIcon } from '@heroicons/react/outline' |
||||
import { Transition } from "@headlessui/react"; |
||||
import { useRouter } from 'next/router' |
||||
|
||||
const navigation = [ |
||||
{ name: 'Главная', href: '/', as: false }, |
||||
{ name: 'Правила', href: '/posts/[slug]', as:'regulations'}, |
||||
{ name: 'Регистрация', href: '/registration', as: false }, |
||||
{ name: 'Расписание', href: '/posts/[slug]', as:'festival-schedule' }, |
||||
{ name: 'Примеры', href: '/posts/[slug]', as:'task-completion-examples'}, |
||||
{ name: 'Контакты', href: '/contacts', as: false}, |
||||
{ name: 'О нас', href: '/about', as: false}, |
||||
] |
||||
|
||||
function classNames(...classes) { |
||||
return classes.filter(Boolean).join(' ') |
||||
} |
||||
|
||||
const Navigation = (): JSX.Element => { |
||||
const [isOpen, setIsOpen] = useState(false); |
||||
const router = useRouter(); |
||||
|
||||
return ( |
||||
<nav className=""> |
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> |
||||
<div className="flex items-center justify-between h-16"> |
||||
<div className="flex items-center"> |
||||
<div className="hidden md:block"> |
||||
<div className="ml-10 flex items-baseline space-x-4"> |
||||
{navigation.map((item) => ( |
||||
<Link as={ item.as ? '/posts/'+item.as : ''} href={item.href} key={item.name}> |
||||
<a |
||||
className={classNames( |
||||
item.as == router.query.slug && router.query.slug !== 'undefined'? |
||||
'bg-gray-900 text-white' : |
||||
item.href == router.pathname && item.as === false ? |
||||
'bg-gray-900 text-white' : |
||||
'text-gray-900 hover:bg-gray-700 hover:text-white', |
||||
'px-3 py-2 rounded-md text-sm font-medium' |
||||
)} |
||||
aria-current={item.href == router.pathname || item.as == router.query.slug ? 'page' : 'false'} |
||||
> |
||||
{item.name} |
||||
</a> |
||||
</Link> |
||||
))} |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div className="-mr-2 flex md:hidden"> |
||||
<button |
||||
onClick={() => setIsOpen(!isOpen)} |
||||
type="button" |
||||
aria-controls="mobile-menu" |
||||
aria-expanded="false" |
||||
> |
||||
<span className="sr-only">Открыть главное меню</span> |
||||
{!isOpen ? ( |
||||
<MenuIcon className="block h-6 w-6" aria-hidden="false" /> |
||||
) : ( |
||||
<XIcon className="block h-6 w-6" aria-hidden="true" /> |
||||
)} |
||||
</button> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<Transition |
||||
show={isOpen} |
||||
enter="transition ease-out duration-100 transform" |
||||
enterFrom="opacity-0 scale-95" |
||||
enterTo="opacity-100 scale-100" |
||||
leave="transition ease-in duration-75 transform" |
||||
leaveFrom="opacity-100 scale-100" |
||||
leaveTo="opacity-0 scale-95" |
||||
className="absolute bg-gray-100 z-50" |
||||
> |
||||
{(ref) => ( |
||||
<div className="md:hidden" id="mobile-menu"> |
||||
<div ref={ref} className="px-2 pt-2 pb-3 space-y-1 sm:px-3"> |
||||
{navigation.map((item) => ( |
||||
<Link as={'/posts/'+item.as} href={item.href} key={item.name}> |
||||
<a |
||||
className={classNames( |
||||
item.as == router.query.slug && router.query.slug !== 'undefined'? |
||||
'bg-gray-900 text-white' : |
||||
item.href == router.pathname && item.as === 'true' ? |
||||
'bg-gray-900 text-white' : |
||||
'text-gray-900 hover:bg-gray-900 hover:text-white', |
||||
'block px-3 py-2 rounded-md text-base font-medium' |
||||
)} |
||||
aria-current={item.href ? 'page' : undefined} |
||||
> |
||||
{item.name} |
||||
</a> |
||||
</Link> |
||||
))} |
||||
</div> |
||||
</div> |
||||
)} |
||||
</Transition> |
||||
</nav> |
||||
); |
||||
}; |
||||
|
||||
export default Navigation; |
@ -0,0 +1,108 @@ |
||||
import Link from 'next/link'; |
||||
import React, { useState } from 'react'; |
||||
import { MenuIcon, XIcon } from '@heroicons/react/outline' |
||||
import { Transition } from "@headlessui/react"; |
||||
import { useRouter } from 'next/router' |
||||
|
||||
const navigation = [ |
||||
{ name: 'Главная', href: '/', as: false }, |
||||
{ name: 'Правила', href: '/posts/[slug]', as:'regulations'}, |
||||
{ name: 'Регистрация', href: '/registration', as: false }, |
||||
{ name: 'Расписание', href: '/posts/[slug]', as:'festival-schedule' }, |
||||
{ name: 'Примеры', href: '/posts/[slug]', as:'task-completion-examples'}, |
||||
{ name: 'Контакты', href: '/contacts', as: false}, |
||||
{ name: 'О нас', href: '/about', as: false}, |
||||
] |
||||
|
||||
function classNames(...classes) { |
||||
return classes.filter(Boolean).join(' ') |
||||
} |
||||
|
||||
const Navigation = (): JSX.Element => { |
||||
const [isOpen, setIsOpen] = useState(false); |
||||
const router = useRouter(); |
||||
|
||||
return ( |
||||
<nav className=""> |
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> |
||||
<div className="flex items-center justify-between h-16"> |
||||
<div className="flex items-center"> |
||||
<div className="hidden md:block"> |
||||
<div className="ml-10 flex items-baseline space-x-4"> |
||||
{navigation.map((item) => ( |
||||
<Link as={ item.as ? '/posts/'+item.as : ''} href={item.href} key={item.name}> |
||||
<a |
||||
className={classNames( |
||||
item.as == router.query.slug && router.query.slug !== 'undefined'? |
||||
'bg-gray-900 text-white' : |
||||
item.href == router.pathname && item.as === false ? |
||||
'bg-gray-900 text-white' : |
||||
'text-gray-900 hover:bg-gray-700 hover:text-white', |
||||
'px-3 py-2 rounded-md text-sm font-medium' |
||||
)} |
||||
aria-current={item.href == router.pathname || item.as == router.query.slug ? 'page' : 'false'} |
||||
> |
||||
{item.name} |
||||
</a> |
||||
</Link> |
||||
))} |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div className="-mr-2 flex md:hidden"> |
||||
<button |
||||
onClick={() => setIsOpen(!isOpen)} |
||||
type="button" |
||||
aria-controls="mobile-menu" |
||||
aria-expanded="false" |
||||
> |
||||
<span className="sr-only">Открыть главное меню</span> |
||||
{!isOpen ? ( |
||||
<MenuIcon className="block h-6 w-6" aria-hidden="false" /> |
||||
) : ( |
||||
<XIcon className="block h-6 w-6" aria-hidden="true" /> |
||||
)} |
||||
</button> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<Transition |
||||
show={isOpen} |
||||
enter="transition ease-out duration-100 transform" |
||||
enterFrom="opacity-0 scale-95" |
||||
enterTo="opacity-100 scale-100" |
||||
leave="transition ease-in duration-75 transform" |
||||
leaveFrom="opacity-100 scale-100" |
||||
leaveTo="opacity-0 scale-95" |
||||
className="absolute bg-gray-100 z-50" |
||||
> |
||||
{(ref) => ( |
||||
<div className="md:hidden" id="mobile-menu"> |
||||
<div ref={ref} className="px-2 pt-2 pb-3 space-y-1 sm:px-3"> |
||||
{navigation.map((item) => ( |
||||
<Link as={'/posts/'+item.as} href={item.href} key={item.name}> |
||||
<a |
||||
className={classNames( |
||||
item.as == router.query.slug && router.query.slug !== 'undefined'? |
||||
'bg-gray-900 text-white' : |
||||
item.href == router.pathname && item.as === 'true' ? |
||||
'bg-gray-900 text-white' : |
||||
'text-gray-900 hover:bg-gray-900 hover:text-white', |
||||
'block px-3 py-2 rounded-md text-base font-medium' |
||||
)} |
||||
aria-current={item.href ? 'page' : undefined} |
||||
> |
||||
{item.name} |
||||
</a> |
||||
</Link> |
||||
))} |
||||
</div> |
||||
</div> |
||||
)} |
||||
</Transition> |
||||
</nav> |
||||
); |
||||
}; |
||||
|
||||
export default Navigation; |
@ -0,0 +1,105 @@ |
||||
import Link from 'next/link'; |
||||
import React, { useState } from 'react'; |
||||
import { MenuIcon, XIcon } from '@heroicons/react/outline' |
||||
import { Transition } from "@headlessui/react"; |
||||
import { useRouter } from 'next/router' |
||||
|
||||
const navigation = [ |
||||
{ name: 'Главная', href: '/', as: false }, |
||||
{ name: 'Программирование', href: '/posts/[slug]', as:'regulations'}, |
||||
{ name: 'Робототехника', href: '/registration', as: false }, |
||||
{ name: '3D моделирование', href: '/posts/[slug]', as:'festival-schedule' } |
||||
] |
||||
|
||||
function classNames(...classes) { |
||||
return classes.filter(Boolean).join(' ') |
||||
} |
||||
|
||||
const Navigation = (): JSX.Element => { |
||||
const [isOpen, setIsOpen] = useState(false); |
||||
const router = useRouter(); |
||||
|
||||
return ( |
||||
<nav className=""> |
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> |
||||
<div className="flex items-center justify-between h-16"> |
||||
<div className="flex items-center"> |
||||
<div className="hidden md:block"> |
||||
<div className="ml-10 flex items-baseline space-x-4"> |
||||
{navigation.map((item) => ( |
||||
<Link as={ item.as ? '/posts/'+item.as : ''} href={item.href} key={item.name}> |
||||
<a |
||||
className={classNames( |
||||
item.as == router.query.slug && router.query.slug !== 'undefined'? |
||||
'bg-gray-900 text-white' : |
||||
item.href == router.pathname && item.as === false ? |
||||
'bg-gray-900 text-white' : |
||||
'text-gray-900 hover:bg-gray-700 hover:text-white', |
||||
'px-3 py-2 rounded-md text-sm font-medium' |
||||
)} |
||||
aria-current={item.href == router.pathname || item.as == router.query.slug ? 'page' : 'false'} |
||||
> |
||||
{item.name} |
||||
</a> |
||||
</Link> |
||||
))} |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div className="-mr-2 flex md:hidden"> |
||||
<button |
||||
onClick={() => setIsOpen(!isOpen)} |
||||
type="button" |
||||
aria-controls="mobile-menu" |
||||
aria-expanded="false" |
||||
> |
||||
<span className="sr-only">Открыть главное меню</span> |
||||
{!isOpen ? ( |
||||
<MenuIcon className="block h-6 w-6" aria-hidden="false" /> |
||||
) : ( |
||||
<XIcon className="block h-6 w-6" aria-hidden="true" /> |
||||
)} |
||||
</button> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<Transition |
||||
show={isOpen} |
||||
enter="transition ease-out duration-100 transform" |
||||
enterFrom="opacity-0 scale-95" |
||||
enterTo="opacity-100 scale-100" |
||||
leave="transition ease-in duration-75 transform" |
||||
leaveFrom="opacity-100 scale-100" |
||||
leaveTo="opacity-0 scale-95" |
||||
className="absolute bg-gray-100 z-50" |
||||
> |
||||
{(ref) => ( |
||||
<div className="md:hidden" id="mobile-menu"> |
||||
<div ref={ref} className="px-2 pt-2 pb-3 space-y-1 sm:px-3"> |
||||
{navigation.map((item) => ( |
||||
<Link as={'/posts/'+item.as} href={item.href} key={item.name}> |
||||
<a |
||||
className={classNames( |
||||
item.as == router.query.slug && router.query.slug !== 'undefined'? |
||||
'bg-gray-900 text-white' : |
||||
item.href == router.pathname && item.as === 'true' ? |
||||
'bg-gray-900 text-white' : |
||||
'text-gray-900 hover:bg-gray-900 hover:text-white', |
||||
'block px-3 py-2 rounded-md text-base font-medium' |
||||
)} |
||||
aria-current={item.href ? 'page' : undefined} |
||||
> |
||||
{item.name} |
||||
</a> |
||||
</Link> |
||||
))} |
||||
</div> |
||||
</div> |
||||
)} |
||||
</Transition> |
||||
</nav> |
||||
); |
||||
}; |
||||
|
||||
export default Navigation; |
@ -0,0 +1,105 @@ |
||||
import Link from 'next/link'; |
||||
import React, { useState } from 'react'; |
||||
import { MenuIcon, XIcon } from '@heroicons/react/outline' |
||||
import { Transition } from "@headlessui/react"; |
||||
import { useRouter } from 'next/router' |
||||
|
||||
const navigation = [ |
||||
{ name: 'Главная', href: '/', as: false }, |
||||
{ name: 'Программирование', href: '/posts/[slug]', as:'programming'}, |
||||
{ name: 'Робототехника', href: '/posts/[slug]', as: 'robotics' }, |
||||
{ name: '3D моделирование', href: '/posts/[slug]', as:'3dmodeling' } |
||||
] |
||||
|
||||
function classNames(...classes) { |
||||
return classes.filter(Boolean).join(' ') |
||||
} |
||||
|
||||
const Navigation = (): JSX.Element => { |
||||
const [isOpen, setIsOpen] = useState(false); |
||||
const router = useRouter(); |
||||
|
||||
return ( |
||||
<nav className=""> |
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> |
||||
<div className="flex items-center justify-between h-16"> |
||||
<div className="flex items-center"> |
||||
<div className="hidden md:block"> |
||||
<div className="ml-10 flex items-baseline space-x-4"> |
||||
{navigation.map((item) => ( |
||||
<Link as={ item.as ? '/posts/'+item.as : ''} href={item.href} key={item.name}> |
||||
<a |
||||
className={classNames( |
||||
item.as == router.query.slug && router.query.slug !== 'undefined'? |
||||
'bg-gray-900 text-white' : |
||||
item.href == router.pathname && item.as === false ? |
||||
'bg-gray-900 text-white' : |
||||
'text-gray-900 hover:bg-gray-700 hover:text-white', |
||||
'px-3 py-2 rounded-md text-sm font-medium' |
||||
)} |
||||
aria-current={item.href == router.pathname || item.as == router.query.slug ? 'page' : 'false'} |
||||
> |
||||
{item.name} |
||||
</a> |
||||
</Link> |
||||
))} |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div className="-mr-2 flex md:hidden"> |
||||
<button |
||||
onClick={() => setIsOpen(!isOpen)} |
||||
type="button" |
||||
aria-controls="mobile-menu" |
||||
aria-expanded="false" |
||||
> |
||||
<span className="sr-only">Открыть главное меню</span> |
||||
{!isOpen ? ( |
||||
<MenuIcon className="block h-6 w-6" aria-hidden="false" /> |
||||
) : ( |
||||
<XIcon className="block h-6 w-6" aria-hidden="true" /> |
||||
)} |
||||
</button> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<Transition |
||||
show={isOpen} |
||||
enter="transition ease-out duration-100 transform" |
||||
enterFrom="opacity-0 scale-95" |
||||
enterTo="opacity-100 scale-100" |
||||
leave="transition ease-in duration-75 transform" |
||||
leaveFrom="opacity-100 scale-100" |
||||
leaveTo="opacity-0 scale-95" |
||||
className="absolute bg-gray-100 z-50" |
||||
> |
||||
{(ref) => ( |
||||
<div className="md:hidden" id="mobile-menu"> |
||||
<div ref={ref} className="px-2 pt-2 pb-3 space-y-1 sm:px-3"> |
||||
{navigation.map((item) => ( |
||||
<Link as={'/posts/'+item.as} href={item.href} key={item.name}> |
||||
<a |
||||
className={classNames( |
||||
item.as == router.query.slug && router.query.slug !== 'undefined'? |
||||
'bg-gray-900 text-white' : |
||||
item.href == router.pathname && item.as === 'true' ? |
||||
'bg-gray-900 text-white' : |
||||
'text-gray-900 hover:bg-gray-900 hover:text-white', |
||||
'block px-3 py-2 rounded-md text-base font-medium' |
||||
)} |
||||
aria-current={item.href ? 'page' : undefined} |
||||
> |
||||
{item.name} |
||||
</a> |
||||
</Link> |
||||
))} |
||||
</div> |
||||
</div> |
||||
)} |
||||
</Transition> |
||||
</nav> |
||||
); |
||||
}; |
||||
|
||||
export default Navigation; |
@ -0,0 +1,102 @@ |
||||
import { useTheme } from 'next-themes'; |
||||
import React from 'react'; |
||||
|
||||
|
||||
const ThemeSwitch = (): JSX.Element => { |
||||
const [mounted, setMounted] = React.useState(false); |
||||
const { theme, setTheme } = useTheme(); |
||||
|
||||
// After mounting, we have access to the theme
|
||||
React.useEffect(() => setMounted(true), []); |
||||
|
||||
if (!mounted) { |
||||
return null; |
||||
} |
||||
|
||||
const isDark = theme === 'dark'; |
||||
const color = isDark ? '#fff' : '#000'; |
||||
const maskColor = isDark ? '#000' : '#fff'; |
||||
return ( |
||||
<button |
||||
className="theme-button" |
||||
type="button" |
||||
aria-label="Toggle Dark Mode" |
||||
onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')} |
||||
> |
||||
<div className="moon-or-sun" /> |
||||
<div className="moon-mask" /> |
||||
<style jsx>{` |
||||
.theme-button { |
||||
opacity: 0.5; |
||||
position: relative; |
||||
border-radius: 5px; |
||||
width: 42px; |
||||
height: 42px; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: center; |
||||
transition: opacity 0.3s ease; |
||||
} |
||||
.theme-button:hover { |
||||
opacity: 1; |
||||
} |
||||
.moon-or-sun { |
||||
position: relative; |
||||
width: 20px; |
||||
height: 20px; |
||||
border-radius: 50%; |
||||
border: ${isDark ? '4px' : '2px'} solid; |
||||
border-color: ${color}; |
||||
background: ${color}; |
||||
transform: scale(${isDark ? 0.5 : 1}); |
||||
transition: all 0.45s ease; |
||||
overflow: ${isDark ? 'visible' : 'hidden'}; |
||||
} |
||||
.moon-or-sun::before { |
||||
content: ''; |
||||
position: absolute; |
||||
right: -9px; |
||||
top: -9px; |
||||
height: 20px; |
||||
width: 20px; |
||||
border: 2px solid; |
||||
border-color: ${color}; |
||||
border-radius: 50%; |
||||
transform: translate(${isDark ? '14px, -14px' : '0, 0'}); |
||||
opacity: ${isDark ? 0 : 1}; |
||||
transition: transform 0.45s ease; |
||||
} |
||||
.moon-or-sun::after { |
||||
content: ''; |
||||
width: 8px; |
||||
height: 8px; |
||||
border-radius: 50%; |
||||
margin: -4px 0 0 -4px; |
||||
position: absolute; |
||||
top: 50%; |
||||
left: 50%; |
||||
box-shadow: 0 -23px 0 ${color}, 0 23px 0 ${color}, 23px 0 0 ${color}, |
||||
-23px 0 0 ${color}, 15px 15px 0 ${color}, -15px 15px 0 ${color}, |
||||
15px -15px 0 ${color}, -15px -15px 0 ${color}; |
||||
transform: scale(${isDark ? 1 : 0}); |
||||
transition: all 0.35s ease; |
||||
} |
||||
.moon-mask { |
||||
position: absolute; |
||||
right: 4px; |
||||
top: 4px; |
||||
height: 20px; |
||||
width: 20px; |
||||
border-radius: 50%; |
||||
border: 0; |
||||
background: ${maskColor}; |
||||
transform: translate(${isDark ? '4px, -4px' : '0, 0'}); |
||||
opacity: ${isDark ? 0 : 1}; |
||||
transition: transform 0.45s ease; |
||||
} |
||||
`}</style>
|
||||
</button> |
||||
); |
||||
}; |
||||
|
||||
export default ThemeSwitch; |
@ -0,0 +1,101 @@ |
||||
import { useTheme } from 'next-themes'; |
||||
import React from 'react'; |
||||
|
||||
const ThemeSwitch = (): JSX.Element => { |
||||
const [mounted, setMounted] = React.useState(false); |
||||
const { theme, setTheme } = useTheme(); |
||||
|
||||
// After mounting, we have access to the theme
|
||||
React.useEffect(() => setMounted(true), []); |
||||
|
||||
if (!mounted) { |
||||
return null; |
||||
} |
||||
|
||||
const isDark = theme === 'dark'; |
||||
const color = isDark ? '#fff' : '#000'; |
||||
const maskColor = isDark ? '#000' : '#fff'; |
||||
return ( |
||||
<button |
||||
className="theme-button" |
||||
type="button" |
||||
aria-label="Toggle Dark Mode" |
||||
onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')} |
||||
> |
||||
<div className="moon-or-sun" /> |
||||
<div className="moon-mask" /> |
||||
<style jsx>{` |
||||
.theme-button { |
||||
opacity: 0.5; |
||||
position: relative; |
||||
border-radius: 5px; |
||||
width: 42px; |
||||
height: 42px; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: center; |
||||
transition: opacity 0.3s ease; |
||||
} |
||||
.theme-button:hover { |
||||
opacity: 1; |
||||
} |
||||
.moon-or-sun { |
||||
position: relative; |
||||
width: 20px; |
||||
height: 20px; |
||||
border-radius: 50%; |
||||
border: ${isDark ? '4px' : '2px'} solid; |
||||
border-color: ${color}; |
||||
background: ${color}; |
||||
transform: scale(${isDark ? 0.5 : 1}); |
||||
transition: all 0.45s ease; |
||||
overflow: ${isDark ? 'visible' : 'hidden'}; |
||||
} |
||||
.moon-or-sun::before { |
||||
content: ''; |
||||
position: absolute; |
||||
right: -9px; |
||||
top: -9px; |
||||
height: 20px; |
||||
width: 20px; |
||||
border: 2px solid; |
||||
border-color: ${color}; |
||||
border-radius: 50%; |
||||
transform: translate(${isDark ? '14px, -14px' : '0, 0'}); |
||||
opacity: ${isDark ? 0 : 1}; |
||||
transition: transform 0.45s ease; |
||||
} |
||||
.moon-or-sun::after { |
||||
content: ''; |
||||
width: 8px; |
||||
height: 8px; |
||||
border-radius: 50%; |
||||
margin: -4px 0 0 -4px; |
||||
position: absolute; |
||||
top: 50%; |
||||
left: 50%; |
||||
box-shadow: 0 -23px 0 ${color}, 0 23px 0 ${color}, 23px 0 0 ${color}, |
||||
-23px 0 0 ${color}, 15px 15px 0 ${color}, -15px 15px 0 ${color}, |
||||
15px -15px 0 ${color}, -15px -15px 0 ${color}; |
||||
transform: scale(${isDark ? 1 : 0}); |
||||
transition: all 0.35s ease; |
||||
} |
||||
.moon-mask { |
||||
position: absolute; |
||||
right: 4px; |
||||
top: 4px; |
||||
height: 20px; |
||||
width: 20px; |
||||
border-radius: 50%; |
||||
border: 0; |
||||
background: ${maskColor}; |
||||
transform: translate(${isDark ? '4px, -4px' : '0, 0'}); |
||||
opacity: ${isDark ? 0 : 1}; |
||||
transition: transform 0.45s ease; |
||||
} |
||||
`}</style>
|
||||
</button> |
||||
); |
||||
}; |
||||
|
||||
export default ThemeSwitch; |
@ -0,0 +1,45 @@ |
||||
import fs from 'fs'; |
||||
import matter from 'gray-matter'; |
||||
import { join } from 'path'; |
||||
import { POSTS_PATH } from '../utils/mdxUtils'; |
||||
|
||||
export function getPostSlugs(): string[] { |
||||
return fs.readdirSync(POSTS_PATH); |
||||
} |
||||
|
||||
type PostItems = { |
||||
[key: string]: string; |
||||
}; |
||||
|
||||
export function getPostBySlug(slug: string, fields: string[] = []): PostItems { |
||||
const realSlug = slug.replace(/\.mdx$/, ''); |
||||
const fullPath = join(POSTS_PATH, `${realSlug}.mdx`); |
||||
const fileContents = fs.readFileSync(fullPath, 'utf8'); |
||||
const { data, content } = matter(fileContents); |
||||
|
||||
const items: PostItems = {}; |
||||
|
||||
// Ensure only the minimal needed data is exposed
|
||||
fields.forEach((field) => { |
||||
if (field === 'slug') { |
||||
items[field] = realSlug; |
||||
} |
||||
if (field === 'content') { |
||||
items[field] = content; |
||||
} |
||||
if (data[field]) { |
||||
items[field] = data[field]; |
||||
} |
||||
}); |
||||
|
||||
return items; |
||||
} |
||||
|
||||
export function getAllPosts(fields: string[] = []): PostItems[] { |
||||
const slugs = getPostSlugs(); |
||||
const posts = slugs |
||||
.map((slug) => getPostBySlug(slug, fields)) |
||||
// sort posts by date in descending order
|
||||
.sort((post1, post2) => (post1.date > post2.date ? -1 : 1)); |
||||
return posts; |
||||
} |
@ -0,0 +1,72 @@ |
||||
import type { NextPage } from 'next' |
||||
import Head from 'next/head' |
||||
import Image from 'next/image' |
||||
import styles from '../styles/Home.module.css' |
||||
|
||||
const Home: NextPage = () => { |
||||
return ( |
||||
<div className={styles.container}> |
||||
<Head> |
||||
<title>Create Next App</title> |
||||
<meta name="description" content="Generated by create next app" /> |
||||
<link rel="icon" href="/favicon.ico" /> |
||||
</Head> |
||||
|
||||
<main className={styles.main}> |
||||
<h1 className={styles.title}> |
||||
Welcome to <a href="https://nextjs.org">Next.js!</a> |
||||
</h1> |
||||
|
||||
<p className={styles.description}> |
||||
Get started by editing{' '} |
||||
<code className={styles.code}>pages/index.tsx</code> |
||||
</p> |
||||
|
||||
<div className={styles.grid}> |
||||
<a href="https://nextjs.org/docs" className={styles.card}> |
||||
<h2>Documentation →</h2> |
||||
<p>Find in-depth information about Next.js features and API.</p> |
||||
</a> |
||||
|
||||
<a href="https://nextjs.org/learn" className={styles.card}> |
||||
<h2>Learn →</h2> |
||||
<p>Learn about Next.js in an interactive course with quizzes!</p> |
||||
</a> |
||||
|
||||
<a |
||||
href="https://github.com/vercel/next.js/tree/canary/examples" |
||||
className={styles.card} |
||||
> |
||||
<h2>Examples →</h2> |
||||
<p>Discover and deploy boilerplate example Next.js projects.</p> |
||||
</a> |
||||
|
||||
<a |
||||
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app" |
||||
className={styles.card} |
||||
> |
||||
<h2>Deploy →</h2> |
||||
<p> |
||||
Instantly deploy your Next.js site to a public URL with Vercel. |
||||
</p> |
||||
</a> |
||||
</div> |
||||
</main> |
||||
|
||||
<footer className={styles.footer}> |
||||
<a |
||||
href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app" |
||||
target="_blank" |
||||
rel="noopener noreferrer" |
||||
> |
||||
Powered by{' '} |
||||
<span className={styles.logo}> |
||||
<Image src="/vercel.svg" alt="Vercel Logo" width={72} height={16} /> |
||||
</span> |
||||
</a> |
||||
</footer> |
||||
</div> |
||||
) |
||||
} |
||||
|
||||
export default Home |
@ -0,0 +1,67 @@ |
||||
import { format, parseISO } from 'date-fns'; |
||||
import { GetStaticProps } from 'next'; |
||||
import Link from 'next/link'; |
||||
import React from 'react'; |
||||
import Layout from '../components/Layout'; |
||||
import { getAllPosts } from '../lib/api'; |
||||
import { PostType } from '../types/post'; |
||||
|
||||
type IndexProps = { |
||||
posts: PostType[]; |
||||
}; |
||||
|
||||
export const Index = ({ posts }: IndexProps): JSX.Element => { |
||||
return ( |
||||
<Layout> |
||||
<h1>Робототехнический фестиваль RobotTop</h1> |
||||
<p>RobotTop – это робототехнические соревнования, в которых могут принять участие молодые любители робототехники, объединившись в команды.</p> |
||||
<ul className="list-disc pl-4 my-6"> |
||||
<li className="mt-2"><b>Дата проведения </b> с 16 января по 20 января 2023 года</li> |
||||
<li className="mt-2"><b>Место проведения </b> г. Краснодар ул. Байбакова 17 (МАОУ СОШ 103)</li> |
||||
<li className="mt-2">Любая робототехническая платформа</li> |
||||
<li className="mt-2">Отдельная возрастная группа для LEGO WEDO 1-2 класс</li> |
||||
<li className="mt-2">Команда от 2 до 3 человек</li> |
||||
<li className="mt-2">11 возрастных групп</li> |
||||
<li className="mt-2">Свобода в творчестве</li> |
||||
</ul> |
||||
<Link href={`/registration`}> |
||||
<a |
||||
className="inline-block px-7 py-3 rounded-md text-white dark:text-white bg-blue-600 hover:bg-blue-700 hover:text-white dark:hover:text-white" |
||||
> |
||||
Регистрация команды |
||||
</a> |
||||
</Link> |
||||
|
||||
{posts.map((post) => ( |
||||
<article key={post.slug} className="mt-12"> |
||||
<p className="mb-1 text-sm text-gray-500 dark:text-gray-400"> |
||||
{format(parseISO(post.date), 'MMMM dd, yyyy')} |
||||
</p> |
||||
<h1 className="mb-2 text-xl"> |
||||
<Link as={`/posts/${post.slug}`} href={`/posts/[slug]`}> |
||||
<a className="text-gray-900 dark:text-white dark:hover:text-blue-400"> |
||||
{post.title} |
||||
</a> |
||||
</Link> |
||||
</h1> |
||||
<p className="mb-3">{post.description}</p> |
||||
<p> |
||||
<Link as={`/posts/${post.slug}`} href={`/posts/[slug]`}> |
||||
<a>Подробнее...</a> |
||||
</Link> |
||||
</p> |
||||
</article> |
||||
))} |
||||
</Layout> |
||||
); |
||||
}; |
||||
|
||||
export const getStaticProps: GetStaticProps = async () => { |
||||
const posts = getAllPosts(['date', 'description', 'slug', 'title']); |
||||
|
||||
return { |
||||
props: { posts }, |
||||
}; |
||||
}; |
||||
|
||||
export default Index; |
@ -0,0 +1,67 @@ |
||||
import { format, parseISO } from 'date-fns'; |
||||
import { GetStaticProps } from 'next'; |
||||
import Link from 'next/link'; |
||||
import React from 'react'; |
||||
import Layout from '../components/Layout'; |
||||
import { getAllPosts } from '../lib/api'; |
||||
import { PostType } from '../types/post'; |
||||
|
||||
type IndexProps = { |
||||
posts: PostType[]; |
||||
}; |
||||
|
||||
export const Index = ({ posts }: IndexProps): JSX.Element => { |
||||
return ( |
||||
<Layout> |
||||
<h1>Робототехнический фестиваль RobotTop</h1> |
||||
<p>RobotTop – это робототехнические соревнования, в которых могут принять участие молодые любители робототехники, объединившись в команды.</p> |
||||
<ul className="list-disc pl-4 my-6"> |
||||
<li className="mt-2"><b>Дата проведения </b> с 16 января по 20 января 2023 года</li> |
||||
<li className="mt-2"><b>Место проведения </b> г. Краснодар ул. Байбакова 17 (МАОУ СОШ 103)</li> |
||||
<li className="mt-2">Любая робототехническая платформа</li> |
||||
<li className="mt-2">Отдельная возрастная группа для LEGO WEDO 1-2 класс</li> |
||||
<li className="mt-2">Команда от 2 до 3 человек</li> |
||||
<li className="mt-2">11 возрастных групп</li> |
||||
<li className="mt-2">Свобода в творчестве</li> |
||||
</ul> |
||||
<Link href={`/registration`}> |
||||
<a |
||||
className="inline-block px-7 py-3 rounded-md text-white dark:text-white bg-blue-600 hover:bg-blue-700 hover:text-white dark:hover:text-white" |
||||
> |
||||
Регистрация команды |
||||
</a> |
||||
</Link> |
||||
|
||||
{posts.map((post) => ( |
||||
<article key={post.slug} className="mt-12"> |
||||
<p className="mb-1 text-sm text-gray-500 dark:text-gray-400"> |
||||
{format(parseISO(post.date), 'MMMM dd, yyyy')} |
||||
</p> |
||||
<h1 className="mb-2 text-xl"> |
||||
<Link as={`/posts/${post.slug}`} href={`/posts/[slug]`}> |
||||
<a className="text-gray-900 dark:text-white dark:hover:text-blue-400"> |
||||
{post.title} |
||||
</a> |
||||
</Link> |
||||
</h1> |
||||
<p className="mb-3">{post.description}</p> |
||||
<p> |
||||
<Link as={`/posts/${post.slug}`} href={`/posts/[slug]`}> |
||||
<a>Подробнее...</a> |
||||
</Link> |
||||
</p> |
||||
</article> |
||||
))} |
||||
</Layout> |
||||
); |
||||
}; |
||||
|
||||
export const getStaticProps: GetStaticProps = async () => { |
||||
const posts = getAllPosts(['date', 'description', 'slug', 'title']); |
||||
|
||||
return { |
||||
props: { posts }, |
||||
}; |
||||
}; |
||||
|
||||
export default Index; |
@ -0,0 +1,51 @@ |
||||
import { format, parseISO } from 'date-fns'; |
||||
import { GetStaticProps } from 'next'; |
||||
import Link from 'next/link'; |
||||
import React from 'react'; |
||||
import Layout from '../components/Layout'; |
||||
import { getAllPosts } from '../lib/api'; |
||||
import { PostType } from '../types/post'; |
||||
|
||||
type IndexProps = { |
||||
posts: PostType[]; |
||||
}; |
||||
|
||||
export const Index = ({ posts }: IndexProps): JSX.Element => { |
||||
return ( |
||||
<Layout> |
||||
<h1>Робототехнический фестиваль RobotTop</h1> |
||||
<p>RobotTop – это робототехнические соревнования, в которых могут принять участие молодые любители робототехники, объединившись в команды.</p> |
||||
|
||||
{posts.map((post) => ( |
||||
<article key={post.slug} className="mt-12"> |
||||
<p className="mb-1 text-sm text-gray-500 dark:text-gray-400"> |
||||
{format(parseISO(post.date), 'MMMM dd, yyyy')} |
||||
</p> |
||||
<h1 className="mb-2 text-xl"> |
||||
<Link as={`/posts/${post.slug}`} href={`/posts/[slug]`}> |
||||
<a className="text-gray-900 dark:text-white dark:hover:text-blue-400"> |
||||
{post.title} |
||||
</a> |
||||
</Link> |
||||
</h1> |
||||
<p className="mb-3">{post.description}</p> |
||||
<p> |
||||
<Link as={`/posts/${post.slug}`} href={`/posts/[slug]`}> |
||||
<a>Подробнее...</a> |
||||
</Link> |
||||
</p> |
||||
</article> |
||||
))} |
||||
</Layout> |
||||
); |
||||
}; |
||||
|
||||
export const getStaticProps: GetStaticProps = async () => { |
||||
const posts = getAllPosts(['date', 'description', 'slug', 'title']); |
||||
|
||||
return { |
||||
props: { posts }, |
||||
}; |
||||
}; |
||||
|
||||
export default Index; |
@ -0,0 +1,49 @@ |
||||
import { format, parseISO } from 'date-fns'; |
||||
import { GetStaticProps } from 'next'; |
||||
import Link from 'next/link'; |
||||
import React from 'react'; |
||||
import Layout from '../components/Layout'; |
||||
import { getAllPosts } from '../lib/api'; |
||||
import { PostType } from '../types/post'; |
||||
|
||||
type IndexProps = { |
||||
posts: PostType[]; |
||||
}; |
||||
|
||||
export const Index = ({ posts }: IndexProps): JSX.Element => { |
||||
return ( |
||||
<Layout> |
||||
<h1>Робототехнический фестиваль RobotTop</h1> |
||||
{posts.map((post) => ( |
||||
<article key={post.slug} className="mt-12"> |
||||
<p className="mb-1 text-sm text-gray-500 dark:text-gray-400"> |
||||
{format(parseISO(post.date), 'MMMM dd, yyyy')} |
||||
</p> |
||||
<h1 className="mb-2 text-xl"> |
||||
<Link as={`/posts/${post.slug}`} href={`/posts/[slug]`}> |
||||
<a className="text-gray-900 dark:text-white dark:hover:text-blue-400"> |
||||
{post.title} |
||||
</a> |
||||
</Link> |
||||
</h1> |
||||
<p className="mb-3">{post.description}</p> |
||||
<p> |
||||
<Link as={`/posts/${post.slug}`} href={`/posts/[slug]`}> |
||||
<a>Подробнее...</a> |
||||
</Link> |
||||
</p> |
||||
</article> |
||||
))} |
||||
</Layout> |
||||
); |
||||
}; |
||||
|
||||
export const getStaticProps: GetStaticProps = async () => { |
||||
const posts = getAllPosts(['date', 'description', 'slug', 'title']); |
||||
|
||||
return { |
||||
props: { posts }, |
||||
}; |
||||
}; |
||||
|
||||
export default Index; |
@ -0,0 +1,49 @@ |
||||
import { format, parseISO } from 'date-fns'; |
||||
import { GetStaticProps } from 'next'; |
||||
import Link from 'next/link'; |
||||
import React from 'react'; |
||||
import Layout from '../components/Layout'; |
||||
import { getAllPosts } from '../lib/api'; |
||||
import { PostType } from '../types/post'; |
||||
|
||||
type IndexProps = { |
||||
posts: PostType[]; |
||||
}; |
||||
|
||||
export const Index = ({ posts }: IndexProps): JSX.Element => { |
||||
return ( |
||||
<Layout> |
||||
<h1>Ули Учись или уходи!</h1> |
||||
{posts.map((post) => ( |
||||
<article key={post.slug} className="mt-12"> |
||||
<p className="mb-1 text-sm text-gray-500 dark:text-gray-400"> |
||||
{format(parseISO(post.date), 'MMMM dd, yyyy')} |
||||
</p> |
||||
<h1 className="mb-2 text-xl"> |
||||
<Link as={`/posts/${post.slug}`} href={`/posts/[slug]`}> |
||||
<a className="text-gray-900 dark:text-white dark:hover:text-blue-400"> |
||||
{post.title} |
||||
</a> |
||||
</Link> |
||||
</h1> |
||||
<p className="mb-3">{post.description}</p> |
||||
<p> |
||||
<Link as={`/posts/${post.slug}`} href={`/posts/[slug]`}> |
||||
<a>Подробнее...</a> |
||||
</Link> |
||||
</p> |
||||
</article> |
||||
))} |
||||
</Layout> |
||||
); |
||||
}; |
||||
|
||||
export const getStaticProps: GetStaticProps = async () => { |
||||
const posts = getAllPosts(['date', 'description', 'slug', 'title']); |
||||
|
||||
return { |
||||
props: { posts }, |
||||
}; |
||||
}; |
||||
|
||||
export default Index; |
@ -0,0 +1,49 @@ |
||||
import { format, parseISO } from 'date-fns'; |
||||
import { GetStaticProps } from 'next'; |
||||
import Link from 'next/link'; |
||||
import React from 'react'; |
||||
import Layout from '../components/Layout'; |
||||
import { getAllPosts } from '../lib/api'; |
||||
import { PostType } from '../types/post'; |
||||
|
||||
type IndexProps = { |
||||
posts: PostType[]; |
||||
}; |
||||
|
||||
export const Index = ({ posts }: IndexProps): JSX.Element => { |
||||
return ( |
||||
<Layout> |
||||
<h1>или Учись или уходи!</h1> |
||||
{posts.map((post) => ( |
||||
<article key={post.slug} className="mt-12"> |
||||
<p className="mb-1 text-sm text-gray-500 dark:text-gray-400"> |
||||
{format(parseISO(post.date), 'MMMM dd, yyyy')} |
||||
</p> |
||||
<h1 className="mb-2 text-xl"> |
||||
<Link as={`/posts/${post.slug}`} href={`/posts/[slug]`}> |
||||
<a className="text-gray-900 dark:text-white dark:hover:text-blue-400"> |
||||
{post.title} |
||||
</a> |
||||
</Link> |
||||
</h1> |
||||
<p className="mb-3">{post.description}</p> |
||||
<p> |
||||
<Link as={`/posts/${post.slug}`} href={`/posts/[slug]`}> |
||||
<a>Подробнее...</a> |
||||
</Link> |
||||
</p> |
||||
</article> |
||||
))} |
||||
</Layout> |
||||
); |
||||
}; |
||||
|
||||
export const getStaticProps: GetStaticProps = async () => { |
||||
const posts = getAllPosts(['date', 'description', 'slug', 'title']); |
||||
|
||||
return { |
||||
props: { posts }, |
||||
}; |
||||
}; |
||||
|
||||
export default Index; |
@ -0,0 +1,49 @@ |
||||
import { format, parseISO } from 'date-fns'; |
||||
import { GetStaticProps } from 'next'; |
||||
import Link from 'next/link'; |
||||
import React from 'react'; |
||||
import Layout from '../components/Layout'; |
||||
import { getAllPosts } from '../lib/api'; |
||||
import { PostType } from '../types/post'; |
||||
|
||||
type IndexProps = { |
||||
posts: PostType[]; |
||||
}; |
||||
|
||||
export const Index = ({ posts }: IndexProps): JSX.Element => { |
||||
return ( |
||||
<Layout> |
||||
<h1>или Учись или Уходи!</h1> |
||||
{posts.map((post) => ( |
||||
<article key={post.slug} className="mt-12"> |
||||
<p className="mb-1 text-sm text-gray-500 dark:text-gray-400"> |
||||
{format(parseISO(post.date), 'MMMM dd, yyyy')} |
||||
</p> |
||||
<h1 className="mb-2 text-xl"> |
||||
<Link as={`/posts/${post.slug}`} href={`/posts/[slug]`}> |
||||
<a className="text-gray-900 dark:text-white dark:hover:text-blue-400"> |
||||
{post.title} |
||||
</a> |
||||
</Link> |
||||
</h1> |
||||
<p className="mb-3">{post.description}</p> |
||||
<p> |
||||
<Link as={`/posts/${post.slug}`} href={`/posts/[slug]`}> |
||||
<a>Подробнее...</a> |
||||
</Link> |
||||
</p> |
||||
</article> |
||||
))} |
||||
</Layout> |
||||
); |
||||
}; |
||||
|
||||
export const getStaticProps: GetStaticProps = async () => { |
||||
const posts = getAllPosts(['date', 'description', 'slug', 'title']); |
||||
|
||||
return { |
||||
props: { posts }, |
||||
}; |
||||
}; |
||||
|
||||
export default Index; |
@ -0,0 +1,49 @@ |
||||
import { format, parseISO } from 'date-fns'; |
||||
import { GetStaticProps } from 'next'; |
||||
import Link from 'next/link'; |
||||
import React from 'react'; |
||||
import Layout from '../components/Layout'; |
||||
import { getAllPosts } from '../lib/api'; |
||||
import { PostType } from '../types/post'; |
||||
|
||||
type IndexProps = { |
||||
posts: PostType[]; |
||||
}; |
||||
|
||||
export const Index = ({ posts }: IndexProps): JSX.Element => { |
||||
return ( |
||||
<Layout> |
||||
<h1>Krasnikov Robotics</h1> |
||||
{posts.map((post) => ( |
||||
<article key={post.slug} className="mt-12"> |
||||
<p className="mb-1 text-sm text-gray-500 dark:text-gray-400"> |
||||
{format(parseISO(post.date), 'MMMM dd, yyyy')} |
||||
</p> |
||||
<h1 className="mb-2 text-xl"> |
||||
<Link as={`/posts/${post.slug}`} href={`/posts/[slug]`}> |
||||
<a className="text-gray-900 dark:text-white dark:hover:text-blue-400"> |
||||
{post.title} |
||||
</a> |
||||
</Link> |
||||
</h1> |
||||
<p className="mb-3">{post.description}</p> |
||||
<p> |
||||
<Link as={`/posts/${post.slug}`} href={`/posts/[slug]`}> |
||||
<a>Подробнее...</a> |
||||
</Link> |
||||
</p> |
||||
</article> |
||||
))} |
||||
</Layout> |
||||
); |
||||
}; |
||||
|
||||
export const getStaticProps: GetStaticProps = async () => { |
||||
const posts = getAllPosts(['date', 'description', 'slug', 'title']); |
||||
|
||||
return { |
||||
props: { posts }, |
||||
}; |
||||
}; |
||||
|
||||
export default Index; |
@ -0,0 +1,95 @@ |
||||
import { format, parseISO } from 'date-fns'; |
||||
import fs from 'fs'; |
||||
import matter from 'gray-matter'; |
||||
import { GetStaticPaths, GetStaticProps } from 'next'; |
||||
import { serialize } from 'next-mdx-remote/serialize'; |
||||
import { MDXRemote, MDXRemoteSerializeResult } from 'next-mdx-remote'; |
||||
import Head from 'next/head'; |
||||
import Image from 'next/image'; |
||||
import Link from 'next/link'; |
||||
import path from 'path'; |
||||
import React from 'react'; |
||||
import rehypeAutolinkHeadings from 'rehype-autolink-headings'; |
||||
import rehypeSlug from 'rehype-slug'; |
||||
import Layout, { WEBSITE_HOST_URL } from '../../components/Layout'; |
||||
import { MetaProps } from '../../types/layout'; |
||||
import { PostType } from '../../types/post'; |
||||
import { postFilePaths, POSTS_PATH } from '../../utils/mdxUtils'; |
||||
|
||||
// Custom components/renderers to pass to MDX.
|
||||
// Since the MDX files aren't loaded by webpack, they have no knowledge of how
|
||||
// to handle import statements. Instead, you must include components in scope
|
||||
// here.
|
||||
const components = { |
||||
Head, |
||||
Image, |
||||
Link, |
||||
}; |
||||
|
||||
type PostPageProps = { |
||||
source: MDXRemoteSerializeResult; |
||||
frontMatter: PostType; |
||||
}; |
||||
|
||||
const PostPage = ({ source, frontMatter }: PostPageProps): JSX.Element => { |
||||
const customMeta: MetaProps = { |
||||
title: `${frontMatter.title} - RoboTop`, |
||||
description: frontMatter.description, |
||||
image: `${WEBSITE_HOST_URL}${frontMatter.image}`, |
||||
date: frontMatter.date, |
||||
type: 'article', |
||||
}; |
||||
return ( |
||||
<Layout customMeta={customMeta}> |
||||
<article className="max-w"> |
||||
<h1 className="mb-3 text-gray-900 dark:text-white"> |
||||
{frontMatter.title} |
||||
</h1> |
||||
<p className="mb-10 text-sm text-gray-500 dark:text-gray-400"> |
||||
{format(parseISO(frontMatter.date), 'MMMM dd, yyyy')} |
||||
</p> |
||||
<div className="prose dark:prose-dark"> |
||||
<MDXRemote {...source} components={components} /> |
||||
</div> |
||||
</article> |
||||
</Layout> |
||||
); |
||||
}; |
||||
|
||||
export const getStaticProps: GetStaticProps = async ({ params }) => { |
||||
const postFilePath = path.join(POSTS_PATH, `${params.slug}.mdx`); |
||||
const source = fs.readFileSync(postFilePath); |
||||
|
||||
const { content, data } = matter(source); |
||||
|
||||
const mdxSource = await serialize(content, { |
||||
// Optionally pass remark/rehype plugins
|
||||
mdxOptions: { |
||||
remarkPlugins: [require('remark-code-titles')], |
||||
rehypePlugins: [rehypeSlug, rehypeAutolinkHeadings], |
||||
}, |
||||
scope: data, |
||||
}); |
||||
|
||||
return { |
||||
props: { |
||||
source: mdxSource, |
||||
frontMatter: data, |
||||
}, |
||||
}; |
||||
}; |
||||
|
||||
export const getStaticPaths: GetStaticPaths = async () => { |
||||
const paths = postFilePaths |
||||
// Remove file extensions for page paths
|
||||
.map((path) => path.replace(/\.mdx?$/, '')) |
||||
// Map the path into the static paths object required by Next.js
|
||||
.map((slug) => ({ params: { slug } })); |
||||
|
||||
return { |
||||
paths, |
||||
fallback: false, |
||||
}; |
||||
}; |
||||
|
||||
export default PostPage; |
@ -0,0 +1,11 @@ |
||||
--- |
||||
title: Примеры выполнения задания |
||||
description: Видео по выполнения заданий и материалы по сборке и программирования робота |
||||
date: '2022-07-02' |
||||
--- |
||||
|
||||
Наданный момент мы подготавливаем материаол для публикации на сайте. |
||||
Весь материал будет опубликован до 15 сентября 2022 года. |
||||
|
||||
|
||||
На главную [Home](/) |
@ -0,0 +1,11 @@ |
||||
--- |
||||
title: 3D моделирование |
||||
description: Видео по выполнения заданий и материалы по сборке и программирования робота |
||||
date: '2022-07-02' |
||||
--- |
||||
|
||||
Наданный момент мы подготавливаем материаол для публикации на сайте. |
||||
Весь материал будет опубликован до 15 сентября 2022 года. |
||||
|
||||
|
||||
На главную [Home](/) |
@ -0,0 +1,11 @@ |
||||
--- |
||||
title: 3D моделирование |
||||
description: ... |
||||
date: '2022-07-02' |
||||
--- |
||||
|
||||
Наданный момент мы подготавливаем материаол для публикации на сайте. |
||||
Весь материал будет опубликован до 15 сентября 2022 года. |
||||
|
||||
|
||||
На главную [Home](/) |
@ -0,0 +1,11 @@ |
||||
--- |
||||
title: 3D моделирование |
||||
description: .. |
||||
date: '2022-07-02' |
||||
--- |
||||
|
||||
Наданный момент мы подготавливаем материаол для публикации на сайте. |
||||
Весь материал будет опубликован до 15 сентября 2022 года. |
||||
|
||||
|
||||
На главную [Home](/) |
@ -0,0 +1,11 @@ |
||||
--- |
||||
title: 3D моделирование |
||||
description: Задачи, материал по теме |
||||
date: '2022-07-02' |
||||
--- |
||||
|
||||
Наданный момент мы подготавливаем материаол для публикации на сайте. |
||||
Весь материал будет опубликован до 15 сентября 2022 года. |
||||
|
||||
|
||||
На главную [Home](/) |
@ -0,0 +1,69 @@ |
||||
--- |
||||
title: Расписание фестиваля |
||||
description: Расписаине фестиваля по дням |
||||
date: '2021-06-01' |
||||
--- |
||||
|
||||
## Расписаие фестиваля РобоТоп |
||||
|
||||
**!!Примерное расписание фестиваля!!** |
||||
|
||||
### Понедельник - Заезды возрастных групп 1, 2 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение первого дня |
||||
|
||||
### Вторник - Заезды возрастных групп 3, 4 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение второго дня |
||||
|
||||
### Среда - Заезды возрастных групп 5, 6 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение третьего дня |
||||
|
||||
### Четверг - Заезды возрастных групп 7, 8 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение четвертого дня |
||||
|
||||
### Пятница - Заезды возрастных групп 9, 10, 11 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение пятого дня |
@ -0,0 +1,11 @@ |
||||
--- |
||||
title: Примеры выполнения задания |
||||
description: Видео по выполнения заданий и материалы по сборке и программирования робота |
||||
date: '2022-07-02' |
||||
--- |
||||
|
||||
Наданный момент мы подготавливаем материаол для публикации на сайте. |
||||
Весь материал будет опубликован до 15 сентября 2022 года. |
||||
|
||||
|
||||
На главную [Home](/) |
@ -0,0 +1,11 @@ |
||||
--- |
||||
title: Программирование - 1 урок |
||||
description: Видео по выполнения заданий и материалы по сборке и программирования робота |
||||
date: '2022-07-02' |
||||
--- |
||||
|
||||
Наданный момент мы подготавливаем материаол для публикации на сайте. |
||||
Весь материал будет опубликован до 15 сентября 2022 года. |
||||
|
||||
|
||||
На главную [Home](/) |
@ -0,0 +1,69 @@ |
||||
--- |
||||
title: Расписание фестиваля |
||||
description: Расписаине фестиваля по дням |
||||
date: '2021-06-01' |
||||
--- |
||||
|
||||
## Расписаие фестиваля РобоТоп |
||||
|
||||
**!!Примерное расписание фестиваля!!** |
||||
|
||||
### Понедельник - Заезды возрастных групп 1, 2 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение первого дня |
||||
|
||||
### Вторник - Заезды возрастных групп 3, 4 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение второго дня |
||||
|
||||
### Среда - Заезды возрастных групп 5, 6 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение третьего дня |
||||
|
||||
### Четверг - Заезды возрастных групп 7, 8 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение четвертого дня |
||||
|
||||
### Пятница - Заезды возрастных групп 9, 10, 11 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение пятого дня |
@ -0,0 +1,69 @@ |
||||
--- |
||||
title: Программирование |
||||
description: Расписаине фестиваля по дням |
||||
date: '2021-06-01' |
||||
--- |
||||
|
||||
## Расписаие фестиваля РобоТоп |
||||
|
||||
**!!Примерное расписание фестиваля!!** |
||||
|
||||
### Понедельник - Заезды возрастных групп 1, 2 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение первого дня |
||||
|
||||
### Вторник - Заезды возрастных групп 3, 4 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение второго дня |
||||
|
||||
### Среда - Заезды возрастных групп 5, 6 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение третьего дня |
||||
|
||||
### Четверг - Заезды возрастных групп 7, 8 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение четвертого дня |
||||
|
||||
### Пятница - Заезды возрастных групп 9, 10, 11 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение пятого дня |
@ -0,0 +1,69 @@ |
||||
--- |
||||
title: Программирование |
||||
description: Расписаине фестиваля по дням |
||||
date: '2021-06-01' |
||||
--- |
||||
|
||||
## Расписаие фестиваля РобоТоп |
||||
|
||||
**!!Примерное расписание фестиваля!!** |
||||
|
||||
### Понедельник - Заезды возрастных групп 1, 2 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение первого дня |
||||
|
||||
### Вторник - Заезды возрастных групп 3, 4 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение второго дня |
||||
|
||||
### Среда - Заезды возрастных групп 5, 6 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение третьего дня |
||||
|
||||
### Четверг - Заезды возрастных групп 7, 8 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение четвертого дня |
||||
|
||||
### Пятница - Заезды возрастных групп 9, 10, 11 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение пятого дня |
@ -0,0 +1,69 @@ |
||||
--- |
||||
title: Программирование |
||||
description: ... |
||||
date: '2021-06-01' |
||||
--- |
||||
|
||||
## Расписаие фестиваля РобоТоп |
||||
|
||||
**!!Примерное расписание фестиваля!!** |
||||
|
||||
### Понедельник - Заезды возрастных групп 1, 2 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение первого дня |
||||
|
||||
### Вторник - Заезды возрастных групп 3, 4 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение второго дня |
||||
|
||||
### Среда - Заезды возрастных групп 5, 6 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение третьего дня |
||||
|
||||
### Четверг - Заезды возрастных групп 7, 8 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение четвертого дня |
||||
|
||||
### Пятница - Заезды возрастных групп 9, 10, 11 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение пятого дня |
@ -0,0 +1,69 @@ |
||||
--- |
||||
title: Программирование |
||||
description: .. |
||||
date: '2021-06-01' |
||||
--- |
||||
|
||||
## Расписаие фестиваля РобоТоп |
||||
|
||||
**!!Примерное расписание фестиваля!!** |
||||
|
||||
### Понедельник - Заезды возрастных групп 1, 2 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение первого дня |
||||
|
||||
### Вторник - Заезды возрастных групп 3, 4 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение второго дня |
||||
|
||||
### Среда - Заезды возрастных групп 5, 6 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение третьего дня |
||||
|
||||
### Четверг - Заезды возрастных групп 7, 8 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение четвертого дня |
||||
|
||||
### Пятница - Заезды возрастных групп 9, 10, 11 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение пятого дня |
@ -0,0 +1,69 @@ |
||||
--- |
||||
title: Программирование |
||||
description: Задачи, материал по теме |
||||
date: '2021-06-01' |
||||
--- |
||||
|
||||
## Расписаие фестиваля РобоТоп |
||||
|
||||
**!!Примерное расписание фестиваля!!** |
||||
|
||||
### Понедельник - Заезды возрастных групп 1, 2 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение первого дня |
||||
|
||||
### Вторник - Заезды возрастных групп 3, 4 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение второго дня |
||||
|
||||
### Среда - Заезды возрастных групп 5, 6 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение третьего дня |
||||
|
||||
### Четверг - Заезды возрастных групп 7, 8 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение четвертого дня |
||||
|
||||
### Пятница - Заезды возрастных групп 9, 10, 11 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение пятого дня |
@ -0,0 +1,69 @@ |
||||
--- |
||||
title: Программирование |
||||
description: Задачи, материал по теме |
||||
date: '2021-06-01' |
||||
--- |
||||
|
||||
## Понедельник 10.10.22 |
||||
|
||||
**!!Примерное расписание фестиваля!!** |
||||
|
||||
### Понедельник - Заезды возрастных групп 1, 2 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение первого дня |
||||
|
||||
### Вторник - Заезды возрастных групп 3, 4 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение второго дня |
||||
|
||||
### Среда - Заезды возрастных групп 5, 6 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение третьего дня |
||||
|
||||
### Четверг - Заезды возрастных групп 7, 8 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение четвертого дня |
||||
|
||||
### Пятница - Заезды возрастных групп 9, 10, 11 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение пятого дня |
@ -0,0 +1,69 @@ |
||||
--- |
||||
title: Программирование |
||||
description: Задачи, материал по теме |
||||
date: '2021-06-01' |
||||
--- |
||||
|
||||
## Понедельник 10.10.22 |
||||
|
||||
Тема урока: ** ** |
||||
|
||||
### Понедельник - Заезды возрастных групп 1, 2 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение первого дня |
||||
|
||||
### Вторник - Заезды возрастных групп 3, 4 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение второго дня |
||||
|
||||
### Среда - Заезды возрастных групп 5, 6 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение третьего дня |
||||
|
||||
### Четверг - Заезды возрастных групп 7, 8 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение четвертого дня |
||||
|
||||
### Пятница - Заезды возрастных групп 9, 10, 11 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение пятого дня |
@ -0,0 +1,69 @@ |
||||
--- |
||||
title: Программирование |
||||
description: Задачи, материал по теме |
||||
date: '2021-06-01' |
||||
--- |
||||
|
||||
## Понедельник 10.10.22 |
||||
|
||||
Тема урока: ** Установк языка программирования** |
||||
|
||||
### Понедельник - Заезды возрастных групп 1, 2 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение первого дня |
||||
|
||||
### Вторник - Заезды возрастных групп 3, 4 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение второго дня |
||||
|
||||
### Среда - Заезды возрастных групп 5, 6 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение третьего дня |
||||
|
||||
### Четверг - Заезды возрастных групп 7, 8 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение четвертого дня |
||||
|
||||
### Пятница - Заезды возрастных групп 9, 10, 11 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение пятого дня |
@ -0,0 +1,69 @@ |
||||
--- |
||||
title: Программирование |
||||
description: Задачи, материал по теме |
||||
date: '2021-06-01' |
||||
--- |
||||
|
||||
## Понедельник 10.10.22 |
||||
|
||||
Тема урока: **Установк языка программирования** |
||||
|
||||
### Понедельник - Заезды возрастных групп 1, 2 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение первого дня |
||||
|
||||
### Вторник - Заезды возрастных групп 3, 4 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение второго дня |
||||
|
||||
### Среда - Заезды возрастных групп 5, 6 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение третьего дня |
||||
|
||||
### Четверг - Заезды возрастных групп 7, 8 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение четвертого дня |
||||
|
||||
### Пятница - Заезды возрастных групп 9, 10, 11 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение пятого дня |
@ -0,0 +1,69 @@ |
||||
--- |
||||
title: Программирование |
||||
description: Задачи, материал по теме |
||||
date: '2021-10-10' |
||||
--- |
||||
|
||||
## Понедельник 10.10.22 |
||||
|
||||
Тема урока: **Установк языка программирования** |
||||
|
||||
### Понедельник - Заезды возрастных групп 1, 2 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение первого дня |
||||
|
||||
### Вторник - Заезды возрастных групп 3, 4 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение второго дня |
||||
|
||||
### Среда - Заезды возрастных групп 5, 6 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение третьего дня |
||||
|
||||
### Четверг - Заезды возрастных групп 7, 8 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение четвертого дня |
||||
|
||||
### Пятница - Заезды возрастных групп 9, 10, 11 классы |
||||
+ 08:00 - 11:00 - Заезд и регистрация команд, отладка роботов |
||||
+ 11:00 - 11:45 - Открытие фесиваля |
||||
+ 11:45 - 12:30 - Обед |
||||
+ 13:00 - 14:00 - Клафикационные заезды |
||||
+ 14:00 - 15:00 - Заеды 1/16 |
||||
+ 15:00 - 16:00 - Заеды 1/8 |
||||
+ 16:00 - 16:30 - Заеды 1/4 |
||||
+ 16:30 - 17:00 - Заеды 1/2 |
||||
+ 17:30 - 18:30 - Ужин |
||||
+ 18:30 - 19:00 - Награждение пятого дня |
@ -0,0 +1,10 @@ |
||||
--- |
||||
title: Программирование |
||||
description: Задачи, материал по теме |
||||
date: '2021-10-10' |
||||
--- |
||||
|
||||
## Понедельник 10.10.22 |
||||
|
||||
Тема урока: **Установк языка программирования** |
||||
|
@ -0,0 +1,13 @@ |
||||
--- |
||||
title: Программирование |
||||
description: Задачи, материал по теме |
||||
date: '2021-10-10' |
||||
--- |
||||
|
||||
## Понедельник 10.10.22 |
||||
|
||||
Тема урока: **Установк языка программирования** |
||||
|
||||
```python |
||||
print('Heloy World') |
||||
``` |
@ -0,0 +1,21 @@ |
||||
--- |
||||
title: Программирование |
||||
description: Задачи, материал по теме |
||||
date: '2021-10-10' |
||||
--- |
||||
|
||||
## Понедельник 10.10.22 |
||||
|
||||
Тема урока: **Установк языка программирования** |
||||
|
||||
```python |
||||
print('Heloy World') |
||||
``` |
||||
|
||||
```mermaid |
||||
graph TD; |
||||
A-->B; |
||||
A-->C; |
||||
B-->D; |
||||
C-->D; |
||||
``` |
@ -0,0 +1,46 @@ |
||||
--- |
||||
title: Программирование |
||||
description: Задачи, материал по теме |
||||
date: '2021-10-10' |
||||
--- |
||||
|
||||
## Понедельник 10.10.22 |
||||
|
||||
Тема урока: **Установк языка программирования** |
||||
|
||||
```python |
||||
print('Heloy World') |
||||
``` |
||||
|
||||
```stl |
||||
solid cube_corner |
||||
facet normal 0.0 -1.0 0.0 |
||||
outer loop |
||||
vertex 0.0 0.0 0.0 |
||||
vertex 1.0 0.0 0.0 |
||||
vertex 0.0 0.0 1.0 |
||||
endloop |
||||
endfacet |
||||
facet normal 0.0 0.0 -1.0 |
||||
outer loop |
||||
vertex 0.0 0.0 0.0 |
||||
vertex 0.0 1.0 0.0 |
||||
vertex 1.0 0.0 0.0 |
||||
endloop |
||||
endfacet |
||||
facet normal -1.0 0.0 0.0 |
||||
outer loop |
||||
vertex 0.0 0.0 0.0 |
||||
vertex 0.0 0.0 1.0 |
||||
vertex 0.0 1.0 0.0 |
||||
endloop |
||||
endfacet |
||||
facet normal 0.577 0.577 0.577 |
||||
outer loop |
||||
vertex 1.0 0.0 0.0 |
||||
vertex 0.0 1.0 0.0 |
||||
vertex 0.0 0.0 1.0 |
||||
endloop |
||||
endfacet |
||||
endsolid |
||||
``` |
@ -0,0 +1,15 @@ |
||||
--- |
||||
title: Программирование |
||||
description: Задачи, материал по теме |
||||
date: '2021-10-10' |
||||
--- |
||||
|
||||
## Понедельник 10.10.22 |
||||
|
||||
Тема урока: **Установк языка программирования** |
||||
|
||||
```python |
||||
print('Heloy World') |
||||
``` |
||||
|
||||
This sentence uses `$` delimiters to show math inline: $\sqrt{3x-1}+(1+x)^2$ |
@ -0,0 +1,14 @@ |
||||
--- |
||||
title: Программирование |
||||
description: Задачи, материал по теме |
||||
date: '2021-10-10' |
||||
--- |
||||
|
||||
## Понедельник 10.10.22 |
||||
|
||||
Тема урока: **Установк языка программирования** |
||||
|
||||
```python |
||||
print('Heloy World') |
||||
``` |
||||
|
@ -0,0 +1,298 @@ |
||||
--- |
||||
title: Регламент проведения соревнования |
||||
description: Регламент проведения соревнования. РоботТОП Junior 2023 |
||||
date: '2022-09-01' |
||||
image: '/images/robottop.png' |
||||
--- |
||||
|
||||
<Image |
||||
alt={`Регламент проведения соревнования. РоботТОП Junior 2023`} |
||||
src={`/images/robottop.png`} |
||||
width={1440} |
||||
height={460} |
||||
priority |
||||
/> |
||||
|
||||
<p>Участникам необходимо подготовить робота, способного наиболее эффективно поменять местами оригинал статуэтки на ее реплику. Состязание проходит на автономных моделях роботов.</p> |
||||
|
||||
## I. Участники: |
||||
* <p>Команда состоит из 2 - 3 учащихся с 1 по 11 класс</p> |
||||
* <p>Каждая команда на соревнованиях должна привезти с собой одного **уникального робота, витрину, статуэтку.**</p> |
||||
* <p>Возрастные группы участников разделяются по классам (команда первоклассников, 2-х, 3-х, 4-х и т.д.) (Класс ученика подтверждается документом). Если в команде присутствуют участники из разных классов, то определяется по самому старшему ученику.</p> |
||||
* <p>Отдельный человек может быть участником лишь одной команды, даже если обе команды принадлежат к одной организации, при этом, обмен опытом всячески приветствуется. На руководителя проекта (учитель, один из родителей, лидер группы, и т. п.) возрастные ограничения не распространяются, но робот должен быть полностью разработан и построен членами команды.</p> |
||||
|
||||
## II. Задачи для робота: |
||||
## 1. Сохранение и экспонирование статуэтки. |
||||
### Действия: |
||||
* За время подготовки команда должна поставить свою статуэтку на пьедестал. |
||||
* Во время подготовки команда должна предварительно поместить реплику в своего робота. |
||||
* Во время заеда робот должнен забрать статуэтку с пьедестала. |
||||
* После того как статуэтка будет взята, роботы должны поместить ее на витрину. |
||||
* Робот должн поставить реплику на пьедестал вместо статуэтки. |
||||
### Ограничения: |
||||
* Реплику и статуэтку нельзя складывать в стопку. |
||||
* Реплика считается стоящей на пьедестале только в том случае, если она находится на постаменте в конце матча. |
||||
* Реплика представляет собой куб со стороной 60 мм. |
||||
* Статуэтка считается стоящей в витрине, если весь ее объем входит в габариты витрины. |
||||
* Статуэтка не может самостоятельно перемещаться ни внутри витрины, ни на игровой площадке. |
||||
* Статуэтка, построенная командой, имеет следующие ограничения по размерам: |
||||
+ Она должна помещаться в кубе со стороной 120 мм. |
||||
+ Она должна быть больше, чем куб со стороной 60 мм для категории LEGO WEDO 30 мм. |
||||
+ Вес статуэтки не должен превышать 600г. |
||||
* Статуэтка может быть оснащена электроникой. В этом случае она должна иметь кнопку аварийной остановки. |
||||
* Допускается использование простого тумблера в качестве кнопки аварийной остановки. Кнопка должна быть видна и доступна судьям в любое время. |
||||
* Статуэтка, все еще находящаяся под контролем робота в конце матча, не будет засчитана. |
||||
* Реплика, находящаяся под контролем робота в конце матча, не засчитывается. |
||||
### Баллы |
||||
* 2 балла за установку статуэтки на пьедестал во время подготовки; |
||||
* 5 баллов, если статуэтка отсутствует на пьедестале в конце игры; |
||||
* 10 баллов, если реплика находится на пьедестале в конце игры; |
||||
* 15 баллов, если статуэтка находится в витрине в конце игры; |
||||
|
||||
<Image |
||||
alt={`Рисунок 3 - Общий вид игрового поля`} |
||||
src={`/images/zadanie.png`} |
||||
width={512} |
||||
height={256} |
||||
priority |
||||
/> |
||||
Рисунок 4 - Перемещение статуэтки и реплики |
||||
|
||||
## 2. Возвращение в лагерь в конце дня. |
||||
### Действия: |
||||
* После окончания матча робот должен быть остановлен в собственном лагере. |
||||
### Ограничения: |
||||
* Чтобы считаться действительным, вертикальная проекция робота должна хотя бы частично находиться в пределах лагеря. |
||||
## Баллы: |
||||
* 20 баллов, если робот команды находится в одной из зон лагеря; |
||||
<p> 3. Оценка своей работы. </p> |
||||
* Устройство для отображения подсчета очков во время матча должно быть сделано командой: |
||||
+ Оно может быть статичным (лист бумаги, грифельная доска и т.д.) или динамическим (электронный дисплей); расположенным либо на роботе, либо на витрине (пожалуйста, убедитесь, что витрина активирована). |
||||
### Действия и ограничения: |
||||
* Команда должна оценить количество очков, набранных в матче ее роботом. Для этого возможны два исключающих варианта: |
||||
+ Предматчевая оценка на статическом дисплее: команда пишет счет, который она намерена сделать во время матча. |
||||
+ Оценка во время матча на динамическом устройстве отображения. |
||||
+ Область дисплея и его ориентация для чтения должны быть легко различимы и идентифицируемы судьями. |
||||
+ Предполагаемый счет является целым числом и должен быть выражен в десятичной системе исчисления. |
||||
+ В случае динамических дисплеев оценочный счет должен отображаться и после окончания матча. |
||||
+ Ни при каких обстоятельствах счет не должен меняться после окончания матча, иначе бонус будет аннулирован! |
||||
### Баллы: |
||||
<p> Оценка основывается на всех предыдущих действиях. </p> |
||||
* Бонус считается по следующей формуле: Бонус = 0.3 x Баллы – Разница |
||||
* Баллы – набранные во время матча баллы за обычные задания. |
||||
* Разница – математическая разница между предсказанными очками и набранными (модуль разности). • Бонус – целое число (округленное вверх). |
||||
* Бонус прибавляется к баллам команды |
||||
* Отрицательный бонус округляется до 0. |
||||
* Нулевое число баллов не может приносить бонуса |
||||
|
||||
## 3. Установка витрины: |
||||
Для этого действия используются витрина и статуэтка. |
||||
### Действия: |
||||
* Команда должна установить свою витрину в выставочном зале во время подготовки. |
||||
* Витрина будет активирована во время матча путем размещения в ней статуэтки. Цель - выделить статуэтку хотя бы одним светящимся элементом. |
||||
### Ограничения: |
||||
* Активация витрины должна быть произведена в момент размещения статуэтки. Активация может осуществляться любым способом, в том числе беспроводным. |
||||
* Витрина должна иметь как минимум один светящийся элемент, активируемый установленной статуэткой. Этот элемент должен быть виден публике, но не должен никого ослеплять. Этот светящийся элемент может находиться внутри статуэтки, в этом случае электропитание должно обеспечиваться от витрины. |
||||
* Витрина считается активированной, если она явно изменила свою форму или внешний вид по сравнению с началом матча. |
||||
* Вертикальная проекция витрины не должна пересекать границы выставочного зала в любое время. |
||||
* Витрина имеет следующие ограничения по размерам (статуэтка включена) : |
||||
+ Максимальная глубина: 222 мм. |
||||
+ Максимальная ширина: 450 мм. |
||||
+ Максимальная высота: 430 мм. |
||||
+ Вес витрины не должен превышать 3 кг. |
||||
* Для участников группы LEGO WEDO витрина устанавливатся на поле без возвышенорсти. |
||||
* После окончания матча, активированный источник света должен продолжать работать. |
||||
* Витрина может содержать источник электрического питания. В этом случае должна присутствовать кнопка аварийной остановки, которая непосредственно выключает витрину. Кнопка аварийной остановки имеет те же характеристики, что и кнопка аварийной остановки робота. Выключатель должен быть видимым, легко доступным и находиться на одной высоте. До начала матча витрина может быть включена в сеть без активации. |
||||
* Допускается подача питания на витрину, подключив ее к источнику питания панели управления, но ни при каких обстоятельствах витрина не может быть активирована панелью управления робота. Соединительные кабели не учитываются в ограничениях по размерам. |
||||
* Это действие не должно быть опасным для публики, людей вокруг стола, игровой площадки или роботов. |
||||
* Витрина не может быть активирована внешним элементом (командой, пультом дистанционного управления, ...). |
||||
### Баллы: |
||||
* 2 балла за установку витрины во время подготовки; |
||||
* 5 дополнительных баллов, если витрина активирована; |
||||
|
||||
## III Поле: |
||||
* Организаторы соревнований стремятся изготовить Игровую Зону как можно точнее и ближе к эталону. Тем не менее они вправе внести некоторые изменения, если сочтут их необходимыми. Жалобы, связанные с отклонениями размеров, не рассматриваются. |
||||
Имейте в виду, что качество поверхностей разных игровых полей может отличаться, также оно может ухудшаться в ходе соревнований по естественным причинам. |
||||
* Размер – 1200х2400 мм с бортиками высотой 70мм. |
||||
* Макет поля указано на рисунке 2. |
||||
|
||||
<Image |
||||
alt={`Рисунок 4 - Общий вид игрового поля`} |
||||
src={`/images/polegon.png`} |
||||
width={256} |
||||
height={512} |
||||
priority |
||||
/> |
||||
Рисунок 2 - Общий вид игрового поля |
||||
### Зоны на игровом поле: |
||||
### СТАРТОВЫЕ ЗОНЫ |
||||
* У каждой команды есть своя стартовая зона для роботов. Это прямоугольная поверхность отделенная границей полоской цвета команды (граница включена в стартовую зону). |
||||
### Ограничения |
||||
* До старта, вертикальная проекция роботов не должна выходить за пределы стартовой зоны. Убедитесь, что ваши роботы полностью помещаются в стартовую зону. |
||||
* Робот может нависать над бортиком, но не выходить за пределы Игрового Поля. |
||||
* Цветные линии включены в стартовую зону. Во время всего матча роботам запрещается находиться в стартовой зоне другой команды. |
||||
|
||||
## IV Робот: |
||||
* Роботы, использующие в конструкции коммерчески приобретенное шасси или основу, могут быть недопущены к соревнованиям. |
||||
* Одна организация (клуб, школа и т. п.) может зарегистрировать несколько команд, только если это допускается регистрационными требованиями. Принятие подобных требований является обязательным для участников соревнований. |
||||
* В том случае, если робот был представлен, построен или изменен наставником в одиночку, организаторы могут дисквалифицировать или не допустить участие команды в соревнованиях. Участники должны быть способны описать и объяснить процесс создания робота. Строго запрещается изменение робота наставником во время соревнования, но он может руководить и давать советы. |
||||
* Размеры роботов и всех элементов, созданных командами, строго ограничены. Настоятельно рекомендуется включать допуски. |
||||
* Периметр робота - это периметр выпуклой оболочки его вертикальной проекции на поверхность. Измеряется он, как показано на рисунках ниже: |
||||
|
||||
<Image |
||||
alt={`Рисунок 5 - Общий вид игрового поля`} |
||||
src={`/images/sizerobot.png`} |
||||
width={612} |
||||
height={512} |
||||
priority |
||||
/> |
||||
Рисунок 5 - Размеры робота |
||||
|
||||
* Периметр робота не должен превышать 1200 мм во время старта. Периметр полностью развернутого робота не должен превышать 1300 мм во время матча. Разрешается изменять форму выпуклой оболочки во время игры, если ее периметр всегда учитывает ограничение максимального периметра. |
||||
* В любой момент, во время матча, высота каждого робота не должна превышать 350 мм. Кнопка Аварийной остановки может быть расположена на высоте 375 мм. |
||||
* Когда робот манипулирует объектом, высота этого объекта не может превышать 350 мм |
||||
### Источники энергии: |
||||
* Разрешены любые источники энергии, встроенные в робота и другие разработанные системы (аккумуляторы, сжатый воздух, энергия гравитации…), за исключением источников энергии, использующих химические реакции, такие как горение или взрыв, которые запрещены из соображений безопасности. Кроме того, запрещено использование живых существ, коррозионных составов и расплескивание жидкостей. |
||||
* Если у вас есть сомнения в отношении необычного источника энергии, лучше заранее посоветуйтесь с судейским комитетом, предоставляя соответствующую техническую документацию. |
||||
* Для предотвращения возгорания рекомендуется обращать особое внимание на выбор проводников в зависимости от проходящего через них тока. Кроме того, рекомендуется защитить систему питания, установив предохранитель как можно ближе к аккумулятору. |
||||
### Аккумулятор: |
||||
* Разрешено использовать только немодифицированные батареи. |
||||
* Роботы должны быть в состоянии участвовать в трёх матчах подряд. Обратите внимание, что это время, помимо прочего, включает период ожидания, во время которого робот включен и ожидает старта. |
||||
* Командам настоятельно рекомендуется приготовить несколько наборов аккумуляторов и обеспечить легкий доступ к ним для проведения замены в случае необходимости. Всегда держите наготове набор полностью заряженных аккумуляторов. |
||||
* <b> Особое внимание к аккумуляторам на основе Лития:</b> |
||||
* Литиевые батареи известны своей нестабильностью и могут легко воспламениться, если не будут приняты определенные меры предосторожности. |
||||
* Использование батарей на основе Лития (например, Li-ion / Li-Po / Li-Fe) разрешается при соблюдении следующих условий: |
||||
+ Подходящее, выпущенное промышленным способом, зарядное устройство, которое должно быть предоставлено на этапе допуска к соревнованиям. |
||||
+ Батареи постоянно хранятся в специальном сертифицированном огнеупорном контейнере (например, огнестойком мешке), как во время соревнований, так и в боксах участников, а также во время транспортировки робота! |
||||
+ Настоятельно рекомендуется снабжать робота системой обнаружения разряда батарей • Данные ограничения снимаются только в случае: |
||||
+ Батарей Lego™ Mindstorms / ноутбука / мобильного телефона и только до тех пор пока они не вынуты из "родного" устройства и они используются по назначению, которое определил производитель. |
||||
+ Lithium-Iron батарей (LifePo4) |
||||
+ Источник питания, передаваемый роботу, может быть только электрическим. Максимально допустимое напряжение составляет 13,8 В (измеряется между любыми двумя проводами кабеля и робота). Этот источник напряжения не предоставляется организаторами. С другой стороны, команды имеют доступ к стандарту (стандарт 230 В 50 Гц) и могут использовать батареи. |
||||
+ Клеммы кабелей должны быть изолированы. |
||||
### Необходимые элементы на роботе |
||||
* На одной из сторон робота должна быть оставлена прямоугольная площадка 100мм x 70мм. По возможности, данная область должна быть видна с наивысшей точки игрового поля. Она так же должна быть визуально доступной на протяжении большей части матча. Команды могут получить наклейки, предназначенные для размещения в этой области. |
||||
* Командам настоятельно рекомендуется делать механизмы внутри робота видимыми для зрителей и других участников. Это создает атмосферу обучения и передачи знаний, необходимую для того, чтобы понять принцип действия роботов. |
||||
### Стартовый шнур робота: |
||||
* В начале матча робот должен быть запущен так называемым «Стартовым Устройством». Оно должно приводиться в действие выдергиванием шнура длиной как минимум 500 мм. После запуска шнур не должен оставаться прикрепленным к роботу. Любые другие системы запуска (например, пульт дистанционного управления, ручной тумблер, отжатие кнопки аварийного выключения и т. п.) не будут одобрены. |
||||
### Кнопка аварийного выключения робота. |
||||
* У роботов, использующих батареи для питания, должна быть кнопка аварийного выключения красного цвета и диаметром как минимум 20 мм. Ее следует разместить в верхней части робота, в безопасном месте, легко доступном для судей в любой момент матча. Допускается, чтобы Кнопка Аварийного Выключения в поднятом состоянии превышала высоту робота на 25 мм. |
||||
* Активация кнопки должна происходить от простого поступательного движения вниз (например, нажатие ладонью). Сразу после активации Кнопки Аварийного Выключения должна прекратиться работа всех приводов робота, оставляя их в свободном состоянии (т. е. НЕ в состоянии активного торможения – обесточенными). |
||||
* При проектировании роботов рекомендуется учитывать возможные неровности игровых площадок. |
||||
### Система управления роботом: |
||||
* Команды могут использовать любой тип системы управления для робота (аналоговый, микропроцессорный, микроконтроллер, встроенный компьютер, программируемая логика и т. д.). |
||||
* Эти системы должны быть полностью интегрированы в робота. |
||||
* Система управления должна позволять роботу передвигаться при любом цвете(расположении на поле), предоставленных командам. В идеале, он должен быть настроен незадолго до оглашения цвета команды. |
||||
|
||||
|
||||
## V Порядок проведения: |
||||
* Перед началом очередного матча у каждой команды есть 2 минуты, чтобы подготовить робота, а так же другое оборудование к игре на Поле. Команда, не подготовившая своего робота вовремя, будет дисквалифицирована. |
||||
* После завершения этапа подготовки роботов, судьи уточняют у участников их готовность. С этого момента командам запрещается прикасаться к роботам. Также с этого момента претензии относительно состояния Игровых Элементов или их расположения в Игровой Зоне, не принимаются к обсуждению. |
||||
* Если команда готова к матчу, этап подготовки можно сократить и начать матч по готовности команды! |
||||
### Заезд: |
||||
* После короткого обратного отсчета судья подаст сигнал к запуску роботов. Во время заезда ни при каких обстоятельствах не разрешается трогать роботов, Игровые Элементы или Игровое Поле (исключение представляет только особое указание судьи). Также не разрешается нажимать на Кнопку Аварийного Выключения! Любое воздействие на робота, Игровой Элемент или Игровое Поле без явного разрешения судьи может привести к дисквалификации команды с матча. Продолжительность одно матча 100 секунд. |
||||
Любой объект, покинувший Игровое Поле во время матча, обратно возвращать запрещено. По истечении основного времени матча роботы должны прекратить всякое передвижение по полю и остановить все свои приводы. |
||||
* После окончания заезда никто кроме судьи не имеет права трогать роботов и Игровые Элементы. Затем судьи должны подсчитать баллы и объявить результат матча (подробности подсчета см. следующий раздел). После этого команды могут забрать своих роботов из Игровой Зоны. Если команды с чем-то несогласны, то они могут спокойно изложить свои аргументы судьям. Роботы продолжают оставаться на своих местах до окончания спора. |
||||
* Помните, что только 2 члена команды должны находиться в Игровой Зоне! В итоге судья выносит окончательное решение. В случае, если найти решение в обсуждении не удается, судьи оставляют за собой решение о необходимости переигровки матча. |
||||
* Команда объявляется дисквалифицированной с матча, если ни один из роботов команды полностью не покинул стартовую площадку в течение матча, была нажата кнопка экстренной остановки или если судья вынес соответствующее решение по итогам матча. |
||||
* Нажатие кнопки экстренной остановки может привести к штрафу или дисквалификации с матча. |
||||
### СИСТЕМА БАЛЛОВ |
||||
* Выезд из лагеря: |
||||
+ 5 баллов, если робот после старта самостоятельно покинул полностью стартовую зону; |
||||
* Возвращение на место в лагерь: |
||||
+ 20 баллов, если один робот команды находятся в лагере; |
||||
* Сохранение и выставление статуэтки: |
||||
+ 2 балла за установку статуэтки на пьедестал во время подготовки; |
||||
+ 5 баллов, если статуэтка отсутствует на пьедестале в конце игры; |
||||
+ 10 баллов, если статуэтка находится на пьедестале в конце игры; |
||||
+ 15 баллов, если статуэтка находится в витрине в конце игры; |
||||
* Витрина: |
||||
+ 2 балла за установку витрины во время подготовки; |
||||
+ 5 дополнительных баллов, если витрина активирована во время игры; |
||||
* Скорость выполнения задания: |
||||
+ 60 секунд минус время выполнения полного задания роботом = дополнительные баллы. (пример: 60 - 54 = 6 балов) |
||||
* Оценка производительности: |
||||
+ Оценка основана на предыдущих действиях |
||||
+ Бонус считается по следующей формуле: Бонус = 0.3 x Баллы - Разница |
||||
+ Баллы – набранные во время матча баллы за обычные задания. |
||||
+ Разница – математическая разница между предсказанными очками и набранными (неотрицательна). • Бонус – целое число (округленное вверх). |
||||
+ Бонус прибавляется к баллам команды |
||||
+ Отрицательный бонус округляется до 0. |
||||
+ Нулевое число баллов не может приносить бонуса. |
||||
+ Бонус за «недисквалификацию» не учитывается в прогнозе |
||||
+ Штрафы не учитываются в прогнозе |
||||
+ ВНИМАНИЕ! Игровой Элемент, который удерживается роботом не приносит баллы. Проверка осуществляется путем передвижения шасси робота в естественной манере, если Элемент движется вместе с роботом – он не засчитывается. |
||||
### Штрафы: |
||||
* Штраф приводит к потере 20 баллов в счете команды в оштрафованном матче. |
||||
* Отрицательный счет округляется до 0. |
||||
* Штрафы предназначены для компенсации урона или созданных помех, которые являются следствием ЧП во время проведения матча. Штрафная ситуация рассматривается как несоблюдение правил: такая ситуация должна оставаться исключительной! В случае повторяющихся штрафов, судьи имеют право дисквалифицировать команду как с матча, так и с соревнований. Судейский комитет также будет обращать внимание на штрафы, накопленные командами в течение отборочных региональных и / или национальных турах соревнований. |
||||
### Бонусные баллы: |
||||
* 1 бонусный балл присуждается команде, которая не была дисквалифицирована в ходе матча. |
||||
* Случаи дисквалификации: |
||||
+ Баллы дисквалифицированной команды приравниваются к нулю. |
||||
## Допуск к заездам: |
||||
### СТАТИЧЕСКАЯ ПРОВЕРКА |
||||
* Перед тем, как выступать на Поле, роботы осматриваются судьей, который проверяет их на соответствие правилам. Роботы должны быть готовы к демонстрации всех своих возможных действий. |
||||
### ДИНАМИЧЕСКАЯ ПРОВЕРКА: |
||||
* Роботы должны в течение 100 секунд продемонстрировать хотя бы одно действие, приносящее минимальное количество очков. Роботы проверяются на Игровом Поле. Также может быть проверено соответствие некоторым обязательным требованиям правил (например, наличие таймера). |
||||
### ЗНАЧИТЕЛЬНЫЕ ИЗМЕНЕНИЯ В РОБОТЕ: |
||||
* В случае значительных технических изменений (функциональных, структурных, размерных...), выполненных после прохождения этапа допуска к соревнованиям, необходимо сообщить о них судье. Судьи должны утвердить изменения и, если посчитают необходимым, могут назначить повторную проверку роботу, подвергшемуся доработке. |
||||
Если организаторы считают, что робот был модифицирован, может потребоваться повторная гомологизация робота, что запрещает ему соревноваться до тех пор, пока не будет получен повторный допуск. |
||||
## VI Определение победитлей |
||||
* В каждой возрастной группе определяется команды занивщае 1,2,3 местот по количеству балов от максимальному к минимальному. |
||||
|
||||
## ОБЩИЕ ПОЛОЖЕНИЯ |
||||
* Во время соревнований только двум членам команды разрешен доступ к зоне ожидания матча и к Игровой Зоне. На пути к Игровой Зоне могут встречаться ступеньки или лестницы, поэтому рекомендуется делать вспомогательное оборудование удобным для переноски |
||||
* Роботы должны быть сделаны из хорошо соединенных частей – части Роботов не должны отделяться и оставаться на Игровом Поле во время матча. Исключением в этом случае являются подобранные Игровые Элементы. |
||||
* Роботы не должны прикреплять себя к игровому полю (например, используя вакуумные присоски). |
||||
* Каждая команда должна разработать уникальный и оригинальный набор роботов. Поэтому не разрешается проектировать роботов, которые в значительной степени аналогичны роботам других команд (например, идентичные колесные базы или исполнительные механизмы). В случае сомнений обращайтесь в судейский комитет. |
||||
* Используйте воображение и творите! Устройте развлекательное шоу для зрителей и СМИ, ваш робот может выражать эмоции, воспроизводить звуки или играть музыку. |
||||
|
||||
## БЕЗОПАСНОСТЬ |
||||
* Все системы должны соответствовать существующим национальным стандартам. В частности, используемые системы должны соответствовать официальным нормам безопасности жизнедеятельности и быть безопасными для участников и зрителей во время и вне матчей (например, в боксах команды или в процессе ожидания/подготовки матча). У роботов не должно быть никаких опасных выступающих или острых частей. |
||||
* Строго запрещается использование жидких, едких и пиротехнических материалов или живых существ в роботе. Все роботы должны соответствовать официальным стандартам «низкого напряжения». То есть электрические напряжения, используемые в роботах или Маяках, не должны превышать 48v. Напряжения выше 48v могут быть использованы только внутри закрытых устройств, произведенных промышленным способом (таких, как лазеры, подсветка LCD панели), если эти устройства не были модифицированы, и если они соответствуют национальным нормативным требованиям. |
||||
* Как правило, любой механизм или система, признанная судьями как потенциально опасная, будет запрещена к применению и должна быть удалена из робота до соревнований, иначе команда будет дисквалифицирована с соревнований. |
||||
|
||||
## Приложение |
||||
### Выставочный зал |
||||
**Размеры:** |
||||
* Высота: 70 мм |
||||
* Ширина: 150 мм |
||||
* Длина: 400 мм |
||||
|
||||
<Image |
||||
alt={`Рисунок 3 - Выставочный зал`} |
||||
src={`/images/vistZal.jpg`} |
||||
width={612} |
||||
height={412} |
||||
priority |
||||
/> |
||||
|
||||
<Image |
||||
alt={`Рисунок 3 - Выставочный зал`} |
||||
src={`/images/vistzal2.jpg`} |
||||
width={612} |
||||
height={412} |
||||
priority |
||||
/> |
||||
### Пьедестал: |
||||
**Размеры:** |
||||
* Высота: 90 мм |
||||
* Ширина: 150 мм |
||||
* Длина: 400 мм |
||||
|
||||
<Image |
||||
alt={`Рисунок 3 - Пьедестал`} |
||||
src={`/images/pedistal.jpg`} |
||||
width={612} |
||||
height={412} |
||||
priority |
||||
/> |
||||
|
||||
<Image |
||||
alt={`Рисунок 3 - Пьедестал`} |
||||
src={`/images/pedistal2.jpg`} |
||||
width={612} |
||||
height={412} |
||||
priority |
||||
/> |
||||
На главную [Главная](/) |
@ -0,0 +1,298 @@ |
||||
--- |
||||
title: Робототехника |
||||
description: Регламент проведения соревнования. РоботТОП Junior 2023 |
||||
date: '2022-09-01' |
||||
image: '/images/robottop.png' |
||||
--- |
||||
|
||||
<Image |
||||
alt={`Регламент проведения соревнования. РоботТОП Junior 2023`} |
||||
src={`/images/robottop.png`} |
||||
width={1440} |
||||
height={460} |
||||
priority |
||||
/> |
||||
|
||||
<p>Участникам необходимо подготовить робота, способного наиболее эффективно поменять местами оригинал статуэтки на ее реплику. Состязание проходит на автономных моделях роботов.</p> |
||||
|
||||
## I. Участники: |
||||
* <p>Команда состоит из 2 - 3 учащихся с 1 по 11 класс</p> |
||||
* <p>Каждая команда на соревнованиях должна привезти с собой одного **уникального робота, витрину, статуэтку.**</p> |
||||
* <p>Возрастные группы участников разделяются по классам (команда первоклассников, 2-х, 3-х, 4-х и т.д.) (Класс ученика подтверждается документом). Если в команде присутствуют участники из разных классов, то определяется по самому старшему ученику.</p> |
||||
* <p>Отдельный человек может быть участником лишь одной команды, даже если обе команды принадлежат к одной организации, при этом, обмен опытом всячески приветствуется. На руководителя проекта (учитель, один из родителей, лидер группы, и т. п.) возрастные ограничения не распространяются, но робот должен быть полностью разработан и построен членами команды.</p> |
||||
|
||||
## II. Задачи для робота: |
||||
## 1. Сохранение и экспонирование статуэтки. |
||||
### Действия: |
||||
* За время подготовки команда должна поставить свою статуэтку на пьедестал. |
||||
* Во время подготовки команда должна предварительно поместить реплику в своего робота. |
||||
* Во время заеда робот должнен забрать статуэтку с пьедестала. |
||||
* После того как статуэтка будет взята, роботы должны поместить ее на витрину. |
||||
* Робот должн поставить реплику на пьедестал вместо статуэтки. |
||||
### Ограничения: |
||||
* Реплику и статуэтку нельзя складывать в стопку. |
||||
* Реплика считается стоящей на пьедестале только в том случае, если она находится на постаменте в конце матча. |
||||
* Реплика представляет собой куб со стороной 60 мм. |
||||
* Статуэтка считается стоящей в витрине, если весь ее объем входит в габариты витрины. |
||||
* Статуэтка не может самостоятельно перемещаться ни внутри витрины, ни на игровой площадке. |
||||
* Статуэтка, построенная командой, имеет следующие ограничения по размерам: |
||||
+ Она должна помещаться в кубе со стороной 120 мм. |
||||
+ Она должна быть больше, чем куб со стороной 60 мм для категории LEGO WEDO 30 мм. |
||||
+ Вес статуэтки не должен превышать 600г. |
||||
* Статуэтка может быть оснащена электроникой. В этом случае она должна иметь кнопку аварийной остановки. |
||||
* Допускается использование простого тумблера в качестве кнопки аварийной остановки. Кнопка должна быть видна и доступна судьям в любое время. |
||||
* Статуэтка, все еще находящаяся под контролем робота в конце матча, не будет засчитана. |
||||
* Реплика, находящаяся под контролем робота в конце матча, не засчитывается. |
||||
### Баллы |
||||
* 2 балла за установку статуэтки на пьедестал во время подготовки; |
||||
* 5 баллов, если статуэтка отсутствует на пьедестале в конце игры; |
||||
* 10 баллов, если реплика находится на пьедестале в конце игры; |
||||
* 15 баллов, если статуэтка находится в витрине в конце игры; |
||||
|
||||
<Image |
||||
alt={`Рисунок 3 - Общий вид игрового поля`} |
||||
src={`/images/zadanie.png`} |
||||
width={512} |
||||
height={256} |
||||
priority |
||||
/> |
||||
Рисунок 4 - Перемещение статуэтки и реплики |
||||
|
||||
## 2. Возвращение в лагерь в конце дня. |
||||
### Действия: |
||||
* После окончания матча робот должен быть остановлен в собственном лагере. |
||||
### Ограничения: |
||||
* Чтобы считаться действительным, вертикальная проекция робота должна хотя бы частично находиться в пределах лагеря. |
||||
## Баллы: |
||||
* 20 баллов, если робот команды находится в одной из зон лагеря; |
||||
<p> 3. Оценка своей работы. </p> |
||||
* Устройство для отображения подсчета очков во время матча должно быть сделано командой: |
||||
+ Оно может быть статичным (лист бумаги, грифельная доска и т.д.) или динамическим (электронный дисплей); расположенным либо на роботе, либо на витрине (пожалуйста, убедитесь, что витрина активирована). |
||||
### Действия и ограничения: |
||||
* Команда должна оценить количество очков, набранных в матче ее роботом. Для этого возможны два исключающих варианта: |
||||
+ Предматчевая оценка на статическом дисплее: команда пишет счет, который она намерена сделать во время матча. |
||||
+ Оценка во время матча на динамическом устройстве отображения. |
||||
+ Область дисплея и его ориентация для чтения должны быть легко различимы и идентифицируемы судьями. |
||||
+ Предполагаемый счет является целым числом и должен быть выражен в десятичной системе исчисления. |
||||
+ В случае динамических дисплеев оценочный счет должен отображаться и после окончания матча. |
||||
+ Ни при каких обстоятельствах счет не должен меняться после окончания матча, иначе бонус будет аннулирован! |
||||
### Баллы: |
||||
<p> Оценка основывается на всех предыдущих действиях. </p> |
||||
* Бонус считается по следующей формуле: Бонус = 0.3 x Баллы – Разница |
||||
* Баллы – набранные во время матча баллы за обычные задания. |
||||
* Разница – математическая разница между предсказанными очками и набранными (модуль разности). • Бонус – целое число (округленное вверх). |
||||
* Бонус прибавляется к баллам команды |
||||
* Отрицательный бонус округляется до 0. |
||||
* Нулевое число баллов не может приносить бонуса |
||||
|
||||
## 3. Установка витрины: |
||||
Для этого действия используются витрина и статуэтка. |
||||
### Действия: |
||||
* Команда должна установить свою витрину в выставочном зале во время подготовки. |
||||
* Витрина будет активирована во время матча путем размещения в ней статуэтки. Цель - выделить статуэтку хотя бы одним светящимся элементом. |
||||
### Ограничения: |
||||
* Активация витрины должна быть произведена в момент размещения статуэтки. Активация может осуществляться любым способом, в том числе беспроводным. |
||||
* Витрина должна иметь как минимум один светящийся элемент, активируемый установленной статуэткой. Этот элемент должен быть виден публике, но не должен никого ослеплять. Этот светящийся элемент может находиться внутри статуэтки, в этом случае электропитание должно обеспечиваться от витрины. |
||||
* Витрина считается активированной, если она явно изменила свою форму или внешний вид по сравнению с началом матча. |
||||
* Вертикальная проекция витрины не должна пересекать границы выставочного зала в любое время. |
||||
* Витрина имеет следующие ограничения по размерам (статуэтка включена) : |
||||
+ Максимальная глубина: 222 мм. |
||||
+ Максимальная ширина: 450 мм. |
||||
+ Максимальная высота: 430 мм. |
||||
+ Вес витрины не должен превышать 3 кг. |
||||
* Для участников группы LEGO WEDO витрина устанавливатся на поле без возвышенорсти. |
||||
* После окончания матча, активированный источник света должен продолжать работать. |
||||
* Витрина может содержать источник электрического питания. В этом случае должна присутствовать кнопка аварийной остановки, которая непосредственно выключает витрину. Кнопка аварийной остановки имеет те же характеристики, что и кнопка аварийной остановки робота. Выключатель должен быть видимым, легко доступным и находиться на одной высоте. До начала матча витрина может быть включена в сеть без активации. |
||||
* Допускается подача питания на витрину, подключив ее к источнику питания панели управления, но ни при каких обстоятельствах витрина не может быть активирована панелью управления робота. Соединительные кабели не учитываются в ограничениях по размерам. |
||||
* Это действие не должно быть опасным для публики, людей вокруг стола, игровой площадки или роботов. |
||||
* Витрина не может быть активирована внешним элементом (командой, пультом дистанционного управления, ...). |
||||
### Баллы: |
||||
* 2 балла за установку витрины во время подготовки; |
||||
* 5 дополнительных баллов, если витрина активирована; |
||||
|
||||
## III Поле: |
||||
* Организаторы соревнований стремятся изготовить Игровую Зону как можно точнее и ближе к эталону. Тем не менее они вправе внести некоторые изменения, если сочтут их необходимыми. Жалобы, связанные с отклонениями размеров, не рассматриваются. |
||||
Имейте в виду, что качество поверхностей разных игровых полей может отличаться, также оно может ухудшаться в ходе соревнований по естественным причинам. |
||||
* Размер – 1200х2400 мм с бортиками высотой 70мм. |
||||
* Макет поля указано на рисунке 2. |
||||
|
||||
<Image |
||||
alt={`Рисунок 4 - Общий вид игрового поля`} |
||||
src={`/images/polegon.png`} |
||||
width={256} |
||||
height={512} |
||||
priority |
||||
/> |
||||
Рисунок 2 - Общий вид игрового поля |
||||
### Зоны на игровом поле: |
||||
### СТАРТОВЫЕ ЗОНЫ |
||||
* У каждой команды есть своя стартовая зона для роботов. Это прямоугольная поверхность отделенная границей полоской цвета команды (граница включена в стартовую зону). |
||||
### Ограничения |
||||
* До старта, вертикальная проекция роботов не должна выходить за пределы стартовой зоны. Убедитесь, что ваши роботы полностью помещаются в стартовую зону. |
||||
* Робот может нависать над бортиком, но не выходить за пределы Игрового Поля. |
||||
* Цветные линии включены в стартовую зону. Во время всего матча роботам запрещается находиться в стартовой зоне другой команды. |
||||
|
||||
## IV Робот: |
||||
* Роботы, использующие в конструкции коммерчески приобретенное шасси или основу, могут быть недопущены к соревнованиям. |
||||
* Одна организация (клуб, школа и т. п.) может зарегистрировать несколько команд, только если это допускается регистрационными требованиями. Принятие подобных требований является обязательным для участников соревнований. |
||||
* В том случае, если робот был представлен, построен или изменен наставником в одиночку, организаторы могут дисквалифицировать или не допустить участие команды в соревнованиях. Участники должны быть способны описать и объяснить процесс создания робота. Строго запрещается изменение робота наставником во время соревнования, но он может руководить и давать советы. |
||||
* Размеры роботов и всех элементов, созданных командами, строго ограничены. Настоятельно рекомендуется включать допуски. |
||||
* Периметр робота - это периметр выпуклой оболочки его вертикальной проекции на поверхность. Измеряется он, как показано на рисунках ниже: |
||||
|
||||
<Image |
||||
alt={`Рисунок 5 - Общий вид игрового поля`} |
||||
src={`/images/sizerobot.png`} |
||||
width={612} |
||||
height={512} |
||||
priority |
||||
/> |
||||
Рисунок 5 - Размеры робота |
||||
|
||||
* Периметр робота не должен превышать 1200 мм во время старта. Периметр полностью развернутого робота не должен превышать 1300 мм во время матча. Разрешается изменять форму выпуклой оболочки во время игры, если ее периметр всегда учитывает ограничение максимального периметра. |
||||
* В любой момент, во время матча, высота каждого робота не должна превышать 350 мм. Кнопка Аварийной остановки может быть расположена на высоте 375 мм. |
||||
* Когда робот манипулирует объектом, высота этого объекта не может превышать 350 мм |
||||
### Источники энергии: |
||||
* Разрешены любые источники энергии, встроенные в робота и другие разработанные системы (аккумуляторы, сжатый воздух, энергия гравитации…), за исключением источников энергии, использующих химические реакции, такие как горение или взрыв, которые запрещены из соображений безопасности. Кроме того, запрещено использование живых существ, коррозионных составов и расплескивание жидкостей. |
||||
* Если у вас есть сомнения в отношении необычного источника энергии, лучше заранее посоветуйтесь с судейским комитетом, предоставляя соответствующую техническую документацию. |
||||
* Для предотвращения возгорания рекомендуется обращать особое внимание на выбор проводников в зависимости от проходящего через них тока. Кроме того, рекомендуется защитить систему питания, установив предохранитель как можно ближе к аккумулятору. |
||||
### Аккумулятор: |
||||
* Разрешено использовать только немодифицированные батареи. |
||||
* Роботы должны быть в состоянии участвовать в трёх матчах подряд. Обратите внимание, что это время, помимо прочего, включает период ожидания, во время которого робот включен и ожидает старта. |
||||
* Командам настоятельно рекомендуется приготовить несколько наборов аккумуляторов и обеспечить легкий доступ к ним для проведения замены в случае необходимости. Всегда держите наготове набор полностью заряженных аккумуляторов. |
||||
* <b> Особое внимание к аккумуляторам на основе Лития:</b> |
||||
* Литиевые батареи известны своей нестабильностью и могут легко воспламениться, если не будут приняты определенные меры предосторожности. |
||||
* Использование батарей на основе Лития (например, Li-ion / Li-Po / Li-Fe) разрешается при соблюдении следующих условий: |
||||
+ Подходящее, выпущенное промышленным способом, зарядное устройство, которое должно быть предоставлено на этапе допуска к соревнованиям. |
||||
+ Батареи постоянно хранятся в специальном сертифицированном огнеупорном контейнере (например, огнестойком мешке), как во время соревнований, так и в боксах участников, а также во время транспортировки робота! |
||||
+ Настоятельно рекомендуется снабжать робота системой обнаружения разряда батарей • Данные ограничения снимаются только в случае: |
||||
+ Батарей Lego™ Mindstorms / ноутбука / мобильного телефона и только до тех пор пока они не вынуты из "родного" устройства и они используются по назначению, которое определил производитель. |
||||
+ Lithium-Iron батарей (LifePo4) |
||||
+ Источник питания, передаваемый роботу, может быть только электрическим. Максимально допустимое напряжение составляет 13,8 В (измеряется между любыми двумя проводами кабеля и робота). Этот источник напряжения не предоставляется организаторами. С другой стороны, команды имеют доступ к стандарту (стандарт 230 В 50 Гц) и могут использовать батареи. |
||||
+ Клеммы кабелей должны быть изолированы. |
||||
### Необходимые элементы на роботе |
||||
* На одной из сторон робота должна быть оставлена прямоугольная площадка 100мм x 70мм. По возможности, данная область должна быть видна с наивысшей точки игрового поля. Она так же должна быть визуально доступной на протяжении большей части матча. Команды могут получить наклейки, предназначенные для размещения в этой области. |
||||
* Командам настоятельно рекомендуется делать механизмы внутри робота видимыми для зрителей и других участников. Это создает атмосферу обучения и передачи знаний, необходимую для того, чтобы понять принцип действия роботов. |
||||
### Стартовый шнур робота: |
||||
* В начале матча робот должен быть запущен так называемым «Стартовым Устройством». Оно должно приводиться в действие выдергиванием шнура длиной как минимум 500 мм. После запуска шнур не должен оставаться прикрепленным к роботу. Любые другие системы запуска (например, пульт дистанционного управления, ручной тумблер, отжатие кнопки аварийного выключения и т. п.) не будут одобрены. |
||||
### Кнопка аварийного выключения робота. |
||||
* У роботов, использующих батареи для питания, должна быть кнопка аварийного выключения красного цвета и диаметром как минимум 20 мм. Ее следует разместить в верхней части робота, в безопасном месте, легко доступном для судей в любой момент матча. Допускается, чтобы Кнопка Аварийного Выключения в поднятом состоянии превышала высоту робота на 25 мм. |
||||
* Активация кнопки должна происходить от простого поступательного движения вниз (например, нажатие ладонью). Сразу после активации Кнопки Аварийного Выключения должна прекратиться работа всех приводов робота, оставляя их в свободном состоянии (т. е. НЕ в состоянии активного торможения – обесточенными). |
||||
* При проектировании роботов рекомендуется учитывать возможные неровности игровых площадок. |
||||
### Система управления роботом: |
||||
* Команды могут использовать любой тип системы управления для робота (аналоговый, микропроцессорный, микроконтроллер, встроенный компьютер, программируемая логика и т. д.). |
||||
* Эти системы должны быть полностью интегрированы в робота. |
||||
* Система управления должна позволять роботу передвигаться при любом цвете(расположении на поле), предоставленных командам. В идеале, он должен быть настроен незадолго до оглашения цвета команды. |
||||
|
||||
|
||||
## V Порядок проведения: |
||||
* Перед началом очередного матча у каждой команды есть 2 минуты, чтобы подготовить робота, а так же другое оборудование к игре на Поле. Команда, не подготовившая своего робота вовремя, будет дисквалифицирована. |
||||
* После завершения этапа подготовки роботов, судьи уточняют у участников их готовность. С этого момента командам запрещается прикасаться к роботам. Также с этого момента претензии относительно состояния Игровых Элементов или их расположения в Игровой Зоне, не принимаются к обсуждению. |
||||
* Если команда готова к матчу, этап подготовки можно сократить и начать матч по готовности команды! |
||||
### Заезд: |
||||
* После короткого обратного отсчета судья подаст сигнал к запуску роботов. Во время заезда ни при каких обстоятельствах не разрешается трогать роботов, Игровые Элементы или Игровое Поле (исключение представляет только особое указание судьи). Также не разрешается нажимать на Кнопку Аварийного Выключения! Любое воздействие на робота, Игровой Элемент или Игровое Поле без явного разрешения судьи может привести к дисквалификации команды с матча. Продолжительность одно матча 100 секунд. |
||||
Любой объект, покинувший Игровое Поле во время матча, обратно возвращать запрещено. По истечении основного времени матча роботы должны прекратить всякое передвижение по полю и остановить все свои приводы. |
||||
* После окончания заезда никто кроме судьи не имеет права трогать роботов и Игровые Элементы. Затем судьи должны подсчитать баллы и объявить результат матча (подробности подсчета см. следующий раздел). После этого команды могут забрать своих роботов из Игровой Зоны. Если команды с чем-то несогласны, то они могут спокойно изложить свои аргументы судьям. Роботы продолжают оставаться на своих местах до окончания спора. |
||||
* Помните, что только 2 члена команды должны находиться в Игровой Зоне! В итоге судья выносит окончательное решение. В случае, если найти решение в обсуждении не удается, судьи оставляют за собой решение о необходимости переигровки матча. |
||||
* Команда объявляется дисквалифицированной с матча, если ни один из роботов команды полностью не покинул стартовую площадку в течение матча, была нажата кнопка экстренной остановки или если судья вынес соответствующее решение по итогам матча. |
||||
* Нажатие кнопки экстренной остановки может привести к штрафу или дисквалификации с матча. |
||||
### СИСТЕМА БАЛЛОВ |
||||
* Выезд из лагеря: |
||||
+ 5 баллов, если робот после старта самостоятельно покинул полностью стартовую зону; |
||||
* Возвращение на место в лагерь: |
||||
+ 20 баллов, если один робот команды находятся в лагере; |
||||
* Сохранение и выставление статуэтки: |
||||
+ 2 балла за установку статуэтки на пьедестал во время подготовки; |
||||
+ 5 баллов, если статуэтка отсутствует на пьедестале в конце игры; |
||||
+ 10 баллов, если статуэтка находится на пьедестале в конце игры; |
||||
+ 15 баллов, если статуэтка находится в витрине в конце игры; |
||||
* Витрина: |
||||
+ 2 балла за установку витрины во время подготовки; |
||||
+ 5 дополнительных баллов, если витрина активирована во время игры; |
||||
* Скорость выполнения задания: |
||||
+ 60 секунд минус время выполнения полного задания роботом = дополнительные баллы. (пример: 60 - 54 = 6 балов) |
||||
* Оценка производительности: |
||||
+ Оценка основана на предыдущих действиях |
||||
+ Бонус считается по следующей формуле: Бонус = 0.3 x Баллы - Разница |
||||
+ Баллы – набранные во время матча баллы за обычные задания. |
||||
+ Разница – математическая разница между предсказанными очками и набранными (неотрицательна). • Бонус – целое число (округленное вверх). |
||||
+ Бонус прибавляется к баллам команды |
||||
+ Отрицательный бонус округляется до 0. |
||||
+ Нулевое число баллов не может приносить бонуса. |
||||
+ Бонус за «недисквалификацию» не учитывается в прогнозе |
||||
+ Штрафы не учитываются в прогнозе |
||||
+ ВНИМАНИЕ! Игровой Элемент, который удерживается роботом не приносит баллы. Проверка осуществляется путем передвижения шасси робота в естественной манере, если Элемент движется вместе с роботом – он не засчитывается. |
||||
### Штрафы: |
||||
* Штраф приводит к потере 20 баллов в счете команды в оштрафованном матче. |
||||
* Отрицательный счет округляется до 0. |
||||
* Штрафы предназначены для компенсации урона или созданных помех, которые являются следствием ЧП во время проведения матча. Штрафная ситуация рассматривается как несоблюдение правил: такая ситуация должна оставаться исключительной! В случае повторяющихся штрафов, судьи имеют право дисквалифицировать команду как с матча, так и с соревнований. Судейский комитет также будет обращать внимание на штрафы, накопленные командами в течение отборочных региональных и / или национальных турах соревнований. |
||||
### Бонусные баллы: |
||||
* 1 бонусный балл присуждается команде, которая не была дисквалифицирована в ходе матча. |
||||
* Случаи дисквалификации: |
||||
+ Баллы дисквалифицированной команды приравниваются к нулю. |
||||
## Допуск к заездам: |
||||
### СТАТИЧЕСКАЯ ПРОВЕРКА |
||||
* Перед тем, как выступать на Поле, роботы осматриваются судьей, который проверяет их на соответствие правилам. Роботы должны быть готовы к демонстрации всех своих возможных действий. |
||||
### ДИНАМИЧЕСКАЯ ПРОВЕРКА: |
||||
* Роботы должны в течение 100 секунд продемонстрировать хотя бы одно действие, приносящее минимальное количество очков. Роботы проверяются на Игровом Поле. Также может быть проверено соответствие некоторым обязательным требованиям правил (например, наличие таймера). |
||||
### ЗНАЧИТЕЛЬНЫЕ ИЗМЕНЕНИЯ В РОБОТЕ: |
||||
* В случае значительных технических изменений (функциональных, структурных, размерных...), выполненных после прохождения этапа допуска к соревнованиям, необходимо сообщить о них судье. Судьи должны утвердить изменения и, если посчитают необходимым, могут назначить повторную проверку роботу, подвергшемуся доработке. |
||||
Если организаторы считают, что робот был модифицирован, может потребоваться повторная гомологизация робота, что запрещает ему соревноваться до тех пор, пока не будет получен повторный допуск. |
||||
## VI Определение победитлей |
||||
* В каждой возрастной группе определяется команды занивщае 1,2,3 местот по количеству балов от максимальному к минимальному. |
||||
|
||||
## ОБЩИЕ ПОЛОЖЕНИЯ |
||||
* Во время соревнований только двум членам команды разрешен доступ к зоне ожидания матча и к Игровой Зоне. На пути к Игровой Зоне могут встречаться ступеньки или лестницы, поэтому рекомендуется делать вспомогательное оборудование удобным для переноски |
||||
* Роботы должны быть сделаны из хорошо соединенных частей – части Роботов не должны отделяться и оставаться на Игровом Поле во время матча. Исключением в этом случае являются подобранные Игровые Элементы. |
||||
* Роботы не должны прикреплять себя к игровому полю (например, используя вакуумные присоски). |
||||
* Каждая команда должна разработать уникальный и оригинальный набор роботов. Поэтому не разрешается проектировать роботов, которые в значительной степени аналогичны роботам других команд (например, идентичные колесные базы или исполнительные механизмы). В случае сомнений обращайтесь в судейский комитет. |
||||
* Используйте воображение и творите! Устройте развлекательное шоу для зрителей и СМИ, ваш робот может выражать эмоции, воспроизводить звуки или играть музыку. |
||||
|
||||
## БЕЗОПАСНОСТЬ |
||||
* Все системы должны соответствовать существующим национальным стандартам. В частности, используемые системы должны соответствовать официальным нормам безопасности жизнедеятельности и быть безопасными для участников и зрителей во время и вне матчей (например, в боксах команды или в процессе ожидания/подготовки матча). У роботов не должно быть никаких опасных выступающих или острых частей. |
||||
* Строго запрещается использование жидких, едких и пиротехнических материалов или живых существ в роботе. Все роботы должны соответствовать официальным стандартам «низкого напряжения». То есть электрические напряжения, используемые в роботах или Маяках, не должны превышать 48v. Напряжения выше 48v могут быть использованы только внутри закрытых устройств, произведенных промышленным способом (таких, как лазеры, подсветка LCD панели), если эти устройства не были модифицированы, и если они соответствуют национальным нормативным требованиям. |
||||
* Как правило, любой механизм или система, признанная судьями как потенциально опасная, будет запрещена к применению и должна быть удалена из робота до соревнований, иначе команда будет дисквалифицирована с соревнований. |
||||
|
||||
## Приложение |
||||
### Выставочный зал |
||||
**Размеры:** |
||||
* Высота: 70 мм |
||||
* Ширина: 150 мм |
||||
* Длина: 400 мм |
||||
|
||||
<Image |
||||
alt={`Рисунок 3 - Выставочный зал`} |
||||
src={`/images/vistZal.jpg`} |
||||
width={612} |
||||
height={412} |
||||
priority |
||||
/> |
||||
|
||||
<Image |
||||
alt={`Рисунок 3 - Выставочный зал`} |
||||
src={`/images/vistzal2.jpg`} |
||||
width={612} |
||||
height={412} |
||||
priority |
||||
/> |
||||
### Пьедестал: |
||||
**Размеры:** |
||||
* Высота: 90 мм |
||||
* Ширина: 150 мм |
||||
* Длина: 400 мм |
||||
|
||||
<Image |
||||
alt={`Рисунок 3 - Пьедестал`} |
||||
src={`/images/pedistal.jpg`} |
||||
width={612} |
||||
height={412} |
||||
priority |
||||
/> |
||||
|
||||
<Image |
||||
alt={`Рисунок 3 - Пьедестал`} |
||||
src={`/images/pedistal2.jpg`} |
||||
width={612} |
||||
height={412} |
||||
priority |
||||
/> |
||||
На главную [Главная](/) |
@ -0,0 +1,298 @@ |
||||
--- |
||||
title: Робототехника |
||||
description: .. |
||||
date: '2022-09-01' |
||||
image: '/images/robottop.png' |
||||
--- |
||||
|
||||
<Image |
||||
alt={`Регламент проведения соревнования. РоботТОП Junior 2023`} |
||||
src={`/images/robottop.png`} |
||||
width={1440} |
||||
height={460} |
||||
priority |
||||
/> |
||||
|
||||
<p>Участникам необходимо подготовить робота, способного наиболее эффективно поменять местами оригинал статуэтки на ее реплику. Состязание проходит на автономных моделях роботов.</p> |
||||
|
||||
## I. Участники: |
||||
* <p>Команда состоит из 2 - 3 учащихся с 1 по 11 класс</p> |
||||
* <p>Каждая команда на соревнованиях должна привезти с собой одного **уникального робота, витрину, статуэтку.**</p> |
||||
* <p>Возрастные группы участников разделяются по классам (команда первоклассников, 2-х, 3-х, 4-х и т.д.) (Класс ученика подтверждается документом). Если в команде присутствуют участники из разных классов, то определяется по самому старшему ученику.</p> |
||||
* <p>Отдельный человек может быть участником лишь одной команды, даже если обе команды принадлежат к одной организации, при этом, обмен опытом всячески приветствуется. На руководителя проекта (учитель, один из родителей, лидер группы, и т. п.) возрастные ограничения не распространяются, но робот должен быть полностью разработан и построен членами команды.</p> |
||||
|
||||
## II. Задачи для робота: |
||||
## 1. Сохранение и экспонирование статуэтки. |
||||
### Действия: |
||||
* За время подготовки команда должна поставить свою статуэтку на пьедестал. |
||||
* Во время подготовки команда должна предварительно поместить реплику в своего робота. |
||||
* Во время заеда робот должнен забрать статуэтку с пьедестала. |
||||
* После того как статуэтка будет взята, роботы должны поместить ее на витрину. |
||||
* Робот должн поставить реплику на пьедестал вместо статуэтки. |
||||
### Ограничения: |
||||
* Реплику и статуэтку нельзя складывать в стопку. |
||||
* Реплика считается стоящей на пьедестале только в том случае, если она находится на постаменте в конце матча. |
||||
* Реплика представляет собой куб со стороной 60 мм. |
||||
* Статуэтка считается стоящей в витрине, если весь ее объем входит в габариты витрины. |
||||
* Статуэтка не может самостоятельно перемещаться ни внутри витрины, ни на игровой площадке. |
||||
* Статуэтка, построенная командой, имеет следующие ограничения по размерам: |
||||
+ Она должна помещаться в кубе со стороной 120 мм. |
||||
+ Она должна быть больше, чем куб со стороной 60 мм для категории LEGO WEDO 30 мм. |
||||
+ Вес статуэтки не должен превышать 600г. |
||||
* Статуэтка может быть оснащена электроникой. В этом случае она должна иметь кнопку аварийной остановки. |
||||
* Допускается использование простого тумблера в качестве кнопки аварийной остановки. Кнопка должна быть видна и доступна судьям в любое время. |
||||
* Статуэтка, все еще находящаяся под контролем робота в конце матча, не будет засчитана. |
||||
* Реплика, находящаяся под контролем робота в конце матча, не засчитывается. |
||||
### Баллы |
||||
* 2 балла за установку статуэтки на пьедестал во время подготовки; |
||||
* 5 баллов, если статуэтка отсутствует на пьедестале в конце игры; |
||||
* 10 баллов, если реплика находится на пьедестале в конце игры; |
||||
* 15 баллов, если статуэтка находится в витрине в конце игры; |
||||
|
||||
<Image |
||||
alt={`Рисунок 3 - Общий вид игрового поля`} |
||||
src={`/images/zadanie.png`} |
||||
width={512} |
||||
height={256} |
||||
priority |
||||
/> |
||||
Рисунок 4 - Перемещение статуэтки и реплики |
||||
|
||||
## 2. Возвращение в лагерь в конце дня. |
||||
### Действия: |
||||
* После окончания матча робот должен быть остановлен в собственном лагере. |
||||
### Ограничения: |
||||
* Чтобы считаться действительным, вертикальная проекция робота должна хотя бы частично находиться в пределах лагеря. |
||||
## Баллы: |
||||
* 20 баллов, если робот команды находится в одной из зон лагеря; |
||||
<p> 3. Оценка своей работы. </p> |
||||
* Устройство для отображения подсчета очков во время матча должно быть сделано командой: |
||||
+ Оно может быть статичным (лист бумаги, грифельная доска и т.д.) или динамическим (электронный дисплей); расположенным либо на роботе, либо на витрине (пожалуйста, убедитесь, что витрина активирована). |
||||
### Действия и ограничения: |
||||
* Команда должна оценить количество очков, набранных в матче ее роботом. Для этого возможны два исключающих варианта: |
||||
+ Предматчевая оценка на статическом дисплее: команда пишет счет, который она намерена сделать во время матча. |
||||
+ Оценка во время матча на динамическом устройстве отображения. |
||||
+ Область дисплея и его ориентация для чтения должны быть легко различимы и идентифицируемы судьями. |
||||
+ Предполагаемый счет является целым числом и должен быть выражен в десятичной системе исчисления. |
||||
+ В случае динамических дисплеев оценочный счет должен отображаться и после окончания матча. |
||||
+ Ни при каких обстоятельствах счет не должен меняться после окончания матча, иначе бонус будет аннулирован! |
||||
### Баллы: |
||||
<p> Оценка основывается на всех предыдущих действиях. </p> |
||||
* Бонус считается по следующей формуле: Бонус = 0.3 x Баллы – Разница |
||||
* Баллы – набранные во время матча баллы за обычные задания. |
||||
* Разница – математическая разница между предсказанными очками и набранными (модуль разности). • Бонус – целое число (округленное вверх). |
||||
* Бонус прибавляется к баллам команды |
||||
* Отрицательный бонус округляется до 0. |
||||
* Нулевое число баллов не может приносить бонуса |
||||
|
||||
## 3. Установка витрины: |
||||
Для этого действия используются витрина и статуэтка. |
||||
### Действия: |
||||
* Команда должна установить свою витрину в выставочном зале во время подготовки. |
||||
* Витрина будет активирована во время матча путем размещения в ней статуэтки. Цель - выделить статуэтку хотя бы одним светящимся элементом. |
||||
### Ограничения: |
||||
* Активация витрины должна быть произведена в момент размещения статуэтки. Активация может осуществляться любым способом, в том числе беспроводным. |
||||
* Витрина должна иметь как минимум один светящийся элемент, активируемый установленной статуэткой. Этот элемент должен быть виден публике, но не должен никого ослеплять. Этот светящийся элемент может находиться внутри статуэтки, в этом случае электропитание должно обеспечиваться от витрины. |
||||
* Витрина считается активированной, если она явно изменила свою форму или внешний вид по сравнению с началом матча. |
||||
* Вертикальная проекция витрины не должна пересекать границы выставочного зала в любое время. |
||||
* Витрина имеет следующие ограничения по размерам (статуэтка включена) : |
||||
+ Максимальная глубина: 222 мм. |
||||
+ Максимальная ширина: 450 мм. |
||||
+ Максимальная высота: 430 мм. |
||||
+ Вес витрины не должен превышать 3 кг. |
||||
* Для участников группы LEGO WEDO витрина устанавливатся на поле без возвышенорсти. |
||||
* После окончания матча, активированный источник света должен продолжать работать. |
||||
* Витрина может содержать источник электрического питания. В этом случае должна присутствовать кнопка аварийной остановки, которая непосредственно выключает витрину. Кнопка аварийной остановки имеет те же характеристики, что и кнопка аварийной остановки робота. Выключатель должен быть видимым, легко доступным и находиться на одной высоте. До начала матча витрина может быть включена в сеть без активации. |
||||
* Допускается подача питания на витрину, подключив ее к источнику питания панели управления, но ни при каких обстоятельствах витрина не может быть активирована панелью управления робота. Соединительные кабели не учитываются в ограничениях по размерам. |
||||
* Это действие не должно быть опасным для публики, людей вокруг стола, игровой площадки или роботов. |
||||
* Витрина не может быть активирована внешним элементом (командой, пультом дистанционного управления, ...). |
||||
### Баллы: |
||||
* 2 балла за установку витрины во время подготовки; |
||||
* 5 дополнительных баллов, если витрина активирована; |
||||
|
||||
## III Поле: |
||||
* Организаторы соревнований стремятся изготовить Игровую Зону как можно точнее и ближе к эталону. Тем не менее они вправе внести некоторые изменения, если сочтут их необходимыми. Жалобы, связанные с отклонениями размеров, не рассматриваются. |
||||
Имейте в виду, что качество поверхностей разных игровых полей может отличаться, также оно может ухудшаться в ходе соревнований по естественным причинам. |
||||
* Размер – 1200х2400 мм с бортиками высотой 70мм. |
||||
* Макет поля указано на рисунке 2. |
||||
|
||||
<Image |
||||
alt={`Рисунок 4 - Общий вид игрового поля`} |
||||
src={`/images/polegon.png`} |
||||
width={256} |
||||
height={512} |
||||
priority |
||||
/> |
||||
Рисунок 2 - Общий вид игрового поля |
||||
### Зоны на игровом поле: |
||||
### СТАРТОВЫЕ ЗОНЫ |
||||
* У каждой команды есть своя стартовая зона для роботов. Это прямоугольная поверхность отделенная границей полоской цвета команды (граница включена в стартовую зону). |
||||
### Ограничения |
||||
* До старта, вертикальная проекция роботов не должна выходить за пределы стартовой зоны. Убедитесь, что ваши роботы полностью помещаются в стартовую зону. |
||||
* Робот может нависать над бортиком, но не выходить за пределы Игрового Поля. |
||||
* Цветные линии включены в стартовую зону. Во время всего матча роботам запрещается находиться в стартовой зоне другой команды. |
||||
|
||||
## IV Робот: |
||||
* Роботы, использующие в конструкции коммерчески приобретенное шасси или основу, могут быть недопущены к соревнованиям. |
||||
* Одна организация (клуб, школа и т. п.) может зарегистрировать несколько команд, только если это допускается регистрационными требованиями. Принятие подобных требований является обязательным для участников соревнований. |
||||
* В том случае, если робот был представлен, построен или изменен наставником в одиночку, организаторы могут дисквалифицировать или не допустить участие команды в соревнованиях. Участники должны быть способны описать и объяснить процесс создания робота. Строго запрещается изменение робота наставником во время соревнования, но он может руководить и давать советы. |
||||
* Размеры роботов и всех элементов, созданных командами, строго ограничены. Настоятельно рекомендуется включать допуски. |
||||
* Периметр робота - это периметр выпуклой оболочки его вертикальной проекции на поверхность. Измеряется он, как показано на рисунках ниже: |
||||
|
||||
<Image |
||||
alt={`Рисунок 5 - Общий вид игрового поля`} |
||||
src={`/images/sizerobot.png`} |
||||
width={612} |
||||
height={512} |
||||
priority |
||||
/> |
||||
Рисунок 5 - Размеры робота |
||||
|
||||
* Периметр робота не должен превышать 1200 мм во время старта. Периметр полностью развернутого робота не должен превышать 1300 мм во время матча. Разрешается изменять форму выпуклой оболочки во время игры, если ее периметр всегда учитывает ограничение максимального периметра. |
||||
* В любой момент, во время матча, высота каждого робота не должна превышать 350 мм. Кнопка Аварийной остановки может быть расположена на высоте 375 мм. |
||||
* Когда робот манипулирует объектом, высота этого объекта не может превышать 350 мм |
||||
### Источники энергии: |
||||
* Разрешены любые источники энергии, встроенные в робота и другие разработанные системы (аккумуляторы, сжатый воздух, энергия гравитации…), за исключением источников энергии, использующих химические реакции, такие как горение или взрыв, которые запрещены из соображений безопасности. Кроме того, запрещено использование живых существ, коррозионных составов и расплескивание жидкостей. |
||||
* Если у вас есть сомнения в отношении необычного источника энергии, лучше заранее посоветуйтесь с судейским комитетом, предоставляя соответствующую техническую документацию. |
||||
* Для предотвращения возгорания рекомендуется обращать особое внимание на выбор проводников в зависимости от проходящего через них тока. Кроме того, рекомендуется защитить систему питания, установив предохранитель как можно ближе к аккумулятору. |
||||
### Аккумулятор: |
||||
* Разрешено использовать только немодифицированные батареи. |
||||
* Роботы должны быть в состоянии участвовать в трёх матчах подряд. Обратите внимание, что это время, помимо прочего, включает период ожидания, во время которого робот включен и ожидает старта. |
||||
* Командам настоятельно рекомендуется приготовить несколько наборов аккумуляторов и обеспечить легкий доступ к ним для проведения замены в случае необходимости. Всегда держите наготове набор полностью заряженных аккумуляторов. |
||||
* <b> Особое внимание к аккумуляторам на основе Лития:</b> |
||||
* Литиевые батареи известны своей нестабильностью и могут легко воспламениться, если не будут приняты определенные меры предосторожности. |
||||
* Использование батарей на основе Лития (например, Li-ion / Li-Po / Li-Fe) разрешается при соблюдении следующих условий: |
||||
+ Подходящее, выпущенное промышленным способом, зарядное устройство, которое должно быть предоставлено на этапе допуска к соревнованиям. |
||||
+ Батареи постоянно хранятся в специальном сертифицированном огнеупорном контейнере (например, огнестойком мешке), как во время соревнований, так и в боксах участников, а также во время транспортировки робота! |
||||
+ Настоятельно рекомендуется снабжать робота системой обнаружения разряда батарей • Данные ограничения снимаются только в случае: |
||||
+ Батарей Lego™ Mindstorms / ноутбука / мобильного телефона и только до тех пор пока они не вынуты из "родного" устройства и они используются по назначению, которое определил производитель. |
||||
+ Lithium-Iron батарей (LifePo4) |
||||
+ Источник питания, передаваемый роботу, может быть только электрическим. Максимально допустимое напряжение составляет 13,8 В (измеряется между любыми двумя проводами кабеля и робота). Этот источник напряжения не предоставляется организаторами. С другой стороны, команды имеют доступ к стандарту (стандарт 230 В 50 Гц) и могут использовать батареи. |
||||
+ Клеммы кабелей должны быть изолированы. |
||||
### Необходимые элементы на роботе |
||||
* На одной из сторон робота должна быть оставлена прямоугольная площадка 100мм x 70мм. По возможности, данная область должна быть видна с наивысшей точки игрового поля. Она так же должна быть визуально доступной на протяжении большей части матча. Команды могут получить наклейки, предназначенные для размещения в этой области. |
||||
* Командам настоятельно рекомендуется делать механизмы внутри робота видимыми для зрителей и других участников. Это создает атмосферу обучения и передачи знаний, необходимую для того, чтобы понять принцип действия роботов. |
||||
### Стартовый шнур робота: |
||||
* В начале матча робот должен быть запущен так называемым «Стартовым Устройством». Оно должно приводиться в действие выдергиванием шнура длиной как минимум 500 мм. После запуска шнур не должен оставаться прикрепленным к роботу. Любые другие системы запуска (например, пульт дистанционного управления, ручной тумблер, отжатие кнопки аварийного выключения и т. п.) не будут одобрены. |
||||
### Кнопка аварийного выключения робота. |
||||
* У роботов, использующих батареи для питания, должна быть кнопка аварийного выключения красного цвета и диаметром как минимум 20 мм. Ее следует разместить в верхней части робота, в безопасном месте, легко доступном для судей в любой момент матча. Допускается, чтобы Кнопка Аварийного Выключения в поднятом состоянии превышала высоту робота на 25 мм. |
||||
* Активация кнопки должна происходить от простого поступательного движения вниз (например, нажатие ладонью). Сразу после активации Кнопки Аварийного Выключения должна прекратиться работа всех приводов робота, оставляя их в свободном состоянии (т. е. НЕ в состоянии активного торможения – обесточенными). |
||||
* При проектировании роботов рекомендуется учитывать возможные неровности игровых площадок. |
||||
### Система управления роботом: |
||||
* Команды могут использовать любой тип системы управления для робота (аналоговый, микропроцессорный, микроконтроллер, встроенный компьютер, программируемая логика и т. д.). |
||||
* Эти системы должны быть полностью интегрированы в робота. |
||||
* Система управления должна позволять роботу передвигаться при любом цвете(расположении на поле), предоставленных командам. В идеале, он должен быть настроен незадолго до оглашения цвета команды. |
||||
|
||||
|
||||
## V Порядок проведения: |
||||
* Перед началом очередного матча у каждой команды есть 2 минуты, чтобы подготовить робота, а так же другое оборудование к игре на Поле. Команда, не подготовившая своего робота вовремя, будет дисквалифицирована. |
||||
* После завершения этапа подготовки роботов, судьи уточняют у участников их готовность. С этого момента командам запрещается прикасаться к роботам. Также с этого момента претензии относительно состояния Игровых Элементов или их расположения в Игровой Зоне, не принимаются к обсуждению. |
||||
* Если команда готова к матчу, этап подготовки можно сократить и начать матч по готовности команды! |
||||
### Заезд: |
||||
* После короткого обратного отсчета судья подаст сигнал к запуску роботов. Во время заезда ни при каких обстоятельствах не разрешается трогать роботов, Игровые Элементы или Игровое Поле (исключение представляет только особое указание судьи). Также не разрешается нажимать на Кнопку Аварийного Выключения! Любое воздействие на робота, Игровой Элемент или Игровое Поле без явного разрешения судьи может привести к дисквалификации команды с матча. Продолжительность одно матча 100 секунд. |
||||
Любой объект, покинувший Игровое Поле во время матча, обратно возвращать запрещено. По истечении основного времени матча роботы должны прекратить всякое передвижение по полю и остановить все свои приводы. |
||||
* После окончания заезда никто кроме судьи не имеет права трогать роботов и Игровые Элементы. Затем судьи должны подсчитать баллы и объявить результат матча (подробности подсчета см. следующий раздел). После этого команды могут забрать своих роботов из Игровой Зоны. Если команды с чем-то несогласны, то они могут спокойно изложить свои аргументы судьям. Роботы продолжают оставаться на своих местах до окончания спора. |
||||
* Помните, что только 2 члена команды должны находиться в Игровой Зоне! В итоге судья выносит окончательное решение. В случае, если найти решение в обсуждении не удается, судьи оставляют за собой решение о необходимости переигровки матча. |
||||
* Команда объявляется дисквалифицированной с матча, если ни один из роботов команды полностью не покинул стартовую площадку в течение матча, была нажата кнопка экстренной остановки или если судья вынес соответствующее решение по итогам матча. |
||||
* Нажатие кнопки экстренной остановки может привести к штрафу или дисквалификации с матча. |
||||
### СИСТЕМА БАЛЛОВ |
||||
* Выезд из лагеря: |
||||
+ 5 баллов, если робот после старта самостоятельно покинул полностью стартовую зону; |
||||
* Возвращение на место в лагерь: |
||||
+ 20 баллов, если один робот команды находятся в лагере; |
||||
* Сохранение и выставление статуэтки: |
||||
+ 2 балла за установку статуэтки на пьедестал во время подготовки; |
||||
+ 5 баллов, если статуэтка отсутствует на пьедестале в конце игры; |
||||
+ 10 баллов, если статуэтка находится на пьедестале в конце игры; |
||||
+ 15 баллов, если статуэтка находится в витрине в конце игры; |
||||
* Витрина: |
||||
+ 2 балла за установку витрины во время подготовки; |
||||
+ 5 дополнительных баллов, если витрина активирована во время игры; |
||||
* Скорость выполнения задания: |
||||
+ 60 секунд минус время выполнения полного задания роботом = дополнительные баллы. (пример: 60 - 54 = 6 балов) |
||||
* Оценка производительности: |
||||
+ Оценка основана на предыдущих действиях |
||||
+ Бонус считается по следующей формуле: Бонус = 0.3 x Баллы - Разница |
||||
+ Баллы – набранные во время матча баллы за обычные задания. |
||||
+ Разница – математическая разница между предсказанными очками и набранными (неотрицательна). • Бонус – целое число (округленное вверх). |
||||
+ Бонус прибавляется к баллам команды |
||||
+ Отрицательный бонус округляется до 0. |
||||
+ Нулевое число баллов не может приносить бонуса. |
||||
+ Бонус за «недисквалификацию» не учитывается в прогнозе |
||||
+ Штрафы не учитываются в прогнозе |
||||
+ ВНИМАНИЕ! Игровой Элемент, который удерживается роботом не приносит баллы. Проверка осуществляется путем передвижения шасси робота в естественной манере, если Элемент движется вместе с роботом – он не засчитывается. |
||||
### Штрафы: |
||||
* Штраф приводит к потере 20 баллов в счете команды в оштрафованном матче. |
||||
* Отрицательный счет округляется до 0. |
||||
* Штрафы предназначены для компенсации урона или созданных помех, которые являются следствием ЧП во время проведения матча. Штрафная ситуация рассматривается как несоблюдение правил: такая ситуация должна оставаться исключительной! В случае повторяющихся штрафов, судьи имеют право дисквалифицировать команду как с матча, так и с соревнований. Судейский комитет также будет обращать внимание на штрафы, накопленные командами в течение отборочных региональных и / или национальных турах соревнований. |
||||
### Бонусные баллы: |
||||
* 1 бонусный балл присуждается команде, которая не была дисквалифицирована в ходе матча. |
||||
* Случаи дисквалификации: |
||||
+ Баллы дисквалифицированной команды приравниваются к нулю. |
||||
## Допуск к заездам: |
||||
### СТАТИЧЕСКАЯ ПРОВЕРКА |
||||
* Перед тем, как выступать на Поле, роботы осматриваются судьей, который проверяет их на соответствие правилам. Роботы должны быть готовы к демонстрации всех своих возможных действий. |
||||
### ДИНАМИЧЕСКАЯ ПРОВЕРКА: |
||||
* Роботы должны в течение 100 секунд продемонстрировать хотя бы одно действие, приносящее минимальное количество очков. Роботы проверяются на Игровом Поле. Также может быть проверено соответствие некоторым обязательным требованиям правил (например, наличие таймера). |
||||
### ЗНАЧИТЕЛЬНЫЕ ИЗМЕНЕНИЯ В РОБОТЕ: |
||||
* В случае значительных технических изменений (функциональных, структурных, размерных...), выполненных после прохождения этапа допуска к соревнованиям, необходимо сообщить о них судье. Судьи должны утвердить изменения и, если посчитают необходимым, могут назначить повторную проверку роботу, подвергшемуся доработке. |
||||
Если организаторы считают, что робот был модифицирован, может потребоваться повторная гомологизация робота, что запрещает ему соревноваться до тех пор, пока не будет получен повторный допуск. |
||||
## VI Определение победитлей |
||||
* В каждой возрастной группе определяется команды занивщае 1,2,3 местот по количеству балов от максимальному к минимальному. |
||||
|
||||
## ОБЩИЕ ПОЛОЖЕНИЯ |
||||
* Во время соревнований только двум членам команды разрешен доступ к зоне ожидания матча и к Игровой Зоне. На пути к Игровой Зоне могут встречаться ступеньки или лестницы, поэтому рекомендуется делать вспомогательное оборудование удобным для переноски |
||||
* Роботы должны быть сделаны из хорошо соединенных частей – части Роботов не должны отделяться и оставаться на Игровом Поле во время матча. Исключением в этом случае являются подобранные Игровые Элементы. |
||||
* Роботы не должны прикреплять себя к игровому полю (например, используя вакуумные присоски). |
||||
* Каждая команда должна разработать уникальный и оригинальный набор роботов. Поэтому не разрешается проектировать роботов, которые в значительной степени аналогичны роботам других команд (например, идентичные колесные базы или исполнительные механизмы). В случае сомнений обращайтесь в судейский комитет. |
||||
* Используйте воображение и творите! Устройте развлекательное шоу для зрителей и СМИ, ваш робот может выражать эмоции, воспроизводить звуки или играть музыку. |
||||
|
||||
## БЕЗОПАСНОСТЬ |
||||
* Все системы должны соответствовать существующим национальным стандартам. В частности, используемые системы должны соответствовать официальным нормам безопасности жизнедеятельности и быть безопасными для участников и зрителей во время и вне матчей (например, в боксах команды или в процессе ожидания/подготовки матча). У роботов не должно быть никаких опасных выступающих или острых частей. |
||||
* Строго запрещается использование жидких, едких и пиротехнических материалов или живых существ в роботе. Все роботы должны соответствовать официальным стандартам «низкого напряжения». То есть электрические напряжения, используемые в роботах или Маяках, не должны превышать 48v. Напряжения выше 48v могут быть использованы только внутри закрытых устройств, произведенных промышленным способом (таких, как лазеры, подсветка LCD панели), если эти устройства не были модифицированы, и если они соответствуют национальным нормативным требованиям. |
||||
* Как правило, любой механизм или система, признанная судьями как потенциально опасная, будет запрещена к применению и должна быть удалена из робота до соревнований, иначе команда будет дисквалифицирована с соревнований. |
||||
|
||||
## Приложение |
||||
### Выставочный зал |
||||
**Размеры:** |
||||
* Высота: 70 мм |
||||
* Ширина: 150 мм |
||||
* Длина: 400 мм |
||||
|
||||
<Image |
||||
alt={`Рисунок 3 - Выставочный зал`} |
||||
src={`/images/vistZal.jpg`} |
||||
width={612} |
||||
height={412} |
||||
priority |
||||
/> |
||||
|
||||
<Image |
||||
alt={`Рисунок 3 - Выставочный зал`} |
||||
src={`/images/vistzal2.jpg`} |
||||
width={612} |
||||
height={412} |
||||
priority |
||||
/> |
||||
### Пьедестал: |
||||
**Размеры:** |
||||
* Высота: 90 мм |
||||
* Ширина: 150 мм |
||||
* Длина: 400 мм |
||||
|
||||
<Image |
||||
alt={`Рисунок 3 - Пьедестал`} |
||||
src={`/images/pedistal.jpg`} |
||||
width={612} |
||||
height={412} |
||||
priority |
||||
/> |
||||
|
||||
<Image |
||||
alt={`Рисунок 3 - Пьедестал`} |
||||
src={`/images/pedistal2.jpg`} |
||||
width={612} |
||||
height={412} |
||||
priority |
||||
/> |
||||
На главную [Главная](/) |
@ -0,0 +1,298 @@ |
||||
--- |
||||
title: Робототехника |
||||
description: Задачи, материал по теме |
||||
date: '2022-09-01' |
||||
image: '/images/robottop.png' |
||||
--- |
||||
|
||||
<Image |
||||
alt={`Регламент проведения соревнования. РоботТОП Junior 2023`} |
||||
src={`/images/robottop.png`} |
||||
width={1440} |
||||
height={460} |
||||
priority |
||||
/> |
||||
|
||||
<p>Участникам необходимо подготовить робота, способного наиболее эффективно поменять местами оригинал статуэтки на ее реплику. Состязание проходит на автономных моделях роботов.</p> |
||||
|
||||
## I. Участники: |
||||
* <p>Команда состоит из 2 - 3 учащихся с 1 по 11 класс</p> |
||||
* <p>Каждая команда на соревнованиях должна привезти с собой одного **уникального робота, витрину, статуэтку.**</p> |
||||
* <p>Возрастные группы участников разделяются по классам (команда первоклассников, 2-х, 3-х, 4-х и т.д.) (Класс ученика подтверждается документом). Если в команде присутствуют участники из разных классов, то определяется по самому старшему ученику.</p> |
||||
* <p>Отдельный человек может быть участником лишь одной команды, даже если обе команды принадлежат к одной организации, при этом, обмен опытом всячески приветствуется. На руководителя проекта (учитель, один из родителей, лидер группы, и т. п.) возрастные ограничения не распространяются, но робот должен быть полностью разработан и построен членами команды.</p> |
||||
|
||||
## II. Задачи для робота: |
||||
## 1. Сохранение и экспонирование статуэтки. |
||||
### Действия: |
||||
* За время подготовки команда должна поставить свою статуэтку на пьедестал. |
||||
* Во время подготовки команда должна предварительно поместить реплику в своего робота. |
||||
* Во время заеда робот должнен забрать статуэтку с пьедестала. |
||||
* После того как статуэтка будет взята, роботы должны поместить ее на витрину. |
||||
* Робот должн поставить реплику на пьедестал вместо статуэтки. |
||||
### Ограничения: |
||||
* Реплику и статуэтку нельзя складывать в стопку. |
||||
* Реплика считается стоящей на пьедестале только в том случае, если она находится на постаменте в конце матча. |
||||
* Реплика представляет собой куб со стороной 60 мм. |
||||
* Статуэтка считается стоящей в витрине, если весь ее объем входит в габариты витрины. |
||||
* Статуэтка не может самостоятельно перемещаться ни внутри витрины, ни на игровой площадке. |
||||
* Статуэтка, построенная командой, имеет следующие ограничения по размерам: |
||||
+ Она должна помещаться в кубе со стороной 120 мм. |
||||
+ Она должна быть больше, чем куб со стороной 60 мм для категории LEGO WEDO 30 мм. |
||||
+ Вес статуэтки не должен превышать 600г. |
||||
* Статуэтка может быть оснащена электроникой. В этом случае она должна иметь кнопку аварийной остановки. |
||||
* Допускается использование простого тумблера в качестве кнопки аварийной остановки. Кнопка должна быть видна и доступна судьям в любое время. |
||||
* Статуэтка, все еще находящаяся под контролем робота в конце матча, не будет засчитана. |
||||
* Реплика, находящаяся под контролем робота в конце матча, не засчитывается. |
||||
### Баллы |
||||
* 2 балла за установку статуэтки на пьедестал во время подготовки; |
||||
* 5 баллов, если статуэтка отсутствует на пьедестале в конце игры; |
||||
* 10 баллов, если реплика находится на пьедестале в конце игры; |
||||
* 15 баллов, если статуэтка находится в витрине в конце игры; |
||||
|
||||
<Image |
||||
alt={`Рисунок 3 - Общий вид игрового поля`} |
||||
src={`/images/zadanie.png`} |
||||
width={512} |
||||
height={256} |
||||
priority |
||||
/> |
||||
Рисунок 4 - Перемещение статуэтки и реплики |
||||
|
||||
## 2. Возвращение в лагерь в конце дня. |
||||
### Действия: |
||||
* После окончания матча робот должен быть остановлен в собственном лагере. |
||||
### Ограничения: |
||||
* Чтобы считаться действительным, вертикальная проекция робота должна хотя бы частично находиться в пределах лагеря. |
||||
## Баллы: |
||||
* 20 баллов, если робот команды находится в одной из зон лагеря; |
||||
<p> 3. Оценка своей работы. </p> |
||||
* Устройство для отображения подсчета очков во время матча должно быть сделано командой: |
||||
+ Оно может быть статичным (лист бумаги, грифельная доска и т.д.) или динамическим (электронный дисплей); расположенным либо на роботе, либо на витрине (пожалуйста, убедитесь, что витрина активирована). |
||||
### Действия и ограничения: |
||||
* Команда должна оценить количество очков, набранных в матче ее роботом. Для этого возможны два исключающих варианта: |
||||
+ Предматчевая оценка на статическом дисплее: команда пишет счет, который она намерена сделать во время матча. |
||||
+ Оценка во время матча на динамическом устройстве отображения. |
||||
+ Область дисплея и его ориентация для чтения должны быть легко различимы и идентифицируемы судьями. |
||||
+ Предполагаемый счет является целым числом и должен быть выражен в десятичной системе исчисления. |
||||
+ В случае динамических дисплеев оценочный счет должен отображаться и после окончания матча. |
||||
+ Ни при каких обстоятельствах счет не должен меняться после окончания матча, иначе бонус будет аннулирован! |
||||
### Баллы: |
||||
<p> Оценка основывается на всех предыдущих действиях. </p> |
||||
* Бонус считается по следующей формуле: Бонус = 0.3 x Баллы – Разница |
||||
* Баллы – набранные во время матча баллы за обычные задания. |
||||
* Разница – математическая разница между предсказанными очками и набранными (модуль разности). • Бонус – целое число (округленное вверх). |
||||
* Бонус прибавляется к баллам команды |
||||
* Отрицательный бонус округляется до 0. |
||||
* Нулевое число баллов не может приносить бонуса |
||||
|
||||
## 3. Установка витрины: |
||||
Для этого действия используются витрина и статуэтка. |
||||
### Действия: |
||||
* Команда должна установить свою витрину в выставочном зале во время подготовки. |
||||
* Витрина будет активирована во время матча путем размещения в ней статуэтки. Цель - выделить статуэтку хотя бы одним светящимся элементом. |
||||
### Ограничения: |
||||
* Активация витрины должна быть произведена в момент размещения статуэтки. Активация может осуществляться любым способом, в том числе беспроводным. |
||||
* Витрина должна иметь как минимум один светящийся элемент, активируемый установленной статуэткой. Этот элемент должен быть виден публике, но не должен никого ослеплять. Этот светящийся элемент может находиться внутри статуэтки, в этом случае электропитание должно обеспечиваться от витрины. |
||||
* Витрина считается активированной, если она явно изменила свою форму или внешний вид по сравнению с началом матча. |
||||
* Вертикальная проекция витрины не должна пересекать границы выставочного зала в любое время. |
||||
* Витрина имеет следующие ограничения по размерам (статуэтка включена) : |
||||
+ Максимальная глубина: 222 мм. |
||||
+ Максимальная ширина: 450 мм. |
||||
+ Максимальная высота: 430 мм. |
||||
+ Вес витрины не должен превышать 3 кг. |
||||
* Для участников группы LEGO WEDO витрина устанавливатся на поле без возвышенорсти. |
||||
* После окончания матча, активированный источник света должен продолжать работать. |
||||
* Витрина может содержать источник электрического питания. В этом случае должна присутствовать кнопка аварийной остановки, которая непосредственно выключает витрину. Кнопка аварийной остановки имеет те же характеристики, что и кнопка аварийной остановки робота. Выключатель должен быть видимым, легко доступным и находиться на одной высоте. До начала матча витрина может быть включена в сеть без активации. |
||||
* Допускается подача питания на витрину, подключив ее к источнику питания панели управления, но ни при каких обстоятельствах витрина не может быть активирована панелью управления робота. Соединительные кабели не учитываются в ограничениях по размерам. |
||||
* Это действие не должно быть опасным для публики, людей вокруг стола, игровой площадки или роботов. |
||||
* Витрина не может быть активирована внешним элементом (командой, пультом дистанционного управления, ...). |
||||
### Баллы: |
||||
* 2 балла за установку витрины во время подготовки; |
||||
* 5 дополнительных баллов, если витрина активирована; |
||||
|
||||
## III Поле: |
||||
* Организаторы соревнований стремятся изготовить Игровую Зону как можно точнее и ближе к эталону. Тем не менее они вправе внести некоторые изменения, если сочтут их необходимыми. Жалобы, связанные с отклонениями размеров, не рассматриваются. |
||||
Имейте в виду, что качество поверхностей разных игровых полей может отличаться, также оно может ухудшаться в ходе соревнований по естественным причинам. |
||||
* Размер – 1200х2400 мм с бортиками высотой 70мм. |
||||
* Макет поля указано на рисунке 2. |
||||
|
||||
<Image |
||||
alt={`Рисунок 4 - Общий вид игрового поля`} |
||||
src={`/images/polegon.png`} |
||||
width={256} |
||||
height={512} |
||||
priority |
||||
/> |
||||
Рисунок 2 - Общий вид игрового поля |
||||
### Зоны на игровом поле: |
||||
### СТАРТОВЫЕ ЗОНЫ |
||||
* У каждой команды есть своя стартовая зона для роботов. Это прямоугольная поверхность отделенная границей полоской цвета команды (граница включена в стартовую зону). |
||||
### Ограничения |
||||
* До старта, вертикальная проекция роботов не должна выходить за пределы стартовой зоны. Убедитесь, что ваши роботы полностью помещаются в стартовую зону. |
||||
* Робот может нависать над бортиком, но не выходить за пределы Игрового Поля. |
||||
* Цветные линии включены в стартовую зону. Во время всего матча роботам запрещается находиться в стартовой зоне другой команды. |
||||
|
||||
## IV Робот: |
||||
* Роботы, использующие в конструкции коммерчески приобретенное шасси или основу, могут быть недопущены к соревнованиям. |
||||
* Одна организация (клуб, школа и т. п.) может зарегистрировать несколько команд, только если это допускается регистрационными требованиями. Принятие подобных требований является обязательным для участников соревнований. |
||||
* В том случае, если робот был представлен, построен или изменен наставником в одиночку, организаторы могут дисквалифицировать или не допустить участие команды в соревнованиях. Участники должны быть способны описать и объяснить процесс создания робота. Строго запрещается изменение робота наставником во время соревнования, но он может руководить и давать советы. |
||||
* Размеры роботов и всех элементов, созданных командами, строго ограничены. Настоятельно рекомендуется включать допуски. |
||||
* Периметр робота - это периметр выпуклой оболочки его вертикальной проекции на поверхность. Измеряется он, как показано на рисунках ниже: |
||||
|
||||
<Image |
||||
alt={`Рисунок 5 - Общий вид игрового поля`} |
||||
src={`/images/sizerobot.png`} |
||||
width={612} |
||||
height={512} |
||||
priority |
||||
/> |
||||
Рисунок 5 - Размеры робота |
||||
|
||||
* Периметр робота не должен превышать 1200 мм во время старта. Периметр полностью развернутого робота не должен превышать 1300 мм во время матча. Разрешается изменять форму выпуклой оболочки во время игры, если ее периметр всегда учитывает ограничение максимального периметра. |
||||
* В любой момент, во время матча, высота каждого робота не должна превышать 350 мм. Кнопка Аварийной остановки может быть расположена на высоте 375 мм. |
||||
* Когда робот манипулирует объектом, высота этого объекта не может превышать 350 мм |
||||
### Источники энергии: |
||||
* Разрешены любые источники энергии, встроенные в робота и другие разработанные системы (аккумуляторы, сжатый воздух, энергия гравитации…), за исключением источников энергии, использующих химические реакции, такие как горение или взрыв, которые запрещены из соображений безопасности. Кроме того, запрещено использование живых существ, коррозионных составов и расплескивание жидкостей. |
||||
* Если у вас есть сомнения в отношении необычного источника энергии, лучше заранее посоветуйтесь с судейским комитетом, предоставляя соответствующую техническую документацию. |
||||
* Для предотвращения возгорания рекомендуется обращать особое внимание на выбор проводников в зависимости от проходящего через них тока. Кроме того, рекомендуется защитить систему питания, установив предохранитель как можно ближе к аккумулятору. |
||||
### Аккумулятор: |
||||
* Разрешено использовать только немодифицированные батареи. |
||||
* Роботы должны быть в состоянии участвовать в трёх матчах подряд. Обратите внимание, что это время, помимо прочего, включает период ожидания, во время которого робот включен и ожидает старта. |
||||
* Командам настоятельно рекомендуется приготовить несколько наборов аккумуляторов и обеспечить легкий доступ к ним для проведения замены в случае необходимости. Всегда держите наготове набор полностью заряженных аккумуляторов. |
||||
* <b> Особое внимание к аккумуляторам на основе Лития:</b> |
||||
* Литиевые батареи известны своей нестабильностью и могут легко воспламениться, если не будут приняты определенные меры предосторожности. |
||||
* Использование батарей на основе Лития (например, Li-ion / Li-Po / Li-Fe) разрешается при соблюдении следующих условий: |
||||
+ Подходящее, выпущенное промышленным способом, зарядное устройство, которое должно быть предоставлено на этапе допуска к соревнованиям. |
||||
+ Батареи постоянно хранятся в специальном сертифицированном огнеупорном контейнере (например, огнестойком мешке), как во время соревнований, так и в боксах участников, а также во время транспортировки робота! |
||||
+ Настоятельно рекомендуется снабжать робота системой обнаружения разряда батарей • Данные ограничения снимаются только в случае: |
||||
+ Батарей Lego™ Mindstorms / ноутбука / мобильного телефона и только до тех пор пока они не вынуты из "родного" устройства и они используются по назначению, которое определил производитель. |
||||
+ Lithium-Iron батарей (LifePo4) |
||||
+ Источник питания, передаваемый роботу, может быть только электрическим. Максимально допустимое напряжение составляет 13,8 В (измеряется между любыми двумя проводами кабеля и робота). Этот источник напряжения не предоставляется организаторами. С другой стороны, команды имеют доступ к стандарту (стандарт 230 В 50 Гц) и могут использовать батареи. |
||||
+ Клеммы кабелей должны быть изолированы. |
||||
### Необходимые элементы на роботе |
||||
* На одной из сторон робота должна быть оставлена прямоугольная площадка 100мм x 70мм. По возможности, данная область должна быть видна с наивысшей точки игрового поля. Она так же должна быть визуально доступной на протяжении большей части матча. Команды могут получить наклейки, предназначенные для размещения в этой области. |
||||
* Командам настоятельно рекомендуется делать механизмы внутри робота видимыми для зрителей и других участников. Это создает атмосферу обучения и передачи знаний, необходимую для того, чтобы понять принцип действия роботов. |
||||
### Стартовый шнур робота: |
||||
* В начале матча робот должен быть запущен так называемым «Стартовым Устройством». Оно должно приводиться в действие выдергиванием шнура длиной как минимум 500 мм. После запуска шнур не должен оставаться прикрепленным к роботу. Любые другие системы запуска (например, пульт дистанционного управления, ручной тумблер, отжатие кнопки аварийного выключения и т. п.) не будут одобрены. |
||||
### Кнопка аварийного выключения робота. |
||||
* У роботов, использующих батареи для питания, должна быть кнопка аварийного выключения красного цвета и диаметром как минимум 20 мм. Ее следует разместить в верхней части робота, в безопасном месте, легко доступном для судей в любой момент матча. Допускается, чтобы Кнопка Аварийного Выключения в поднятом состоянии превышала высоту робота на 25 мм. |
||||
* Активация кнопки должна происходить от простого поступательного движения вниз (например, нажатие ладонью). Сразу после активации Кнопки Аварийного Выключения должна прекратиться работа всех приводов робота, оставляя их в свободном состоянии (т. е. НЕ в состоянии активного торможения – обесточенными). |
||||
* При проектировании роботов рекомендуется учитывать возможные неровности игровых площадок. |
||||
### Система управления роботом: |
||||
* Команды могут использовать любой тип системы управления для робота (аналоговый, микропроцессорный, микроконтроллер, встроенный компьютер, программируемая логика и т. д.). |
||||
* Эти системы должны быть полностью интегрированы в робота. |
||||
* Система управления должна позволять роботу передвигаться при любом цвете(расположении на поле), предоставленных командам. В идеале, он должен быть настроен незадолго до оглашения цвета команды. |
||||
|
||||
|
||||
## V Порядок проведения: |
||||
* Перед началом очередного матча у каждой команды есть 2 минуты, чтобы подготовить робота, а так же другое оборудование к игре на Поле. Команда, не подготовившая своего робота вовремя, будет дисквалифицирована. |
||||
* После завершения этапа подготовки роботов, судьи уточняют у участников их готовность. С этого момента командам запрещается прикасаться к роботам. Также с этого момента претензии относительно состояния Игровых Элементов или их расположения в Игровой Зоне, не принимаются к обсуждению. |
||||
* Если команда готова к матчу, этап подготовки можно сократить и начать матч по готовности команды! |
||||
### Заезд: |
||||
* После короткого обратного отсчета судья подаст сигнал к запуску роботов. Во время заезда ни при каких обстоятельствах не разрешается трогать роботов, Игровые Элементы или Игровое Поле (исключение представляет только особое указание судьи). Также не разрешается нажимать на Кнопку Аварийного Выключения! Любое воздействие на робота, Игровой Элемент или Игровое Поле без явного разрешения судьи может привести к дисквалификации команды с матча. Продолжительность одно матча 100 секунд. |
||||
Любой объект, покинувший Игровое Поле во время матча, обратно возвращать запрещено. По истечении основного времени матча роботы должны прекратить всякое передвижение по полю и остановить все свои приводы. |
||||
* После окончания заезда никто кроме судьи не имеет права трогать роботов и Игровые Элементы. Затем судьи должны подсчитать баллы и объявить результат матча (подробности подсчета см. следующий раздел). После этого команды могут забрать своих роботов из Игровой Зоны. Если команды с чем-то несогласны, то они могут спокойно изложить свои аргументы судьям. Роботы продолжают оставаться на своих местах до окончания спора. |
||||
* Помните, что только 2 члена команды должны находиться в Игровой Зоне! В итоге судья выносит окончательное решение. В случае, если найти решение в обсуждении не удается, судьи оставляют за собой решение о необходимости переигровки матча. |
||||
* Команда объявляется дисквалифицированной с матча, если ни один из роботов команды полностью не покинул стартовую площадку в течение матча, была нажата кнопка экстренной остановки или если судья вынес соответствующее решение по итогам матча. |
||||
* Нажатие кнопки экстренной остановки может привести к штрафу или дисквалификации с матча. |
||||
### СИСТЕМА БАЛЛОВ |
||||
* Выезд из лагеря: |
||||
+ 5 баллов, если робот после старта самостоятельно покинул полностью стартовую зону; |
||||
* Возвращение на место в лагерь: |
||||
+ 20 баллов, если один робот команды находятся в лагере; |
||||
* Сохранение и выставление статуэтки: |
||||
+ 2 балла за установку статуэтки на пьедестал во время подготовки; |
||||
+ 5 баллов, если статуэтка отсутствует на пьедестале в конце игры; |
||||
+ 10 баллов, если статуэтка находится на пьедестале в конце игры; |
||||
+ 15 баллов, если статуэтка находится в витрине в конце игры; |
||||
* Витрина: |
||||
+ 2 балла за установку витрины во время подготовки; |
||||
+ 5 дополнительных баллов, если витрина активирована во время игры; |
||||
* Скорость выполнения задания: |
||||
+ 60 секунд минус время выполнения полного задания роботом = дополнительные баллы. (пример: 60 - 54 = 6 балов) |
||||
* Оценка производительности: |
||||
+ Оценка основана на предыдущих действиях |
||||
+ Бонус считается по следующей формуле: Бонус = 0.3 x Баллы - Разница |
||||
+ Баллы – набранные во время матча баллы за обычные задания. |
||||
+ Разница – математическая разница между предсказанными очками и набранными (неотрицательна). • Бонус – целое число (округленное вверх). |
||||
+ Бонус прибавляется к баллам команды |
||||
+ Отрицательный бонус округляется до 0. |
||||
+ Нулевое число баллов не может приносить бонуса. |
||||
+ Бонус за «недисквалификацию» не учитывается в прогнозе |
||||
+ Штрафы не учитываются в прогнозе |
||||
+ ВНИМАНИЕ! Игровой Элемент, который удерживается роботом не приносит баллы. Проверка осуществляется путем передвижения шасси робота в естественной манере, если Элемент движется вместе с роботом – он не засчитывается. |
||||
### Штрафы: |
||||
* Штраф приводит к потере 20 баллов в счете команды в оштрафованном матче. |
||||
* Отрицательный счет округляется до 0. |
||||
* Штрафы предназначены для компенсации урона или созданных помех, которые являются следствием ЧП во время проведения матча. Штрафная ситуация рассматривается как несоблюдение правил: такая ситуация должна оставаться исключительной! В случае повторяющихся штрафов, судьи имеют право дисквалифицировать команду как с матча, так и с соревнований. Судейский комитет также будет обращать внимание на штрафы, накопленные командами в течение отборочных региональных и / или национальных турах соревнований. |
||||
### Бонусные баллы: |
||||
* 1 бонусный балл присуждается команде, которая не была дисквалифицирована в ходе матча. |
||||
* Случаи дисквалификации: |
||||
+ Баллы дисквалифицированной команды приравниваются к нулю. |
||||
## Допуск к заездам: |
||||
### СТАТИЧЕСКАЯ ПРОВЕРКА |
||||
* Перед тем, как выступать на Поле, роботы осматриваются судьей, который проверяет их на соответствие правилам. Роботы должны быть готовы к демонстрации всех своих возможных действий. |
||||
### ДИНАМИЧЕСКАЯ ПРОВЕРКА: |
||||
* Роботы должны в течение 100 секунд продемонстрировать хотя бы одно действие, приносящее минимальное количество очков. Роботы проверяются на Игровом Поле. Также может быть проверено соответствие некоторым обязательным требованиям правил (например, наличие таймера). |
||||
### ЗНАЧИТЕЛЬНЫЕ ИЗМЕНЕНИЯ В РОБОТЕ: |
||||
* В случае значительных технических изменений (функциональных, структурных, размерных...), выполненных после прохождения этапа допуска к соревнованиям, необходимо сообщить о них судье. Судьи должны утвердить изменения и, если посчитают необходимым, могут назначить повторную проверку роботу, подвергшемуся доработке. |
||||
Если организаторы считают, что робот был модифицирован, может потребоваться повторная гомологизация робота, что запрещает ему соревноваться до тех пор, пока не будет получен повторный допуск. |
||||
## VI Определение победитлей |
||||
* В каждой возрастной группе определяется команды занивщае 1,2,3 местот по количеству балов от максимальному к минимальному. |
||||
|
||||
## ОБЩИЕ ПОЛОЖЕНИЯ |
||||
* Во время соревнований только двум членам команды разрешен доступ к зоне ожидания матча и к Игровой Зоне. На пути к Игровой Зоне могут встречаться ступеньки или лестницы, поэтому рекомендуется делать вспомогательное оборудование удобным для переноски |
||||
* Роботы должны быть сделаны из хорошо соединенных частей – части Роботов не должны отделяться и оставаться на Игровом Поле во время матча. Исключением в этом случае являются подобранные Игровые Элементы. |
||||
* Роботы не должны прикреплять себя к игровому полю (например, используя вакуумные присоски). |
||||
* Каждая команда должна разработать уникальный и оригинальный набор роботов. Поэтому не разрешается проектировать роботов, которые в значительной степени аналогичны роботам других команд (например, идентичные колесные базы или исполнительные механизмы). В случае сомнений обращайтесь в судейский комитет. |
||||
* Используйте воображение и творите! Устройте развлекательное шоу для зрителей и СМИ, ваш робот может выражать эмоции, воспроизводить звуки или играть музыку. |
||||
|
||||
## БЕЗОПАСНОСТЬ |
||||
* Все системы должны соответствовать существующим национальным стандартам. В частности, используемые системы должны соответствовать официальным нормам безопасности жизнедеятельности и быть безопасными для участников и зрителей во время и вне матчей (например, в боксах команды или в процессе ожидания/подготовки матча). У роботов не должно быть никаких опасных выступающих или острых частей. |
||||
* Строго запрещается использование жидких, едких и пиротехнических материалов или живых существ в роботе. Все роботы должны соответствовать официальным стандартам «низкого напряжения». То есть электрические напряжения, используемые в роботах или Маяках, не должны превышать 48v. Напряжения выше 48v могут быть использованы только внутри закрытых устройств, произведенных промышленным способом (таких, как лазеры, подсветка LCD панели), если эти устройства не были модифицированы, и если они соответствуют национальным нормативным требованиям. |
||||
* Как правило, любой механизм или система, признанная судьями как потенциально опасная, будет запрещена к применению и должна быть удалена из робота до соревнований, иначе команда будет дисквалифицирована с соревнований. |
||||
|
||||
## Приложение |
||||
### Выставочный зал |
||||
**Размеры:** |
||||
* Высота: 70 мм |
||||
* Ширина: 150 мм |
||||
* Длина: 400 мм |
||||
|
||||
<Image |
||||
alt={`Рисунок 3 - Выставочный зал`} |
||||
src={`/images/vistZal.jpg`} |
||||
width={612} |
||||
height={412} |
||||
priority |
||||
/> |
||||
|
||||
<Image |
||||
alt={`Рисунок 3 - Выставочный зал`} |
||||
src={`/images/vistzal2.jpg`} |
||||
width={612} |
||||
height={412} |
||||
priority |
||||
/> |
||||
### Пьедестал: |
||||
**Размеры:** |
||||
* Высота: 90 мм |
||||
* Ширина: 150 мм |
||||
* Длина: 400 мм |
||||
|
||||
<Image |
||||
alt={`Рисунок 3 - Пьедестал`} |
||||
src={`/images/pedistal.jpg`} |
||||
width={612} |
||||
height={412} |
||||
priority |
||||
/> |
||||
|
||||
<Image |
||||
alt={`Рисунок 3 - Пьедестал`} |
||||
src={`/images/pedistal2.jpg`} |
||||
width={612} |
||||
height={412} |
||||
priority |
||||
/> |
||||
На главную [Главная](/) |
@ -0,0 +1,43 @@ |
||||
--- |
||||
title: Робототехника |
||||
description: Задачи, материал по теме |
||||
date: '2022-09-01' |
||||
image: '/images/robottop.png' |
||||
--- |
||||
|
||||
<Image |
||||
alt={`Регламент проведения соревнования. РоботТОП Junior 2023`} |
||||
src={`/images/robottop.png`} |
||||
width={1440} |
||||
height={460} |
||||
priority |
||||
/> |
||||
|
||||
<p>Участникам необходимо подготовить робота, способного наиболее эффективно поменять местами оригинал статуэтки на ее реплику. Состязание проходит на автономных моделях роботов.</p> |
||||
|
||||
## I. Участники: |
||||
* <p>Команда состоит из 2 - 3 учащихся с 1 по 11 класс</p> |
||||
* <p>Каждая команда на соревнованиях должна привезти с собой одного **уникального робота, витрину, статуэтку.**</p> |
||||
* <p>Возрастные группы участников разделяются по классам (команда первоклассников, 2-х, 3-х, 4-х и т.д.) (Класс ученика подтверждается документом). Если в команде присутствуют участники из разных классов, то определяется по самому старшему ученику.</p> |
||||
* <p>Отдельный человек может быть участником лишь одной команды, даже если обе команды принадлежат к одной организации, при этом, обмен опытом всячески приветствуется. На руководителя проекта (учитель, один из родителей, лидер группы, и т. п.) возрастные ограничения не распространяются, но робот должен быть полностью разработан и построен членами команды.</p> |
||||
|
||||
## II. Задачи для робота: |
||||
## 1. Сохранение и экспонирование статуэтки. |
||||
### Действия: |
||||
* За время подготовки команда должна поставить свою статуэтку на пьедестал. |
||||
* Во время подготовки команда должна предварительно поместить реплику в своего робота. |
||||
* Во время заеда робот должнен забрать статуэтку с пьедестала. |
||||
* После того как статуэтка будет взята, роботы должны поместить ее на витрину. |
||||
* Робот должн поставить реплику на пьедестал вместо статуэтки. |
||||
### Ограничения: |
||||
* Реплику и статуэтку нельзя складывать в стопку. |
||||
* Реплика считается стоящей на пьедестале только в том случае, если она находится на постаменте в конце матча. |
||||
* Реплика представляет собой куб со стороной 60 мм. |
||||
* Статуэтка считается стоящей в витрине, если весь ее объем входит в габариты витрины. |
||||
* Статуэтка не может самостоятельно перемещаться ни внутри витрины, ни на игровой площадке. |
||||
* Статуэтка, построенная командой, имеет следующие ограничения по размерам: |
||||
+ Она должна помещаться в кубе со стороной 120 мм. |
||||
+ Она должна быть больше, чем куб со стороной 60 мм для категории LEGO WEDO 30 мм. |
||||
+ Вес статуэтки не должен превышать 600г. |
||||
|
||||
На главную [Главная](/) |
@ -0,0 +1,95 @@ |
||||
import { format, parseISO } from 'date-fns'; |
||||
import fs from 'fs'; |
||||
import matter from 'gray-matter'; |
||||
import { GetStaticPaths, GetStaticProps } from 'next'; |
||||
import { serialize } from 'next-mdx-remote/serialize'; |
||||
import { MDXRemote, MDXRemoteSerializeResult } from 'next-mdx-remote'; |
||||
import Head from 'next/head'; |
||||
import Image from 'next/image'; |
||||
import Link from 'next/link'; |
||||
import path from 'path'; |
||||
import React from 'react'; |
||||
import rehypeAutolinkHeadings from 'rehype-autolink-headings'; |
||||
import rehypeSlug from 'rehype-slug'; |
||||
import Layout, { WEBSITE_HOST_URL } from '../../components/Layout'; |
||||
import { MetaProps } from '../../types/layout'; |
||||
import { PostType } from '../../types/post'; |
||||
import { postFilePaths, POSTS_PATH } from '../../utils/mdxUtils'; |
||||
|
||||
// Custom components/renderers to pass to MDX.
|
||||
// Since the MDX files aren't loaded by webpack, they have no knowledge of how
|
||||
// to handle import statements. Instead, you must include components in scope
|
||||
// here.
|
||||
const components = { |
||||
Head, |
||||
Image, |
||||
Link, |
||||
}; |
||||
|
||||
type PostPageProps = { |
||||
source: MDXRemoteSerializeResult; |
||||
frontMatter: PostType; |
||||
}; |
||||
|
||||
const PostPage = ({ source, frontMatter }: PostPageProps): JSX.Element => { |
||||
const customMeta: MetaProps = { |
||||
title: `${frontMatter.title} - RoboTop`, |
||||
description: frontMatter.description, |
||||
image: `${WEBSITE_HOST_URL}${frontMatter.image}`, |
||||
date: frontMatter.date, |
||||
type: 'article', |
||||
}; |
||||
return ( |
||||
<Layout customMeta={customMeta}> |
||||
<article className="max-w"> |
||||
<h1 className="mb-3 text-gray-900 dark:text-white"> |
||||
{frontMatter.title} |
||||
</h1> |
||||
<p className="mb-10 text-sm text-gray-500 dark:text-gray-400"> |
||||
{format(parseISO(frontMatter.date), 'MMMM dd, yyyy')} |
||||
</p> |
||||
<div className="prose dark:prose-dark"> |
||||
<MDXRemote {...source} components={components} /> |
||||
</div> |
||||
</article> |
||||
</Layout> |
||||
); |
||||
}; |
||||
|
||||
export const getStaticProps: GetStaticProps = async ({ params }) => { |
||||
const postFilePath = path.join(POSTS_PATH, `${params.slug}.mdx`); |
||||
const source = fs.readFileSync(postFilePath); |
||||
|
||||
const { content, data } = matter(source); |
||||
|
||||
const mdxSource = await serialize(content, { |
||||
// Optionally pass remark/rehype plugins
|
||||
mdxOptions: { |
||||
remarkPlugins: [require('remark-code-titles')], |
||||
rehypePlugins: [rehypeSlug, rehypeAutolinkHeadings], |
||||
}, |
||||
scope: data, |
||||
}); |
||||
|
||||
return { |
||||
props: { |
||||
source: mdxSource, |
||||
frontMatter: data, |
||||
}, |
||||
}; |
||||
}; |
||||
|
||||
export const getStaticPaths: GetStaticPaths = async () => { |
||||
const paths = postFilePaths |
||||
// Remove file extensions for page paths
|
||||
.map((path) => path.replace(/\.mdx?$/, '')) |
||||
// Map the path into the static paths object required by Next.js
|
||||
.map((slug) => ({ params: { slug } })); |
||||
|
||||
return { |
||||
paths, |
||||
fallback: false, |
||||
}; |
||||
}; |
||||
|
||||
export default PostPage; |
@ -0,0 +1,26 @@ |
||||
html, |
||||
body { |
||||
padding: 0; |
||||
margin: 0; |
||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, |
||||
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; |
||||
} |
||||
|
||||
a { |
||||
color: inherit; |
||||
text-decoration: none; |
||||
} |
||||
|
||||
* { |
||||
box-sizing: border-box; |
||||
} |
||||
|
||||
@media (prefers-color-scheme: dark) { |
||||
html { |
||||
color-scheme: dark; |
||||
} |
||||
body { |
||||
color: white; |
||||
background: black; |
||||
} |
||||
} |
@ -0,0 +1,119 @@ |
||||
@tailwind base; |
||||
@tailwind components; |
||||
@tailwind utilities; |
||||
|
||||
@layer base { |
||||
h1 { |
||||
@apply mb-6 text-3xl font-semibold; |
||||
} |
||||
h2 { |
||||
@apply text-2xl font-semibold; |
||||
} |
||||
p { |
||||
@apply mb-4; |
||||
} |
||||
a { |
||||
@apply text-blue-500 hover:text-blue-400 dark:text-blue-400 dark:hover:text-blue-300; |
||||
} |
||||
} |
||||
|
||||
/* Post styles */ |
||||
.prose { |
||||
max-width: 100vh; |
||||
} |
||||
|
||||
.prose pre { |
||||
@apply bg-gray-50 border border-gray-200 dark:border-gray-700 dark:bg-gray-900; |
||||
} |
||||
|
||||
.prose code { |
||||
@apply text-gray-800 dark:text-gray-200 px-1 py-0.5 border border-gray-100 dark:border-gray-800 rounded-md bg-gray-100 dark:bg-gray-900; |
||||
} |
||||
|
||||
.prose img { |
||||
/* Don't apply styles to next/image */ |
||||
@apply m-0; |
||||
} |
||||
|
||||
/* Prism Styles */ |
||||
.token.comment, |
||||
.token.prolog, |
||||
.token.doctype, |
||||
.token.cdata { |
||||
@apply text-gray-700 dark:text-gray-300; |
||||
} |
||||
|
||||
.token.punctuation { |
||||
@apply text-gray-700 dark:text-gray-300; |
||||
} |
||||
|
||||
.token.property, |
||||
.token.tag, |
||||
.token.boolean, |
||||
.token.number, |
||||
.token.constant, |
||||
.token.symbol, |
||||
.token.deleted { |
||||
@apply text-green-500; |
||||
} |
||||
|
||||
.token.selector, |
||||
.token.attr-name, |
||||
.token.string, |
||||
.token.char, |
||||
.token.builtin, |
||||
.token.inserted { |
||||
@apply text-purple-500; |
||||
} |
||||
|
||||
.token.operator, |
||||
.token.entity, |
||||
.token.url, |
||||
.language-css .token.string, |
||||
.style .token.string { |
||||
@apply text-yellow-500; |
||||
} |
||||
|
||||
.token.atrule, |
||||
.token.attr-value, |
||||
.token.keyword { |
||||
@apply text-blue-500; |
||||
} |
||||
|
||||
.token.function, |
||||
.token.class-name { |
||||
@apply text-pink-500; |
||||
} |
||||
|
||||
.token.regex, |
||||
.token.important, |
||||
.token.variable { |
||||
@apply text-yellow-500; |
||||
} |
||||
|
||||
code[class*='language-'], |
||||
pre[class*='language-'] { |
||||
@apply text-gray-800 dark:text-gray-50; |
||||
} |
||||
|
||||
pre::-webkit-scrollbar { |
||||
display: none; |
||||
} |
||||
|
||||
pre { |
||||
-ms-overflow-style: none; /* IE and Edge */ |
||||
scrollbar-width: none; /* Firefox */ |
||||
} |
||||
|
||||
/* Remark Styles */ |
||||
.remark-code-title { |
||||
@apply text-gray-800 dark:text-gray-200 px-5 py-3 border border-b-0 border-gray-200 dark:border-gray-700 rounded-t bg-gray-200 dark:bg-gray-800 text-sm font-mono font-bold; |
||||
} |
||||
|
||||
.remark-code-title + pre { |
||||
@apply mt-0 rounded-t-none; |
||||
} |
||||
|
||||
.mdx-marker { |
||||
@apply block -mx-4 px-4 bg-gray-100 dark:bg-gray-800 border-l-4 border-blue-500; |
||||
} |
@ -0,0 +1,75 @@ |
||||
const { spacing } = require('tailwindcss/defaultTheme'); |
||||
|
||||
module.exports = { |
||||
mode: 'jit', |
||||
purge: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'], |
||||
darkMode: 'class', // or 'media' or 'class'
|
||||
theme: { |
||||
extend: { |
||||
typography: (theme) => ({ |
||||
DEFAULT: { |
||||
css: { |
||||
color: theme('colors.gray.700'), |
||||
a: { |
||||
color: theme('colors.blue.500'), |
||||
'&:hover': { |
||||
color: theme('colors.blue.700'), |
||||
}, |
||||
code: { color: theme('colors.blue.400') }, |
||||
}, |
||||
'h2,h3,h4': { |
||||
'scroll-margin-top': spacing[32], |
||||
}, |
||||
code: { color: theme('colors.pink.500') }, |
||||
'blockquote p:first-of-type::before': false, |
||||
'blockquote p:last-of-type::after': false, |
||||
}, |
||||
}, |
||||
dark: { |
||||
css: { |
||||
color: theme('colors.gray.300'), |
||||
a: { |
||||
color: theme('colors.blue.400'), |
||||
'&:hover': { |
||||
color: theme('colors.blue.600'), |
||||
}, |
||||
code: { color: theme('colors.blue.400') }, |
||||
}, |
||||
blockquote: { |
||||
borderLeftColor: theme('colors.gray.800'), |
||||
color: theme('colors.gray.300'), |
||||
}, |
||||
'h2,h3,h4': { |
||||
color: theme('colors.gray.100'), |
||||
'scroll-margin-top': spacing[32], |
||||
}, |
||||
hr: { borderColor: theme('colors.gray.800') }, |
||||
ol: { |
||||
li: { |
||||
'&:before': { color: theme('colors.gray.500') }, |
||||
}, |
||||
}, |
||||
ul: { |
||||
li: { |
||||
'&:before': { backgroundColor: theme('colors.gray.500') }, |
||||
}, |
||||
}, |
||||
strong: { color: theme('colors.gray.300') }, |
||||
thead: { |
||||
color: theme('colors.gray.100'), |
||||
}, |
||||
tbody: { |
||||
tr: { |
||||
borderBottomColor: theme('colors.gray.700'), |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
}), |
||||
}, |
||||
}, |
||||
variants: { |
||||
typography: ['dark'], |
||||
}, |
||||
plugins: [require('@tailwindcss/typography')], |
||||
}; |
@ -0,0 +1,9 @@ |
||||
import { PostType } from './post'; |
||||
|
||||
export interface MetaProps |
||||
extends Pick<PostType, 'date' | 'description' | 'image' | 'title'> { |
||||
/** |
||||
* For the meta tag `og:type` |
||||
*/ |
||||
type?: string; |
||||
} |
@ -0,0 +1,9 @@ |
||||
import { PostType } from './post'; |
||||
|
||||
export interface MetaProps |
||||
extends Pick<PostType, 'date' | 'description' | 'image' | 'title'> { |
||||
/** |
||||
* For the meta tag `og:type` |
||||
*/ |
||||
type?: string; |
||||
} |
@ -0,0 +1,7 @@ |
||||
export type PostType = { |
||||
date?: string; |
||||
description?: string; |
||||
image?: string; |
||||
slug: string; |
||||
title: string; |
||||
}; |
@ -0,0 +1,11 @@ |
||||
import fs from 'fs'; |
||||
import path from 'path'; |
||||
|
||||
// POSTS_PATH is useful when you want to get the path to a specific file
|
||||
export const POSTS_PATH = path.join(process.cwd(), 'posts'); |
||||
|
||||
// postFilePaths is the list of all mdx files inside the POSTS_PATH directory
|
||||
export const postFilePaths = fs |
||||
.readdirSync(POSTS_PATH) |
||||
// Only include md(x) files
|
||||
.filter((path) => /\.mdx?$/.test(path)); |
@ -0,0 +1,26 @@ |
||||
# RoboTop сайт робототехнического фестиваля |
||||
|
||||
Сайт для мероприятия с возможностью регистрировать пользователей в безе данный MySql. Построен на: |
||||
|
||||
- Сайт написан на [Typescript](https://www.typescriptlang.org/) |
||||
- Написание постов [MDX](https://mdxjs.com/) |
||||
- Стили и дизайн [Tailwind CSS](https://tailwindcss.com/) |
||||
- Статически анализ кода [ESLint](https://eslint.org/) |
||||
- Linting, проверка типов и форматирование включены по умолчанию. [`husky`](https://github.com/typicode/husky) |
||||
- Тестирование с [Jest](https://jestjs.io/) и [`react-testing-library`](https://testing-library.com/docs/react-testing-library/intro) |
||||
- [Redux Toolkit](https://redux-toolkit.js.org/) |
||||
- [Mysql2](https://www.npmjs.com/package/mysql2) |
||||
|
||||
## Для запуска сайта: |
||||
|
||||
```bash |
||||
git clone http://62.113.100.171:3000/Lab/robotop.krasnikov.pro.git |
||||
cd robotop.krasnikov.pro |
||||
|
||||
npm install |
||||
|
||||
npm run dev |
||||
|
||||
Ваш новый сайт будет доступен в http://localhost:3000/ |
||||
|
||||
Для настройки подключения к базе данных отредактируйте файл env.local и переименуйте его в .env.local |
@ -0,0 +1,45 @@ |
||||
import NextHead from 'next/head'; |
||||
import { useRouter } from 'next/router'; |
||||
import React from 'react'; |
||||
import { MetaProps } from '../types/layout'; |
||||
|
||||
export type WithYandexMetrikaProps = { |
||||
children: React.ReactNode; |
||||
} |
||||
|
||||
export const WEBSITE_HOST_URL = 'https://robotop.krasnikov.pro'; |
||||
|
||||
const Head = ({ customMeta }: { customMeta?: MetaProps }): JSX.Element => { |
||||
const router = useRouter(); |
||||
const meta: MetaProps = { |
||||
title: 'Информатика 7 класс', |
||||
description: |
||||
'Информатика 7 класс', |
||||
image: `${WEBSITE_HOST_URL}/images/site-preview.png`, |
||||
type: 'website', |
||||
...customMeta, |
||||
}; |
||||
|
||||
return ( |
||||
<NextHead> |
||||
<title>{meta.title}</title> |
||||
<meta content={meta.description} name="Информатика 7 класс" /> |
||||
<meta property="og:url" content={`${WEBSITE_HOST_URL}${router.asPath}`} /> |
||||
<link rel="canonical" href={`${WEBSITE_HOST_URL}${router.asPath}`} /> |
||||
<meta property="og:type" content={meta.type} /> |
||||
<meta property="og:site_name" content="Информатика 7 класс" /> |
||||
<meta property="og:description" content={meta.description} /> |
||||
<meta property="og:title" content={meta.title} /> |
||||
<meta property="og:image" content={meta.image} /> |
||||
<meta name="twitter:card" content="summary_large_image" /> |
||||
<meta name="twitter:title" content={meta.title} /> |
||||
<meta name="twitter:description" content={meta.description} /> |
||||
<meta name="twitter:image" content={meta.image} /> |
||||
{meta.date && ( |
||||
<meta property="article:published_time" content={meta.date} /> |
||||
)} |
||||
</NextHead> |
||||
); |
||||
}; |
||||
|
||||
export default Head; |
@ -0,0 +1,46 @@ |
||||
import React from 'react'; |
||||
import { MetaProps } from '../types/layout'; |
||||
import Head from './Head'; |
||||
import Navigation from './Navigation'; |
||||
import ThemeSwitch from './ThemeSwitch'; |
||||
|
||||
type LayoutProps = { |
||||
children: React.ReactNode; |
||||
customMeta?: MetaProps; |
||||
}; |
||||
|
||||
export const WEBSITE_HOST_URL = 'https://robotop.krasnikov.pro/'; |
||||
|
||||
const Layout = ({ children, customMeta }: LayoutProps): JSX.Element => { |
||||
return ( |
||||
<> |
||||
<Head customMeta={customMeta} /> |
||||
<header> |
||||
<div className="max-w-5xl px-8 mx-auto max-w"> |
||||
<div className="flex items-center justify-between py-6"> |
||||
<Navigation /> |
||||
<ThemeSwitch /> |
||||
</div> |
||||
</div> |
||||
</header> |
||||
<main> |
||||
<div className="max-w-5xl px-8 py-4 mx-auto max-w"> |
||||
{children} |
||||
</div> |
||||
</main> |
||||
<footer className="py-8"> |
||||
<div className="max-w-5xl px-8 mx-auto max-w"> |
||||
Разработано {' '} |
||||
<a |
||||
className="text-gray-900 dark:text-white" |
||||
href="https://krasnikov.pro" target='_blank' rel="noreferrer" |
||||
> |
||||
Krasnikov.pro - {(new Date()).getFullYear()} год |
||||
</a> |
||||
</div> |
||||
</footer> |
||||
</> |
||||
); |
||||
}; |
||||
|
||||
export default Layout; |
@ -0,0 +1,18 @@ |
||||
import Link from 'next/link' |
||||
|
||||
export interface Link { |
||||
title: string; |
||||
src: string; |
||||
} |
||||
|
||||
export function Links(props: Link) { |
||||
return ( |
||||
<Link passHref href={props.src}> |
||||
<a target="_blank"> |
||||
{props.title} |
||||
</a> |
||||
</Link> |
||||
); |
||||
} |
||||
|
||||
export default Links; |
@ -0,0 +1,53 @@ |
||||
import React from 'react'; |
||||
|
||||
type UserProps = { |
||||
team_name: string; |
||||
name_team_coach: string; |
||||
training_institution_team: string; |
||||
name_first_participant: string; |
||||
name_second_participant: string; |
||||
name_third_party: string; |
||||
classTeam: string[]; |
||||
}; |
||||
|
||||
|
||||
export const LoadingTeamsForm : React.FC<UserProps> = ({ |
||||
team_name, |
||||
name_team_coach, |
||||
training_institution_team, |
||||
name_first_participant, |
||||
name_second_participant, |
||||
name_third_party, |
||||
classTeam |
||||
}) => { |
||||
|
||||
const flatten = (arr) => { |
||||
const arrOfNum = []; |
||||
arr.split(',').forEach(str => { |
||||
arrOfNum.push(Number(str)); |
||||
}); |
||||
return Math.min.apply(null, arrOfNum.filter(Boolean)); //Math.min(...arrOfNum);
|
||||
} |
||||
|
||||
return ( |
||||
<tr className="bg-white border-b dark:bg-gray-800 dark:border-gray-700"> |
||||
<th scope="row" className="px-6 py-4 font-medium text-gray-900 dark:text-white whitespace-nowrap"> |
||||
{team_name} |
||||
</th> |
||||
<td className="px-6 py-4"> |
||||
{name_team_coach} |
||||
</td> |
||||
<td className="px-6 py-4"> |
||||
{training_institution_team} |
||||
</td> |
||||
<td className="px-6 py-4"> |
||||
{name_first_participant +', ' + name_second_participant + ', ' + name_third_party} |
||||
</td> |
||||
<td className="px-6 py-4"> |
||||
{ flatten(classTeam)} |
||||
</td> |
||||
</tr> |
||||
); |
||||
}; |
||||
|
||||
export default LoadingTeamsForm; |
@ -0,0 +1,91 @@ |
||||
import Link from 'next/link'; |
||||
import React, { useState } from 'react'; |
||||
import { MenuIcon, XIcon } from '@heroicons/react/outline' |
||||
import { Transition } from "@headlessui/react"; |
||||
import { useRouter } from 'next/router' |
||||
|
||||
const navigation = [ |
||||
{ name: 'Главная', href: '/', as: false } |
||||
] |
||||
|
||||
function classNames(...classes) { |
||||
return classes.filter(Boolean).join(' ') |
||||
} |
||||
|
||||
const Navigation = (): JSX.Element => { |
||||
const [isOpen, setIsOpen] = useState(false); |
||||
const router = useRouter(); |
||||
|
||||
return ( |
||||
<nav className=""> |
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> |
||||
<div className="flex items-center justify-between h-16"> |
||||
<div className="flex items-center"> |
||||
<div className="hidden md:block"> |
||||
<div className="ml-10 flex items-baseline space-x-4"> |
||||
{navigation.map((item) => ( |
||||
<Link as={ item.as ? '/posts/'+item.as : ''} href={item.href} key={item.name}> |
||||
<a |
||||
className={classNames('bg-gray-900 text-white text-gray-900 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium' |
||||
)} |
||||
aria-current={false} |
||||
> |
||||
{item.name} |
||||
</a> |
||||
</Link> |
||||
))} |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div className="-mr-2 flex md:hidden"> |
||||
<button |
||||
onClick={() => setIsOpen(!isOpen)} |
||||
type="button" |
||||
aria-controls="mobile-menu" |
||||
aria-expanded="false" |
||||
> |
||||
<span className="sr-only">Открыть главное меню</span> |
||||
{!isOpen ? ( |
||||
<MenuIcon className="block h-6 w-6" aria-hidden="false" /> |
||||
) : ( |
||||
<XIcon className="block h-6 w-6" aria-hidden="true" /> |
||||
)} |
||||
</button> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<Transition |
||||
show={isOpen} |
||||
enter="transition ease-out duration-100 transform" |
||||
enterFrom="opacity-0 scale-95" |
||||
enterTo="opacity-100 scale-100" |
||||
leave="transition ease-in duration-75 transform" |
||||
leaveFrom="opacity-100 scale-100" |
||||
leaveTo="opacity-0 scale-95" |
||||
className="absolute bg-gray-100 z-50" |
||||
> |
||||
{(ref) => ( |
||||
<div className="md:hidden" id="mobile-menu"> |
||||
<div ref={ref} className="px-2 pt-2 pb-3 space-y-1 sm:px-3"> |
||||
{navigation.map((item) => ( |
||||
<Link as={'/posts/'+item.as} href={item.href} key={item.name}> |
||||
<a |
||||
className={classNames('text-gray-900 hover:bg-gray-900 hover:text-white', |
||||
'block px-3 py-2 rounded-md text-base font-medium' |
||||
)} |
||||
aria-current={item.href ? 'page' : undefined} |
||||
> |
||||
{item.name} |
||||
</a> |
||||
</Link> |
||||
))} |
||||
</div> |
||||
</div> |
||||
)} |
||||
</Transition> |
||||
</nav> |
||||
); |
||||
}; |
||||
|
||||
export default Navigation; |
@ -0,0 +1,136 @@ |
||||
import React,{useRef} from 'react'; |
||||
import { useForm, SubmitHandler, FormProvider } from "react-hook-form"; |
||||
import { Select, Input, Link } from "./UX"; |
||||
|
||||
interface IFormInputs { |
||||
name_team_coach: string, |
||||
coach_telefon_number: string, |
||||
email_address: string, |
||||
city_team: string, |
||||
training_institution_team: string, |
||||
team_name: string, |
||||
name_first_participant: string, |
||||
first_partial_class: number, |
||||
name_second_participant: string, |
||||
second_class: number, |
||||
name_third_party: string, |
||||
third_part_class: number, |
||||
body?: string[] | number[] |
||||
} |
||||
|
||||
const defaultValues = { |
||||
name_team_coach: ``, |
||||
coach_telefon_number: ``, |
||||
email_address: '', |
||||
city_team: '', |
||||
training_institution_team: '', |
||||
team_name: '', |
||||
name_first_participant: '', |
||||
first_partial_class: 0, |
||||
name_second_participant: 'нет', |
||||
second_class: 0, |
||||
name_third_party: 'нет', |
||||
third_part_class: 0, |
||||
}; |
||||
|
||||
export const RegistrationForm = (props): JSX.Element => { |
||||
const form = useRef(null); |
||||
const methods = useForm({ defaultValues }); |
||||
|
||||
const onSubmit: SubmitHandler<IFormInputs> = data => { |
||||
fetch('/api/registration', { method: 'POST', body: Object.values(data) as any}) |
||||
.then((data) => { |
||||
props.updateData(data); |
||||
}) |
||||
methods.reset(defaultValues); |
||||
} |
||||
return ( |
||||
<> |
||||
<div className="mt-10 sm:mt-0"> |
||||
<div className="md:grid md:grid-cols-3 md:gap-6"> |
||||
<div className="md:col-span-1"> |
||||
<div className="px-4 sm:px-0"> |
||||
<h3 className="text-lg font-medium leading-6">Регистрация команды</h3> |
||||
<p className="mt-1 text-sm">Введите актуальные данные команды</p> |
||||
<p className="mt-1 text-sm">От каждого учебного заведения может быть зарегистрированно неограниченое количеставо команд</p> |
||||
<p className="mt-1 text-sm"> Подписывайтесь на наш |
||||
<Link href="https://t.me/robotop_competition"> Telegram канал</Link> |
||||
, что-бы быть в курсе новостей про соревнование </p> |
||||
</div> |
||||
</div> |
||||
<div className="mt-5 md:mt-0 md:col-span-2"> |
||||
<FormProvider {...methods} > |
||||
<form ref={form} onSubmit={methods.handleSubmit(onSubmit)}> |
||||
<div className="shadow overflow-hidden sm:rounded-md"> |
||||
<div className="px-4 py-5 bg-white sm:p-6"> |
||||
<div className="grid grid-cols-6 gap-6"> |
||||
|
||||
<div className="col-span-6 sm:col-span-3"> |
||||
<Input placeholder="Иванов Иван Иванович" name="name_team_coach" text="Введите ФИО тренера" additional={""}/> |
||||
</div> |
||||
|
||||
<div className="col-span-6 sm:col-span-3"> |
||||
<Input placeholder="+79181234567" name="coach_telefon_number" text="Номер телефона тренера" additional={"valueAsNumber: true"} /> |
||||
</div> |
||||
|
||||
<div className="col-span-6 sm:col-span-3"> |
||||
<Input placeholder="you@example.com" name="email_address" text="Email тренера" additional={`pattern: /^(([^<>()[]\\.,;:s@"]+(.[^<>()[]\\.,;:s@"]+)*)|(".+"))@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}])|(([a-zA-Z-0-9]+.)+[a-zA-Z]{2,}))$/ })`} /> |
||||
</div> |
||||
|
||||
<div className="col-span-6 sm:col-span-3"> |
||||
<Input placeholder="Краснодар" name="city_team" text="Город команда" additional={""} /> |
||||
</div> |
||||
|
||||
<div className="col-span-3"> |
||||
<Input placeholder="МАОУ СОШ 103" name="training_institution_team" text="Учебное заведение команды" additional={""} /> |
||||
</div> |
||||
|
||||
<div className="col-span-3"> |
||||
<Input placeholder="Фиксики" name="team_name" text="Название команды" additional={""} /> |
||||
</div> |
||||
|
||||
<div className="col-span-6 sm:col-span-3"> |
||||
<Input placeholder="Иванов Иван Иванович" name="name_first_participant" text="ФИО первого участника" additional={""} /> |
||||
</div> |
||||
|
||||
<div className="col-span-6 sm:col-span-3"> |
||||
<Select text={'Класс участника'} name={'first_partial_class'}/> |
||||
</div> |
||||
|
||||
<div className="col-span-6 sm:col-span-3"> |
||||
<Input placeholder="Иванов Петр Иванович / нет" name="name_second_participant" text="ФИО второго участника" additional={""} /> |
||||
</div> |
||||
|
||||
<div className="col-span-6 sm:col-span-3"> |
||||
<Select text={'Класс участника'} name={'second_class'}/> |
||||
</div> |
||||
|
||||
<div className="col-span-6 sm:col-span-3"> |
||||
<Input placeholder="Иванов Дмитрий Иванович / нет" name="name_third_party" text="ФИО третьего участника" additional={""}/> |
||||
</div> |
||||
|
||||
<div className="col-span-6 sm:col-span-3"> |
||||
<Select text={'Класс участника'} name={'third_part_class'}/> |
||||
</div> |
||||
|
||||
</div> |
||||
</div> |
||||
<div className="px-4 py-3 bg-gray-50 text-right sm:px-6"> |
||||
<button |
||||
type="submit" |
||||
className="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" |
||||
> |
||||
Зарегистрировать команду |
||||
</button> |
||||
</div> |
||||
</div> |
||||
</form> |
||||
</FormProvider> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</> |
||||
); |
||||
}; |
||||
|
||||
export default RegistrationForm; |
@ -0,0 +1,102 @@ |
||||
import { useTheme } from 'next-themes'; |
||||
import React from 'react'; |
||||
|
||||
|
||||
const ThemeSwitch = (): JSX.Element => { |
||||
const [mounted, setMounted] = React.useState(false); |
||||
const { theme, setTheme } = useTheme(); |
||||
|
||||
// After mounting, we have access to the theme
|
||||
React.useEffect(() => setMounted(true), []); |
||||
|
||||
if (!mounted) { |
||||
return null; |
||||
} |
||||
|
||||
const isDark = theme === 'dark'; |
||||
const color = isDark ? '#fff' : '#000'; |
||||
const maskColor = isDark ? '#000' : '#fff'; |
||||
return ( |
||||
<button |
||||
className="theme-button" |
||||
type="button" |
||||
aria-label="Toggle Dark Mode" |
||||
onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')} |
||||
> |
||||
<div className="moon-or-sun" /> |
||||
<div className="moon-mask" /> |
||||
<style jsx>{` |
||||
.theme-button { |
||||
opacity: 0.5; |
||||
position: relative; |
||||
border-radius: 5px; |
||||
width: 42px; |
||||
height: 42px; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: center; |
||||
transition: opacity 0.3s ease; |
||||
} |
||||
.theme-button:hover { |
||||
opacity: 1; |
||||
} |
||||
.moon-or-sun { |
||||
position: relative; |
||||
width: 20px; |
||||
height: 20px; |
||||
border-radius: 50%; |
||||
border: ${isDark ? '4px' : '2px'} solid; |
||||
border-color: ${color}; |
||||
background: ${color}; |
||||
transform: scale(${isDark ? 0.5 : 1}); |
||||
transition: all 0.45s ease; |
||||
overflow: ${isDark ? 'visible' : 'hidden'}; |
||||
} |
||||
.moon-or-sun::before { |
||||
content: ''; |
||||
position: absolute; |
||||
right: -9px; |
||||
top: -9px; |
||||
height: 20px; |
||||
width: 20px; |
||||
border: 2px solid; |
||||
border-color: ${color}; |
||||
border-radius: 50%; |
||||
transform: translate(${isDark ? '14px, -14px' : '0, 0'}); |
||||
opacity: ${isDark ? 0 : 1}; |
||||
transition: transform 0.45s ease; |
||||
} |
||||
.moon-or-sun::after { |
||||
content: ''; |
||||
width: 8px; |
||||
height: 8px; |
||||
border-radius: 50%; |
||||
margin: -4px 0 0 -4px; |
||||
position: absolute; |
||||
top: 50%; |
||||
left: 50%; |
||||
box-shadow: 0 -23px 0 ${color}, 0 23px 0 ${color}, 23px 0 0 ${color}, |
||||
-23px 0 0 ${color}, 15px 15px 0 ${color}, -15px 15px 0 ${color}, |
||||
15px -15px 0 ${color}, -15px -15px 0 ${color}; |
||||
transform: scale(${isDark ? 1 : 0}); |
||||
transition: all 0.35s ease; |
||||
} |
||||
.moon-mask { |
||||
position: absolute; |
||||
right: 4px; |
||||
top: 4px; |
||||
height: 20px; |
||||
width: 20px; |
||||
border-radius: 50%; |
||||
border: 0; |
||||
background: ${maskColor}; |
||||
transform: translate(${isDark ? '4px, -4px' : '0, 0'}); |
||||
opacity: ${isDark ? 0 : 1}; |
||||
transition: transform 0.45s ease; |
||||
} |
||||
`}</style>
|
||||
</button> |
||||
); |
||||
}; |
||||
|
||||
export default ThemeSwitch; |
@ -0,0 +1,7 @@ |
||||
import React from 'react'; |
||||
|
||||
export const Alert = (text) => { |
||||
return( |
||||
<p className="mt-2 text-sm text-red-600 dark:text-red-500 font-medium">{text}</p> |
||||
) |
||||
} |
@ -0,0 +1,27 @@ |
||||
import React from 'react'; |
||||
import { useFormContext } from "react-hook-form"; |
||||
|
||||
type Props = { |
||||
text: string; |
||||
name: string; |
||||
placeholder: string; |
||||
additional: string; |
||||
} |
||||
|
||||
export const Input: React.FC<Props> = ({text, name, placeholder, additional}) => { |
||||
const { register } = useFormContext(); |
||||
const options = {required: true, maxLength: 80, additional}; |
||||
return( |
||||
<> |
||||
<label htmlFor={name} className="block text-sm font-medium text-gray-700"> |
||||
{text} |
||||
</label> |
||||
<input |
||||
{...register(name, options )} |
||||
name={name} |
||||
placeholder={placeholder} |
||||
className="mt-1 block w-full py-2 px-3 border border-gray-300 bg-white rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" |
||||
/> |
||||
</> |
||||
) |
||||
} |
@ -0,0 +1,14 @@ |
||||
import React from 'react'; |
||||
|
||||
type Props = { |
||||
children: string; |
||||
href: string; |
||||
} |
||||
|
||||
export const Link: React.FC<Props> = ({children, href}) => { |
||||
return( |
||||
<> |
||||
<a href={href} target='_blank' rel="noreferrer" className="dark:text-white">{children}</a> |
||||
</> |
||||
) |
||||
} |
@ -0,0 +1,40 @@ |
||||
import React from 'react'; |
||||
//import { useFormContext } from "react-hook-form";
|
||||
import { useFormContext } from "react-hook-form"; |
||||
|
||||
type Props = { |
||||
text: string; |
||||
name: string; |
||||
children?: JSX.Element[] | JSX.Element; |
||||
} |
||||
|
||||
|
||||
export const Select: React.FC<Props> = ({text, name}) => { |
||||
const { register } = useFormContext(); |
||||
return( |
||||
<> |
||||
<label htmlFor="country" className="block text-sm font-medium text-gray-700"> |
||||
{text} |
||||
</label> |
||||
<select |
||||
{...register(name)} // ...register("first_partial_class")
|
||||
name={name} |
||||
defaultValue={0} |
||||
className="mt-1 block w-full py-2 px-3 border border-gray-300 bg-white rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" |
||||
> |
||||
<option value={0}>-- Выбрать --</option> |
||||
<option >1</option> |
||||
<option >2</option> |
||||
<option >3</option> |
||||
<option >4</option> |
||||
<option >5</option> |
||||
<option >6</option> |
||||
<option >7</option> |
||||
<option >8</option> |
||||
<option >9</option> |
||||
<option >10</option> |
||||
<option >11</option> |
||||
</select> |
||||
</> |
||||
) |
||||
} |
@ -0,0 +1,4 @@ |
||||
export * from './Select' |
||||
export * from './Alert' |
||||
export * from './Input' |
||||
export * from './Link' |
@ -0,0 +1,14 @@ |
||||
export interface VideoProps { |
||||
title: string; |
||||
src: string; |
||||
} |
||||
|
||||
export function Video(props: VideoProps) { |
||||
return ( |
||||
<video controls style={{ width: '960px' }}> |
||||
<source src={props.src} /> |
||||
</video> |
||||
); |
||||
} |
||||
|
||||
export default Video; |
@ -0,0 +1,6 @@ |
||||
// .env.local |
||||
|
||||
USER_="Имя пользователя базы данных" |
||||
HOST="IP адрес базы данных" |
||||
DATABASE="Имя базы данных" |
||||
PASSWORD="Пароль доступа к базе данных" |
@ -0,0 +1,17 @@ |
||||
module.exports = { |
||||
roots: ['<rootDir>'], |
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'json', 'jsx'], |
||||
testPathIgnorePatterns: ['<rootDir>[/\\\\](node_modules|.next)[/\\\\]'], |
||||
transformIgnorePatterns: ['[/\\\\]node_modules[/\\\\].+\\.(ts|tsx)$'], |
||||
transform: { |
||||
'^.+\\.(ts|tsx)$': 'babel-jest', |
||||
}, |
||||
watchPlugins: [ |
||||
'jest-watch-typeahead/filename', |
||||
'jest-watch-typeahead/testname', |
||||
], |
||||
moduleNameMapper: { |
||||
'\\.(css|less|sass|scss)$': 'identity-obj-proxy', |
||||
'\\.(gif|ttf|eot|svg|png)$': '<rootDir>/test/__mocks__/fileMock.js', |
||||
}, |
||||
}; |
@ -0,0 +1,45 @@ |
||||
import fs from 'fs'; |
||||
import matter from 'gray-matter'; |
||||
import { join } from 'path'; |
||||
import { POSTS_PATH } from '../utils/mdxUtils'; |
||||
|
||||
export function getPostSlugs(): string[] { |
||||
return fs.readdirSync(POSTS_PATH); |
||||
} |
||||
|
||||
type PostItems = { |
||||
[key: string]: string; |
||||
}; |
||||
|
||||
export function getPostBySlug(slug: string, fields: string[] = []): PostItems { |
||||
const realSlug = slug.replace(/\.mdx$/, ''); |
||||
const fullPath = join(POSTS_PATH, `${realSlug}.mdx`); |
||||
const fileContents = fs.readFileSync(fullPath, 'utf8'); |
||||
const { data, content } = matter(fileContents); |
||||
|
||||
const items: PostItems = {}; |
||||
|
||||
// Ensure only the minimal needed data is exposed
|
||||
fields.forEach((field) => { |
||||
if (field === 'slug') { |
||||
items[field] = realSlug; |
||||
} |
||||
if (field === 'content') { |
||||
items[field] = content; |
||||
} |
||||
if (data[field]) { |
||||
items[field] = data[field]; |
||||
} |
||||
}); |
||||
|
||||
return items; |
||||
} |
||||
|
||||
export function getAllPosts(fields: string[] = []): PostItems[] { |
||||
const slugs = getPostSlugs(); |
||||
const posts = slugs |
||||
.map((slug) => getPostBySlug(slug, fields)) |
||||
// sort posts by date in descending order
|
||||
.sort((post1, post2) => (post1.date > post2.date ? -1 : 1)); |
||||
return posts; |
||||
} |
@ -0,0 +1,63 @@ |
||||
-- phpMyAdmin SQL Dump |
||||
-- version 4.9.7 |
||||
-- https://www.phpmyadmin.net/ |
||||
|
||||
-- -------------------------------------------------------- |
||||
|
||||
-- |
||||
-- Table structure for table `members` |
||||
-- |
||||
-- Creation: Jun 14, 2022 at 04:25 AM |
||||
-- Last update: Jul 15, 2022 at 10:08 PM |
||||
-- |
||||
|
||||
DROP TABLE IF EXISTS `members`; |
||||
CREATE TABLE `members` ( |
||||
`id` int(5) NOT NULL, |
||||
`name_team_coach` varchar(100) NOT NULL, |
||||
`coach_telefon_number` varchar(100) NOT NULL, |
||||
`trainer_mail` varchar(100) NOT NULL, |
||||
`city_team` varchar(100) NOT NULL, |
||||
`training_institution_team` varchar(100) NOT NULL, |
||||
`team_name` varchar(100) NOT NULL, |
||||
`name_first_participant` varchar(100) NOT NULL, |
||||
`first_partial_class` int(2) NOT NULL, |
||||
`name_second_participant` varchar(100) NOT NULL, |
||||
`second_class` int(2) NOT NULL, |
||||
`name_third_party` varchar(100) NOT NULL, |
||||
`third_part_class` int(2) NOT NULL, |
||||
`reg_time_add` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, |
||||
`status` int(1) NOT NULL DEFAULT '1' |
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8; |
||||
|
||||
-- |
||||
-- Dumping data for table `members` |
||||
-- |
||||
|
||||
INSERT INTO `members` (`id`, `name_team_coach`, `coach_telefon_number`, `trainer_mail`, `city_team`, `training_institution_team`, `team_name`, `name_first_participant`, `first_partial_class`, `name_second_participant`, `second_class`, `name_third_party`, `third_part_class`, `reg_time_add`, `status`) VALUES |
||||
(36, 'Красников Павел Геннадьевич', '79189458044', 'crapsh@gmail.com', 'Краснодар', 'МАОУ СОШ 103', 'Фиксики', 'Иван Филлипов', 8, 'Владислав Дельнов', 8, 'нет', 0, '2022-07-02 18:34:33', 1); |
||||
|
||||
-- |
||||
-- Indexes for dumped tables |
||||
-- |
||||
|
||||
-- |
||||
-- Indexes for table `members` |
||||
-- |
||||
ALTER TABLE `members` |
||||
ADD PRIMARY KEY (`id`); |
||||
|
||||
-- |
||||
-- AUTO_INCREMENT for dumped tables |
||||
-- |
||||
|
||||
-- |
||||
-- AUTO_INCREMENT for table `members` |
||||
-- |
||||
ALTER TABLE `members` |
||||
MODIFY `id` int(5) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=98; |
||||
COMMIT; |
||||
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; |
||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; |
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; |
@ -0,0 +1,17 @@ |
||||
import nextMDX from '@next/mdx' |
||||
import remarkGfm from 'remark-gfm' |
||||
import remarkParse from 'remark-parse' |
||||
import remarkRehype from 'remark-rehype' |
||||
import rehypeStringify from 'rehype-stringify' |
||||
|
||||
const withMDX = nextMDX({ |
||||
extension: /\.mdx?$/, |
||||
options: { |
||||
remarkPlugins: [remarkGfm, remarkParse, remarkRehype], |
||||
rehypePlugins: [rehypeStringify], |
||||
}, |
||||
}) |
||||
|
||||
export default withMDX({ |
||||
pageExtensions: ['js', 'jsx', 'ts', 'tsx', 'md', 'mdx'], |
||||
}) |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,79 @@ |
||||
{ |
||||
"name": "nextjs-typescript-mdx-blog", |
||||
"version": "1.0.0", |
||||
"scripts": { |
||||
"dev": "next dev", |
||||
"build": "next build", |
||||
"start": "next start -p 3005", |
||||
"type-check": "tsc --pretty --noEmit", |
||||
"format": "prettier --write .", |
||||
"lint": "eslint . --ext ts --ext tsx --ext js", |
||||
"test": "jest", |
||||
"test-all": "yarn lint && yarn type-check && yarn test" |
||||
}, |
||||
"husky": { |
||||
"hooks": { |
||||
"pre-commit": "lint-staged", |
||||
"pre-push": "yarn run type-check" |
||||
} |
||||
}, |
||||
"lint-staged": { |
||||
"*.@(ts|tsx)": [ |
||||
"yarn lint", |
||||
"yarn format" |
||||
] |
||||
}, |
||||
"dependencies": { |
||||
"@headlessui/react": "^1.6.5", |
||||
"@heroicons/react": "^1.0.6", |
||||
"@mux/mux-player": "^1.6.0", |
||||
"@mux/mux-player-react": "^1.6.0", |
||||
"@next/mdx": "^12.2.0", |
||||
"@reduxjs/toolkit": "^1.8.3", |
||||
"@tailwindcss/typography": "^0.5.2", |
||||
"@types/node-fetch": "^2.6.2", |
||||
"axios": "^0.27.2", |
||||
"date-fns": "^2.28.0", |
||||
"gray-matter": "^4.0.3", |
||||
"mysql2": "^2.3.3", |
||||
"next": "^12.2.0", |
||||
"next-mdx-remote": "^4.0.3", |
||||
"next-themes": "^0.2.0", |
||||
"next-videos": "^1.4.1", |
||||
"react": "^18.2.0", |
||||
"react-confirm-alert": "^3.0.2", |
||||
"react-dom": "^18.2.0", |
||||
"react-hook-form": "^7.33.1", |
||||
"react-redux": "^8.0.2", |
||||
"react-toastify": "^9.0.5", |
||||
"react-yandex-metrika": "^2.6.0", |
||||
"rehype-autolink-headings": "^6.1.1", |
||||
"rehype-slug": "^5.0.1", |
||||
"remark-code-titles": "^0.1.2", |
||||
"remark-gfm": "^3.0.1" |
||||
}, |
||||
"devDependencies": { |
||||
"@testing-library/react": "^13.3.0", |
||||
"@types/gtag.js": "^0.0.10", |
||||
"@types/jest": "^28.1.4", |
||||
"@types/node": "^18.0.0", |
||||
"@types/react": "^18.0.14", |
||||
"@typescript-eslint/eslint-plugin": "^5.30.3", |
||||
"autoprefixer": "^10.4.7", |
||||
"babel-jest": "^28.1.2", |
||||
"eslint": "^8.19.0", |
||||
"eslint-config-next": "^12.2.0", |
||||
"eslint-config-prettier": "^8.5.0", |
||||
"eslint-plugin-react": "^7.30.1", |
||||
"husky": "^8.0.1", |
||||
"identity-obj-proxy": "^3.0.0", |
||||
"jest": "^28.1.2", |
||||
"jest-watch-typeahead": "^1.1.0", |
||||
"lint-staged": "^13.0.3", |
||||
"postcss": "^8.4.14", |
||||
"prettier": "^2.7.1", |
||||
"rehype": "^12.0.1", |
||||
"tailwindcss": "^3.1.4", |
||||
"typescript": "^4.7.4" |
||||
} |
||||
} |
@ -0,0 +1,18 @@ |
||||
import { ThemeProvider } from 'next-themes'; |
||||
import type { AppProps } from 'next/app'; |
||||
import React from 'react'; |
||||
import { Provider } from 'react-redux'; |
||||
import '../styles/globals.css'; |
||||
import { store } from '../redux/store'; |
||||
|
||||
const MyApp = ({ Component, pageProps }: AppProps): JSX.Element => { |
||||
return ( |
||||
<ThemeProvider attribute="class" enableSystem={false} defaultTheme="light"> |
||||
<Provider store={store}> |
||||
<Component {...pageProps} /> |
||||
</Provider> |
||||
</ThemeProvider> |
||||
); |
||||
}; |
||||
|
||||
export default MyApp; |
@ -0,0 +1,30 @@ |
||||
import Document, { Head, Html, Main, NextScript } from 'next/document'; |
||||
class MyDocument extends Document { |
||||
render(): JSX.Element { |
||||
return ( |
||||
<Html lang="ru"> |
||||
<Head /> |
||||
<body className="bg-white dark:bg-black text-gray-900 dark:text-white"> |
||||
<script type="text/javascript" |
||||
dangerouslySetInnerHTML={{ |
||||
__html: ` |
||||
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)}; |
||||
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)}) |
||||
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym"); |
||||
ym(89626868, "init", { |
||||
clickmap:true, |
||||
trackLinks:true, |
||||
accurateTrackBounce:true |
||||
}); |
||||
`,
|
||||
}} |
||||
/> |
||||
<Main /> |
||||
<NextScript /> |
||||
</body> |
||||
</Html> |
||||
); |
||||
} |
||||
} |
||||
|
||||
export default MyDocument; |
@ -0,0 +1,20 @@ |
||||
import React from 'react'; |
||||
import Layout from '../components/Layout'; |
||||
|
||||
export const About = (): JSX.Element => { |
||||
return ( |
||||
<Layout |
||||
customMeta={{ |
||||
title: 'О нас', |
||||
}} |
||||
> |
||||
<h2>RobotTop</h2> |
||||
<p>Организатор соревнований лаборатория робототехники Krasnikov Robotics</p> |
||||
<p>Занимаемся робототехникой с 2006 года</p> |
||||
<p>Наши ученики участники так соревнований как EUROBOT, Робофест, FLL, РТК</p> |
||||
<p>В 2022 году проводим первый Краевой робототехнический фестиваль на базе МАОУ СОШ № 103 </p> |
||||
</Layout> |
||||
); |
||||
}; |
||||
|
||||
export default About; |
@ -0,0 +1,23 @@ |
||||
import React from 'react'; |
||||
import Layout from '../components/Layout'; |
||||
import { Link } from '../components/UX'; |
||||
|
||||
export const About = (): JSX.Element => { |
||||
return ( |
||||
<Layout |
||||
customMeta={{ |
||||
title: 'Контакты', |
||||
}} |
||||
> |
||||
<h1>РоботТоп</h1> |
||||
<p><b>Организатор соревнований</b> <Link href="https://school103.centerstart.ru/sveden/common" >МАОУ СОШ 103 г. Краснодар</Link> </p> |
||||
<p><b>Главный судья соревнований</b><Link href="https://krasnikov.pro"> Красников Павел Геннадьевич </Link> - |
||||
<Link href="tel:+7-918-945-80-44"> 8-918-945-80-44 </Link> -
|
||||
<Link href="https://t.me/krasnikovPavel"> Telegram</Link> |
||||
</p> |
||||
<p><b>Вопросы по соревнованиям можно задавать в </b><Link href="https://t.me/robotop_competition"> Telegram группе </Link></p> |
||||
</Layout> |
||||
); |
||||
}; |
||||
|
||||
export default About; |
@ -0,0 +1,52 @@ |
||||
import { format, parseISO } from 'date-fns'; |
||||
import { GetStaticProps } from 'next'; |
||||
import Link from 'next/link'; |
||||
import React from 'react'; |
||||
import Layout from '../components/Layout'; |
||||
import { getAllPosts } from '../lib/api'; |
||||
import { PostType } from '../types/post'; |
||||
|
||||
type IndexProps = { |
||||
posts: PostType[]; |
||||
}; |
||||
|
||||
export const Index = ({ posts }: IndexProps): JSX.Element => { |
||||
return ( |
||||
<Layout> |
||||
<h1>Информатика 7 класс</h1> |
||||
{posts.map((post) => ( |
||||
<article key={post.slug} className="mt-12"> |
||||
<p className="mb-1 text-sm text-gray-500 dark:text-gray-400"> |
||||
{format(parseISO(post.date), 'MMMM dd, yyyy')} |
||||
</p> |
||||
<h1 className="mb-2 text-xl"> |
||||
<Link as={`/posts/${post.slug}`} href={`/posts/[slug]`}> |
||||
<a className="text-gray-900 dark:text-white dark:hover:text-blue-400"> |
||||
{post.title} |
||||
</a> |
||||
</Link> |
||||
</h1> |
||||
<p className="mb-3">{post.description}</p> |
||||
<p> |
||||
<Link as={`/posts/${post.slug}`} href={`/posts/[slug]`}> |
||||
<a>Подробнее...</a> |
||||
</Link> |
||||
</p> |
||||
</article> |
||||
))} |
||||
<div> |
||||
</div> |
||||
|
||||
</Layout> |
||||
); |
||||
}; |
||||
|
||||
export const getStaticProps: GetStaticProps = async () => { |
||||
const posts = getAllPosts(['date', 'description', 'slug', 'title']); |
||||
|
||||
return { |
||||
props: { posts }, |
||||
}; |
||||
}; |
||||
|
||||
export default Index; |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue