/// <inheritdoc/> public override object ConvertFrom(ref ObjectContext objectContext, Scalar fromScalar) { var idIndex = fromScalar.Value.IndexOf('~'); var id = ItemId.Empty; var keyString = fromScalar.Value; if (idIndex >= 0) { var idString = fromScalar.Value.Substring(0, idIndex); keyString = fromScalar.Value.Substring(idIndex + 1); id = ItemId.Parse(idString); } var keyType = objectContext.Descriptor.Type.GetGenericArguments()[0]; var keyDescriptor = objectContext.SerializerContext.FindTypeDescriptor(keyType); var keySerializer = objectContext.SerializerContext.Serializer.GetSerializer(objectContext.SerializerContext, keyDescriptor); var scalarKeySerializer = keySerializer as ScalarSerializerBase; // TODO: deserialize non-scalar keys! if (scalarKeySerializer == null) { throw new InvalidOperationException("Non-scalar key not yet supported!"); } var context = new ObjectContext(objectContext.SerializerContext, null, keyDescriptor); var key = scalarKeySerializer.ConvertFrom(ref context, new Scalar(keyString)); var result = Activator.CreateInstance(typeof(KeyWithId <>).MakeGenericType(keyType), id, key); return(result); }
/// <summary> /// This method executes on the bidder's partition. /// Called by web: priority 0 /// </summary> public async Task <ItemInfo> CreateItemAsync(String sellerEmail, String itemName, String imageUrl, DateTime expiration, Decimal startAmount, CancellationToken cancellationToken) { // NOTE: If items gets large, old item value (but not key) can move to warm storage // If user exists, create item & transactionally and it to user's items dictionary & unexpired items dictionary Email _sellerEmail = Email.Parse(sellerEmail); using (var tx = CreateTransaction()) { var cr = await m_users.TryGetValueAsync(tx, _sellerEmail); if (!cr.HasValue) { throw new InvalidOperationException($"Seller '{_sellerEmail}' doesn't exist."); } // Look up user's (seller's) auction item dictionary & add the new item to it: IReliableDictionary <ItemId, ItemInfo> userItems = await GetSellerItemsAsync(_sellerEmail); ItemId itemId = ItemId.Parse(_sellerEmail, itemName); ItemInfo item = new ItemInfo(itemId, imageUrl, expiration, new[] { new Bid(_sellerEmail, startAmount) }); // Seller places first bid try { await userItems.AddAsync(tx, itemId, item); // TODO: If already exists } catch (Exception ex) { throw new InvalidOperationException($"Seller '{itemId.Seller}' is already selling '{itemId.ItemName}'.", ex); } await m_unexpiredItems.AddAsync(tx, itemId); await tx.CommitAsync(); return(item); } }
/// <summary> /// This method executes on the bidder's partition. /// Called by web: priority 0 /// </summary> public async Task <Bid[]> PlaceBidAsync(String bidderEmail, String sellerEmail, String itemName, Decimal bidAmount, CancellationToken ct) { Email _sellerEmail = Email.Parse(sellerEmail); using (var tx = CreateTransaction()) { Email _bidderEmail = Email.Parse(bidderEmail); ItemId itemId = ItemId.Parse(_sellerEmail, itemName); var cr = await m_users.TryGetValueAsync(tx, _bidderEmail); if (!cr.HasValue) { throw new InvalidOperationException($"Bidder '{_bidderEmail}' doesn't exist."); } // Create new User object identical to current with new itemId added to it (if not already in collection [idempotent]) UserInfo userInfo = cr.Value; if (!userInfo.ItemsBidding.Contains(itemId)) { userInfo = userInfo.AddItemBidding(itemId); await m_users.SetAsync(tx, _bidderEmail, userInfo); await tx.CommitAsync(); } // NOTE: If we fail here, the bidder thinks they're bidding on an item but the // item doesn't know about the bidder. If so, the bidder will not see their latest bid. // The bidder could bid again (which is why adding the item is idempotent). } // Tell seller's partition to place a bid var proxy = (IInternalOperations) new ServiceOperations(s_partitionEndpointResolver, AuctionServiceNameUri); return(await proxy.PlaceBid2Async(bidderEmail, sellerEmail, itemName, bidAmount, ct)); }
/// <summary> /// This method executes on the seller's partition. This method is only ever called by PlaceBidAsync; not via Internet /// Not called by web at all /// </summary> public async Task <Bid[]> PlaceBid2Async(String bidderEmail, String sellerEmail, String itemName, Decimal bidAmount, CancellationToken ct) { // This method executes on the seller's partition Email _sellerEmail = Email.Parse(sellerEmail); using (var tx = CreateTransaction()) { Email _bidderEmail = Email.Parse(bidderEmail); ItemId itemId = ItemId.Parse(_sellerEmail, itemName); Boolean isUnexpiredItem = await m_unexpiredItems.ContainsAsync(tx, itemId); if (!isUnexpiredItem) { throw new InvalidOperationException("Item's auction expired or item doesn't exist."); } var sellersItems = await GetSellerItemsAsync(itemId.Seller); var conditionalItemInfo = await sellersItems.TryGetValueAsync(tx, itemId); if (!conditionalItemInfo.HasValue) { throw new InvalidOperationException("Item doesn't exist."); // We should never get here } var itemInfo = conditionalItemInfo.Value; var bids = itemInfo.Bids; var lastBid = bids.Last(); // Get current last bid //var cr = await m_users.TryGetValueAsync(tx2, itemId.Seller); if (DateTime.UtcNow > itemInfo.Expiration) { throw new InvalidOperationException("The action for this item has expired."); } if (_bidderEmail == lastBid.Bidder) { throw new InvalidOperationException("You cannot outbid yourself."); } if (bidAmount <= lastBid.Amount) { throw new InvalidOperationException("Your bid must be greater than the highest bid."); } // Create a new item copied from the original with the new bid itemInfo = itemInfo.AddBid(new Bid(_bidderEmail, bidAmount)); await sellersItems.SetAsync(tx, itemId, itemInfo); await tx.CommitAsync(); return(itemInfo.Bids.ToArray()); } }
public static ChestEvent Parse(string[] args) { if (args == null) { throw new ArgumentNullException(nameof(args)); } return(new ChestEvent(TextId.None) { ChestId = ChestId.Parse(args[1]), PickDifficulty = args.Length > 2 ? byte.Parse(args[2], CultureInfo.InvariantCulture) : (byte)0, InitialTextId = args.Length > 3 ? byte.Parse(args[3], CultureInfo.InvariantCulture) : (byte)255, UnlockedTextId = args.Length > 4 ? byte.Parse(args[4], CultureInfo.InvariantCulture) : (byte)255, KeyItemId = args.Length > 5 ? ItemId.Parse(args[5]) : ItemId.None, }); }
public void Parse(GameBitBuffer buffer) { Field0 = new RequiredMessageHeader(); Field0.Parse(buffer); Field1 = new ItemId(); Field1.Parse(buffer); }