public default Map<FanType, Integer> getFans(WinInfo winInfo) {
		// 先parse和牌units
		getAllWinTypes().forEach(winType -> winType.parseWinTileUnits(winInfo));
		// 如果没parse出来，说明不和牌，直接返回空map
		if (winInfo.getUnits() == null || winInfo.getUnits().isEmpty())
			return Collections.emptyMap();

		// 算番
		Map<FanType, Integer> attachedFanTypes = new HashMap<>();
		LinkedList<FanType> uncheckedFanTypes = new LinkedList<>(getAllFanTypes());
		Map<FanType, Integer> fans = new HashMap<>();

		FanType crtFanType;
		while ((crtFanType = uncheckedFanTypes.pollFirst()) != null) {
			Integer matchCount;

			matchCount = attachedFanTypes.get(crtFanType);
			if (matchCount == null)
				matchCount = crtFanType.match(winInfo);

			if (matchCount > 0) {
				fans.put(crtFanType, crtFanType.score() * matchCount);
				attachedFanTypes.put(crtFanType, matchCount);
				Set<? extends FanType> covered = crtFanType.covered();
				if (covered != null && !covered.isEmpty())
					uncheckedFanTypes.removeAll(covered);
			}
		}

		return fans;
	}