به افتخار اول آوریل، Reddit صفحه ای را برای کاربران باز کرد تا نظرات خود را بیان کنند، اما این پروژه که به عنوان یک شوخی ایجاد شد، به نوعی دیوار برای گرافیتی جمعی از شرکت کنندگان از سراسر جهان تبدیل شد و نشان می داد که آنها می خواهند چه ردپایی در تاریخ بگذارند. .

در ۱ آوریل، Reddit پروژه Place را راه‌اندازی کرد، صفحه‌ای با بوم خالی که هر کاربر انجمن می‌توانست هر تصویری را روی آن بکشد. هنرمندان محدودیت‌هایی داشتند: آنها فقط می‌توانستند هر پنج دقیقه یک پیکسل از یکی از ۱۶ رنگ را بکشند و اندازه‌های بوم نیز محدود بود. پیکسل های دیگر را می توان روی پیکسل های ترسیم شده ترسیم کرد (و سپس نویسنده اول می تواند دوباره پیکسل خود را روی پیکسل حریف بکشد)، به همین دلیل است که نویسندگان تصاویر به طور پیشینی درگیر می شوند. همانطور که در توضیحات بوم گفته شد، پروژه به این صورت طراحی شده است خلاقیت مشترک- "هر یک از شما می توانید چیزی منحصر به فرد ایجاد کنید. با هم می توانید چیزی بزرگتر خلق کنید."

در لحظه شروع پروژه، همه به معنای واقعی کلمه به بوم حمله کردند - هر پیکسل روی آن پر شد. در ابتدا، کاربران به سادگی رنگ‌ها را در پیکسل‌های آزاد قرار می‌دادند، اما سپس تیم‌ها شروع به شکل‌گیری کردند و شروع به ترسیم یکی از ساده‌ترین ایده‌های ممکن کردند که افراد همفکر را پیدا کرد. پرچم های ملی. هر چه کاربران بیشتر روی بوم کار کنند، جالب تر و جذاب تر است ایده های پیچیدهبه ذهنشان رسید. و "مکان" از یک پروژه اول آوریل به مکانی تبدیل شده است که در آن کاربران در سراسر جهان در جوامع واقعی متحد می شوند تا چیزی را به جهان نشان دهند و از خلق خود از گروه هایی از مهاجمان حمایت کنند که واقعاً فقط می خواهند نوعی از خود را ترسیم کنند. طراحی

در اولین ساعات کار قرار دهید

"مکان" به یک تابلوی برچسب آنلاین تبدیل شده است، اما هر کدام با آن ساخته می شوند با سختی زیاد. به عنوان مثال، برای ترسیم و محافظت از یک لوگوی لینوکس با ابعاد 48 در 68 پیکسل، 3264 نفر باید به طور همزمان این کار را انجام دهند.

کاربران متحد می شوند تا ایده های کوچکتر و ساده تر را اجرا کنند، اما هنوز هم ایده های بسیار تیمی، مانند این ردیف قلب ها با پرچم های کشورهای مختلف (و نه تنها): همه مسئول قلب "خود" هستند، اما همه افراد با هم به طور غیرارادی یک تیم را تشکیل می دهند.

و دیگران تمام بوم های متن را می نویسند، به عنوان مثال، مانند این گروه از طرفداران " جنگ ستارگان"، که نوشتند و حمایت کردند مونولوگ معروفصدراعظم پالپاتین در مورد سیث دارث پلاگیس از قسمت سوم حماسه فضایی.

با این حال، برخی از کاربران شکایت داشتند که شرکت کنندگان پروژه خود را با ربات هایی جایگزین می کنند که به طور خودکار پیکسل های اشغال شده توسط نویسنده را هر پنج دقیقه به روز می کنند. علیرغم این واقعیت که هنگام ترسیم هر پیکسل، کاربر باید مجموعه ای از اقدامات را تکرار کند (به عنوان مثال، انتخاب یک رنگ خاص)، برخی از آنها توانستند مکانیسم امنیتی را دور بزنند و ربات هایی ایجاد کنند که برای آنها تصاویر ترسیم می کنند.

با این حال، کسانی هستند که هنوز تاپیک های خاصی ایجاد می کنند و سعی می کنند افراد همفکری را تشویق کنند که به ترسیم کردن کمک می کنند و برای نسل های آینده چیزی مانند... استفراغ ریک سانچز از کارتون "ریک و مورتی" را تشویق می کنند. جدی؟ مطمئنی که اینها ربات نیستند؟

پس از 72 ساعت کار، پروژه تعطیل شد. اداره منابع از همه برای مشارکت و این واقعیت که مردم متحد شدند "برای ایجاد چیزی بیشتر" تشکر کرد.

Reddit اغلب به مکانی برای فعالیت های اجتماعی مختلف تبدیل می شود. به عنوان مثال، اخیراً کاربران غمگین این منبع تصمیم گرفتند بپرسند که بیدار شدن هر روز با لبخند چگونه است؟ و قبل از آن، خوانندگان Reddit داستان هایی درباره دختران با یکدیگر به اشتراک گذاشتند. این فقط افراد ناشناس نیستند که از این منبع محبوب استفاده می کنند: این بازیگر اخیراً چندین ساعت به سوالات کاربران در مورد فیلم "Trainspotting" پاسخ داده است.

برای شروع، تعیین الزامات پروژه اول آوریل بسیار مهم بود، زیرا باید بدون "اورکلاک" راه اندازی می شد تا همه کاربران Reddit بلافاصله به آن دسترسی داشته باشند. اگر از همان ابتدا بی نقص کار نمی کرد، به سختی توجه بسیاری از افراد را به خود جلب می کرد.

    اندازه "تخته" باید 1000x1000 کاشی باشد تا بسیار بزرگ به نظر برسد.

    همه کلاینت ها باید همگام شوند و وضعیت برد یکسانی را نمایش دهند. پس از همه، اگر کاربران مختلف داشته باشند نسخه های مختلف، برای آنها تعامل دشوار خواهد بود.

    شما باید حداقل 100000 کاربر همزمان را پشتیبانی کنید.

    کاربران می توانند هر پنج دقیقه یک کاشی قرار دهند. بنابراین، لازم است میانگین نرخ به روز رسانی 100000 کاشی در پنج دقیقه (333 به روز رسانی در ثانیه) حفظ شود.

    پروژه نباید بر عملکرد سایر قسمت ها و عملکردهای سایت تأثیر منفی بگذارد (حتی اگر ترافیک زیادی در r/Place وجود داشته باشد).

  • در صورت بروز گلوگاه یا شکست غیرمنتظره باید پیکربندی انعطاف پذیر ارائه شود. یعنی باید بتوانید اندازه برد و فرکانس مجاز ترسیم را در صورت افزایش حجم داده یا فرکانس به روز رسانی خیلی زیاد تنظیم کنید.

Backend

راهکارهای اجرایی

مشکل اصلی در ایجاد backend همگام سازی نمایش وضعیت برد برای همه مشتریان بود. تصمیم گرفته شد که مشتریان در زمان واقعی به رویدادهای قرار دادن کاشی گوش دهند و فوراً وضعیت کل تابلو را جویا شوند. اگر قبل از ایجاد حالت کامل در به‌روزرسانی‌ها مشترک شده باشید، داشتن یک حالت کامل کمی قدیمی قابل قبول است. هنگامی که مشتری وضعیت کامل را دریافت می کند، تمام کاشی هایی را که در حین انتظار دریافت کرده است نمایش می دهد. تمام کاشی های بعدی باید به محض دریافت روی تابلو ظاهر شوند.


برای اینکه این طرح کار کند، درخواست وضعیت کامل هیئت مدیره باید در اسرع وقت تکمیل شود. در ابتدا، می‌خواستیم کل تابلو را در یک ردیف در Cassandra ذخیره کنیم و هر درخواست به سادگی آن ردیف را بخواند. فرمت هر ستون در این خط به صورت زیر بود:


(x، y): ("مهر زمان": دوره، "نویسنده": نام_کاربر، "رنگ": رنگ)

اما از آنجایی که تابلو شامل یک میلیون کاشی است، ما نیاز به خواندن یک میلیون ستون داشتیم. در خوشه تولید ما، این تا 30 ثانیه طول کشید، که غیرقابل قبول بود و می‌تواند منجر به بارگذاری بیش از حد بر روی کاساندرا شود.


سپس تصمیم گرفتیم کل برد را در Redis ذخیره کنیم. ما یک میدان بیتی از یک میلیون عدد چهار بیتی گرفتیم، که هر کدام می توانست یک رنگ چهار بیتی را رمزگذاری کند، و مختصات x و y با آفست (offset = x + 1000y) در فیلد بیت تعیین شد. برای به دست آوردن وضعیت کامل برد، کل فیلد بیت باید خوانده می شد.


امکان به‌روزرسانی کاشی‌ها با به‌روزرسانی مقادیر در افست‌های خاص (بدون نیاز به مسدود کردن یا انجام کل فرآیند خواندن/به‌روزرسانی/نوشتن) وجود داشت. اما تمام جزئیات هنوز باید در Cassandra ذخیره شود تا کاربران بتوانند بفهمند چه کسی و چه زمانی هر یک از کاشی ها را قرار داده است. همچنین قصد داشتیم از کاساندرا برای بازیابی برد هنگام سقوط ردیس استفاده کنیم. خواندن کل برد از روی آن کمتر از 100 میلی ثانیه طول کشید که بسیار سریع بود.


در اینجا نحوه ذخیره رنگ ها در Redis با استفاده از یک نمونه برد 2x2 آمده است:



ما نگران بودیم که ممکن است در Redis با توان خواندن مواجه شویم. اگر بسیاری از مشتریان به طور همزمان متصل یا به روز شوند، همه آنها به طور همزمان درخواست هایی را برای وضعیت کامل برد ارسال می کنند. از آنجایی که هیئت مدیره یک دولت جهانی مشترک را نشان می داد، راه حل واضح استفاده از حافظه پنهان بود. ما تصمیم گرفتیم در سطح CDN (سریع) حافظه پنهان کنیم زیرا پیاده سازی آن آسان تر بود و کش نزدیک ترین به کلاینت ها به دست آمد که زمان دریافت پاسخ را کاهش داد.


درخواست‌ها برای حالت فول برد توسط Fastly با تایم اوت یک ثانیه ذخیره شدند. برای جلوگیری از تعداد زیادیدرخواست‌هایی که زمانی که مهلت زمانی منقضی شد، از سرصفحه stale-while-revalidate استفاده کردیم. Fastly از حدود 33 POP که به طور مستقل یکدیگر را ذخیره می کنند، پشتیبانی می کند، بنابراین انتظار داشتیم تا 33 درخواست حالت فول برد در هر ثانیه دریافت کنیم.


برای انتشار به‌روزرسانی‌ها برای همه مشتریان، از سرویس وب سوکت خود استفاده کردیم. ما قبلاً با موفقیت از آن برای تقویت Reddit.Live با بیش از 100000 کاربر همزمان برای اعلان‌های پیام خصوصی زنده و سایر ویژگی‌ها استفاده کردیم. سرویس همچنین سنگ بنای پروژه‌های گذشته اول آوریل ما، The Button و Robin بود. در مورد r/Place، مشتریان از اتصالات وب سوکت برای دریافت به‌روزرسانی‌های بی‌درنگ در محل‌های کاشی پشتیبانی می‌کردند.

API

گرفتن حالت فول برد


در ابتدا درخواست ها به Fastly می رفت. اگر یک نسخه معتبر از برد داشت، بلافاصله بدون تماس با سرورهای برنامه Reddit آن را برمی گرداند. اگر نه، یا کپی خیلی قدیمی بود، برنامه Reddit برد کامل را از Redis می خواند و آن را به Fastly برمی گرداند تا کش شود و به مشتری بازگردانده شود.




توجه داشته باشید که نرخ درخواست هرگز به 33 در ثانیه نرسید، به این معنی که کش با Fastly در محافظت از برنامه Reddit در برابر اکثر درخواست‌ها بسیار موثر بود.



و هنگامی که درخواست ها به برنامه رسید، Redis خیلی سریع پاسخ داد.

کشیدن کاشی


مراحل کشیدن کاشی:

  1. مهر زمانی آخرین قرار دادن کاشی توسط کاربر از Cassandra خوانده می شود. اگر کمتر از پنج دقیقه پیش بود، هیچ کاری انجام نمی‌دهیم و یک خطا به کاربر برمی‌گردد.
  2. جزئیات کاشی به ردیس و کاساندرا نوشته شده است.
  3. زمان فعلی در کاساندرا به عنوان آخرین باری که کاربر کاشی قرار داده بود ثبت می شود.
  4. سرویس websocket پیامی در مورد کاشی جدید به همه مشتریان متصل ارسال می کند.

برای حفظ ثبات دقیق، تمام نوشتن و خواندن در Cassandra با استفاده از لایه قوام QUORUM انجام شد.


در واقع، ما در اینجا مسابقه ای داشتیم که در آن کاربران می توانستند چندین کاشی را در یک زمان قرار دهند. در مراحل 1 تا 3 هیچ مسدودی وجود نداشت، بنابراین تلاش‌های همزمان برای کشیدن کاشی‌ها می‌توانست در مرحله اول بررسی را پشت سر بگذارد و در مرحله دوم کشیده شود. به نظر می رسد که برخی از کاربران این باگ را کشف کردند (یا از ربات هایی استفاده کردند که محدودیت تعداد درخواست ها را نادیده گرفتند) - و در نتیجه، حدود 15000 کاشی با استفاده از آن قرار گرفتند (~0.09٪ از کل).


نرخ درخواست و زمان پاسخ اندازه گیری شده توسط برنامه Reddit:



اوج میزان قرارگیری کاشی تقریباً 200 در ثانیه بود. این کمتر از حد تخمینی ما یعنی 333 کاشی در ثانیه است (میانگین با فرض اینکه 100000 کاربر هر پنج دقیقه کاشی را قرار می دهند).


دریافت جزئیات برای یک کاشی خاص


هنگام درخواست کاشی های خاص، داده ها مستقیماً از Cassandra خوانده می شد.


نرخ درخواست و زمان پاسخ اندازه گیری شده توسط برنامه Reddit:



این درخواست بسیار محبوب شد. علاوه بر درخواست‌های مشتری معمولی، افراد اسکریپت‌هایی را برای بازیابی کل تخته یک کاشی در یک زمان نوشته‌اند. از آنجایی که این درخواست در CDN ذخیره نمی شد، همه درخواست ها توسط برنامه Reddit ارائه می شدند.



زمان پاسخگویی به این درخواست ها بسیار کوتاه بود و در طول عمر پروژه در همان سطح باقی ماند.

سوکت های وب

ما معیارهای جداگانه ای نداریم که نشان دهد r/Place چگونه بر سرویس وب سوکت تأثیر گذاشته است. اما می توان با مقایسه داده ها قبل از شروع پروژه و پس از اتمام آن، مقادیر را تخمین زد.


تعداد کل اتصالات به سرویس وب سوکت:



بار پایه قبل از راه اندازی r/Place حدود 20000 اتصال بود، اوج آن 100000 اتصال بود. بنابراین در اوج ما احتمالاً حدود 80000 کاربر همزمان به r/Place متصل بودند.


توان عملیاتی سرویس Websocket:



در اوج بار روی r/Place، سرویس وب سوکت بیش از 4 گیگابیت در ثانیه (150 مگابیت در ثانیه در هر نمونه، در مجموع 24 نمونه) انتقال داد.

Frontend: مشتریان وب و موبایل

در فرآیند ایجاد فرانت‌اند برای Place، ما مجبور بودیم بسیاری از مشکلات پیچیده مربوط به توسعه بین پلتفرمی را حل کنیم. ما می‌خواستیم این پروژه روی همه پلتفرم‌های اصلی از جمله دسکتاپ و دستگاه های تلفن همراهدر iOS و اندروید.


رابط کاربری باید سه عملکرد مهم را انجام می داد:

  1. نمایش وضعیت تابلو در زمان واقعی
  2. به کاربران اجازه تعامل با برد را بدهید.
  3. روی همه پلتفرم ها از جمله برنامه های موبایل کار کنید.

هدف اصلی رابط بوم بود و Canvas API برای آن ایده آل بود. ما از عنصر استفاده کردیم اندازه 1000x1000، و هر کاشی به صورت یک پیکسل کشیده شده است.

کشیدن بوم

بوم باید وضعیت تخته را در زمان واقعی منعکس می کرد. لازم بود وقتی صفحه بارگذاری شد، کل تابلو ترسیم شود و به‌روزرسانی‌های ترسیمی که از طریق وب‌سوکت‌ها می‌آمدند، تمام شود. یک عنصر بوم که از رابط CanvasRenderingContext2D استفاده می کند می تواند به سه روش به روز شود:

  1. با استفاده از drawImage() یک تصویر موجود را روی بوم بکشید.
  2. رسم اشکال با استفاده از روش های مختلففرم های نقاشی به عنوان مثال، fillRect() یک مستطیل را با مقداری رنگ پر می کند.
  3. یک شی ImageData بسازید و با استفاده از ()putImageData آن را روی بوم بکشید.

گزینه اول برای ما مناسب نبود زیرا تابلویی به شکل یک تصویر تمام شده نداشتیم. که گزینه‌های 2 و 3 باقی مانده است. ساده‌ترین راه این بود که کاشی‌ها را با استفاده از fillRect() به‌روزرسانی کنید: وقتی یک به‌روزرسانی از طریق websocket می‌آید، ما به سادگی یک مستطیل 1x1 را در موقعیت (x, y) ترسیم می‌کنیم. به طور کلی، روش کار می کرد، اما برای ترسیم حالت اولیه تخته خیلی راحت نبود. روش putImageData() بسیار بهتر بود: می‌توانستیم رنگ هر پیکسل را در یک شیء ImageData مشخص کنیم و کل بوم را یکجا ترسیم کنیم.

ترسیم حالت اولیه تابلو

استفاده از putImageData() مستلزم تعریف وضعیت برد به صورت Uint8ClampedArray است که در آن هر مقدار یک عدد هشت بیتی بدون علامت در محدوده 0 تا 255 است. هر مقدار نشان دهنده یک کانال رنگی (قرمز، سبز، آبی، آلفا) و هر یک پیکسل به چهار عنصر در آرایه نیاز دارد. یک بوم 2x2 به یک آرایه 16 بایتی نیاز دارد که در آن چهار بایت اول نشان دهنده پیکسل بالای سمت چپ بوم و چهار بایت آخر نشان دهنده پیکسل پایین سمت راست است.


در اینجا نحوه ارتباط پیکسل های بوم با نمایش های Uint8ClampedArray آنها آمده است:



برای بوم پروژه ما به آرایه ای از چهار میلیون بایت نیاز داشتیم - 4 مگابایت.


در باطن، وضعیت برد به صورت یک فیلد چهار بیتی ذخیره می شود. هر رنگ با عددی از 0 تا 15 نشان داده می شود که به ما امکان می دهد دو پیکسل را در هر بایت قرار دهیم. برای استفاده از آن در دستگاه مشتری، باید سه کار را انجام دهید:

  1. انتقال داده های باینری از API ما به مشتری.
  2. داده ها را باز کنید.
  3. تبدیل رنگ های چهار بیتی به 32 بیتی.

برای انتقال داده‌های باینری، ما از Fetch API در مرورگرهایی که از آن پشتیبانی می‌کنند استفاده کردیم. و در مواردی که پشتیبانی نمی کنند، استفاده کردیم XMLHttpRequestبا answerType بر روی "arraybuffer" تنظیم شده است.


داده های باینری دریافتی از API شامل دو پیکسل در هر بایت است. کوچکترین سازنده TypedArray که داشتیم به شما امکان می دهد با داده های باینری در قالب واحدهای تک بایتی کار کنید. اما استفاده از آنها در دستگاه های مشتری دشوار است، بنابراین ما داده ها را باز کردیم تا کار با آنها آسان تر شود. فرآیند ساده است: ما از طریق داده‌های بسته‌بندی شده، بیت‌های مرتبه بالا و پایین را بیرون آوردیم و سپس آنها را در بایت‌های جداگانه در آرایه دیگری کپی کردیم.


در نهایت، رنگ های چهار بیتی باید به 32 بیت تبدیل می شدند.



ساختار ImageData که برای استفاده از putImageData() نیاز داشتیم، مستلزم آن است که نتیجه نهایی یک Uint8ClampedArray با بایت‌هایی باشد که کانال‌های رنگی را به ترتیب RGBA کدگذاری می‌کنند. این به این معنی است که ما نیاز داشتیم یک فشرده سازی دیگر انجام دهیم، هر رنگ را به بایت های کانال کامپوننت بشکنیم و آنها را در فهرست درست قرار دهیم. انجام چهار نوشتن در هر پیکسل خیلی راحت نیست. اما خوشبختانه گزینه دیگری هم وجود داشت.


اشیاء TypedArray اساساً نمایش آرایه ای از ArrayBuffer هستند. در اینجا یک اخطار وجود دارد: چندین نمونه TypedArray می توانند در یک نمونه ArrayBuffer بخوانند و بنویسند. به جای نوشتن چهار مقدار در یک آرایه هشت بیتی، می توانیم یک مقدار را در یک آرایه 32 بیتی بنویسیم! با استفاده از Uint32Array برای نوشتن، ما توانستیم به راحتی رنگ های کاشی را با به روز رسانی یک شاخص آرایه به روز کنیم. با این حال، ما مجبور بودیم پالت رنگ خود را به ترتیب بایت بزرگ (ABGR) ذخیره کنیم تا بایت ها به طور خودکار در مکان های صحیح در هنگام خواندن با استفاده از Uint8ClampedArray قرار گیرند.


پردازش به روز رسانی های دریافت شده از طریق وب سوکت

متد drawRect() برای ترسیم به‌روزرسانی‌ها برای پیکسل‌های جداگانه به هنگام دریافت آنها خوب بود، اما یک چیز وجود داشت. نقطه ضعف: دسته بزرگی از به‌روزرسانی‌هایی که به طور همزمان می‌رسند می‌توانند منجر به کندی سرعت مرورگرها شوند. و ما فهمیدیم که به‌روزرسانی‌های وضعیت هیئت مدیره ممکن است اغلب انجام شود، بنابراین مشکل باید به نحوی حل می‌شد.


به‌جای اینکه هر بار که یک به‌روزرسانی از طریق وب‌سوکت دریافت می‌شود، بلافاصله بوم را دوباره ترسیم کنیم، تصمیم گرفتیم آن را به گونه‌ای انجام دهیم که به‌روزرسانی‌های وب‌سوکت که در همان زمان می‌رسند را بتوان دسته‌بندی و رندر کرد. برای رسیدن به این هدف، دو تغییر ایجاد شد:

  1. استفاده از drawRect() را متوقف کنید - ما پیدا کردیم راه راحتبا استفاده از ()putImageData، تعداد زیادی پیکسل را در یک زمان به روز کنید.
  2. انتقال رندر بوم به حلقه requestAnimationFrame.

با انتقال رندر به حلقه انیمیشن، می‌توانیم بلافاصله به‌روزرسانی‌های وب سوکت را در یک ArrayBuffer بنویسیم و در عین حال رندر واقعی را به تعویق بیندازیم. همه به‌روزرسانی‌های وب سوکت که بین فریم‌ها (حدود 16 میلی‌ثانیه) می‌رسند، به‌طور همزمان دسته‌بندی و ارائه شدند. به لطف استفاده از requestAnimationFrame، اگر رندر بیش از حد طول بکشد (بیش از 16 میلی ثانیه)، تنها بر نرخ تازه سازی بوم تأثیر می گذارد (به جای کاهش عملکرد کل مرورگر).

تعامل با بوم

مهم است که توجه داشته باشید که بوم برای راحت تر کردن تعامل کاربران با سیستم مورد نیاز بود. سناریوی تعامل اصلی، قرار دادن کاشی ها بر روی بوم است.


اما انجام یک رندر دقیق از هر پیکسل در مقیاس 1:1 بسیار دشوار خواهد بود و ما از اشتباه جلوگیری نمی کنیم. بنابراین ما به یک زوم (بزرگ!) نیاز داشتیم. علاوه بر این، کاربران باید بتوانند به راحتی روی بوم حرکت کنند، زیرا برای اکثر صفحه‌ها بسیار بزرگ بود (مخصوصاً هنگام استفاده از زوم).

بزرگنمایی ضربه بزنید؛

از آنجایی که کاربران می‌توانند هر پنج دقیقه یک بار کاشی‌ها را قرار دهند، خطاهای قرار دادن به‌ویژه برای آنها ناامیدکننده خواهد بود. لازم بود بزرگنمایی به اندازه ای اجرا شود که کاشی به اندازه کافی بزرگ باشد و بتوان به راحتی در مکان مناسب قرار گیرد. این به ویژه در دستگاه های صفحه لمسی مهم بود.


ما زوم 40 برابری اجرا کردیم، یعنی هر کاشی اندازه 40x40 داشت. ما عنصر را پیچیدیم V

، که برای آن تبدیل CSS: مقیاس (40، 40) اعمال شد. این یک راه‌حل عالی برای قرار دادن کاشی‌ها بود، اما مشاهده تخته را دشوار می‌کرد (مخصوصاً در صفحه‌های کوچک)، بنابراین ما آن را به بزرگنمایی دو مرحله‌ای تبدیل کردیم: 40 برابر برای کشیدن کاشی، 4 برابر برای مشاهده تخته.


استفاده از CSS برای مقیاس‌بندی بوم، جدا کردن کد مسئول طراحی تابلو را از کد مسئول مقیاس‌بندی آسان کرد. اما معلوم شد که این رویکرد دارای چندین معایب است. هنگامی که مقیاس یک تصویر (بوم)، مرورگرها به طور پیش فرض الگوریتم های هموارسازی تصویر را اعمال می کنند. در برخی موارد این باعث ناراحتی نمی شود، اما به سادگی گرافیک پیکسل را از بین می برد و آنها را به ماش صابونی تبدیل می کند. خبر خوب- یک ویژگی CSS ارائه تصویر وجود دارد که با آن توانستیم از مرورگرها بخواهیم که anti-aliasing را اعمال نکنند. خبر بد این است که همه مرورگرها از این ویژگی پشتیبانی کامل ندارند.


زوم تاری:



برای چنین مرورگرهایی، ما باید راه دیگری برای مقیاس‌بندی پیدا می‌کردیم. در بالا اشاره کردم که سه راه برای طراحی روی بوم وجود دارد. اولین مورد، drawImage()، از کشیدن یک تصویر موجود یا بوم دیگر پشتیبانی می کند. همچنین از مقیاس بندی تصویر هنگام رندر (بزرگنمایی یا کوچکنمایی) پشتیبانی می کند. و در حالی که بزرگ‌نمایی دارای همان مشکلات تار شدن CSS فوق‌الذکر است، می‌توان آن‌ها را به روشی جهانی‌تر از نظر پشتیبانی مرورگر حل کرد - با برداشتن علامت CanvasRenderingContext2D.imageSmoothingEnabled.


بنابراین، با اضافه کردن یک مرحله دیگر به فرآیند رندر، مشکل تاری بوم را حل کردیم. برای این ما یک عنصر دیگر ایجاد کردیم ، که از نظر اندازه و موقعیت با عنصر ظرف (یعنی با ناحیه قابل مشاهده تخته) منطبق است. پس از ترسیم مجدد بوم با استفاده از drawImage ()، قسمت قابل مشاهده آن در بوم جدید در مقیاس مورد نیاز ترسیم می شود. از آنجایی که این مرحله اضافی هزینه کمی به رندر اضافه می کند، ما فقط از آن در مرورگرهایی استفاده می کنیم که از ویژگی CSS رندر تصویر پشتیبانی نمی کنند.

حرکت روی بوم

بوم یک تصویر نسبتاً بزرگ است، به خصوص وقتی بزرگنمایی می شود، بنابراین باید بتوانیم در اطراف آن حرکت کنیم. برای تنظیم موقعیت بوم روی صفحه، از همان روشی که در مورد پوسته پوسته شدن استفاده می شود استفاده کردیم: عنصر را پیچیده کردیم. به دیگری

، که تبدیل CSS: translate(x,y) برای آن اعمال شده است. به لطف یک div جداگانه، ما به راحتی توانستیم ترتیب اعمال تغییرات روی بوم را کنترل کنیم، که برای جلوگیری از حرکت "دوربین" هنگام تغییر زوم ضروری بود.


در نتیجه ما حمایت کردیم راه های مختلفتنظیمات موقعیت دوربین:

  • «کلیک کنید و بکشید» (کلیک کنید و بکشید، یا لمس کنید تا بکشید).
  • "کلیک برای حرکت"؛
  • ناوبری صفحه کلید

هر یک از این روش ها به طور متفاوتی اجرا می شوند.

"کلیک کنید و بکشید"

این روش اصلی ناوبری است. مختصات x و y رویداد mousedown را ذخیره کردیم. برای هر یک از این رویدادها، ما فاصله مکان نما ماوس را نسبت به موقعیت شروع پیدا کردیم و سپس این افست را به افست موجود بوم اضافه کردیم. موقعیت دوربین بلافاصله به روز شد، بنابراین ناوبری بسیار پاسخگو بود.

"برای حرکت کلیک کنید"

وقتی روی یک کاشی کلیک می‌کردید، در مرکز صفحه قرار می‌گرفت. برای پیاده سازی این مکانیسم، ما باید فاصله بین رویدادهای موس و ماوس را ردیابی می کردیم تا «کلیک ها» را از «حرکت ها» جدا کنیم. اگر فاصله حرکت ماوس برای در نظر گرفتن "حرکت" کافی نبود، موقعیت "دوربین" بر اساس تفاوت بین موقعیت ماوس و نقطه در مرکز صفحه تغییر می کرد. برخلاف روش ناوبری قبلی، موقعیت "دوربین" با استفاده از عملکرد صافی به روز شد. به جای اینکه بلافاصله یک موقعیت جدید تعیین کنیم، آن را به عنوان یک "هدف" ذخیره کردیم. در داخل چرخه انیمیشن (همان چیزی که برای ترسیم مجدد بوم استفاده شد)، موقعیت فعلی "دوربین" با استفاده از عملکرد صافی به موقعیت هدف نزدیکتر شد. این باعث شد تا از اثر حرکت خیلی ناگهانی خلاص شوید.

ناوبری صفحه کلید

می توانید با استفاده از فلش های صفحه کلید یا WASD در اطراف بوم حرکت کنید. این کلیدها بردار حرکت داخلی را کنترل می کردند. اگر هیچ کلیدی فشار داده نمی شد، بردار پیش فرض دارای مختصات (0، 0) بود. با فشار دادن هر یک از کلیدهای پیمایش 1 به x یا y اضافه شد. به عنوان مثال، اگر "راست" و "بالا" را فشار دهید، مختصات بردار (1، -1) خواهد بود. سپس از این وکتور در داخل حلقه انیمیشن برای حرکت "دوربین" استفاده شد.


در طول فرآیند انیمیشن، سرعت حرکت بسته به سطح زوم با استفاده از فرمول زیر محاسبه شد:


moveSpeed ​​= maxZoom / currentZoom * speedMultiplier

وقتی زوم خاموش بود، کارکردن دکمه‌ها سریع‌تر و طبیعی‌تر بود.


سپس بردار حرکت نرمال شد، در سرعت حرکت ضرب شد و در موقعیت فعلی "دوربین" اعمال شد. نرمال سازی برای اطمینان از یکسان بودن سرعت حرکات مورب و متعامد استفاده شد. در نهایت، تابع صافی را برای تغییرات در خود بردار حرکت اعمال کردیم. این تغییرات جهت و سرعت را هموار کرد، به طوری که "دوربین" بسیار بیشتر حرکت کرد صاف تر.

پشتیبانی از اپلیکیشن موبایل

هنگام جاسازی بوم در برنامه های iOS و اندروید، با مشکلاتی مواجه شدیم. ابتدا باید کاربر را احراز هویت کنیم تا بتواند کاشی ها را قرار دهد. بر خلاف نسخه وب، که در آن احراز هویت مبتنی بر جلسه است، اپلیکیشن های موبایلما از OAuth استفاده کردیم: در این مورد، برنامه ها باید به کاربر وارد شده یک WebView با یک نشانه دسترسی ارائه دهند. امن ترین راه برای پیاده سازی این، تزریق هدرهای مجوز OAuth از طریق تماس JS از برنامه به WebView است. این به ما این امکان را می دهد که در صورت لزوم سایر هدرها را سفارشی کنیم. سپس شما فقط باید سرصفحه های مجوز را در هر تماس API تجزیه کنید:


r.place.injectHeaders(('Authorization': 'Bearer ’});

در نسخه iOS، ما به‌علاوه پشتیبانی از اعلان‌ها را زمانی که کاشی کاربر برای قرار دادن روی بوم آماده بود، اجرا کردیم. از آنجایی که قرار دادن به طور کامل در WebView انجام شد، ما مجبور شدیم یک برنامه بازگشت به تماس را پیاده سازی کنیم. خوشبختانه، در iOS 8 و بالاتر، این کار با یک تماس ساده JS انجام می شود:


webkit.messageHandlers.tilePlacedHandler.postMessage(this.cooldown / 1000);

سپس روش نمایندگی در برنامه، اعلان‌هایی را بر اساس تایمر خنک‌سازی ارسال شده به آن ارسال می‌کند.


چیزی که یاد گرفتیم

همیشه چیزی هست که شما از دست می دهید

ما همه چیز را کاملاً برنامه ریزی کردیم. ما می دانستیم که پرتاب کی خواهد بود. همه چیز باید مثل ساعت پیش می رفت. ما قسمت جلویی و باطن بار را آزمایش کردیم. ما انسان ها به سادگی دیگر نمی توانستیم اشتباه کنیم. درسته؟


پرتاب واقعاً بدون مشکل انجام شد. در طول صبح، با افزایش محبوبیت r/Place، تعداد اتصالات افزایش یافت و ترافیک به نمونه های وب سوکت افزایش یافت:




ما شاهد آمدن این بودیم. و ما برای این واقعیت آماده می شدیم که در نتیجه شبکه به گلوگاهی در سیستم ما تبدیل شود. اما معلوم شد که ما عرضه زیادی داریم. با این حال، با نگاهی به بار CPU، تصویر کاملا متفاوتی را دیدیم:



اینها ماشینهای هشت هسته ای هستند، بنابراین واضح بود که آنها به حد خود رسیده اند. چرا این "جعبه ها" اینقدر غیرمنتظره رفتار کردند؟ ما تصمیم گرفتیم که بار تولید شده توسط Place از نظر ماهیت با آنچه قبلا بود بسیار متفاوت است. علاوه بر این، تعداد زیادی پیام بسیار کوچک استفاده شد، در حالی که ما معمولاً پیام‌های بزرگ‌تری مانند به‌روزرسانی‌ها و اعلان‌های تاپیک زنده ارسال می‌کنیم. همچنین معمولاً تعداد زیادی از کاربرانی که پیام مشابهی دریافت می کنند نداریم. بنابراین شرایط کار با معمول بسیار متفاوت بود.


ما به این نتیجه رسیدیم که هیچ اتفاق بدی نمی‌افتد: ما بزرگ‌تر شدیم و این پایان کار بود. کارمند مسئول به سادگی تعداد موارد را دو برابر کرد و بدون ذره ای هیجان به دکتر رفت.


و بعد این اتفاق افتاد:



در نگاه اول چیز خاصی نیست. اگر به خاطر این واقعیت نبود که این نمونه تولید RabbitMQ ما بود، که نه تنها پیام های وب سوکت، بلکه به طور کلی هر چیزی را که عملکرد reddit.com به آن بستگی دارد، پردازش می کند. و خوب نبود اصلا خوب نیست


پس از بررسی‌های زیاد، دستکاری و ارتقاء نمونه، جستجوی خود را برای منبع مشکل به رابط مدیریت محدود کردیم. همیشه به نوعی کند به نظر می رسید، و ما تصمیم گرفتیم که کلکسیونر الماس خرگوش ما مرتباً آن را درخواست می کند. ما فکر می‌کردیم که ارتباطات اضافی مرتبط با راه‌اندازی نمونه‌های وب‌سوکت جدید، همراه با انبوه پیام‌های دریافت‌شده در ارتباط با این تبادل، منجر به بارگذاری بیش از حد Rabbit برای پیگیری اجرای درخواست‌ها به پنل مدیریت شد. بنابراین ما آن را خاموش کردیم - و وضعیت بهبود یافت.


اما ما دوست نداریم در تاریکی باشیم، بنابراین یک رفع سریعما یک اسکریپت نظارت موقت ایجاد کردیم:


$ cat s****y_diamond.sh #!/bin/bash /usr/sbin/rabbitmqctl list_queues | /usr/bin/awk "$2~//(print "servers.foo.bar.rabbit.rabbitmq.queues." $1 ".messages " $2 " " systime())" | /bin/grep -v "amq.gen" | /bin/nc 10.1.2.3 2013

اگر تعجب می‌کنید که چرا ما به تنظیم زمان‌های قرارگیری پیکسل‌ها ادامه می‌دهیم، پاسخ این است که ما تلاش می‌کردیم بار کل پروژه را کاهش دهیم. به همین دلیل، مدتی بود که برخی از پیکسل ها برای مدت طولانی روی برد ظاهر نمی شدند.


متاسفانه با وجود پیام های زیر:



تغییرات زمان بارگذاری مجدد که در اینجا ذکر شد کاملاً بود دلایل فنی. اگرچه بعد از آنها تماشای r/place/thread جدید جالب بود:



شاید این بخشی از انگیزه کاربران بوده است.

ربات ها ربات باقی خواهند ماند

در مرحله پایانی پروژه با مشکل دیگری مواجه شدیم. ما مرتباً با مشتریانی که از نظر تکرار تلاش‌ها بد رفتار می‌کنند، مشکل داریم. بسیاری از مشتریان، هنگامی که با خطا مواجه می شوند، به سادگی درخواست های مکرر را ارسال می کنند. و دوباره. و دوباره. یعنی وقتی مشکلی در سایت ظاهر می‌شود، منجر به سیل درخواست‌های مکرر مشتریانی می‌شود که نمی‌دانند استقامت چیست.


وقتی Place را غیرفعال کردیم، نقاط پایانی که بسیاری از ربات‌ها به آن‌ها دسترسی داشتند، شروع به بازگشت خطاهای «نه 200» کردند. این کد چندان موفق نبود. خوشبختانه تمامی این درخواست های مکرر به راحتی در سطح Fastly مسدود شدند.

ایجاد چیزی بیشتر

r/Place اگر به خاطر کار تیمی نبود، آنقدر موفق نبود. مایلیم از u/gooeyblob، u/egonkasper، u/eggplanticarus، u/spladug، u/thephilthe، u/d3fect و هر کس دیگری که به ما کمک کرد تا این آزمایش اول آوریل را به واقعیت تبدیل کنیم، تشکر کنیم.

فیس بوک

توییتر

جیبی

لینکدین

پیام رسان fb

نمی توان گفت که 100٪ جوک های شرکتی در روز طنز موفقیت آمیز و جذاب هستند. امسال، دولت Reddit Place را راه اندازی کرد، یک بوم گرافیکی تعاملی با ابعاد 1000 در 1000 پیکسل، و بخشی به آن اختصاص داده شده است. فرض بر این بود که اعضای جامعه به طور مشترک این بوم را هر طور که دوست دارند نقاشی کنند. اما در نتیجه، این به نبردی برای مکان تبدیل شد و گاهی اوقات به یک تقابل فلسفی تبدیل می‌شد. یک تمرین نقاشی معمولی به یک آزمایش اجتماعی هیجان انگیز تبدیل شده است. این داستان از ابتدا تا انتها توسط وبلاگ Sudoscript مستند شده است.

قوانین محل ساده بود. هر شرکت‌کننده می‌توانست از میان 16 رنگ، یک پیکسل را انتخاب کند و آن را در هر نقطه از بوم قرار دهد. شما می توانید هر تعداد پیکسل را که می خواهید قرار دهید، اما باید 5 دقیقه بین هر جایگذاری صبر کنید. بعد از 72 ساعت این خیلی قوانین سادهمنجر به ایجاد یک بوم جمعی شگفت انگیز شد:

هر یک از پیکسل های قابل مشاهده در بالا به صورت دستی قرار داده شد. هر نماد، هر پرچم، هر الگوی رفتاری با دقت توسط هزاران نفر ایجاد شده است که هیچ چیز مشترکی جز اتصال به اینترنت نداشتند.

در طول ایجاد آن، درام ها، ایده ها، دعواها، حتی جنگ های بی شماری رخ داد. اما به طور کلی، تاریخ مکان یک درام ابدی درباره سه نیروی ضروری برای بشریت برای ایجاد و ایجاد و توسعه فناوری است.

سازندگان

ابتدا سازندگان بودند. اینها هنرمندانی بودند که بوم خالی برایشان فرصتی غیرقابل مقاومت به نظر می رسید. هنرمندان اولیه پیکسل ها را به صورت تصادفی قرار می دادند، فقط برای اینکه ببینند چه کاری می توانند انجام دهند. در اولین دقایق، اولین طرح ها ظاهر شد. خشن و نابالغ شبیه بودند هنر صخره ایمردم غار

سازندگان بلافاصله متوجه شدند که پیکسل ها چه قدرت و پتانسیلی را پنهان می کنند. اما با کار به تنهایی، آنها می توانند هر 5 یا 10 دقیقه یک پیکسل قرار دهند. خلقت نقاشی معنی داربرای همیشه طول می کشد برای ترسیم چیزی باید با هم کار می کردند.

سپس شخصی ایده درخشانی داشت که از یک شبکه برای طراحی استفاده کند، که بر روی نقاشی پوشانده می شود و نشان می دهد که پیکسل های بعدی باید در کجا قرار گیرند. اولین کسی که این آزمایش را انجام داد، میم معروف اینترنت انگلیسی زبان، دیک بات بود. و ساکنان Place دست به کار شدند: دیک‌بات به معنای واقعی کلمه در عرض چند دقیقه در گوشه پایین سمت چپ بوم ظاهر شد. اولین ایجاد خلاقیت جمعی در سایت ظاهر شد.

سپس، زمانی که سازندگان کمی از احتمالات مست شدند، پوکمون چارمندر ظاهر شد که به زودی به جای پا، آلت تناسلی داشت. و اولین درگیری شروع شد: برخی از سازندگان با پشتکار سعی کردند نقاشی های توهین آمیز را تمیز کنند، اما برخی دیگر به طور مداوم فحاشی را اضافه کردند.

سازندگان با یک اساسی روبرو بودند مشکل فلسفی: آزادی بیش از حد منجر به هرج و مرج می شود. خلاقیت به همان اندازه که به آزادی نیاز دارد به محدودیت نیاز دارد.

مدافعان

نوع دیگری از کاربر در Place ظاهر شد که دقیقاً باید با این مشکل دست و پنجه نرم می کرد. اما آنها با اهداف ابتدایی تری شروع کردند: تسخیر جهان. آنها بر اساس رنگ به دسته ها تقسیم شدند و سعی کردند مکان را تصرف کنند. یکی از اولین ها گوشه آبی بود. از گوشه سمت راست پایین سرچشمه می گیرد و مانند طاعون گسترش می یابد.

گروه دیگری گوشه سرخ را در طرف مقابل بوم تأسیس کردند، آنها به سمت چپ سیاسی متمایل شدند. گروه دیگری به نام گرید گرید بوم را از طریق پیکسل ها نقاشی کردند - سلول های سبز رنگ که با سلول های سفید در هم آمیخته شده بودند. از آنجایی که آنها فقط باید نیمی از پیکسل ها را رنگ آمیزی می کردند، کارایی بیشتری نسبت به سایر بخش ها داشتند.

طولی نکشید که جناح ها با سازندگان درگیر شدند. چارمندر یکی از اولین اهداف نبرد شد. گوشه آبی شروع به ترسیم پوکمون با پیکسل‌های آبی کرد و سازندگان از «جنگ‌های فالیک» (که می‌توانند بیشترین دیک‌ها را بکشند) به یک تهدید جدی‌تر روی آوردند. آنها مبارزه کردند و هر پیکسل آبی را با پیکسل خود رنگ آمیزی کردند. اما مزیت کمی به نفع آنها نبود.

بنابراین سازندگان تسلیم رحمت برنده شدند و این به نوعی احساسات آبی ها را جریحه دار کرد. در میان آنها کسانی ظاهر شدند که به نقش خود در دنیای مکان شک داشتند. یکی از این گروه پرسید: "موج ما به ناچار تمام جهان را از انتها تا انتها فرا خواهد گرفت، اگر به هنر دیگری که با آن برخورد می کنیم رحم کنیم."

هر جناحی با این سوال روبرو بود. و همه تصمیم گرفتند نقاشی های دیگر را ذخیره کنند. بنابراین امواج رنگ بدون رنگ آمیزی در اطراف نقاشی ها به جریان افتادند.

این یک نقطه عطف بود. گروه های رنگی بی فکر مدافعان مفیدی شدند.

اما هنوز پایان خوشی ندارد

سرانجام، امواج سیری ناپذیر رنگ متوقف شد و خالقان توانستند به خلاقیت بازگردند. نقاشی ها بیشتر و پیچیده تر شدند. متون نوشته شده در پیکسل ظاهر شد.

سازندگان گروه‌های کوچکی را تشکیل دادند و زیرمجموعه‌هایی ایجاد کردند که در آن می‌توانستند پیش‌نویس هنر و استراتژی را مورد بحث قرار دهند. یکی از بیشترین گروه های موفقمن یک نوار وظیفه به سبک ویندوز 95 کشیدم. یکی دیگر مکان را با قلب ترسیم کرد.

سپس ون گوگ ظاهر شد.

اما به این سادگی هم نبود. مدافعان به ظالم تبدیل شدند و سبک نقاشی ها را دیکته می کردند. آنها تصمیم گرفتند که چه چیزی را می توان ترسیم کرد و چه چیزی را نمی توان. جناح ها شروع به تقسیم کاربران بین خود کردند و طرفداران را فراخواندند، در حالی که سازندگان منتظر تأیید ایده های جدید بودند.

نبردهای بین مدافعان شدیدتر شد. یکی از استریمرهای توییچ از فالوورهایش خواست به بلو حمله کنند. استراتژی های نبرد توسعه داده شد. حتی تحریکاتی نیز وجود داشت: طرفداران همرنگ خود پیکسل هایی از رنگ دشمن را در قلمرو خود رنگ کردند تا بهانه ای برای حمله تلافی جویانه داشته باشند. در حالی که جناح‌ها با یکدیگر می‌جنگیدند، خالقان دریافتند که دیگر جایی برای طرح‌های جدید باقی نمانده است.

پرچم های کشورهای مختلف شروع به ظاهر شدن کردند - همانطور که رشد کردند، به ناچار به یکدیگر برخورد کردند. برای مثال، پرچم‌های آلمان و فرانسه در «سرزمین هیچ‌کس» با هم برخورد کردند.

به نظر می رسید که این دنیای کوچک در آستانه جنگ بود. همه طرف ها سعی کردند مناقشه را از طریق دیپلماتیک حل کنند. رهبران خالقین و مدافعان در چت ها با هم ارتباط برقرار می کردند، اما معمولاً به اتهامات متقابل ختم می شد.

این مکان به یک شرور نیاز داشت که همه بتوانند علیه او متحد شوند.

ویرانگرها

پوچی اومده

با 4chan، معروف ترین ایمیجبورد در جهان شروع شد. شوخی‌های ساکن آن متوجه اتفاقاتی که در Reddit رخ می‌دادند و نمی‌توانستند آن را نادیده بگیرند. آنها باطل شدند.

نقطه ای از پیکسل های سیاه در مرکز مکان شروع به رشد کرد. ابتدا جناح ها سعی کردند با استفاده از دیپلماسی با خلأ پیمانی منعقد کنند. اما آنها شکست خوردند، Void طور دیگری عمل کرد. او یکی از مدافعان نبود، از هنر محافظت نکرد. پیروان او موعظه می کردند که خلاء همه چیز را خواهد بلعید. آنها دو طرف تشکیل نمی دادند، آنها فقط می خواستند تمام دنیا را سیاه کنند.

این دقیقا همان ضربه ای بود که Place به آن نیاز داشت. خالقان و مدافعان که با یک تهدید مشترک مواجه شدند، دوباره متحد شدند تا هنر را نجات دهند. اما هدف از Void فقط تخریب نبود، به نوعی باعث ایجاد یک هنر جدید و بهتر شد.

به عنوان مثال، موقعیت در مرکز یکی از رقابتی ترین در میان سازندگان بود. و هنگامی که سیاه شد، مدافعان متوجه شدند که باید ایده بهتری ارائه دهند که برای مبارزه با هیولای سیاه طرفداران کافی را جذب کند. یکی از این ایده ها پرچم آمریکا بود.

در آخرین روز از وجود مکان، باورنکردنی ترین ائتلاف در آن تشکیل شد که برای مبارزه با خلأ طراحی شده بود - طرفداران ترامپ و مخالفان ترامپ، جمهوری خواهان و دموکرات ها، آمریکایی ها و اروپایی ها بودند.

آزمایش Reddit به زودی به پایان رسید. حتی یک نقاشی نژادپرستانه یا حتی یک نماد نفرت روی بوم نهایی وجود نداشت.

توییتر

جیبی

لینکدین

پیام رسان fb

قوانین ساده بود. هر کاربر می تواند یکی از 16 رنگ را انتخاب کند و با آن یک پیکسل را در هر نقطه از بوم نقاشی کند. شما می توانید هر تعداد پیکسل را که می خواهید و با هر رنگی که می خواهید نقاشی کنید، اما برای رنگ آمیزی مجدد پیکسل بعدی باید 5 دقیقه صبر کنید.

درست است، قوانین می‌گفتند: "با هماهنگی با دیگران، می‌توانید خیلی بیشتر از عمل کردن به تنهایی خلق کنید."

اتفاقی که طی 72 ساعت آینده رخ داد، سازمان دهندگان را در شوک فرو برد. این روی بوم خالی ظاهر شد:

هر پیکسل روی بوم به صورت دستی قرار داده شد. هر نماد، هر پرچم، هر الگوی رفتاری به سختی توسط صدها هزار نفر ساخته شده است که هیچ وجه اشتراکی با یکدیگر به جز اتصال اینترنت نداشتند. بنابراین، به هر شکلی، آنچه در Reddit اتفاق افتاد به درستی می تواند تولد هنر در نظر گرفته شود.

چگونه همه چیز اتفاق افتاد

توصیف این موضوع در چند کلمه غیرممکن است. درام های بی شماری بر روی بوم اتفاق افتاد - دعوا، نبرد و جنگ، گاهی اوقات حتی به دلایل نامعلوم. آنها در انجمن های کوچک، در چت های خصوصی انجام می شدند، تعداد آنها بسیار زیاد بود و همه آنها به یکباره اتفاق می افتادند، بنابراین پیگیری همه چیز غیرممکن بود. به طور کلی، بوم نشان داد داستان ابدیدر مورد سه نیروی لازم برای خلقت بشر.

سازندگان

سازندگان اول شدند. آنها هنرمندانی بودند که بوم خالی برایشان جذابیت مقاومت ناپذیری دارد.

سازندگان شروع به رنگ آمیزی مجدد پیکسل ها به صورت تصادفی کردند تا ببینند چه کاری می توانند انجام دهند. بنابراین، اولین نقاشی ها بیشتر یادآور نقاشی های غار بود - هنرمندان تازه شروع به باز کردن بال های خود کردند.

آنها خیلی سریع متوجه شدند که کار به تنهایی و قرار دادن تنها یک پیکسل در هر 5-10 دقیقه، ایجاد چیز قابل توجهی غیرممکن است. یک نفر مجبور است کارش را خراب کند. برای ایجاد چیزی بزرگتر، آنها باید با هم کار کنند.

و سپس شخصی پیشنهاد کرد که روی یک شبکه طراحی شود، که به وضوح نشان می دهد که پیکسل بعدی برای ایجاد یک تصویر منسجم کجا باید نقاشی شود. اینگونه بود که Dickbutt در قسمت پایین سمت چپ بوم ظاهر شد - یک الگوی رفتاری معروف اینترنتی ، ثمره یک حس شوخ طبعی نوجوان. اولین کار مشترک شد.

اما سازندگان به همین جا بسنده نکردند. آنها شروع به اضافه کردن عناصر مختلف به Dickbutt کردند، آن را در رنگ های مختلف رنگ آمیزی کردند و حتی سعی کردند آن را به Dickbutterfly تبدیل کنند. پشت این ایده احمقانه اشاره ای به یک سونامی خلاقانه قریب الوقوع وجود داشت.

با این حال، این بلافاصله اتفاق نیفتاد. سازندگان سرمست قدرتشان بودند. Pokemon Charmander در کنار Dickbutt ظاهر شد و به جای پنجه، آلت تناسلی شروع به رشد کرد و سپس دو تن دیگر.

دیگر طرحی نبود. برخی از سازندگان ناامیدانه تلاش کردند تا اضافات تحریک آمیز را حذف کنند و خواهان هنر "پاک" بودند، اما برخی دیگر به کارهای خود ادامه دادند. اما اینطور نبود.

معلوم شد که همینطور است آزادی بیشترمنجر به هرج و مرج می شود خلاقیت به همان اندازه که به آزادی نیاز دارد به محدودیت نیاز دارد. وقتی کسی می تواند هر پیکسلی را در هر جایی قرار دهد، چگونه می تواند منجر به خرابکاری نشود؟

نگهبانان

این مشکل به سرعت توسط نوع دیگری از کاربران - متولیان - حل شد. آنها با یک هدف آمدند - تسخیر تمام جهان.

با تشکیل جناح های رنگی، آنها شروع به تسخیر فضا کردند و آن را به رنگ خاصی رنگ آمیزی کردند. یکی از اولین و بزرگترین جناح ها، فراکسیون گوشه آبی بود. با ظاهر شدن در گوشه پایین سمت راست، مانند طاعون پخش شد. پیروان او اعلام کردند که به این ترتیب باید تمام فضای بوم را بپوشانند. پیکسل به پیکسل، آنها شروع به ترجمه ایده خود به واقعیت کردند و به زودی مناطق بزرگی را به تصرف خود درآوردند.

بلو کرنر در آرزوهایش تنها نبود. در طرف دیگر بوم، گروه دیگری ظاهر شد - گوشه قرمز (گوشه قرمز). شرکت کنندگان آن اظهار داشتند که از طرفداران چپ هستند. دیدگاه های سیاسی. گروه دیگری - شبکه سبز (شبکه سبز) - شروع به پراکندگی پیکسل های سبز و سفید در همه جا کردند. او کارایی بالایی از خود نشان داد، زیرا نیاز داشت که نیمی از پیکسل های دیگر را نقاشی کند.

نگهبانان حمله ای از پیش روی سازندگان آغاز کردند. چارمندر اولین مکان نبرد شد. سازندگان پس از اینکه متوجه شدند که Blue Corner شروع به پر کردن پوکمون با پیکسل های آبی کرده است، متوجه این تهدید شدند و جنگ های داخلی را متوقف کردند.

آنها به مقابله پرداختند و هر پیکسل آبی را با پیکسل خود جایگزین کردند. اما نیروها برابر نبودند. به لطف اختصاص خود، Blue Corner چیزهای زیادی جمع آوری کرده است ارتش بزرگنسبت به سازندگان و تنها کاری که سازندگان در چنین شرایطی می توانستند انجام دهند، التماس جانشان بود.

و به نوعی جریان را تغییر داد. گوشه آبی بحثی را در مورد نقش آنها در آن آغاز کرد فرآیند خلاق. یکی از شرکت کنندگان پرسید: "از آنجایی که موج ما به ناچار جهان را به طور کامل فرا می گیرد، آیا باید به سایر اشکال هنری که با آنها برخورد می کنیم رحم کنیم؟"

این سوالی بود که دیر یا زود در مقابل هر جناحی مطرح می شد. با تمام غیرت توسعه طلبانه شان، قرار بود با هنری که سر راهشان بود چه کنند؟

این یک نقطه عطف بود. جناح های بی فکر به محافظ تبدیل شده اند.

اما هنوز تمام نشده بود

در دنیایی پر از رنگ های درنده، سازندگان توانستند به خلاقیت های خود بازگردند. با افزودن عناصر یکی پس از دیگری، آنها شروع به پیچیده تر کردن آنها کردند. با استفاده از فونت های سه پیکسل شروع به نوشتن متن کردیم. یکی از معروف ترین ساخته ها پیش درآمد جنگ ستارگان بود.

سازندگان در گروه هایی که روی آن کار می کنند متحد شدند پروژه مشترک. آنها استراتژی ها و الگوهایی را بین خود به اشتراک گذاشتند. یکی از موفق ترین ها گروهی بود که پنل ویندوز 95 را با دکمه Start در گوشه ای ایجاد کرد.

دیگران قلب هایی مانند قلب بازی های قدیمی مانند Zelda ایجاد کردند. فقط چند نفر این پروژه را شروع کردند، اما دیگران به سرعت به آنها پیوستند و در نهایت قلب ها که به رنگ پرچم های مختلف رنگ آمیزی شده بودند، روی نیمی از بوم کشیده شدند.

گروهی دیگر شب پرستاره ون گوگ را بازسازی کردند.

با این حال، همه چیز به آرامی پیش نرفت. طرفدارانی که زمانی خلق آثار هنری را جشن می‌گرفتند، به ظالمی تبدیل شدند که مد را دیکته می‌کردند. آنها شروع کردند به نشان دادن آنچه می تواند ایجاد شود و چه چیزی نمی تواند. اندکی قبل از اینکه سازندگان شروع به ایجاد بر اساس قوانین خود کنند، شروع شد.

جناح ها نگاه خود را به یکدیگر معطوف کردند و از پیروان خود خواستند که در نبردهای حماسی جانبداری کنند. آنها فرصتی برای توجه به التماس های رقت انگیز سازندگانی که خواهان تأیید ایده های یک هنر جدید بودند، نداشتند.

درگیری بین مدافعان به شدت شعله ور شد. پخش‌کننده‌های زنده توییچ فالوورهای خود را تشویق کردند که به Blue Corner و Purple حمله کنند. نقشه های جنگی ساخته شد. متوسل به احساسات شد.

حتی حملات جعلی وجود داشت، که در آن پیروان همرنگ پیکسل‌های حریف را درون پیکسل‌های خود قرار می‌دادند تا بتوانند از نقض شکایت کنند و به آن حمله کنند.

با این حال، بزرگترین مشکل قانون سخت بود - بوم را نمی توان بزرگ کرد. هم جناح های متخاصم و هم سازندگان متوجه شدند که به سادگی جایی برای هنر جدید نخواهند داشت.

از همان ابتدا، پرچم کشورهای مختلف بر روی بوم ظاهر شد. آنها بزرگ شدند و به یکدیگر برخورد کردند. واقعی نبرد حماسیبین پرچم های آلمان و فرانسه فوران کرد. مشخص شد که برای توسعه فضاهای جدید به یک واسطه نیاز است.

ناگهان جهان که در آغاز از حملات بدوی فرار کرده بود، برای جنگی همه جانبه آماده شد. تلاش های مذبوحانه برای حل دیپلماتیک مشکل به جایی نرسید. با ملاقات در چت، رهبران سازندگان و مدافعان فقط یکدیگر را مقصر می دانستند.

چیزی که لازم بود یک راسو بود که همه بتوانند با آن به توافق برسند.

ویرانگرها

سایت اینترنتی 4chan توجه را به آنچه در Reddit اتفاق می‌افتد جلب کرد. و نتوانستند از آنجا بگذرند. کاربران آنها نزدیک ترین رنگ را به دل خود انتخاب کردند - مشکی. آنها باطل شدند.

درست زمانی که اشک به آرامی روی سطح پخش می‌شود، پیکسل‌های سیاه در مرکز بوم ظاهر می‌شوند و همه چیز را در مسیر خود نابود می‌کنند.

در ابتدا، جناح های دیگر سعی کردند با آنها ائتلاف کنند و ساده لوحانه معتقد بودند که دیپلماسی کارساز است. اما آنها شکست خوردند زیرا Void متفاوت بود.

خلأ محافظ نبود. او برخلاف دیگر جناح‌ها، هیچ وفاداری به هنر نشان نداد. پیروان پوچی تحت شعار «خلأ همه چیز را خواهد بلعید» ادعای برابری طلبی مخرب کردند. ارتباطی با دیگران نداشتند. آنها فقط می خواستند تمام دنیا را سیاه کنند.

و این دقیقا همان چیزی بود که لازم بود. با یافتن خود در آستانه انقراض، همه شرکت کنندگان در پروژه متحد شدند تا با Void مبارزه کنند تا هنر خود را حفظ کنند.

اما شکست دادن Void چندان آسان نبود، زیرا به آن نیاز بود. لازم بود همه چیز نابود شود تا هنر جدید، بهترین، از خاکستر دوباره متولد شود. و بدون Void این غیر ممکن بود.

بنابراین خلأ کاتالیزور خلقت شد بزرگترین کارهنر

برای بخش مرکزیاز همان ابتدا یک کشمکش سرسختانه بین بوم ها وجود داشت. سازندگان این قلمرو را برای آثار خود ادعا کردند. در ابتدا سعی کردند این کار را با استفاده از نمادها انجام دهند. سپس در تلاشی هماهنگ برای ایجاد منشوری مانند آنچه روی جلد آلبوم است پینک فلوید « سمت معکوسماه."

اما باطل همه چیز را خورد. خلقت یکی پس از دیگری فقط به اشتهای هولناک او برای هرج و مرج دامن می زد.

و با این حال، این دقیقا همان چیزی بود که مورد نیاز بود. پس از از بین بردن این هنر، Void کاربران را مجبور کرد تا چیز بهتری ارائه دهند. آنها می دانستند که می توانند هیولای سیاه را شکست دهند. آنها فقط به یک ایده با پتانسیل خوب نیاز دارند که به اندازه کافی فالوور جذب کند.

و این ایده به پرچم آمریکا تبدیل شد.

در آخرین روز پروژه همه دور هم جمع شدند تا یک بار برای همیشه جای خالی را از بین ببرند. ائتلافی از افرادی ایجاد شد که در موقعیتی متفاوت یکدیگر را از هم جدا می کردند - از طرفداران و مخالفان ترامپ، از دموکرات ها و جمهوری خواهان، از آمریکایی ها و اروپایی ها.

آنها گرد هم آمدند تا در این گوشه کوچک اینترنت چیزی خلق کنند و ثابت کنند که در عصری که چنین همکاری غیرممکن به نظر می رسد، هنوز هم می توانند آن را انجام دهند.

قدیم ها درست می گفتند

کمی بعد، آزمایش Reddit به پایان رسید. امروز او با داستان های زیادی که در ده ها چت گفته می شود همراه است. هر اثر هنری خلق شده در این پروژه با صدها اثر جدید پوشانده شد که تنها تعداد کمی از آنها بر روی بوم نهایی باقی مانده بود.

اما شگفت‌انگیزترین چیز، شاید این باشد که، با وجود ناشناس بودن و عدم ممنوعیت، هیچ نماد نژادپرستانه یا انسان‌پرستانه روی بوم نهایی وجود نداشت. این یک چرخه زیبا از هنر، زندگی و مرگ بود. و او اولین نفر در تاریخ ما نبود.

هزاران سال پیش، زمانی که بشریت (واقعی، نه فقط موجود در ردیت) هنوز در مراحل اولیه خود بود، فیلسوفان هندو این نظریه را مطرح کردند که آسمان ها از سه خدای رقیب، اما ضروری تشکیل شده است: برهما خالق، ویشنو حافظ، و شیوا.

حتی بدون یکی از آنها، کیهان قادر به کار نخواهد بود. برای اینکه نور وجود داشته باشد، تاریکی لازم است. برای وجود زندگی، مرگ لازم است. برای آفرینش و هنر باید تخریب وجود داشته باشد.

چندین روز پروژه نشان داد که این رویکرد نبوی است. Reddit به روشی باورنکردنی ثابت کرده است که خلقت به هر سه جزء نیاز دارد.

نقاشی نهایی