در این مسئله، سلیب میخواهد بازیای تعریف کند تا از تنهایی ابدی خود نجات یابد و کمی سرگرم شود. این بار میخواهد تا یک برنامه تعاملی بنویسد تا عددی که کد دیگر او انتخاب کرده را پیدا کند :). بازی به این صورت است که سلیب میخواهد تابع GuessMyNumber
را در فایل main.go
پیادهسازی کند. امضای این تابع به شکل زیر است:
این تابع یک شی از نوع Game
را دریافت میکند. هدف این تابع پیدا کردن عددی است که بازی انتخاب کرده و در داخل Game
ذخیره شده است. اما پیدا کردن به شکل مستقیم امکان ندارد و باید حتما بازی کنیم! در واقع ما فقط به یک تابع دسترسی داریم که حدسهای خود را به آن میدهیم و حدسمان را بررسی میکند و به ما راهنمایی میکند که به جواب اصلی نزدیکتر شویم.
در نهایت تابع GuessMyNumber
پس از اینکه حدسهای مختلفی میزند و نهایتا پاسخ را پیدا میکند، پاسخ خود را با یک پیام به شکل رشته باز میگرداند:
برای مثال اگر عدد بازی برابر با 269
باشد، این تابع پس از فهمیدن عدد باید عبارت زیر را برگرداند.
در فایل utils.go
، اینترفیس Game
آمده است که در اینجا نیز میتوانیم آن را ببینیم:
تابع CheckNumber
عددی که به عنوان حدس میگیرد را بررسی میکند و ۳ حالت مختلف را برمیگرداند:
n
از عدد مورد نظر بازی کمتر باشد، عبارت My Number is Greater
را برمیگرداند.n
از عدد مورد نظر بازی بیشتر باشد، عبارت My Number is Lower
را برمیگرداند.n
دقیقا برابر با عدد مورد نظر بازی باشد، عبارت CORRECT
را برمیگرداند.از آنجا که اجرای تابع CheckNumber
برای سلیب هزینه دارد (و شاید هم به دنبال پیچاندن و سختتر کردن مسئله است!) سلیب مسئله را در ۴ بخش تعریف کرده است:
مسئله | نمره |
---|---|
با پرسیدن حداکثر ۳۶۰ پرسش به عدد برسد | ۲۵ |
با پرسیدن حداکثر ۱۸۰ پرسش به عدد برسد | ۲۵ |
با پرسیدن حداکثر ۶۰ پرسش به عدد برسد | ۲۵ |
با پرسیدن حداکثر ۱۰ پرسش به عدد برسد | ۲۵ |
هرچه الگوریتم شما برای یافتن عدد بهتر باشد، نمره بیشتری در این مسئله دریافت میکنید :) پس به دنبال راهحلهای خلاقانه باشید.
پروژهی اولیه را از این لینک دانلود کنید. ساختار فایلهای پروژه بهصورت زیر است:
فایل utils.go
شامل اینترفیس Game
است. فایل main_sample_test.go
نیز شامل یک پیادهسازی نمونه از Game
است که برای تستهای اولیهی کد خود میتوانید از آن استفاده کنید. فایل main.go
نیز شامل تابعی است که شما باید پیادهسازی کنید.
توجه: در این سؤال تنها مجاز به استفاده از کتابخانههای bufio
و fmt
و math/rand
و os
و strings
هستید.
پس از پیادهسازی تابع GuessMyNumber
، فایل main.go
را آپلود کنید.
بعد از تقویمهای جلالی، میلادی و کلندرهای مجازی که گوگل و سایر شرکتها ارائه میدهند؛ ما در کوئرا به فکر طراحی تقویم خودمان افتادهایم. و وظیفهی آن به اون یکی همکارمون در شرکت محول شده. از شما میخواهیم این پروژه را طبق معمول کوئرا برای اون یکی همکارمون پیادهسازی کنید.
پروژهی اولیه را از این لینک دانلود کنید. در این پروژه شما باید قسمتهای مشخصشده با // TODO
را پیادهسازی کنید.
ساختار struct
هایی که جداول شما رو میسازند باید به شکل زیر باشد:
1- User
نام ستون | نوع | ملاحظات |
---|---|---|
gorm.Model |
struct |
PRIMARY KEY AUTO_INCREMENT |
Username |
string |
نام کاربری |
FirstName |
string |
نام |
LastName |
string |
نام خانوادگی |
2- Calendar
نام ستون | نوع | ملاحظات |
---|---|---|
gorm.Model |
struct |
PRIMARY KEY AUTO_INCREMENT |
Name |
string |
نام تقویم |
UserID |
uint |
کلید خارجی به جدول users و ستون id |
3- Appointment
نام ستون | نوع | ملاحظات |
---|---|---|
gorm.Model |
struct |
PRIMARY KEY AUTO_INCREMENT |
Subject |
string |
موضوع ملاقات |
Description |
string |
توضیحات ملاقات |
StartTime |
time.Time |
زمان شروع ملاقات |
Length |
uint |
مدت زمان ملاقات |
OwnerID |
uint |
آیدی دارنده ملاقات |
OwnerType |
string |
تایپ کلاس دارنده ملاقات |
4- TaskList
نام ستون | نوع | ملاحظات |
---|---|---|
gorm.Model |
struct |
PRIMARY KEY AUTO_INCREMENT |
جهت اطلاعات بیشتر در مورد gorm.Model
میتوانید به این لینک مراجعه نمایید.
در ادامه شما باید به پیادهسازی روابط بین مدلها بپردازید که ارتباطات بین مدلها باید بهصورت زیر باشد:
appointment_user
)شما باید بدنه توابع زیر را به شکلی مطلوب تکمیل نمایید.
RefreshDatabase
🔗این تابع با دریافت آبجکتی از نوع *gorm.DB
و لیستی از جداول، ابتدا باید آنها را حذف کند و سپس آنها را طبق آخرین تغییرات بر اساس استراکتهای مربوطه بسازد. در صورت موفقیتآمیز بودن عملیات باید Refresh database successfully done
به عنوان رشته برگردانده شود به همره nil
و اگر خطایی در طی فرآیند رخ داد باید رشته خالی به همراه ارور مربوطه برگردانده شود.
امضای تابع به شکل زیر است:
SeedUser
🔗این تابع باید به صورت Seeder عمل کند و با دریافت پارامترهای لازم یک کاربر با تقویم و لیست ملاقاتهای مربوطه بسازد و در جدول ذخیره کند و در صورت موفقیتآمیز بودن عملیات پیام Seeding database successfully done
را چاپ کند و در غیر این صورت ارور را به همراه یک رشته خالی برگرداند.
امضای تابع به شکل زیر است:
updateAppointment
🔗این تابع باید به تمام وقتملاقاتهایی که اسم تقویم آنها برابر با calendarName
، زمان شروع آنها بین startTime
و endTime
و موضوع رویداد، شامل keyword
باشد یک ساعت به زمان شروع ملاقاتها اضافه کند و به انتهای توضیحات آنها هم event
(یک فاصله و بعد event) را اضافه کند و در جدول ذخیره نماید در غیر این صورت ارور مربوطه را برگرداند.
امضای تابع به شکل زیر است:
UserWithRangeAppointment
🔗این اسکوپ باید تمام کاربرانی که زمان شروع ملاقات آنها بین startDate
و endDate
است، موضوع ملاقات آنها برابر subject
است و اسم تقویم آنها برابر calendarTableName
را برگرداند.
امضای اسکوپ به شکل زیر است:
db.go
جهت اتصال GORM با دیتابیس است که در آن از دیزانپترن singleton استفاده شده و شما نیازی به تغییر آن ندارید و صرفا ثابتهای آن را جهت اجرا در محیط لوکال خود میتوانید تغییر دهید. فرض کنید سمت سرور نیز این فایل به درستی و مطابق دیتابیس سرور وجود دارد. پس از پیادهسازی موارد خواسته شده، فایل main.go
را که شامل تمام موارد گفته شده در بالا است آپلود کنید.
در این سوال میخوایم یک پیام رسان ساده با استفاده از گولنگ پیاده سازی کنیم. فقط این پیام رسان برای آن دسته از افرادی است که خیلی حوصله فضای مجازی را ندارند و دوست ندارند هربار که وارد برنامه میشوند با تعداد زیادی از پیامهای جدید رو به رو شوند و به جایش دوست دارند هربار که خودشان خواستند سرور یکی از پیامهای جدیدشان را (در صورت وجود) برایشان نمایش دهد.
پروژهی اولیه را از این لینک دانلود کنید. ساختار فایلهای پروژه به صورت زیر است:
در هر کدام از فایلهای go توابع و استراکتهایی وجود دارد که باید کاملشان کنید که در ادامه به آنها خواهیم پرداخت.
در این پروژه هر کاربر میتواند به کاربر یا گروهی دیگر پیام ارسال کند. فقط برای ارسال پیام از سمت سرور به گیرنده چندتا شرط وجود دارد.
subscribed
باشد یا نباشد که با توجه به این ویژگی عدد n برای هر پیام از طرف او مشخص میشود. به این صورت که اگر subscribed
باشد سرور هر 110 میلی ثانیه یک بار سعی میکند پیام او را به گیرنده بفرستد و اگر subscribed
نباشد هر 290 میلی ثانیه یک بار. دقت کنید که این تایمر از زمان فرستادن هر پیام شروع میشود (یعنی هر پیام تایمر جدا دارد). همچنین هر بار 1 میلی ثانیه از مدت زمان تایمر کم میشود. یعنی اگر پیامی اولین بار پس از 110 میلی ثانیه سعی شود فرستاده شود و ناموفق بوده باشد (گیرنده پیام خوانده نشده از قبل داشته)، دفعه بعد پس از 109 میلی ثانیه دوباره سرور تلاش میکند ارسالش کند.message.go
🔗در این فایل استراکت حاوی اطلاعات پیامها وجود دارد که نباید آن را تغییر بدهید.
فیلد اول نشان دهنده آیدی کاربر فرستنده است. فیلد دوم آیدی کاربر گیرنده. فیلد سوم متن پیام است. فیلد چهارم نشان دهنده زمانی است که طول کشیده است تا پیام به سمت گیرنده ارسال شود (به میلی ثانیه). درباره فیلد آخر دقت کنید که هربار سرور سعی میکند پیام را به گیرنده ارسال کند باید آپدیت شود (یعنی با زمان سیستم نباید کار کنید).
server.go
🔗در این فایل استراکت زیر وجود دارد که باید خودتان کامل کنید.
همچنین تابع زیر را داریم که لیست کاربر و گروهها را میگیرد و سرور را برمیگرداند.
در ادامه تابع زیر را داریم که باید لیستی از پیامهای موجود در صف سرور در آن لحظه را برگرداند. خروجی این تابع، ترتیبدار است. به این ترتیب پیامی که اول ارسال شده است باید اول لیست باشد.
توجه: برای سرور امکان add و remove گروهها و کاربرها را نداریم. به این معنی که همان اطلاعاتی که موقع setup داشتیم، تا آخر برنامه معتبر است.
user.go
🔗این فایل شامل دو دسته از استراکتها و توابع است که باید آنها را پیاده سازی کنید. قسمت اول مربوط به کاربرها است.
تابع NewUser
دو مقدار به عنوان ورودی میگیرد. اولی آیدی کاربر است. دومی یک بولین است که نشان میدهد این کاربر جز کاربرهای subscribed
است یا خیر. در آخر یوزر ساخته شده را برمیگرداند.
تابع SendMessage
نیز دو مقدار به عنوان ورودی میگیرد. اولی آیدی کاربر گیرنده و دومی متن پیام است. همچنین اگر آیدی گیرنده در سرور وجود نداشت، این تابع باید یک ارور برگرداند (متن ارور مهم نیست).
تابع ReceiveMessage
: این تابع در صورت وجود پیام جدید برای کاربر، آن را برمیگرداند. در غیر این صورت یک استراکت خالی برمیگرداند
قسمت دوم مربوط به گروهها است (که کاربرها میتوانند عضو آنها شوند)
تابع NewGroup
: آیدی گروه و لیست کاربرهای موجود در این گروه را میگیرد. تضمین میشود آیدی هیچ گروهی با هیچ کاربری یکسان نیست.
تابع AddUser
: یک کاربر را میگیرد و به گروه اضافه میکند. اگر کاربر در گروه نبود و با موفقیت به گروه اضافه شد رشته بالا و اگر از قبل عضو گروه بود رشته پایین را برمیگرداند.
تابع RemoveUser
: این تابع کاربر را از گروه حذف میکند. اگر کاربر در گروه بود و حذف شد پیام بالا و اگر اصلا عضو گروه نبود پیام پایین را برمیگرداند.
درباره فرستادن پیام به گروهها:
ToID
آن برابر آیدی گروه است) و هروقت به همه اعضای گروه ارسال شد از صف حذف میشود. همچنین هربار که این پیام به یکی از اعضای گروه ارسال میشود، فیلد MsInQueueBeforeBeingSent
این پیام در صف آپدیت میشود. به این معنی که اگر پیام برای بعضی از اعضا در 110 میلی ثانیه ارسال شد، این فیلد 110 میشود و... بدیهی است اگر پیام در یک زمان به همه اعضا ارسال شود از queue حذف میشود و دیگر به این پیام دسترسی نخواهیم داشت و نیازی به آپدیت این فیلد نیست.SendMessage
لازم است چک کنید آیدی گیرنده در سرور وجود دارد یا خیر.یک فایل زیپ آپلود کنید که وقتی آن را باز میکنیم دایرکتوریهای user
که شامل user.go
است و server
که شامل server.go
است را میبینیم.