8 int _GetMinBalance(int Account);
9 int _CanTransfer(int Source, int Destination, int Ammount);
10 int _Transfer(int Source, int Destination, int Ammount, const char *Reason);
11 int _GetSalesAcct(tItem *Item);
15 * \brief Dispense an item for a user
17 * The core of the dispense system, I kinda like it :)
19 int DispenseItem(int ActualUser, int User, tItem *Item)
23 char *username, *actualUsername;
25 handler = Item->Handler;
27 salesAcct = _GetSalesAcct(Item);
29 // Check if the user can afford it
30 if( Item->Price && !_CanTransfer(User, salesAcct, Item->Price) )
32 return 2; // 2: No balance
35 // HACK: Naming a slot "dead" disables it
36 if( strcmp(Item->Name, "dead") == 0 )
39 // Check if the dispense is possible
40 if( handler->CanDispense ) {
41 ret = handler->CanDispense( User, Item->ID );
42 if(ret) return 1; // 1: Unable to dispense
45 // Get username for debugging
46 username = Bank_GetAcctName(User);
48 // Actually do the dispense
49 if( handler->DoDispense ) {
50 ret = handler->DoDispense( User, Item->ID );
52 Log_Error("Dispense failed (%s dispensing %s:%i '%s')",
53 username, Item->Handler->Name, Item->ID, Item->Name);
55 return -1; // 1: Unknown Error again
63 reason = mkstr("Dispense - %s:%i %s", handler->Name, Item->ID, Item->Name);
64 _Transfer( User, salesAcct, Item->Price, reason );
68 actualUsername = Bank_GetAcctName(ActualUser);
70 // And log that it happened
73 // Special format for zero cost dispenses
74 Log_Info("test dispense '%s' (%s:%i) for %s by %s [no change]",
75 Item->Name, handler->Name, Item->ID,
76 username, actualUsername
81 Log_Info("dispense '%s' (%s:%i) for %s by %s [cost %i, balance %i]",
82 Item->Name, handler->Name, Item->ID,
83 username, actualUsername, Item->Price, Bank_GetBalance(User)
88 free( actualUsername );
93 * \brief Refund a dispense
95 int DispenseRefund(int ActualUser, int DestUser, tItem *Item, int OverridePrice)
99 char *username, *actualUsername;
101 src_acct = _GetSalesAcct(Item);
103 if( OverridePrice > 0 )
104 price = OverridePrice;
108 ret = _Transfer( src_acct, DestUser, price, "Refund");
111 username = Bank_GetAcctName(DestUser);
112 actualUsername = Bank_GetAcctName(ActualUser);
114 Log_Info("refund '%s' (%s:%i) to %s by %s [cost %i, balance %i]",
115 Item->Name, Item->Handler->Name, Item->ID,
116 username, actualUsername, price, Bank_GetBalance(DestUser)
120 free(actualUsername);
126 * \brief Give money from one user to another
128 int DispenseGive(int ActualUser, int SrcUser, int DestUser, int Ammount, const char *ReasonGiven)
131 char *actualUsername;
132 char *srcName, *dstName;
134 // HACK: Naming a slot "dead" disables it (catch for snack)
135 if( strcmp(ReasonGiven, "dead") == 0 )
138 if( Ammount < 0 ) return 1; // Um... negative give? Not on my watch!
140 ret = _Transfer( SrcUser, DestUser, Ammount, ReasonGiven );
141 if(ret) return 2; // No Balance
144 actualUsername = Bank_GetAcctName(ActualUser);
145 srcName = Bank_GetAcctName(SrcUser);
146 dstName = Bank_GetAcctName(DestUser);
148 Log_Info("give %i from %s to %s by %s [balances %i, %i] - %s",
149 Ammount, srcName, dstName, actualUsername,
150 Bank_GetBalance(SrcUser), Bank_GetBalance(DestUser),
156 free(actualUsername);
163 * \brief Move money from one user to another (Admin Only)
165 int DispenseTransfer(int ActualUser, int SrcUser, int DestUser, int Ammount, const char *ReasonGiven)
168 char *actualUsername;
169 char *srcName, *dstName;
171 // Make sure the user is an admin
172 if( !(Bank_GetFlags(ActualUser) & USER_FLAG_ADMIN) )
175 ret = _Transfer( SrcUser, DestUser, Ammount, ReasonGiven );
176 if(ret) return 2; // No Balance
179 actualUsername = Bank_GetAcctName(ActualUser);
180 srcName = Bank_GetAcctName(SrcUser);
181 dstName = Bank_GetAcctName(DestUser);
183 Log_Info("move %i from %s to %s by %s [balances %i, %i] - %s",
184 Ammount, srcName, dstName, actualUsername,
185 Bank_GetBalance(SrcUser), Bank_GetBalance(DestUser),
191 free(actualUsername);
198 * \brief Add money to an account
200 int DispenseAdd(int ActualUser, int User, int Ammount, const char *ReasonGiven)
203 char *dstName, *byName;
205 #if DISPENSE_ADD_BELOW_MIN
206 ret = _Transfer( Bank_GetAcctByName(COKEBANK_ADDSRC_ACCT,1), User, Ammount, ReasonGiven );
208 ret = Bank_Transfer( Bank_GetAcctByName(COKEBANK_ADDSRC_ACCT,1), User, Ammount, ReasonGiven );
212 byName = Bank_GetAcctName(ActualUser);
213 dstName = Bank_GetAcctName(User);
215 Log_Info("add %i to %s by %s [balance %i] - %s",
216 Ammount, dstName, byName, Bank_GetBalance(User), ReasonGiven
225 int DispenseSet(int ActualUser, int User, int Balance, const char *ReasonGiven, int *OrigBalance)
227 int curBal = Bank_GetBalance(User);
228 char *byName, *dstName;
230 _Transfer( Bank_GetAcctByName(COKEBANK_DEBT_ACCT,1), User, Balance-curBal, ReasonGiven );
232 byName = Bank_GetAcctName(ActualUser);
233 dstName = Bank_GetAcctName(User);
235 Log_Info("set balance of %s to %i by %s [was %i, balance %i] - %s",
236 dstName, Balance, byName, curBal, Bank_GetBalance(User), ReasonGiven
239 *OrigBalance = curBal;
247 * \brief Donate money to the club
249 int DispenseDonate(int ActualUser, int User, int Ammount, const char *ReasonGiven)
252 char *srcName, *byName;
254 if( Ammount < 0 ) return 2;
256 ret = _Transfer( User, Bank_GetAcctByName(COKEBANK_DONATE_ACCT,1), Ammount, ReasonGiven );
259 byName = Bank_GetAcctName(ActualUser);
260 srcName = Bank_GetAcctName(User);
262 Log_Info("donate %i from %s by %s [balance %i] - %s",
263 Ammount, srcName, byName, Bank_GetBalance(User), ReasonGiven
272 int DispenseUpdateItem(int User, tItem *Item, const char *NewName, int NewPrice)
277 if( NewPrice < 0 ) return 2;
278 if( !Item ) return 2;
279 if( strlen(NewName) < 1 ) return 2;
283 Item->Name = strdup(NewName);
284 Item->Price = NewPrice;
286 username = Bank_GetAcctName(User);
288 Log_Info("item %s:%i updated to '%s' %i by %s",
289 Item->Handler->Name, Item->ID,
290 NewName, NewPrice, username
301 // --- Internal Functions ---
302 int _GetMinBalance(int Account)
304 int flags = Bank_GetFlags(Account);
306 // Evil little piece of HACK:
307 // root's balance cannot be changed by any of the above functions
308 // - Stops dispenses as root by returning insufficent balance.
310 char *username = Bank_GetAcctName(Account);
311 if( strcmp(username, "root") == 0 )
319 // - Internal accounts have no lower bound
320 if( flags & USER_FLAG_INTERNAL ) return INT_MIN;
323 // if( flags & USER_FLAG_ADMIN ) return -5000;
326 // if( flags & USER_FLAG_COKE ) return -2000;
328 // Anyone else, non-negative
333 * \brief Check if a transfer is possible
334 * \return Boolean success
336 int _CanTransfer(int Source, int Destination, int Ammount)
338 // if( Bank_GetFlags(Source) & USER_FLAG_DISABLED )
342 if( Bank_GetBalance(Source) - Ammount < _GetMinBalance(Source) )
347 if( Bank_GetBalance(Destination) + Ammount < _GetMinBalance(Destination) )
353 int _Transfer(int Source, int Destination, int Ammount, const char *Reason)
355 if( !_CanTransfer(Source, Destination, Ammount) )
357 return Bank_Transfer(Source, Destination, Ammount, Reason);
360 int _GetSalesAcct(tItem *Item)
362 char string[sizeof(COKEBANK_SALES_PREFIX)+strlen(Item->Handler->Name)];
363 strcpy(string, COKEBANK_SALES_PREFIX);
364 strcat(string, Item->Handler->Name);
365 return Bank_GetAcctByName(string, 1);