Practical multiple providers in Entity Framework Core

I’ve been developing an ASP.Net Core backend. Naturally, Entity Framework (EF) Core is used as the object-database mapper.

One cool thing about EF is that it supports many database providers: sqlite, postgres, mssql, etc. Therefore, I decided to allow configuration-based provider selection. The site administrator can choose a preferred db provider in configuration:

1
2
3
4
{
"DbProvider": "sqlite",
"DbConnString": "DataSource=/tmp/db.sqlite",
}

Unfortunately, this is one of a few things that are, albeit documented, quite poorly described in MSDN. After spending an hour to figure out everything not mentioned in the docs, I came up with my own pattern for this, and this post is to keep a reference for myself. Hopefully, others can also benefit from this.

关于雀魂公平性与“牌山声明”的思考

最近开始玩雀魂了。我也就自然而然地开始考虑:对于这种运气成分很重的游戏,怎样保证运营方公平对待玩家、不因为猫粮购买量控制胜率?现在CRT这样的高水平赛事也在雀魂上举办了,运营能否干预比赛结果就更为重要。我们先看看雀魂现在是怎么做的,以下内容摘自萌娘百科

雀魂保证游戏生成完全随机,在游戏开始之时牌山序列已经固定,不会根据场面情况针对性地发牌。为证明此声明,游戏引入了MD5码验证系统。MD5码被广泛的应用于加密解密技术,它通过一个固定的算法把输入的字节(牌山序列)转化成一个字符串码。MD5码具有单向性、唯一性和混沌性的。

对局中,玩家可以点击左上角的宝牌位置查看本次对局牌山生成MD5码并记录下来。MD5码是每一次配牌生成一次的。对局结束后,玩家可以在牌谱中对照每一个小局的MD5码是否相同。以此验证游戏中给的MD5码没有给错。

本文引自萌娘百科(https://zh.moegirl.org),文字内容默认使用《知识共享 署名-非商业性使用-相同方式共享 3.0》协议。

的确,MD5验证牌山代码可以保证发牌姬不会在对局中针对性地发牌,但是它忽略了另一个问题:

如果运营想给玩家发个天和四暗刻单骑怎么办?

换言之,这个系统还是不能保证运营没有控制玩家手牌好坏、从而操作一局甚至一场比赛的结果。个人来说,我愿意相信猫粮没有这么做。但当你考虑密码学问题(都上MD5了),信任就只能基于“技术上不可行(一般指算力不足)”了。

于是我们希望解决的问题是:怎样让玩家相信运营没有控制牌山?我第一时间想到的是这样的一个协议:

  1. 公开由随机数种子生成牌山的代码,公开一段长字符串(app)。
  2. 在每局的开始时,生成一个随机数X。向玩家公开 SHA256(X),并把 SHA256(X||app) 作为种子生成牌山。
  3. 在对局结束时公开 X。玩家可以验证两个哈希值和牌山生成过程。

这样做保证了运营不能刻意构造一个牌山,因为即使可以从牌山倒退回需要的种子(这已经很难了,尤其是代码需要被公开审查的情况下),也无法从种子推出 X但是,运营可以用一台小霸王不停生成牌山并保存符合某些条件(比如天和)的 X 日后使用。因此这个协议也并不完美。

这里的问题是,运营仍然可以选择 X。于是我们可以稍微修改一下“生成一个随机数X”这一步:由每一个玩家(客户端)生成一个随机数,最终 X 为这些随机数拼接后的SHA256哈希值。游戏后,玩家们(尤其是比赛场)可以线下验证各自的随机数。

当然这个协议也只是一时兴起的产物,可能有其他问题,不知各位看官有什么想法。

另外,在密码学中有一个有趣的问题:怎样让两个人通过电话打扑克,同时保证公平性?利用这个问题的解法,应该可以设计一个由客户端负责合作洗牌的协议。这就留给读者作为练习了(?)

试用了一下各种出版社官方漫画app

学读音:app [ ap ]

前段时间想看点原版漫画,顺便练习一下日语(?)。本来是在B漫和DMG看,但一方面担心更新速度,另一方面担心内容删减……所以下载了芳文社、讲谈社、小学馆的官方app。
单是搞明白各家的阅读/付费模式就花了一些时间,遂写这么篇文章记录一下。

TL;DR B漫的用户体验吊打全场,但是我选择……

JavaScript event listener for history.pushState

In HTML there is an event onpopstate, but not onpushstate or onalterstate. How can we monitor such state changes? The answer is to alter the history.pushState function and manually dispatch an event inside.

More over, suppose we are writing a Chrome extension which has run_at: "document_start" that aims to capture all changes in states. Then we need to inject a <script> tag into the HTML, and we must do it as early as possible - right after the <head> tag is available. To achieve this we use a MutationObserver.

Optimizing C# reflection method calls

TL;DR: Func<> and Action<> instead of MethodInfo.Invoke runs 50 times faster

I can recall the excitement when I first learnt about reflection in C#. At that time my programming experience was limited to basic VB6 and C, so being able to browse type information was completely new to me. I was shocked and inspired by the possiblities that reflection can bring.

Reflection enables a lot of applications. For example, GameObject.SendMessage in Unity is fulfilled by finding the method with a name via reflection and then invoking it. Another important application is generic serializers. Without reflection, serializing objects will involve the pain of writing similar routines for every class[1]. Generic serializers like XmlSerializer and BinaryFormatter have saved a huge amount of development effort.

[1] Or some messy template and macro magic in C++ - see this StackOverflow answer for more.

However, we may overlook the performance cost as we enjoy the convenience. The rest of this post measures the reflection method calls in C#, and propose an optimization with delegate.