ببخشید من بی سوادم و PHP بلد نیستم ولی چون الگوریتم خواستید می تونم اینجور توضیح بدم،
البته خودم نمی دونم دارم الگوریتم رو می گم، شبه کد می نویسم یا چیز دیگه ای :
اول اینکه لیست فیلد ها تون یک مورد کم داره، یعنی به ازای هر رکورد باید یک فیلد موجودی هم اضافه کنید،
این موجودی بین 0 تا مقدار tonage خواهد بود. اگر اسمش را بگذاریم curstore تعریف رکورد هایتان می شود :
`id` bigint(50) NOT NULL auto_increment,
`enter_date` date NOT NULL,
`tonage` float(10,3) NOT NULL,
`curstore` float(10,3) NOT NULL,
`owner_id` int(20) NOT NULL,
`product_id` int(20) NOT NULL,
چرا؟ چون جدول ورودی ها بایستی سوابق رو نگه دارند. اگه قرار باشه بعد از اینکه از محصول فلان تاریخ فلان مقدار
کم بشه بایستی این تغییرات رو یک جایی ذخیره کنید. توی رکورد های جدول خروجی که نمیشه چون اون فقط یک
فیلد تاریخ داره که تاریخ خروج از انباره و مشخص هم نمی کنه که از محصول مربوط به ورودی کدوم تاریخ کم می کنه.
فیلد اصلی tonage را هم که اصلا نباید تغییر بدهیم. چرا؟ چون لیست سوابق انباره. اگه مقدارش رو تغییر بدهید
فردا معلوم نمیشه که توی فلان تاریخ چقدر جنس وارد شده بوده. همین فیلد curstore را در جدول ورودی ها اضافه کنید.
پس ما دو جدول در بانک اطلاعاتی خواهیم داشت :
اولی ورودی ها به انبار است، وقتی محصولی وارد انبار شد مشخصات curstore و tonage اون یکسان هستند.
tonage از این لحظه به بعد مربوط به سوابق است و دیگر تغییر نمی کند. شما صرفا می توانید برای چک کردن سوابق
انبار از این فیلد استفاده کنید.
وقتی محصول وارد شده از انبار خارج میشه محتویات curstore کم میشه و می تونه به صفر برسه. وقتی صفر شد
دیگه برای الگوریتم خروج محصول ارزش اطلاعاتی نداره. ولی رکوردش رو پاک نمی کنیم چون بعدا ممکنه ازش به عنوان
رکورد سوابق انبار استفاده کنیم.
همانطور که گفتید می توانید بعد با استفاده از curstore چک کنید که مقدار خروجی انبار از ورودی ها بیشتر نشده باشد.
یعنی curstore ها فلان محصول مربوط به فلان فرد رو جمع بزنید و با مقدار tonage های خروجی همون محصول همون آقا
مقایسه کنید. ولی اینجا دیگه tonage بدرد نمی خوره چون مقداری رو نشون میده که شاید اصلا دیگه توی انبار وجود نداره.
جدول دومی جدول خروجی ها است و که هر بار از محصول فلان مقداری از انبار خارج شد در این جدول ثبت می شود.
حالا نمی دانم برایتان ساده تر است که جدول اش رو مثل جدول ورودی ها فرض کنید که یک فیلد بدردنخور curstore داشته باشه
یا تعریف اش مثل جدول ورودی ها نباشه و فیلد curstore رو در نظر نگیرید.
فرض کنیم قراره از محصول product_id که متعلق به owner_id است به اندازه count تن از انبار خارج بشه.
غیر از رکوردهایی که باید در قسمت موجودی (همان جدول ورودی) انبار تغییر کنند و رکورد هایی که باید در قسمت
خروجی ها ثبت شوند ما باید یک هزینه خروج باید داشته باشیم، درسته؟
پس یک متغیر به اسم charge اضافه می کنیم که مقدار اولی اش باید صفر باشه و به تدریج در توی یک حلقه افزایش پیدا کنه.
حالا یک حلقه loop بسازیم که در هنگام ورود به حلقه شرط پایان حلقه این باشه که count == 0 بشه یعنی دیگه
همه مقدار محصولی که قرار بوده از انبار خارج بشه رو بردیم بیرون.
کد:
do until (count == 0)
loop
قبل از ورود به حلقه ما باید یک لیست از تمامی رکورد های اون بابا (owner_id) رو که مربوط به محصول مورد نظر (product_id)
هستند رو داشته باشیم که بر اساس تاریخ ورود به انبار مرتب باشند. اولین رکورد این لیست باید قدیمی ترین تاریخ ورود
اون محصول باشه و آخرین رکورد لیست هم جدید ترین تاریخ ورود.
این لیست، لیست موجودی ها رو تشکیل میده که از جدول ورودی استخراج میشه.
یعنی قبل از ورود به حلقه یک فیلتری در جدول ورودی ها اجرا کنید که نشون بشه فلان شخص فلان محصول رو در چه تاریخ
هایی وارد انبار کرده. البته در بعضی از رکورد های این لیست مقدار curstore ممکنه صفر باشه که از نظر الگوریتم وجود
و یا عدم وجود اونها مهم نیست. اگر چنین رکورد های هم باشند طبق اصول همیشه در ابتدای لیست اند یعنی اگر
در پنج تا رکورد مقدار curstore صفر باشه همون پنج رکورد اول لیست اند چون تاریخ شان از بقیه حتما عقب تر (قدیمی تر)
است.
داخل الگوریتم این اتفاق می افته که یک به یک رکورد های لیست ای که ساختیم رو دونه به دونه از قدیمی ترین تاریخ
چک می کنیم، نمی دونم این رکوردی که از لیست بررسی میشه رو با یک اندیس مثل i مشخص می کنید که i در هر بار
یک واحد اضافه میشه و یا از متد هایی مثل records.next برای رفتن به رکورد بعدی استفاده میشه
به هر حال هر رکوردی از لیست که بررسی شد باید سراغ رکورد بعدی برویم. اگر حلقه اونقدر ادامه پیدا کرد که به انتهای
لیست رسیدیم، مفهوم اش اینه که مقدار count اشتباهه چون داریم از انباری که موجودی اش کمتر از count بوده برداشت
می کنیم. اگر مقدار count درست باشه پیش از رسیدن به انتهای لیست مقدار count به صفر می رسه و از حلقه
خارج می شویم.
حالا ببینیم نحوه چک کردن رکورد ها در داخل حلقه چطوره. فرض می کنم که اسم رکورد مورد نظر که داریم بررسی اش
می کنیم record باشد.
یک متغیر مثلا به اسم x از نوع float باید مقدار فعلی count را اختیار کند، این رکورد برای محاسبه خروجی محصول از
یک رکورد بکار می رود :
اگه مقدار x از مقدار curstore (موجودی) اون رکورد record بیشتر شد برابر با مقدار curstore قرار می دهیم،
یعنی هیچگاه x نباید بیشتر از curstore باشد.
کد:
if (x > record.curstore) then x = record.curstore
حالا مقدار x را از curstore اون رکورد کم کنید و تغییرات را در جدول ورودی بصورت درجا روی رکورد ثبت نمایید (Update)
حالا تاریخ فعلی (today) را از تاریخ رکورد کم کنید تا اختلاف روز میان ورود به انبار و خروج بدست آید و در یک متغیر
مثل day ذخیره کنید.
کد:
day = today - record.enter_date
اگر day از 3 بیشتر نشده که باید از هزینه معاف اش کنید پس دیگه ادامه ندید تا دوباره به اول حلقه برگرده (continue)
ولی قبلش از مقدار count کم می کنیم و سراغ رکورد بعدی می رویم.
کد:
if (day < 4) then
count = count - x
records.next
continue
end if
ولی فرض کنیم که سه روز رو رد کرده. حالا مقدار day را در x که مقدار خروجی است ضرب کنید تا مقدار روز در تن ضرب بشه.
دوباره حاصل آنرا در در مقدار به ازای روز ضرب کنید که گفتید مثلا 10 تومن. حاصل این فرمول را به مقدار فعلی charge
اضافه کنید، فراموش نکردیم که charge قراره هزینه رو جمع بزنه.
کد:
charge = charge + ( day * x * 10)
خب حالا که مقدار x رو از محصول حساب کردیم می تونیم از مقدار کل count کم کنیم.
حالا دو وضعیت پیش میاد یا count از صفر بزرگتره، یعنی با کم کردن از مقدار curstore رکورد فعلی، مقدار curstore رو به صفر
رسوندیم ولی هنوز به محصول بیشتری نیاز داریم پس باید بریم سراغ محصولی که در تاریخ های بعدی وارد شده (که ارزونتر
حساب میشه)
حالت دوم هم یعنی count به صفر می رسه و حلقه در دور بعدی با شرط count == 0 به پایان می رسه.
فقط قبل از شروع دور بعدی از حلقه باید به رکورد بعدی بپریم.
وقتی کار حلقه به پایان رسید اصولا مقدار count صفر است و charge مقدار هزینه رو محاسبه کرده.
فقط فراموش نکنید که در جدول خروجی ها بایستی یک رکورد جدید بابت خروج درج کنید.
چون مقدار curstore رکورد های جدول ورودی ها در توی حلقه کم شده، فرایندی دیگه ای برای جدول ورودی مورد نیاز نیست.
راستی این متنی که من نوشتم الگوریتم بود؟ شبه کد بود؟ داستان بود؟