初始化

master
小余迪 2023-09-01 10:51:28 +08:00
commit 889e9f7c6c
129 changed files with 9089 additions and 0 deletions

50
.gitignore vendored 100644
View File

@ -0,0 +1,50 @@
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
target
.project
.DS_Store
.classpath
.settings
*.log
*.log.*
.idea
.gradle
build
bin
out
*.iml
target
.project
.DS_Store
.classpath
.settings
/.classpath
/target
/.settings
/.project
/ratel-landlords/.project
.vscode

201
LICENSE 100644
View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

176
PROTOCO_CN.md 100644
View File

@ -0,0 +1,176 @@
[toc]
# Ratel-Client开发文档
## 介绍
### 什么是Ratel
[Ratel](https://github.com/ainilili/ratel) 是一个可以在命令行中玩斗地主的项目可以使用小巧的jar包在拥有JVM环境的终端中进行游戏同时支持人人对战和人机对战两种模式丰富你的空闲时间
Ratel使用Java语言开发[Netty 4.x](https://github.com/netty/netty)网络框架搭配[protobuf](https://github.com/protocolbuffers/protobuf)数据协议,可以支持多客户端同时游戏。
### Ratel-Client扩展
Ratel面向响应式架构通过事件码进行通讯对于Ratel-Client支持跨平台扩展换一种说法任何后端语言都可以开发Ratel-Client
在开发Ratel-Client前应该知道
- Ratel Server-Client交互网络协议为``TCP/IP``。
- Ratel Server-Client交互数据协议为[protobuf](https://github.com/protocolbuffers/protobuf)。
- Ratel以事件为驱动在Client将各个环节串联起来。
- Ratel所有的文案都由Client显示。
## 对接
### 架构你的客户端
我们可以使用任何后端语言就重写Ratel客户端Ratel默认的客户端的由Java语言编写如果你想使用其他语言重写以下是我们推荐的一种架构
![](https://user-gold-cdn.xitu.io/2018/11/17/16720fa649dfaea0?w=898&h=500&f=png&s=33655)
这种架构对于事件的处理非常友好,你可以设计一个抽象的``Event-Listener``接口,然后开发不同的实现去处理不同``CODE``对应的响应数据例如一个而简单的例子——Poker的显示以下是我们的处理流程的伪代码:
```
1、对服务端响应数据解码 ->
decode(msg)
2、解码后的数据 ->
ClientData{
String code;
String data;
}
3、通过code寻找对应的EventListener ->
showPokersEventListener = Map<code, EventListener>.get(code)
4、处理响应数据 ->
showPokersEventListener.call(server, data){
show(data);
server.write(msg);
}
```
以上只是简单的``Server-Client``的交互流程,有时候可能会出现``Client-Client``的场景例如客户端的选项面板的显示在我们从A层切换到B层再从B层返回到A层这时就需要做``Client-Client``的交互。
当然,大多数的交互重点集中在``Server-Client``而另一方面客户端大多都是在处理并显示服务端响应的数据对于真正的业务交互很少这对于客户端来说只要将事件绝对的丰富那么客户端的流程就会绝对的灵活。因此Ratel的客户端响应事件相比于服务端的响应事件数量多了几倍有余所以这对于客户端的架构要求就是要有足够的灵活性能够支持以下两个业务流
- Server-Client-Server
- Server-Client-Client-Server
之后,我们进入下一步!
### 定义数据实体
对于客户端和服务端交互的数据,为了承载,我们需要设计两个类去存放编解码后的数据,值得一提的是,客户端和服务端的数据结构一样,都由``CODE``、``DATA``和``INFO``三个字段组成:
- CODE - 对应的事件
- DATA - 传递的数据
- INFO - 信息(暂时用不到)
我们的编解码方式为``Protobuf``序列化,参考文件请看[这里](https://github.com/ainilili/ratel/tree/master/protoc-resource)。
### 对接协议
在我们做好对接的准备工作之后,可以通过以下协议文档开始实现客户端的业务!
#### 客户端事件
##### 连接成功事件
- ``CODE`` - CODE_CLIENT_CONNECT
- ``TYPE`` - TEXT
- ``DATA`` - 客户端被分配的ID
##### 退出房间事件
- ``CODE`` - CODE_CLIENT_EXIT
- ``TYPE`` - JSON
- ``DATA`` - 如下
字段名 | 含义
---|---
roomId | 房间ID
exitClientId | 退出者ID
exitClientNickname | 退出者昵称
参考数据
```
{"roomId":14,"exitClientId":64330,"exitClientNickname":"nico"}
```
##### 客户端踢出事件
- ``CODE`` - CODE_CLIENT_KICK
- ``TYPE`` - Text
- ``DATA`` - NULL
##### 设置昵称事件
- ``CODE`` - CODE_CLIENT_NICKNAME_SET
- ``TYPE`` - JSON
- ``DATA`` - 如下
字段名 | 含义
---|---
invalidLength | 有效长度当设置昵称超过10个字节会返回此字段
参考数据:
```
{"invalidLength":10}
```
##### 抢地主-地主诞生事件
- ``CODE`` - CODE_GAME_LANDLORD_CONFIRM
- ``TYPE`` - JSON
- ``DATA`` - 如下
字段名 | 含义
---|---
roomId | 房间ID
roomOwner | 房间所有者昵称
roomClientCount | 房间人数
landlordNickname | 地主昵称
landlordId | 地主ID
additionalPokers | 额外的三张牌
参考数据:
```
{"roomId":14,"roomOwner":"nico","roomClientCount":3,"landlordNickname":"robot_2","landlordId":-8,"additionalPokers":[{"level":"LEVEL_5","type":"DIAMOND"},{"level":"LEVEL_6","type":"CLUB"},{"level":"LEVEL_A","type":"DIAMOND"}]}
```
##### 抢地主-大家都没抢事件
- ``CODE`` - CODE_GAME_LANDLORD_CYCLE
- ``TYPE`` - TEXT
- ``DATA`` - NULL
TIP该事件触发后会连续触发重新游戏事件
##### 抢地主-抢地主决策事件
- ``CODE`` - CODE_GAME_LANDLORD_ELECT
- ``TYPE`` - JSON
- ``DATA`` - 如下
字段名 | 含义
---|---
roomId | 房间ID
roomOwner | 房间所有者昵称
roomClientCount | 房间人数
preClientNickname | 上一个客户端的昵称
nextClientNickname | 下一个客户端的昵称
nextClientId | 下一个客户端的ID
参考数据:
```
{"roomId":14,"roomOwner":"nico","roomClientCount":3,"preClientNickname":"nico1","nextClientNickname":"nico2","nextClientId":2}
```
##### 游戏结束事件
- ``CODE`` - CODE_GAME_OVER
- ``TYPE`` - JSON
- ``DATA`` - 如下
字段名 | 含义
---|---
winnerNickname | 获胜者昵称
winnerType | 获胜者类型(地主?农民)
参考数据:
```
{"winnerNickname":"nico","winnerType":"LANDLORD?PEASANT"}
```

86
README.md 100644
View File

@ -0,0 +1,86 @@
# Ratel
[![GitHub forks](https://img.shields.io/github/forks/ainilili/ratel?style=flat-square)](https://github.com/ainilili/ratel/network)
![GitHub release (latest by date)](https://img.shields.io/github/v/release/ainilili/ratel?style=flat-square)
![GitHub all releases](https://img.shields.io/github/downloads/ainilili/ratel/total?logo=spring&style=flat-square)
[![GitHub stars](https://img.shields.io/github/stars/ainilili/ratel?logo=java&style=flat-square)](https://github.com/ainilili/ratel/stargazers)
[![GitHub license](https://img.shields.io/github/license/ainilili/ratel?logo=apache&style=flat-square)](https://github.com/ainilili/ratel/blob/master/LICENSE)
![Build ratel(Java with Maven)](https://github.com/ainilili/ratel/workflows/Build%20ratel(Java%20with%20Maven)/badge.svg?branch=master)
![Docker Image Version (latest by date)](https://img.shields.io/docker/v/kebyn/ratel?label=Docker&logo=docker&style=flat-square)
## 介绍
基于Netty实现的命令行斗地主游戏为划水摸鱼而生~
> 新版开发中:[直通车](https://github.com/ratel-online),新增癞子模式,增加超时机制,完美复现欢乐斗地主,欢迎体验在线版 [http://rtol.isnico.com/](http://rtol.isnico.com/)
## 安装
首先下载打包确保本地安装有maven及JRE环境
```powershell
git clone https://github.com/ainilili/ratel.git
cd ratel
mvn install package
```
接下来分别运行 ``landlords-client`` 和 ``landlords-server`` 的 ``target`` 文件夹下的Jar包
```powershell
java -jar landlords-server/target/landlords-server-#{version}.jar -p 1024
java -jar landlords-client/target/landlords-client-#{version}.jar -p 1024 -h 127.0.0.1
```
客户端亦可直接运行,程序会自动拉取[Serverlist](https://github.com/ainilili/ratel/blob/master/serverlist.json)中的公网服务器:
```powershell
java -jar landlords-client/target/landlords-client-#{version}.jar
```
**注意**,实际运行中请将``#{version}``改为当前运行版本!
## 玩法介绍
在线试玩:[传送门](http://ratel.isnico.com)
![demo](demo.gif)
### 出牌规则
所有牌型:
```
┌──┐──┐──┐──┐──┐──┐──┐──┐──┐──┐──┐──┐──┐──┐──┐
│3 |4 |5 |6 |7 |8 |9 |10|J |Q |K |A |2 |S |X |
│♦ |♦ |♦ |♦ |♦ |♦ |♦ |♦ |♦ |♦ |♦ |♦ |♦ | | |
└──┘──┘──┘──┘──┘──┘──┘──┘──┘──┘──┘──┘──┘──┘──┘
```
示例:
- 王炸:``sx``
- 顺子:``34567``
- 三带一:``3334``
- 飞机:``333444a2``
- 单张10``0``或者``t``
- 单张A``a``或者``1``
- 封顶顺子:``34567890jqka``
- 不想出牌: ``pass``或``p``
- 退出: ``exit``或者``e``
- [更多](https://zh.wikipedia.org/zh-sg/%E9%AC%A5%E5%9C%B0%E4%B8%BB)
#### 协议支持
- TCP
- Websocket
Websocket协议的地址为 ``ws://host:port/ratel``Websocket的端口需要在原端口基础上加1 如果tcp端口为1024则ws端口需要为1025
## 划水俱乐部
QQ群 ``948365095``,划水一时爽,一直划水一直爽!
## 生态
- [go-ratel-client](https://github.com/ZuoFuhong/go-ratel)
- [javafx-ratel-client](https://github.com/marmot-z/javafx-ratel-client)
- [javascript-ratel-client](https://github.com/marmot-z/js-ratel-client)
## 教学
- [Ratel浅析] (https://github.com/HelloGitHub-Team/Article/blob/master/contents/Java/landlords/content.md)
- [Ratel玩法视频教学] (https://www.bilibili.com/video/av97603585)
## 更新日志
- [更新日志](https://github.com/ainilili/ratel/blob/master/UPDATE.md)
## 计划
- 支持高级难度机器人
## More
- [Serverlist.json](https://github.com/ainilili/ratel/blob/master/serverlist.json) 是当前的服务器列表, 如果你的服务器部署着当前最新版本的服务端并且分享给大家可以通过PR提交给我们!
- 如果您想贡献代码,非常欢迎提``PR``,我们将会合并优秀的代码.
- 如果您发现了``Bug``,非常欢迎提``Issue``给我们.
- 欢迎扩展其他语言的客户端.
- 联系我们请发邮件到 ``ainililia@163.com``.

13
UPDATE.md 100644
View File

@ -0,0 +1,13 @@
> Version 1.0.0 Updated
- Create room
- Join room
- Play game
> Version 1.1.0 Updated
- Service list selection
- The Robot model
- Nickname length verify
- Room timeout detection
- Let's replace the room timeout with Robot

BIN
demo.gif 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 536 KiB

60
docker/README.md 100644
View File

@ -0,0 +1,60 @@
1. [安装`docker`](https://docs.docker.com/install/linux/docker-ce/ubuntu/#install-using-the-convenience-script)
```
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
```
2. 客户端
+ 直接使用已经编译好的客户端
- `docker` 运行客户端,默认加入公网服务器 `39.105.65.8`
```
docker run --rm -it kebyn/ratel:client
```
等同于
```
docker run --rm -it kebyn/ratel:client -- 'java -jar *.jar -h 39.105.65.8'
```
- `docker` 运行客户端,加入公网服务器 `x.x.x.x`
```
docker run --rm -it kebyn/ratel:client -- 'java -jar *.jar -h x.x.x.x'
```
+ 自行编译 `docker` 客户端
- 下载并编译
```
git clone https://github.com/ainilili/ratel.git
cd ratel/docker/client
docker build -f Dockerfile -t ratel:client .
```
- 使用 `docker` 运行客户端,默认加入公网服务器 `39.105.65.8`
```
docker run --rm -it ratel:client
```
等同于
```
docker run --rm -it ratel:client -- 'java -jar *.jar -h 39.105.65.8'
```
- `docker` 运行客户端,加入公网服务器 `x.x.x.x`
```
docker run --rm -it kebyn/ratel:client -- 'java -jar *.jar -h x.x.x.x'
```
3. 服务端
+ 直接使用已经编译好的服务端
- `docker` 运行客户端,并指定使用`1024`端口
```
docker run --rm -d -p 1024:1024 kebyn/ratel:server
```
+ 自行编译 `docker` 客户端
- 下载并编译
```
git clone https://github.com/ainilili/ratel.git
cd ratel/docker/server
docker build -f Dockerfile -t ratel:server .
```
- 使用 `docker` 运行客户端
```
docker run --rm -d -p 1024:1024 ratel:server
```
等同于
```
docker run --rm -d -p 1024:1024 ratel:server -- 'java -jar *.jar -p 1024'
```
> 确保服务器防火墙允许`1024`端口访问,并且没有其它应用占用`1024`端口

View File

@ -0,0 +1,10 @@
FROM maven:3-jdk-8
RUN git clone https://github.com/ainilili/ratel.git
WORKDIR /ratel
RUN mvn install package
FROM openjdk:8-slim
COPY --from=0 /ratel/landlords-client/target/*.jar /opt
WORKDIR /opt
ENTRYPOINT ["bash", "-c"]
CMD ["java -jar *.jar -h 39.105.65.8"]

View File

@ -0,0 +1,10 @@
FROM maven:3-jdk-8
RUN git clone https://github.com/ainilili/ratel.git
WORKDIR /ratel
RUN mvn install package
FROM openjdk:8-slim
COPY --from=0 /ratel/landlords-server/target/*.jar /opt
WORKDIR /opt
ENTRYPOINT ["bash", "-c"]
CMD ["java -jar *.jar -p 1024"]

View File

@ -0,0 +1,59 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>landlords-client</artifactId>
<name>landlords-client</name>
<description>This is a console version of the fight landlord game</description>
<properties>
<start-class>org.nico.ratel.landlords.client.SimpleClient</start-class>
</properties>
<parent>
<groupId>com.smallnico.ratel</groupId>
<artifactId>landlords</artifactId>
<version>1.4.0</version>
</parent>
<dependencies>
<dependency>
<groupId>com.smallnico.ratel</groupId>
<artifactId>landlords-common</artifactId>
<version>1.4.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>${start-class}</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
<fork>true</fork>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,100 @@
package org.nico.ratel.landlords.client;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.List;
import java.util.Objects;
import org.nico.noson.Noson;
import org.nico.noson.entity.NoType;
import org.nico.ratel.landlords.client.entity.User;
import org.nico.ratel.landlords.client.proxy.ProtobufProxy;
import org.nico.ratel.landlords.client.proxy.WebsocketProxy;
import org.nico.ratel.landlords.features.Features;
import org.nico.ratel.landlords.print.SimplePrinter;
import org.nico.ratel.landlords.print.SimpleWriter;
import org.nico.ratel.landlords.utils.StreamUtils;
public class SimpleClient {
public static int id = -1;
public final static String VERSION = Features.VERSION_1_3_0;
public static String serverAddress;
public static int port = 1024;
public static String protocol = "pb";
private final static String[] serverAddressSource = new String[]{
"https://raw.githubusercontent.com/ainilili/ratel/master/serverlist.json", //Source
"https://cdn.jsdelivr.net/gh/ainilili/ratel@master/serverlist.json", //CN CDN
"https://raw.fastgit.org/ainilili/ratel/master/serverlist.json", //HongKong CDN
"https://cdn.staticaly.com/gh/ainilili/ratel/master/serverlist.json", //Japanese CDN
"https://ghproxy.com/https://raw.githubusercontent.com/ainilili/ratel/master/serverlist.json", //Korea CDN
"https://gitee.com/ainilili/ratel/raw/master/serverlist.json" //CN Gitee
};
public static void main(String[] args) throws InterruptedException, IOException, URISyntaxException {
if (args != null && args.length > 0) {
for (int index = 0; index < args.length; index = index + 2) {
if (index + 1 < args.length) {
if (args[index].equalsIgnoreCase("-p") || args[index].equalsIgnoreCase("-port")) {
port = Integer.parseInt(args[index + 1]);
}
if (args[index].equalsIgnoreCase("-h") || args[index].equalsIgnoreCase("-host")) {
serverAddress = args[index + 1];
}
if (args[index].equalsIgnoreCase("-ptl") || args[index].equalsIgnoreCase("-protocol")) {
protocol = args[index + 1];
}
}
}
}
if (serverAddress == null) {
List<String> serverAddressList = getServerAddressList();
if (serverAddressList == null || serverAddressList.size() == 0) {
throw new RuntimeException("Please use '-host' to setting server address.");
}
SimplePrinter.printNotice("Please select a server:");
for (int i = 0; i < serverAddressList.size(); i++) {
SimplePrinter.printNotice((i + 1) + ". " + serverAddressList.get(i));
}
int serverPick = Integer.parseInt(SimpleWriter.write(User.INSTANCE.getNickname(), "option"));
while (serverPick < 1 || serverPick > serverAddressList.size()) {
try {
SimplePrinter.printNotice("The server address does not exist!");
serverPick = Integer.parseInt(SimpleWriter.write(User.INSTANCE.getNickname(), "option"));
} catch (NumberFormatException ignore) {}
}
serverAddress = serverAddressList.get(serverPick - 1);
String[] elements = serverAddress.split(":");
serverAddress = elements[0];
port = Integer.parseInt(elements[1]);
}
if (Objects.equals(protocol, "pb")) {
new ProtobufProxy().connect(serverAddress, port);
} else if (Objects.equals(protocol, "ws")) {
new WebsocketProxy().connect(serverAddress, port + 1);
} else {
throw new UnsupportedOperationException("Unsupported protocol " + protocol);
}
}
private static List<String> getServerAddressList() {
for (String serverAddressSource : serverAddressSource) {
try {
String serverInfo = StreamUtils.convertToString(new URL(serverAddressSource));
return Noson.convert(serverInfo, new NoType<List<String>>() {});
} catch (IOException e) {
SimplePrinter.printNotice("Try connected " + serverAddressSource + " failed: " + e.getMessage());
}
}
return null;
}
}

View File

@ -0,0 +1,39 @@
package org.nico.ratel.landlords.client.entity;
public class User {
public static final User INSTANCE = new User();
/** 是否游戏中 */
private volatile boolean isPlaying = false;
/** 是否观战中 */
private volatile boolean isWatching = false;
private String nickname = "player";
private User() {}
public boolean isPlaying() {
return isPlaying;
}
public void setPlaying(boolean playing) {
isPlaying = playing;
}
public boolean isWatching() {
return isWatching;
}
public void setWatching(boolean watching) {
isWatching = watching;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
}

View File

@ -0,0 +1,60 @@
package org.nico.ratel.landlords.client.event;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.nico.ratel.landlords.channel.ChannelUtils;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.enums.ServerEventCode;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
public abstract class ClientEventListener {
public abstract void call(Channel channel, String data);
public final static Map<ClientEventCode, ClientEventListener> LISTENER_MAP = new HashMap<>();
private final static String LISTENER_PREFIX = "org.nico.ratel.landlords.client.event.ClientEventListener_";
protected static List<Poker> lastPokers = null;
protected static String lastSellClientNickname = null;
protected static String lastSellClientType = null;
protected static void initLastSellInfo() {
lastPokers = null;
lastSellClientNickname = null;
lastSellClientType = null;
}
@SuppressWarnings("unchecked")
public static ClientEventListener get(ClientEventCode code) {
ClientEventListener listener;
try {
if (ClientEventListener.LISTENER_MAP.containsKey(code)) {
listener = ClientEventListener.LISTENER_MAP.get(code);
} else {
String eventListener = LISTENER_PREFIX + code.name().toUpperCase(Locale.ROOT);
Class<ClientEventListener> listenerClass = (Class<ClientEventListener>) Class.forName(eventListener);
listener = listenerClass.newInstance();
ClientEventListener.LISTENER_MAP.put(code, listener);
}
return listener;
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
protected ChannelFuture pushToServer(Channel channel, ServerEventCode code, String datas) {
return ChannelUtils.pushToServer(channel, code, datas);
}
protected ChannelFuture pushToServer(Channel channel, ServerEventCode code) {
return pushToServer(channel, code, null);
}
}

View File

@ -0,0 +1,28 @@
package org.nico.ratel.landlords.client.event;
import org.nico.noson.Noson;
import org.nico.ratel.landlords.client.SimpleClient;
import org.nico.ratel.landlords.enums.ServerEventCode;
import org.nico.ratel.landlords.features.Features;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.print.SimplePrinter;
import io.netty.channel.Channel;
import org.nico.ratel.landlords.utils.JsonUtils;
import java.util.HashMap;
import java.util.Map;
public class ClientEventListener_CODE_CLIENT_CONNECT extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
SimplePrinter.printNotice("Connected to server. Welcome to ratel!");
SimpleClient.id = Integer.parseInt(data);
Map<String, Object> infos = new HashMap<>();
infos.put("version", SimpleClient.VERSION);
pushToServer(channel, ServerEventCode.CODE_CLIENT_INFO_SET, Noson.reversal(infos));
}
}

View File

@ -0,0 +1,30 @@
package org.nico.ratel.landlords.client.event;
import java.util.Map;
import org.nico.ratel.landlords.client.SimpleClient;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.print.SimplePrinter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_CLIENT_EXIT extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
Map<String, Object> map = MapHelper.parser(data);
Integer exitClientId = (Integer) map.get("exitClientId");
String role;
if (exitClientId == SimpleClient.id) {
role = "You";
} else {
role = String.valueOf(map.get("exitClientNickname"));
}
SimplePrinter.printNotice(role + " left the room. Room disbanded!\n");
get(ClientEventCode.CODE_SHOW_OPTIONS).call(channel, data);
}
}

View File

@ -0,0 +1,18 @@
package org.nico.ratel.landlords.client.event;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.print.SimplePrinter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_CLIENT_KICK extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
SimplePrinter.printNotice("You have been kicked from the room for being idle.\n");
get(ClientEventCode.CODE_SHOW_OPTIONS).call(channel, data);
}
}

View File

@ -0,0 +1,44 @@
package org.nico.ratel.landlords.client.event;
import java.util.Map;
import org.nico.noson.util.string.StringUtils;
import org.nico.ratel.landlords.client.entity.User;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.enums.ServerEventCode;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.print.SimplePrinter;
import org.nico.ratel.landlords.print.SimpleWriter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_CLIENT_NICKNAME_SET extends ClientEventListener {
public static final int NICKNAME_MAX_LENGTH = 10;
@Override
public void call(Channel channel, String data) {
// If it is not the first time that the user is prompted to enter nickname
// If first time, data = null or "" otherwise not empty
if (StringUtils.isNotBlank(data)) {
Map<String, Object> dataMap = MapHelper.parser(data);
if (dataMap.containsKey("invalidLength")) {
SimplePrinter.printNotice("Your nickname has invalid length: " + dataMap.get("invalidLength"));
}
}
SimplePrinter.printNotice("Please set your nickname (upto " + NICKNAME_MAX_LENGTH + " characters)");
String nickname = SimpleWriter.write(User.INSTANCE.getNickname(), "nickname");
// If the length of nickname is more that NICKNAME_MAX_LENGTH
if (nickname.trim().length() > NICKNAME_MAX_LENGTH) {
String result = MapHelper.newInstance().put("invalidLength", nickname.trim().length()).json();
get(ClientEventCode.CODE_CLIENT_NICKNAME_SET).call(channel, result);
} else {
pushToServer(channel, ServerEventCode.CODE_CLIENT_NICKNAME_SET, nickname);
User.INSTANCE.setNickname(nickname);
}
}
}

View File

@ -0,0 +1,31 @@
package org.nico.ratel.landlords.client.event;
import java.util.List;
import java.util.Map;
import org.nico.noson.Noson;
import org.nico.noson.entity.NoType;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.enums.ServerEventCode;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.print.SimplePrinter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_GAME_LANDLORD_CONFIRM extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
Map<String, Object> map = MapHelper.parser(data);
String landlordNickname = String.valueOf(map.get("landlordNickname"));
SimplePrinter.printNotice(landlordNickname + " has become the landlord and gotten three extra cards");
List<Poker> additionalPokers = Noson.convert(map.get("additionalPokers"), new NoType<List<Poker>>() {});
SimplePrinter.printPokers(additionalPokers);
pushToServer(channel, ServerEventCode.CODE_GAME_POKER_PLAY_REDIRECT);
}
}

View File

@ -0,0 +1,15 @@
package org.nico.ratel.landlords.client.event;
import org.nico.ratel.landlords.print.SimplePrinter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_GAME_LANDLORD_CYCLE extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
SimplePrinter.printNotice("No player takes the landlord, so redealing cards.");
}
}

View File

@ -0,0 +1,44 @@
package org.nico.ratel.landlords.client.event;
import java.util.Map;
import org.nico.ratel.landlords.client.SimpleClient;
import org.nico.ratel.landlords.client.entity.User;
import org.nico.ratel.landlords.enums.ServerEventCode;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.print.SimplePrinter;
import org.nico.ratel.landlords.print.SimpleWriter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_GAME_LANDLORD_ELECT extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
Map<String, Object> map = MapHelper.parser(data);
int turnClientId = (int) map.get("nextClientId");
if (map.containsKey("preClientNickname")) {
SimplePrinter.printNotice(map.get("preClientNickname") + " don't rob the landlord!");
}
if(turnClientId == SimpleClient.id) {
SimplePrinter.printNotice("It's your turn. Do you want to rob the landlord? [Y/N] (enter [exit|e] to exit current room)");
String line = SimpleWriter.write(User.INSTANCE.getNickname(), "Y/N");
if (line.equalsIgnoreCase("exit") || line.equalsIgnoreCase("e")) {
pushToServer(channel, ServerEventCode.CODE_CLIENT_EXIT);
} else if (line.equalsIgnoreCase("Y")) {
pushToServer(channel, ServerEventCode.CODE_GAME_LANDLORD_ELECT, "TRUE");
} else if (line.equalsIgnoreCase("N")) {
pushToServer(channel, ServerEventCode.CODE_GAME_LANDLORD_ELECT, "FALSE");
} else {
SimplePrinter.printNotice("Invalid options");
call(channel, data);
}
} else {
SimplePrinter.printNotice("It's " + map.get("nextClientNickname") + "'s turn. Please wait patiently for his/her confirmation !");
}
}
}

View File

@ -0,0 +1,45 @@
package org.nico.ratel.landlords.client.event;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.nico.noson.Noson;
import org.nico.noson.entity.NoType;
import org.nico.ratel.landlords.client.SimpleClient;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.print.SimplePrinter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_GAME_OVER extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
Map<String, Object> map = MapHelper.parser(data);
SimplePrinter.printNotice("\nPlayer " + map.get("winnerNickname") + "[" + map.get("winnerType") + "]" + " won the game");
if (map.containsKey("scores")){
List<Map<String, Object>> scores = Noson.convert(map.get("scores"), new NoType<List<Map<String, Object>>>() {});
for (Map<String, Object> score : scores) {
if (! Objects.equals(score.get("clientId"), SimpleClient.id)) {
SimplePrinter.printNotice(score.get("nickName").toString() + "'s rest poker is:");
SimplePrinter.printPokers(Noson.convert(score.get("pokers"), new NoType<List<Poker>>() {}));
}
}
SimplePrinter.printNotice("\n");
// print score
for (Map<String, Object> score : scores) {
String scoreInc = score.get("scoreInc").toString();
String scoreTotal = score.get("score").toString();
if (SimpleClient.id != (int) score.get("clientId")) {
SimplePrinter.printNotice(score.get("nickName").toString() + "'s score is " + scoreInc + ", total score is " + scoreTotal);
} else {
SimplePrinter.printNotice("your score is " + scoreInc + ", total score is " + scoreTotal);
}
}
ClientEventListener_CODE_GAME_READY.gameReady(channel);
}
}
}

View File

@ -0,0 +1,130 @@
package org.nico.ratel.landlords.client.event;
import io.netty.channel.Channel;
import org.nico.noson.Noson;
import org.nico.noson.entity.NoType;
import org.nico.ratel.landlords.client.SimpleClient;
import org.nico.ratel.landlords.client.entity.User;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.entity.PokerSell;
import org.nico.ratel.landlords.enums.PokerLevel;
import org.nico.ratel.landlords.enums.ServerEventCode;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.helper.PokerHelper;
import org.nico.ratel.landlords.print.SimplePrinter;
import org.nico.ratel.landlords.print.SimpleWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class ClientEventListener_CODE_GAME_POKER_PLAY extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
Map<String, Object> map = MapHelper.parser(data);
SimplePrinter.printNotice("It's your turn to play, your cards are as follows: ");
List<Poker> pokers = Noson.convert(map.get("pokers"), new NoType<List<Poker>>() {
});
SimplePrinter.printPokers(pokers);
SimplePrinter.printNotice("Last cards are");
SimplePrinter.printNotice(map.containsKey("lastPokers")?map.get("lastPokers").toString():"");
SimplePrinter.printNotice("Please enter the combination you came up with (enter [exit|e] to exit current room, enter [pass|p] to jump current round, enter [view|v] to show all valid combinations.)");
String line = SimpleWriter.write(User.INSTANCE.getNickname(), "combination");
if (line == null) {
SimplePrinter.printNotice("Invalid enter");
call(channel, data);
} else {
if (line.equalsIgnoreCase("pass") || line.equalsIgnoreCase("p")) {
pushToServer(channel, ServerEventCode.CODE_GAME_POKER_PLAY_PASS);
} else if (line.equalsIgnoreCase("exit") || line.equalsIgnoreCase("e")) {
pushToServer(channel, ServerEventCode.CODE_CLIENT_EXIT);
} else if (line.equalsIgnoreCase("view") || line.equalsIgnoreCase("v")) {
if (!map.containsKey("lastSellPokers") || !map.containsKey("lastSellClientId")) {
SimplePrinter.printNotice("Current server version unsupport this feature, need more than v1.2.4.");
call(channel, data);
return;
}
Object lastSellPokersObj = map.get("lastSellPokers");
if (lastSellPokersObj == null || Integer.valueOf(SimpleClient.id).equals(map.get("lastSellClientId"))) {
SimplePrinter.printNotice("Up to you !");
call(channel, data);
return;
} else {
List<Poker> lastSellPokers = Noson.convert(lastSellPokersObj, new NoType<List<Poker>>() {});
List<PokerSell> sells = PokerHelper.validSells(PokerHelper.checkPokerType(lastSellPokers), pokers);
if (sells.size() == 0) {
SimplePrinter.printNotice("It is a pity that, there is no winning combination...");
call(channel, data);
return;
}
for (int i = 0; i < sells.size(); i++) {
SimplePrinter.printNotice(i + 1 + ". " + PokerHelper.textOnlyNoType(sells.get(i).getSellPokers()));
}
while (true) {
SimplePrinter.printNotice("You can enter index to choose anyone.(enter [back|b] to go back.)");
line = SimpleWriter.write(User.INSTANCE.getNickname(), "choose");
if (line.equalsIgnoreCase("back") || line.equalsIgnoreCase("b")) {
call(channel, data);
return;
} else {
try {
int choose = Integer.valueOf(line);
if (choose < 1 || choose > sells.size()) {
SimplePrinter.printNotice("The input number must be in the range of 1 to " + sells.size() + ".");
} else {
List<Poker> choosePokers = sells.get(choose - 1).getSellPokers();
List<Character> options = new ArrayList<>();
for (Poker poker : choosePokers) {
options.add(poker.getLevel().getAlias()[0]);
}
pushToServer(channel, ServerEventCode.CODE_GAME_POKER_PLAY, Noson.reversal(options.toArray(new Character[]{})));
break;
}
} catch (NumberFormatException e) {
SimplePrinter.printNotice("Please input a number.");
}
}
}
}
// PokerHelper.validSells(lastPokerSell, pokers);
} else {
String[] strs = line.split(" ");
List<Character> options = new ArrayList<>();
boolean access = true;
for (int index = 0; index < strs.length; index++) {
String str = strs[index];
for (char c : str.toCharArray()) {
if (c == ' ' || c == '\t') {
} else {
if (!PokerLevel.aliasContains(c)) {
access = false;
break;
} else {
options.add(c);
}
}
}
}
if (access) {
pushToServer(channel, ServerEventCode.CODE_GAME_POKER_PLAY, Noson.reversal(options.toArray(new Character[]{})));
} else {
SimplePrinter.printNotice("Invalid enter");
if (lastPokers != null) {
SimplePrinter.printNotice(lastSellClientNickname + "[" + lastSellClientType + "] played:");
SimplePrinter.printPokers(lastPokers);
}
call(channel, data);
}
}
}
}
}

View File

@ -0,0 +1,16 @@
package org.nico.ratel.landlords.client.event;
import org.nico.ratel.landlords.enums.ServerEventCode;
import org.nico.ratel.landlords.print.SimplePrinter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_GAME_POKER_PLAY_CANT_PASS extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
SimplePrinter.printNotice("You played the previous card, so you can't pass.");
pushToServer(channel, ServerEventCode.CODE_GAME_POKER_PLAY_REDIRECT);
}
}

View File

@ -0,0 +1,23 @@
package org.nico.ratel.landlords.client.event;
import org.nico.ratel.landlords.enums.ServerEventCode;
import org.nico.ratel.landlords.print.SimplePrinter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_GAME_POKER_PLAY_INVALID extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
SimplePrinter.printNotice("This combination is invalid.");
if(lastPokers != null) {
SimplePrinter.printNotice(lastSellClientNickname + "[" + lastSellClientType + "] played:");
SimplePrinter.printPokers(lastPokers);
}
pushToServer(channel, ServerEventCode.CODE_GAME_POKER_PLAY_REDIRECT);
}
}

View File

@ -0,0 +1,22 @@
package org.nico.ratel.landlords.client.event;
import org.nico.ratel.landlords.enums.ServerEventCode;
import org.nico.ratel.landlords.print.SimplePrinter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_GAME_POKER_PLAY_LESS extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
SimplePrinter.printNotice("Your combination has lower rank than the previous. You cannot play this combination!");
if(lastPokers != null) {
SimplePrinter.printNotice(lastSellClientNickname + "[" + lastSellClientType + "] played:");
SimplePrinter.printPokers(lastPokers);
}
pushToServer(channel, ServerEventCode.CODE_GAME_POKER_PLAY_REDIRECT);
}
}

View File

@ -0,0 +1,27 @@
package org.nico.ratel.landlords.client.event;
import java.util.Map;
import org.nico.ratel.landlords.enums.ServerEventCode;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.print.SimplePrinter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_GAME_POKER_PLAY_MISMATCH extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
Map<String, Object> map = MapHelper.parser(data);
SimplePrinter.printNotice("Your combination is " + map.get("playType") + " (" + map.get("playCount") + "), but the previous combination is " + map.get("preType") + " (" + map.get("preCount") + "). Mismatch!");
if(lastPokers != null) {
SimplePrinter.printNotice(lastSellClientNickname + "[" + lastSellClientType + "] played:");
SimplePrinter.printPokers(lastPokers);
}
pushToServer(channel, ServerEventCode.CODE_GAME_POKER_PLAY_REDIRECT);
}
}

View File

@ -0,0 +1,15 @@
package org.nico.ratel.landlords.client.event;
import org.nico.ratel.landlords.print.SimplePrinter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_GAME_POKER_PLAY_ORDER_ERROR extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
SimplePrinter.printNotice("It is not your turn yet. Please wait for other players!");
}
}

View File

@ -0,0 +1,26 @@
package org.nico.ratel.landlords.client.event;
import java.util.Map;
import org.nico.ratel.landlords.client.SimpleClient;
import org.nico.ratel.landlords.enums.ServerEventCode;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.print.SimplePrinter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_GAME_POKER_PLAY_PASS extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
Map<String, Object> map = MapHelper.parser(data);
SimplePrinter.printNotice(map.get("clientNickname") + " passed. It is now " + map.get("nextClientNickname") + "'s turn.");
int turnClientId = (int) map.get("nextClientId");
if (SimpleClient.id == turnClientId) {
pushToServer(channel, ServerEventCode.CODE_GAME_POKER_PLAY_REDIRECT);
}
}
}

View File

@ -0,0 +1,48 @@
package org.nico.ratel.landlords.client.event;
import io.netty.channel.Channel;
import org.nico.ratel.landlords.client.SimpleClient;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.print.FormatPrinter;
import org.nico.ratel.landlords.print.SimplePrinter;
import java.util.List;
import java.util.Map;
import static org.nico.ratel.landlords.client.event.ClientEventListener_CODE_CLIENT_NICKNAME_SET.NICKNAME_MAX_LENGTH;
public class ClientEventListener_CODE_GAME_POKER_PLAY_REDIRECT extends ClientEventListener {
private static String[] choose = new String[]{"UP", "DOWN"};
private static String format = "\n[%-4s] %-" + NICKNAME_MAX_LENGTH + "s surplus %-2s [%-8s]";
@SuppressWarnings("unchecked")
@Override
public void call(Channel channel, String data) {
Map<String, Object> map = MapHelper.parser(data);
int sellClientId = (int) map.get("sellClientId");
List<Map<String, Object>> clientInfos = (List<Map<String, Object>>) map.get("clientInfos");
for (int index = 0; index < 2; index++) {
for (Map<String, Object> clientInfo : clientInfos) {
String position = (String) clientInfo.get("position");
if (position.equalsIgnoreCase(choose[index])) {
FormatPrinter.printNotice(format, clientInfo.get("position"), clientInfo.get("clientNickname"), clientInfo.get("surplus"), clientInfo.get("type"));
}
}
}
SimplePrinter.printNotice("");
if (sellClientId == SimpleClient.id) {
get(ClientEventCode.CODE_GAME_POKER_PLAY).call(channel, data);
} else {
SimplePrinter.printNotice("It is " + map.get("sellClientNickname") + "'s turn. Please wait for him to play his cards.");
}
}
}

View File

@ -0,0 +1,34 @@
package org.nico.ratel.landlords.client.event;
import io.netty.channel.Channel;
import org.nico.ratel.landlords.channel.ChannelUtils;
import org.nico.ratel.landlords.client.SimpleClient;
import org.nico.ratel.landlords.client.entity.User;
import org.nico.ratel.landlords.enums.ServerEventCode;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.print.SimplePrinter;
import org.nico.ratel.landlords.print.SimpleWriter;
import java.util.Map;
public class ClientEventListener_CODE_GAME_READY extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
Map<String, Object> map = MapHelper.parser(data);
if (SimpleClient.id == (int) map.get("clientId")) {
SimplePrinter.printNotice("you are ready to play game.");
return;
}
SimplePrinter.printNotice(map.get("clientNickName").toString() + " is ready to play game.");
}
static void gameReady(Channel channel) {
SimplePrinter.printNotice("\nDo you want to continue the game? [Y/N]");
String line = SimpleWriter.write(User.INSTANCE.getNickname(), "notReady");
if (line.equals("Y") || line.equals("y")) {
ChannelUtils.pushToServer(channel, ServerEventCode.CODE_GAME_READY, "");
return;
}
ChannelUtils.pushToServer(channel, ServerEventCode.CODE_CLIENT_EXIT, "");
}
}

View File

@ -0,0 +1,34 @@
package org.nico.ratel.landlords.client.event;
import io.netty.channel.Channel;
import org.nico.noson.Noson;
import org.nico.noson.entity.NoType;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.print.SimplePrinter;
import java.util.List;
import java.util.Map;
public class ClientEventListener_CODE_GAME_STARTING extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
Map<String, Object> map = MapHelper.parser(data);
SimplePrinter.printNotice("Game starting!");
List<Poker> pokers = Noson.convert(map.get("pokers"), new NoType<List<Poker>>() {});
SimplePrinter.printNotice("");
SimplePrinter.printNotice("Your cards are");
SimplePrinter.printPokers(pokers);
SimplePrinter.printNotice("Last cards are");
SimplePrinter.printNotice(map.containsKey("lastPokers")?map.get("lastPokers").toString():"");
get(ClientEventCode.CODE_GAME_LANDLORD_ELECT).call(channel, data);
}
}

View File

@ -0,0 +1,152 @@
package org.nico.ratel.landlords.client.event;
import io.netty.channel.Channel;
import org.nico.noson.Noson;
import org.nico.noson.entity.NoType;
import org.nico.ratel.landlords.client.entity.User;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.print.SimplePrinter;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
public class ClientEventListener_CODE_GAME_WATCH extends ClientEventListener {
@Override
public void call(Channel channel, String wrapData) {
// 退出观战模式后不处理观战请求
if (!User.INSTANCE.isWatching()) {
return;
}
Map<String, Object> wrapMap = MapHelper.parser(wrapData);
ClientEventCode rawCode = ClientEventCode.valueOf(wrapMap.get("code").toString());
Object rawData = wrapMap.get("data");
switch (rawCode) {
case CODE_ROOM_JOIN_SUCCESS:
printJoinPlayerInfo(rawData);
break;
// 游戏开始
case CODE_GAME_STARTING:
printGameStartInfo(rawData);
break;
// 抢地主
case CODE_GAME_LANDLORD_ELECT:
printRobLandlord(rawData);
break;
// 地主确认
case CODE_GAME_LANDLORD_CONFIRM:
printConfirmLandlord(rawData);
break;
// 出牌
case CODE_SHOW_POKERS:
printPlayPokers(rawData);
break;
// 不出(过)
case CODE_GAME_POKER_PLAY_PASS:
printPlayPass(rawData);
break;
// 玩家退出此时可以退出观战修改User.isWatching状态
case CODE_CLIENT_EXIT:
printPlayerExit(rawData, channel);
break;
// 玩家被提出房间
case CODE_CLIENT_KICK:
printKickInfo(rawData);
break;
// 游戏结束此时可以退出观战修改User.isWatching状态
case CODE_GAME_OVER:
printGameResult(rawData, channel);
break;
// 其他事件忽略
default:
break;
}
}
private void printJoinPlayerInfo(Object rawData) {
printNoticeWithTime("Player [" + rawData + "] joined the room");
}
private void printGameStartInfo(Object rawData) {
Map<String, Object> map = MapHelper.parser(rawData.toString());
printNoticeWithTime("Game starting");
printNoticeWithTime("Player1 : " + map.get("player1"));
printNoticeWithTime("Player2 : " + map.get("player2"));
printNoticeWithTime("Player3 : " + map.get("player3"));
}
private void printRobLandlord(Object rawData) {
printNoticeWithTime("Player [" + rawData + "] didn't choose to become the landlord.");
}
private void printConfirmLandlord(Object rawData) {
Map<String, Object> map = MapHelper.parser(rawData.toString());
printNoticeWithTime("Player [" + map.get("landlord") + "] has become the landlord and gotten three extra cards:");
SimplePrinter.printPokers(Noson.convert(map.get("additionalPokers"), new NoType<List<Poker>>() {}));
}
private void printPlayPokers(Object rawData) {
Map<String, Object> map = MapHelper.parser(rawData.toString());
printNoticeWithTime("Player [" + map.get("clientNickname") + "] played:");
SimplePrinter.printPokers(Noson.convert(map.get("pokers"), new NoType<List<Poker>>() {}));
}
private void printPlayPass(Object rawData) {
printNoticeWithTime("Player [" + rawData + "] : passed");
}
private void printPlayerExit(Object rawData, Channel channel) {
printNoticeWithTime("Player [" + rawData + "] left the room");
quitWatch(channel);
}
private void quitWatch(Channel channel) {
printNoticeWithTime("This room will be closed!");
printNoticeWithTime("Spectating ended. Bye.");
SimplePrinter.printNotice("");
SimplePrinter.printNotice("");
// 修改玩家是否观战状态
User.INSTANCE.setWatching(false);
// 退出watch展示
get(ClientEventCode.CODE_SHOW_OPTIONS).call(channel, "");
}
private void printGameResult(Object rawData, Channel channel) {
Map<String, Object> map = MapHelper.parser(rawData.toString());
printNoticeWithTime("Player [" + map.get("winnerNickname") + "](" + map.get("winnerType") + ") won the game.");
}
private void printKickInfo(Object rawData) {
printNoticeWithTime("Player [" + rawData + "] has been kicked out for being idle.");
}
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private void printNoticeWithTime(String notice) {
String msg = FORMATTER.format(LocalDateTime.now()) + " " + notice;
SimplePrinter.printNotice(msg);
}
}

View File

@ -0,0 +1,71 @@
package org.nico.ratel.landlords.client.event;
import io.netty.channel.Channel;
import org.nico.noson.Noson;
import org.nico.ratel.landlords.client.entity.User;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.enums.ServerEventCode;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.print.SimplePrinter;
import org.nico.ratel.landlords.print.SimpleWriter;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
public class ClientEventListener_CODE_GAME_WATCH_SUCCESSFUL extends ClientEventListener {
private static final String WATCH_SUCCESSFUL_TIPS = " \n" +
"+------------------------------------------------\n" +
"|You are already watching the game. \n" +
"|Room owner: %s. Room current status: %s.\n" +
"+------------------------------------------------\n" +
"(Hint: enter [exit|e] to exit.) \n" +
" ";
@Override
public void call(Channel channel, String data) {
// 修改User.isWatching状态
// Edit User.isWatching
User.INSTANCE.setWatching(true);
// 进入观战提示
// Enter spectator mode
Map<String, Object> map = MapHelper.parser(data);
SimplePrinter.printNotice(String.format(WATCH_SUCCESSFUL_TIPS, map.get("owner"), map.get("status")));
// 监听输入用于退出
// Listen enter event to exit spectator mode
new Thread(() -> registerExitEvent(channel), "exit-spectator-input-thread").start();
}
private void registerExitEvent(Channel channel) {
String enter = SimpleWriter.write();
if ("exit".equalsIgnoreCase(enter) || "e".equalsIgnoreCase(enter)) {
quitWatch(channel);
return;
}
printCommandUsage();
registerExitEvent(channel);
}
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private void quitWatch(Channel channel) {
SimplePrinter.printNotice(FORMATTER.format(LocalDateTime.now()) + " Spectating ended. Bye.");
SimplePrinter.printNotice("");
SimplePrinter.printNotice("");
// 修改玩家是否观战状态
User.INSTANCE.setWatching(false);
// 退出观战模式
pushToServer(channel, ServerEventCode.CODE_GAME_WATCH_EXIT);
get(ClientEventCode.CODE_SHOW_OPTIONS).call(channel, "");
}
private void printCommandUsage() {
SimplePrinter.printNotice("Enter [exit|e] to exit");
}
}

View File

@ -0,0 +1,17 @@
package org.nico.ratel.landlords.client.event;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.print.SimplePrinter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_PVE_DIFFICULTY_NOT_SUPPORT extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
SimplePrinter.printNotice("The current difficulty is not supported, please pay attention to the following.\n");
get(ClientEventCode.CODE_SHOW_OPTIONS_PVE).call(channel, data);
}
}

View File

@ -0,0 +1,19 @@
package org.nico.ratel.landlords.client.event;
import org.nico.noson.Noson;
import org.nico.ratel.landlords.entity.Room;
import org.nico.ratel.landlords.print.SimplePrinter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_ROOM_CREATE_SUCCESS extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
Room room = Noson.convert(data, Room.class);
initLastSellInfo();
SimplePrinter.printNotice("You have created a room with id " + room.getId());
SimplePrinter.printNotice("Please wait for other players to join !");
}
}

View File

@ -0,0 +1,22 @@
package org.nico.ratel.landlords.client.event;
import java.util.Map;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.print.SimplePrinter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_ROOM_JOIN_FAIL_BY_FULL extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
Map<String, Object> dataMap = MapHelper.parser(data);
SimplePrinter.printNotice("Join room failed. Room " + dataMap.get("roomId") + " is full!");
ClientEventListener.get(ClientEventCode.CODE_SHOW_OPTIONS).call(channel, data);
}
}

View File

@ -0,0 +1,20 @@
package org.nico.ratel.landlords.client.event;
import java.util.Map;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.print.SimplePrinter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_ROOM_JOIN_FAIL_BY_INEXIST extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
Map<String, Object> dataMap = MapHelper.parser(data);
SimplePrinter.printNotice("Join room failed. Room " + dataMap.get("roomId") + " doesn't exist!");
ClientEventListener.get(ClientEventCode.CODE_SHOW_OPTIONS).call(channel, data);
}
}

View File

@ -0,0 +1,28 @@
package org.nico.ratel.landlords.client.event;
import java.util.Map;
import org.nico.ratel.landlords.client.SimpleClient;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.print.SimplePrinter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_ROOM_JOIN_SUCCESS extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
Map<String, Object> map = MapHelper.parser(data);
initLastSellInfo();
int joinClientId = (int) map.get("clientId");
if (SimpleClient.id == joinClientId) {
SimplePrinter.printNotice("You have joined room" + map.get("roomId") + ". There are " + map.get("roomClientCount") + " players in the room now.");
SimplePrinter.printNotice("Please wait for other players to join. The game would start at three players!");
} else {
SimplePrinter.printNotice(map.get("clientNickname") + " joined room, there are currently " + map.get("roomClientCount") + " in the room.");
}
}
}

View File

@ -0,0 +1,18 @@
package org.nico.ratel.landlords.client.event;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.print.SimplePrinter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_ROOM_PLAY_FAIL_BY_INEXIST extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
SimplePrinter.printNotice("Play failed. Room already disbanded!");
ClientEventListener.get(ClientEventCode.CODE_SHOW_OPTIONS).call(channel, data);
}
}

View File

@ -0,0 +1,38 @@
package org.nico.ratel.landlords.client.event;
import org.nico.ratel.landlords.client.entity.User;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.print.SimplePrinter;
import org.nico.ratel.landlords.print.SimpleWriter;
import org.nico.ratel.landlords.utils.OptionsUtils;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_SHOW_OPTIONS extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
SimplePrinter.printNotice("Options: ");
SimplePrinter.printNotice("1. PvP");
SimplePrinter.printNotice("2. PvE");
SimplePrinter.printNotice("3. Settings");
SimplePrinter.printNotice("Please select an option above (enter [exit|e] to log out)");
String line = SimpleWriter.write(User.INSTANCE.getNickname(), "selection");
if(line.equalsIgnoreCase("exit") || line.equalsIgnoreCase("e")) {
System.exit(0);
} else {
int choose = OptionsUtils.getOptions(line);
if (choose == 1) {
get(ClientEventCode.CODE_SHOW_OPTIONS_PVP).call(channel, data);
} else if (choose == 2) {
get(ClientEventCode.CODE_SHOW_OPTIONS_PVE).call(channel, data);
} else if (choose == 3) {
get(ClientEventCode.CODE_SHOW_OPTIONS_SETTING).call(channel, data);
} else {
SimplePrinter.printNotice("Invalid option, please choose again");
call(channel, data);
}
}
}
}

View File

@ -0,0 +1,38 @@
package org.nico.ratel.landlords.client.event;
import org.nico.ratel.landlords.client.entity.User;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.enums.ServerEventCode;
import org.nico.ratel.landlords.print.SimplePrinter;
import org.nico.ratel.landlords.print.SimpleWriter;
import org.nico.ratel.landlords.utils.OptionsUtils;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_SHOW_OPTIONS_PVE extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
SimplePrinter.printNotice("PVE: ");
SimplePrinter.printNotice("1. Easy Mode");
SimplePrinter.printNotice("2. Medium Mode");
SimplePrinter.printNotice("3. Hard Mode");
SimplePrinter.printNotice("Please select an option above (enter [back|b] to return to options list)");
String line = SimpleWriter.write(User.INSTANCE.getNickname(), "pve");
if(line.equalsIgnoreCase("back") || line.equalsIgnoreCase("b")) {
get(ClientEventCode.CODE_SHOW_OPTIONS).call(channel, data);
return;
}
int choose = OptionsUtils.getOptions(line);
if (choose < 0 || choose >= 4) {
SimplePrinter.printNotice("Invalid option, please choose again");
call(channel, data);
return;
}
initLastSellInfo();
pushToServer(channel, ServerEventCode.CODE_ROOM_CREATE_PVE, String.valueOf(choose));
}
}

View File

@ -0,0 +1,86 @@
package org.nico.ratel.landlords.client.event;
import org.nico.ratel.landlords.client.entity.User;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.enums.ServerEventCode;
import org.nico.ratel.landlords.print.SimplePrinter;
import org.nico.ratel.landlords.print.SimpleWriter;
import org.nico.ratel.landlords.utils.OptionsUtils;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_SHOW_OPTIONS_PVP extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
SimplePrinter.printNotice("PVP: ");
SimplePrinter.printNotice("1. Create Room");
SimplePrinter.printNotice("2. Room List");
SimplePrinter.printNotice("3. Join Room");
SimplePrinter.printNotice("4. Spectate Game");
SimplePrinter.printNotice("Please select an option above (enter [back|b] to return to options list)");
String line = SimpleWriter.write(User.INSTANCE.getNickname(), "pvp");
if (line == null) {
SimplePrinter.printNotice("Invalid options, please choose again");
call(channel, data);
return;
}
if (line.equalsIgnoreCase("BACK") || line.equalsIgnoreCase("b")) {
get(ClientEventCode.CODE_SHOW_OPTIONS).call(channel, data);
return;
}
int choose = OptionsUtils.getOptions(line);
switch (choose) {
case 1:
pushToServer(channel, ServerEventCode.CODE_ROOM_CREATE, null);
break;
case 2:
pushToServer(channel, ServerEventCode.CODE_GET_ROOMS, null);
break;
case 3:
handleJoinRoom(channel, data);
break;
case 4:
handleJoinRoom(channel, data, true);
break;
default:
SimplePrinter.printNotice("Invalid option, please choose again");
call(channel, data);
}
}
private void parseInvalid(Channel channel, String data) {
SimplePrinter.printNotice("Invalid options, please choose again");
call(channel, data);
}
private void handleJoinRoom(Channel channel, String data) {
handleJoinRoom(channel, data, false);
}
private void handleJoinRoom(Channel channel, String data, Boolean watchMode) {
String notice = String.format("Please enter the room id you want to %s (enter [back|b] return options list)", watchMode ? "spectate" : "join");
SimplePrinter.printNotice(notice);
String line = SimpleWriter.write(User.INSTANCE.getNickname(), "roomid");
if (line == null) {
parseInvalid(channel, data);
return;
}
if (line.equalsIgnoreCase("BACK") || line.equalsIgnoreCase("b")) {
call(channel, data);
return;
}
int option = OptionsUtils.getOptions(line);
if (option < 1) {
parseInvalid(channel, data);
return;
}
pushToServer(channel, watchMode? ServerEventCode.CODE_GAME_WATCH : ServerEventCode.CODE_ROOM_JOIN, String.valueOf(option));
}
}

View File

@ -0,0 +1,42 @@
package org.nico.ratel.landlords.client.event;
import org.nico.ratel.landlords.client.entity.User;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.helper.PokerHelper;
import org.nico.ratel.landlords.print.SimplePrinter;
import org.nico.ratel.landlords.print.SimpleWriter;
import org.nico.ratel.landlords.utils.OptionsUtils;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_SHOW_OPTIONS_SETTING extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
SimplePrinter.printNotice("Setting: ");
SimplePrinter.printNotice("1. Card with shape edges (Default)");
SimplePrinter.printNotice("2. Card with rounded edges");
SimplePrinter.printNotice("3. Text Only with types");
SimplePrinter.printNotice("4. Text Only without types");
SimplePrinter.printNotice("5. Unicode Cards");
SimplePrinter.printNotice("Please select an option above (enter [BACK] to return to options list)");
String line = SimpleWriter.write(User.INSTANCE.getNickname(), "setting");
if (line.equalsIgnoreCase("BACK")) {
get(ClientEventCode.CODE_SHOW_OPTIONS).call(channel, data);
} else {
int choose = OptionsUtils.getOptions(line);
if (choose >= 1 && choose <= 5) {
PokerHelper.pokerPrinterType = choose - 1;
get(ClientEventCode.CODE_SHOW_OPTIONS).call(channel, data);
} else {
SimplePrinter.printNotice("Invalid setting, please choose again");
call(channel, data);
}
}
}
}

View File

@ -0,0 +1,33 @@
package org.nico.ratel.landlords.client.event;
import java.util.List;
import java.util.Map;
import org.nico.noson.Noson;
import org.nico.noson.entity.NoType;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.print.SimplePrinter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_SHOW_POKERS extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
Map<String, Object> map = MapHelper.parser(data);
lastSellClientNickname = (String) map.get("clientNickname");
lastSellClientType = (String) map.get("clientType");
SimplePrinter.printNotice(lastSellClientNickname + "[" + lastSellClientType + "] played:");
lastPokers = Noson.convert(map.get("pokers"), new NoType<List<Poker>>() {});
SimplePrinter.printPokers(lastPokers);
if (map.containsKey("sellClientNickname")) {
SimplePrinter.printNotice("Next player is " + map.get("sellClientNickname") + ". Please wait for him to play his combination.");
}
}
}

View File

@ -0,0 +1,35 @@
package org.nico.ratel.landlords.client.event;
import static org.nico.ratel.landlords.client.event.ClientEventListener_CODE_CLIENT_NICKNAME_SET.NICKNAME_MAX_LENGTH;
import java.util.List;
import java.util.Map;
import org.nico.noson.Noson;
import org.nico.noson.entity.NoType;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.print.FormatPrinter;
import org.nico.ratel.landlords.print.SimplePrinter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_SHOW_ROOMS extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
List<Map<String, Object>> roomList = Noson.convert(data, new NoType<List<Map<String, Object>>>() {});
if (roomList != null && !roomList.isEmpty()) {
// "COUNT" begins after NICKNAME_MAX_LENGTH characters. The dash means that the string is left-justified.
String format = "#\t%s\t|\t%-" + NICKNAME_MAX_LENGTH + "s\t|\t%-6s\t|\t%-6s\t#\n";
FormatPrinter.printNotice(format, "ID", "OWNER", "COUNT", "TYPE");
for (Map<String, Object> room : roomList) {
FormatPrinter.printNotice(format, room.get("roomId"), room.get("roomOwner"), room.get("roomClientCount"), room.get("roomType"));
}
SimplePrinter.printNotice("");
get(ClientEventCode.CODE_SHOW_OPTIONS_PVP).call(channel, data);
} else {
SimplePrinter.printNotice("No available room. Please create a room!");
get(ClientEventCode.CODE_SHOW_OPTIONS_PVP).call(channel, data);
}
}
}

View File

@ -0,0 +1,61 @@
package org.nico.ratel.landlords.client.handler;
import org.nico.noson.Noson;
import org.nico.ratel.landlords.channel.ChannelUtils;
import org.nico.ratel.landlords.client.entity.User;
import org.nico.ratel.landlords.client.event.ClientEventListener;
import org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.enums.ServerEventCode;
import org.nico.ratel.landlords.print.SimplePrinter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import java.util.HashMap;
import java.util.Map;
public class ProtobufTransferHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
if (msg instanceof ClientTransferDataProtoc) {
ClientTransferDataProtoc clientTransferData = (ClientTransferDataProtoc) msg;
if (!clientTransferData.getInfo().isEmpty()) {
SimplePrinter.printNotice(clientTransferData.getInfo());
}
ClientEventCode code = ClientEventCode.valueOf(clientTransferData.getCode());
if (User.INSTANCE.isWatching()) {
Map<String, Object> wrapMap = new HashMap<>(3);
wrapMap.put("code", code);
wrapMap.put("data", clientTransferData.getData());
ClientEventListener.get(ClientEventCode.CODE_GAME_WATCH).call(ctx.channel(), Noson.reversal(wrapMap));
} else {
ClientEventListener.get(code).call(ctx.channel(), clientTransferData.getData());
}
}
}
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
if (evt instanceof IdleStateEvent) {
IdleStateEvent event = (IdleStateEvent) evt;
if (event.state() == IdleState.WRITER_IDLE) {
ChannelUtils.pushToServer(ctx.channel(), ServerEventCode.CODE_CLIENT_HEAD_BEAT, "heartbeat");
}
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
if (cause instanceof java.io.IOException) {
SimplePrinter.printNotice("The network is not good or did not operate for a long time, has been offline");
System.exit(0);
}
}
}

View File

@ -0,0 +1,24 @@
package org.nico.ratel.landlords.client.handler;
import java.util.List;
import org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc;
import com.google.protobuf.MessageLite;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
public class SecondProtobufCodec extends MessageToMessageCodec<ClientTransferDataProtoc, MessageLite> {
@Override
protected void encode(ChannelHandlerContext ctx, MessageLite msg, List<Object> out) {
out.add(msg);
}
@Override
protected void decode(ChannelHandlerContext ctx, ClientTransferDataProtoc msg, List<Object> out) {
out.add(msg);
}
}

View File

@ -0,0 +1,62 @@
package org.nico.ratel.landlords.client.handler;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.*;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import org.nico.noson.Noson;
import org.nico.ratel.landlords.channel.ChannelUtils;
import org.nico.ratel.landlords.client.entity.User;
import org.nico.ratel.landlords.client.event.ClientEventListener;
import org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc;
import org.nico.ratel.landlords.entity.Msg;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.enums.ServerEventCode;
import org.nico.ratel.landlords.print.SimplePrinter;
import org.nico.ratel.landlords.utils.JsonUtils;
import java.util.HashMap;
import java.util.Map;
public class WebsocketTransferHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame frame) {
Msg msg = JsonUtils.fromJson(frame.text(), Msg.class);
if(msg.getInfo() != null && ! msg.getInfo().isEmpty()) {
SimplePrinter.printNotice(msg.getInfo());
}
ClientEventCode code = ClientEventCode.valueOf(msg.getCode());
if (User.INSTANCE.isWatching()) {
Map<String, Object> wrapMap = new HashMap<>(3);
wrapMap.put("code", code);
wrapMap.put("data", msg.getData());
ClientEventListener.get(ClientEventCode.CODE_GAME_WATCH).call(ctx.channel(), JsonUtils.toJson(wrapMap));
} else {
ClientEventListener.get(code).call(ctx.channel(), msg.getData());
}
}
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof IdleStateEvent) {
IdleStateEvent event = (IdleStateEvent) evt;
if (event.state() == IdleState.WRITER_IDLE) {
ChannelUtils.pushToServer(ctx.channel(), ServerEventCode.CODE_CLIENT_HEAD_BEAT, "heartbeat");
}
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
if(cause instanceof java.io.IOException) {
SimplePrinter.printNotice("The network is not good or did not operate for a long time, has been offline");
System.exit(0);
}
}
}

View File

@ -0,0 +1,50 @@
package org.nico.ratel.landlords.client.proxy;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
import io.netty.handler.timeout.IdleStateHandler;
import org.nico.ratel.landlords.client.handler.ProtobufTransferHandler;
import org.nico.ratel.landlords.client.handler.SecondProtobufCodec;
import org.nico.ratel.landlords.entity.ClientTransferData;
import org.nico.ratel.landlords.print.SimplePrinter;
import java.util.concurrent.TimeUnit;
public class ProtobufProxy implements Proxy {
@Override
public void connect(String serverAddress, int port) throws InterruptedException {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap()
.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline()
.addLast(new IdleStateHandler(0, 4, 0, TimeUnit.SECONDS))
.addLast(new ProtobufVarint32FrameDecoder())
.addLast(new ProtobufDecoder(ClientTransferData.ClientTransferDataProtoc.getDefaultInstance()))
.addLast(new ProtobufVarint32LengthFieldPrepender())
.addLast(new ProtobufEncoder())
.addLast(new SecondProtobufCodec())
.addLast(new ProtobufTransferHandler());
}
});
SimplePrinter.printNotice("Connecting to " + serverAddress + ":" + port);
Channel channel = bootstrap.connect(serverAddress, port).sync().channel();
channel.closeFuture().sync();
} finally {
group.shutdownGracefully().sync();
}
}
}

View File

@ -0,0 +1,8 @@
package org.nico.ratel.landlords.client.proxy;
import java.net.URISyntaxException;
public interface Proxy {
void connect(String serverAddress, int port) throws InterruptedException, URISyntaxException;
}

View File

@ -0,0 +1,61 @@
package org.nico.ratel.landlords.client.proxy;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.*;
import io.netty.handler.codec.http.websocketx.*;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleStateHandler;
import org.nico.ratel.landlords.client.handler.SecondProtobufCodec;
import org.nico.ratel.landlords.client.handler.ProtobufTransferHandler;
import org.nico.ratel.landlords.client.handler.WebsocketTransferHandler;
import org.nico.ratel.landlords.entity.ClientTransferData;
import org.nico.ratel.landlords.print.SimplePrinter;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.concurrent.TimeUnit;
public class WebsocketProxy implements Proxy{
@Override
public void connect(String serverAddress, int port) throws InterruptedException, URISyntaxException {
URI uri = new URI("ws://" + serverAddress + ":" + port + "/ratel");
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap()
.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline()
.addLast(new IdleStateHandler(60 * 30, 0, 0, TimeUnit.SECONDS))
.addLast(new HttpClientCodec())
.addLast(new HttpObjectAggregator(8192))
.addLast(new WebSocketClientProtocolHandler(uri
, WebSocketVersion.V13
, null
, true
, new DefaultHttpHeaders(), 100000))
.addLast("ws", new WebsocketTransferHandler());
}
});
SimplePrinter.printNotice("Connecting to " + serverAddress + ":" + port);
Channel channel = bootstrap.connect(serverAddress, port).sync().channel();
channel.closeFuture().sync();
} finally {
group.shutdownGracefully().sync();
}
}
}

View File

@ -0,0 +1,16 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>landlords-common</artifactId>
<name>landlords-common</name>
<description>This is a console version of the fight landlord game</description>
<parent>
<groupId>com.smallnico.ratel</groupId>
<artifactId>landlords</artifactId>
<version>1.4.0</version>
</parent>
</project>

View File

@ -0,0 +1,62 @@
package org.nico.ratel.landlords.channel;
import org.nico.ratel.landlords.entity.ClientTransferData;
import org.nico.ratel.landlords.entity.Msg;
import org.nico.ratel.landlords.entity.ServerTransferData;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.enums.ServerEventCode;
import org.nico.ratel.landlords.utils.JsonUtils;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
public class ChannelUtils {
public static void pushToClient(Channel channel, ClientEventCode code, String data) {
pushToClient(channel, code, data, null);
}
public static void pushToClient(Channel channel, ClientEventCode code, String data, String info) {
if (channel != null) {
if (channel.pipeline().get("ws") != null) {
Msg msg = new Msg();
msg.setCode(code.toString());
msg.setData(data);
msg.setInfo(info);
channel.writeAndFlush(new TextWebSocketFrame(JsonUtils.toJson(msg)));
} else {
ClientTransferData.ClientTransferDataProtoc.Builder clientTransferData = ClientTransferData.ClientTransferDataProtoc.newBuilder();
if (code != null) {
clientTransferData.setCode(code.toString());
}
if (data != null) {
clientTransferData.setData(data);
}
if (info != null) {
clientTransferData.setInfo(info);
}
channel.writeAndFlush(clientTransferData);
}
}
}
public static ChannelFuture pushToServer(Channel channel, ServerEventCode code, String data) {
if (channel.pipeline().get("ws") != null) {
Msg msg = new Msg();
msg.setCode(code.toString());
msg.setData(data);
return channel.writeAndFlush(new TextWebSocketFrame(JsonUtils.toJson(msg)));
} else {
ServerTransferData.ServerTransferDataProtoc.Builder serverTransferData = ServerTransferData.ServerTransferDataProtoc.newBuilder();
if (code != null) {
serverTransferData.setCode(code.toString());
}
if (data != null) {
serverTransferData.setData(data);
}
return channel.writeAndFlush(serverTransferData);
}
}
}

View File

@ -0,0 +1,186 @@
package org.nico.ratel.landlords.entity;
import java.util.List;
import org.nico.ratel.landlords.enums.ClientRole;
import org.nico.ratel.landlords.enums.ClientStatus;
import org.nico.ratel.landlords.enums.ClientType;
import io.netty.channel.Channel;
public class ClientSide {
private int id;
private int roomId;
private int score;
private int scoreInc;
private String nickname;
private List<Poker> pokers;
private ClientStatus status;
private ClientRole role;
private ClientType type;
private ClientSide next;
private ClientSide pre;
private transient Channel channel;
private String version;
public ClientSide() {}
public ClientSide(int id, ClientStatus status, Channel channel) {
this.id = id;
this.status = status;
this.channel = channel;
}
public void init() {
roomId = 0;
pokers = null;
status = ClientStatus.TO_CHOOSE;
type = null;
next = null;
pre = null;
score = 0;
}
public final ClientRole getRole() {
return role;
}
public final void setRole(ClientRole role) {
this.role = role;
}
public final String getNickname() {
return nickname;
}
public final void setNickname(String nickname) {
this.nickname = nickname;
}
public final Channel getChannel() {
return channel;
}
public final void setChannel(Channel channel) {
this.channel = channel;
}
public final int getRoomId() {
return roomId;
}
public final void setRoomId(int roomId) {
this.roomId = roomId;
}
public final List<Poker> getPokers() {
return pokers;
}
public final void setPokers(List<Poker> pokers) {
this.pokers = pokers;
}
public final int getScore() {
return score;
}
public final void setScore(int score) {
this.score = score;
}
public final void addScore(int score) {
this.score += score;
this.scoreInc = score;
}
public final void setScoreInc(int scoreInc) {
this.scoreInc = scoreInc;
}
public final int getScoreInc() {
return this.scoreInc;
}
public final ClientStatus getStatus() {
return status;
}
public final void setStatus(ClientStatus status) {
this.status = status;
}
public final ClientType getType() {
return type;
}
public final void setType(ClientType type) {
this.type = type;
}
public final int getId() {
return id;
}
public final void setId(int id) {
this.id = id;
}
public final ClientSide getNext() {
return next;
}
public final void setNext(ClientSide next) {
this.next = next;
}
public final ClientSide getPre() {
return pre;
}
public final void setPre(ClientSide pre) {
this.pre = pre;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ClientSide other = (ClientSide) obj;
return id == other.id;
}
}

View File

@ -0,0 +1,882 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: ClientTransferDataProtoc.proto
package org.nico.ratel.landlords.entity;
public final class ClientTransferData {
private ClientTransferData() {}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistryLite registry) {
}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistry registry) {
registerAllExtensions(
(com.google.protobuf.ExtensionRegistryLite) registry);
}
public interface ClientTransferDataProtocOrBuilder extends
// @@protoc_insertion_point(interface_extends:org.nico.ratel.landlords.entity.ClientTransferDataProtoc)
com.google.protobuf.MessageOrBuilder {
/**
* <code>string code = 1;</code>
*/
java.lang.String getCode();
/**
* <code>string code = 1;</code>
*/
com.google.protobuf.ByteString
getCodeBytes();
/**
* <code>string data = 2;</code>
*/
java.lang.String getData();
/**
* <code>string data = 2;</code>
*/
com.google.protobuf.ByteString
getDataBytes();
/**
* <code>string info = 3;</code>
*/
java.lang.String getInfo();
/**
* <code>string info = 3;</code>
*/
com.google.protobuf.ByteString
getInfoBytes();
}
/**
* Protobuf type {@code org.nico.ratel.landlords.entity.ClientTransferDataProtoc}
*/
public static final class ClientTransferDataProtoc extends
com.google.protobuf.GeneratedMessageV3 implements
// @@protoc_insertion_point(message_implements:org.nico.ratel.landlords.entity.ClientTransferDataProtoc)
ClientTransferDataProtocOrBuilder {
private static final long serialVersionUID = 0L;
// Use ClientTransferDataProtoc.newBuilder() to construct.
private ClientTransferDataProtoc(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
super(builder);
}
private ClientTransferDataProtoc() {
code_ = "";
data_ = "";
info_ = "";
}
@java.lang.Override
public final com.google.protobuf.UnknownFieldSet
getUnknownFields() {
return this.unknownFields;
}
private ClientTransferDataProtoc(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
this();
if (extensionRegistry == null) {
throw new java.lang.NullPointerException();
}
int mutable_bitField0_ = 0;
com.google.protobuf.UnknownFieldSet.Builder unknownFields =
com.google.protobuf.UnknownFieldSet.newBuilder();
try {
boolean done = false;
while (!done) {
int tag = input.readTag();
switch (tag) {
case 0:
done = true;
break;
case 10: {
java.lang.String s = input.readStringRequireUtf8();
code_ = s;
break;
}
case 18: {
java.lang.String s = input.readStringRequireUtf8();
data_ = s;
break;
}
case 26: {
java.lang.String s = input.readStringRequireUtf8();
info_ = s;
break;
}
default: {
if (!parseUnknownFieldProto3(
input, unknownFields, extensionRegistry, tag)) {
done = true;
}
break;
}
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
throw e.setUnfinishedMessage(this);
} catch (java.io.IOException e) {
throw new com.google.protobuf.InvalidProtocolBufferException(
e).setUnfinishedMessage(this);
} finally {
this.unknownFields = unknownFields.build();
makeExtensionsImmutable();
}
}
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return org.nico.ratel.landlords.entity.ClientTransferData.internal_static_org_nico_ratel_landlords_entity_ClientTransferDataProtoc_descriptor;
}
@java.lang.Override
protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
internalGetFieldAccessorTable() {
return org.nico.ratel.landlords.entity.ClientTransferData.internal_static_org_nico_ratel_landlords_entity_ClientTransferDataProtoc_fieldAccessorTable
.ensureFieldAccessorsInitialized(
org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc.class, org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc.Builder.class);
}
public static final int CODE_FIELD_NUMBER = 1;
private volatile java.lang.Object code_;
/**
* <code>string code = 1;</code>
*/
public java.lang.String getCode() {
java.lang.Object ref = code_;
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
code_ = s;
return s;
}
}
/**
* <code>string code = 1;</code>
*/
public com.google.protobuf.ByteString
getCodeBytes() {
java.lang.Object ref = code_;
if (ref instanceof java.lang.String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
code_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
public static final int DATA_FIELD_NUMBER = 2;
private volatile java.lang.Object data_;
/**
* <code>string data = 2;</code>
*/
public java.lang.String getData() {
java.lang.Object ref = data_;
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
data_ = s;
return s;
}
}
/**
* <code>string data = 2;</code>
*/
public com.google.protobuf.ByteString
getDataBytes() {
java.lang.Object ref = data_;
if (ref instanceof java.lang.String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
data_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
public static final int INFO_FIELD_NUMBER = 3;
private volatile java.lang.Object info_;
/**
* <code>string info = 3;</code>
*/
public java.lang.String getInfo() {
java.lang.Object ref = info_;
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
info_ = s;
return s;
}
}
/**
* <code>string info = 3;</code>
*/
public com.google.protobuf.ByteString
getInfoBytes() {
java.lang.Object ref = info_;
if (ref instanceof java.lang.String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
info_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
private byte memoizedIsInitialized = -1;
@java.lang.Override
public final boolean isInitialized() {
byte isInitialized = memoizedIsInitialized;
if (isInitialized == 1) return true;
if (isInitialized == 0) return false;
memoizedIsInitialized = 1;
return true;
}
@java.lang.Override
public void writeTo(com.google.protobuf.CodedOutputStream output)
throws java.io.IOException {
if (!getCodeBytes().isEmpty()) {
com.google.protobuf.GeneratedMessageV3.writeString(output, 1, code_);
}
if (!getDataBytes().isEmpty()) {
com.google.protobuf.GeneratedMessageV3.writeString(output, 2, data_);
}
if (!getInfoBytes().isEmpty()) {
com.google.protobuf.GeneratedMessageV3.writeString(output, 3, info_);
}
unknownFields.writeTo(output);
}
@java.lang.Override
public int getSerializedSize() {
int size = memoizedSize;
if (size != -1) return size;
size = 0;
if (!getCodeBytes().isEmpty()) {
size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, code_);
}
if (!getDataBytes().isEmpty()) {
size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, data_);
}
if (!getInfoBytes().isEmpty()) {
size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, info_);
}
size += unknownFields.getSerializedSize();
memoizedSize = size;
return size;
}
@java.lang.Override
public boolean equals(final java.lang.Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc)) {
return super.equals(obj);
}
org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc other = (org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc) obj;
boolean result = true;
result = result && getCode()
.equals(other.getCode());
result = result && getData()
.equals(other.getData());
result = result && getInfo()
.equals(other.getInfo());
result = result && unknownFields.equals(other.unknownFields);
return result;
}
@java.lang.Override
public int hashCode() {
if (memoizedHashCode != 0) {
return memoizedHashCode;
}
int hash = 41;
hash = (19 * hash) + getDescriptor().hashCode();
hash = (37 * hash) + CODE_FIELD_NUMBER;
hash = (53 * hash) + getCode().hashCode();
hash = (37 * hash) + DATA_FIELD_NUMBER;
hash = (53 * hash) + getData().hashCode();
hash = (37 * hash) + INFO_FIELD_NUMBER;
hash = (53 * hash) + getInfo().hashCode();
hash = (29 * hash) + unknownFields.hashCode();
memoizedHashCode = hash;
return hash;
}
public static org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc parseFrom(
java.nio.ByteBuffer data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc parseFrom(
java.nio.ByteBuffer data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc parseFrom(
com.google.protobuf.ByteString data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc parseFrom(
com.google.protobuf.ByteString data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc parseFrom(byte[] data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc parseFrom(
byte[] data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc parseFrom(java.io.InputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseWithIOException(PARSER, input);
}
public static org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc parseFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseWithIOException(PARSER, input, extensionRegistry);
}
public static org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc parseDelimitedFrom(java.io.InputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseDelimitedWithIOException(PARSER, input);
}
public static org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc parseDelimitedFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseDelimitedWithIOException(PARSER, input, extensionRegistry);
}
public static org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc parseFrom(
com.google.protobuf.CodedInputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseWithIOException(PARSER, input);
}
public static org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc parseFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseWithIOException(PARSER, input, extensionRegistry);
}
@java.lang.Override
public Builder newBuilderForType() { return newBuilder(); }
public static Builder newBuilder() {
return DEFAULT_INSTANCE.toBuilder();
}
public static Builder newBuilder(org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc prototype) {
return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
}
@java.lang.Override
public Builder toBuilder() {
return this == DEFAULT_INSTANCE
? new Builder() : new Builder().mergeFrom(this);
}
@java.lang.Override
protected Builder newBuilderForType(
com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
Builder builder = new Builder(parent);
return builder;
}
/**
* Protobuf type {@code org.nico.ratel.landlords.entity.ClientTransferDataProtoc}
*/
public static final class Builder extends
com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
// @@protoc_insertion_point(builder_implements:org.nico.ratel.landlords.entity.ClientTransferDataProtoc)
org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtocOrBuilder {
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return org.nico.ratel.landlords.entity.ClientTransferData.internal_static_org_nico_ratel_landlords_entity_ClientTransferDataProtoc_descriptor;
}
@java.lang.Override
protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
internalGetFieldAccessorTable() {
return org.nico.ratel.landlords.entity.ClientTransferData.internal_static_org_nico_ratel_landlords_entity_ClientTransferDataProtoc_fieldAccessorTable
.ensureFieldAccessorsInitialized(
org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc.class, org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc.Builder.class);
}
// Construct using org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc.newBuilder()
private Builder() {
maybeForceBuilderInitialization();
}
private Builder(
com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
super(parent);
maybeForceBuilderInitialization();
}
private void maybeForceBuilderInitialization() {
if (com.google.protobuf.GeneratedMessageV3
.alwaysUseFieldBuilders) {
}
}
@java.lang.Override
public Builder clear() {
super.clear();
code_ = "";
data_ = "";
info_ = "";
return this;
}
@java.lang.Override
public com.google.protobuf.Descriptors.Descriptor
getDescriptorForType() {
return org.nico.ratel.landlords.entity.ClientTransferData.internal_static_org_nico_ratel_landlords_entity_ClientTransferDataProtoc_descriptor;
}
@java.lang.Override
public org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc getDefaultInstanceForType() {
return org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc.getDefaultInstance();
}
@java.lang.Override
public org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc build() {
org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc result = buildPartial();
if (!result.isInitialized()) {
throw newUninitializedMessageException(result);
}
return result;
}
@java.lang.Override
public org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc buildPartial() {
org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc result = new org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc(this);
result.code_ = code_;
result.data_ = data_;
result.info_ = info_;
onBuilt();
return result;
}
@java.lang.Override
public Builder clone() {
return (Builder) super.clone();
}
@java.lang.Override
public Builder setField(
com.google.protobuf.Descriptors.FieldDescriptor field,
java.lang.Object value) {
return (Builder) super.setField(field, value);
}
@java.lang.Override
public Builder clearField(
com.google.protobuf.Descriptors.FieldDescriptor field) {
return (Builder) super.clearField(field);
}
@java.lang.Override
public Builder clearOneof(
com.google.protobuf.Descriptors.OneofDescriptor oneof) {
return (Builder) super.clearOneof(oneof);
}
@java.lang.Override
public Builder setRepeatedField(
com.google.protobuf.Descriptors.FieldDescriptor field,
int index, java.lang.Object value) {
return (Builder) super.setRepeatedField(field, index, value);
}
@java.lang.Override
public Builder addRepeatedField(
com.google.protobuf.Descriptors.FieldDescriptor field,
java.lang.Object value) {
return (Builder) super.addRepeatedField(field, value);
}
@java.lang.Override
public Builder mergeFrom(com.google.protobuf.Message other) {
if (other instanceof org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc) {
return mergeFrom((org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc)other);
} else {
super.mergeFrom(other);
return this;
}
}
public Builder mergeFrom(org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc other) {
if (other == org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc.getDefaultInstance()) return this;
if (!other.getCode().isEmpty()) {
code_ = other.code_;
onChanged();
}
if (!other.getData().isEmpty()) {
data_ = other.data_;
onChanged();
}
if (!other.getInfo().isEmpty()) {
info_ = other.info_;
onChanged();
}
this.mergeUnknownFields(other.unknownFields);
onChanged();
return this;
}
@java.lang.Override
public final boolean isInitialized() {
return true;
}
@java.lang.Override
public Builder mergeFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc parsedMessage = null;
try {
parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
parsedMessage = (org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc) e.getUnfinishedMessage();
throw e.unwrapIOException();
} finally {
if (parsedMessage != null) {
mergeFrom(parsedMessage);
}
}
return this;
}
private java.lang.Object code_ = "";
/**
* <code>string code = 1;</code>
*/
public java.lang.String getCode() {
java.lang.Object ref = code_;
if (!(ref instanceof java.lang.String)) {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
code_ = s;
return s;
} else {
return (java.lang.String) ref;
}
}
/**
* <code>string code = 1;</code>
*/
public com.google.protobuf.ByteString
getCodeBytes() {
java.lang.Object ref = code_;
if (ref instanceof String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
code_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
/**
* <code>string code = 1;</code>
*/
public Builder setCode(
java.lang.String value) {
if (value == null) {
throw new NullPointerException();
}
code_ = value;
onChanged();
return this;
}
/**
* <code>string code = 1;</code>
*/
public Builder clearCode() {
code_ = getDefaultInstance().getCode();
onChanged();
return this;
}
/**
* <code>string code = 1;</code>
*/
public Builder setCodeBytes(
com.google.protobuf.ByteString value) {
if (value == null) {
throw new NullPointerException();
}
checkByteStringIsUtf8(value);
code_ = value;
onChanged();
return this;
}
private java.lang.Object data_ = "";
/**
* <code>string data = 2;</code>
*/
public java.lang.String getData() {
java.lang.Object ref = data_;
if (!(ref instanceof java.lang.String)) {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
data_ = s;
return s;
} else {
return (java.lang.String) ref;
}
}
/**
* <code>string data = 2;</code>
*/
public com.google.protobuf.ByteString
getDataBytes() {
java.lang.Object ref = data_;
if (ref instanceof String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
data_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
/**
* <code>string data = 2;</code>
*/
public Builder setData(
java.lang.String value) {
if (value == null) {
throw new NullPointerException();
}
data_ = value;
onChanged();
return this;
}
/**
* <code>string data = 2;</code>
*/
public Builder clearData() {
data_ = getDefaultInstance().getData();
onChanged();
return this;
}
/**
* <code>string data = 2;</code>
*/
public Builder setDataBytes(
com.google.protobuf.ByteString value) {
if (value == null) {
throw new NullPointerException();
}
checkByteStringIsUtf8(value);
data_ = value;
onChanged();
return this;
}
private java.lang.Object info_ = "";
/**
* <code>string info = 3;</code>
*/
public java.lang.String getInfo() {
java.lang.Object ref = info_;
if (!(ref instanceof java.lang.String)) {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
info_ = s;
return s;
} else {
return (java.lang.String) ref;
}
}
/**
* <code>string info = 3;</code>
*/
public com.google.protobuf.ByteString
getInfoBytes() {
java.lang.Object ref = info_;
if (ref instanceof String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
info_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
/**
* <code>string info = 3;</code>
*/
public Builder setInfo(
java.lang.String value) {
if (value == null) {
throw new NullPointerException();
}
info_ = value;
onChanged();
return this;
}
/**
* <code>string info = 3;</code>
*/
public Builder clearInfo() {
info_ = getDefaultInstance().getInfo();
onChanged();
return this;
}
/**
* <code>string info = 3;</code>
*/
public Builder setInfoBytes(
com.google.protobuf.ByteString value) {
if (value == null) {
throw new NullPointerException();
}
checkByteStringIsUtf8(value);
info_ = value;
onChanged();
return this;
}
@java.lang.Override
public final Builder setUnknownFields(
final com.google.protobuf.UnknownFieldSet unknownFields) {
return super.setUnknownFieldsProto3(unknownFields);
}
@java.lang.Override
public final Builder mergeUnknownFields(
final com.google.protobuf.UnknownFieldSet unknownFields) {
return super.mergeUnknownFields(unknownFields);
}
// @@protoc_insertion_point(builder_scope:org.nico.ratel.landlords.entity.ClientTransferDataProtoc)
}
// @@protoc_insertion_point(class_scope:org.nico.ratel.landlords.entity.ClientTransferDataProtoc)
private static final org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc DEFAULT_INSTANCE;
static {
DEFAULT_INSTANCE = new org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc();
}
public static org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc getDefaultInstance() {
return DEFAULT_INSTANCE;
}
private static final com.google.protobuf.Parser<ClientTransferDataProtoc>
PARSER = new com.google.protobuf.AbstractParser<ClientTransferDataProtoc>() {
@java.lang.Override
public ClientTransferDataProtoc parsePartialFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return new ClientTransferDataProtoc(input, extensionRegistry);
}
};
public static com.google.protobuf.Parser<ClientTransferDataProtoc> parser() {
return PARSER;
}
@java.lang.Override
public com.google.protobuf.Parser<ClientTransferDataProtoc> getParserForType() {
return PARSER;
}
@java.lang.Override
public org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc getDefaultInstanceForType() {
return DEFAULT_INSTANCE;
}
}
private static final com.google.protobuf.Descriptors.Descriptor
internal_static_org_nico_ratel_landlords_entity_ClientTransferDataProtoc_descriptor;
private static final
com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
internal_static_org_nico_ratel_landlords_entity_ClientTransferDataProtoc_fieldAccessorTable;
public static com.google.protobuf.Descriptors.FileDescriptor
getDescriptor() {
return descriptor;
}
private static com.google.protobuf.Descriptors.FileDescriptor
descriptor;
static {
java.lang.String[] descriptorData = {
"\n\036ClientTransferDataProtoc.proto\022\037org.ni" +
"co.ratel.landlords.entity\"D\n\030ClientTrans" +
"ferDataProtoc\022\014\n\004code\030\001 \001(\t\022\014\n\004data\030\002 \001(" +
"\t\022\014\n\004info\030\003 \001(\tB5\n\037org.nico.ratel.landlo" +
"rds.entityB\022ClientTransferDatab\006proto3"
};
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() {
public com.google.protobuf.ExtensionRegistry assignDescriptors(
com.google.protobuf.Descriptors.FileDescriptor root) {
descriptor = root;
return null;
}
};
com.google.protobuf.Descriptors.FileDescriptor
.internalBuildGeneratedFileFrom(descriptorData,
new com.google.protobuf.Descriptors.FileDescriptor[] {
}, assigner);
internal_static_org_nico_ratel_landlords_entity_ClientTransferDataProtoc_descriptor =
getDescriptor().getMessageTypes().get(0);
internal_static_org_nico_ratel_landlords_entity_ClientTransferDataProtoc_fieldAccessorTable = new
com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
internal_static_org_nico_ratel_landlords_entity_ClientTransferDataProtoc_descriptor,
new java.lang.String[] { "Code", "Data", "Info", });
}
// @@protoc_insertion_point(outer_class_scope)
}

View File

@ -0,0 +1,34 @@
package org.nico.ratel.landlords.entity;
public class Msg {
private String code;
private String data;
private String info;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
}

View File

@ -0,0 +1,70 @@
package org.nico.ratel.landlords.entity;
import org.nico.ratel.landlords.enums.PokerLevel;
import org.nico.ratel.landlords.enums.PokerType;
/**
* Poke, with {@link PokerLevel} and {@link PokerType}
*
* @author nico
*/
public class Poker {
private PokerLevel level;
private PokerType type;
public Poker() {
}
public Poker(PokerLevel level, PokerType type) {
this.level = level;
this.type = type;
}
public final PokerLevel getLevel() {
return level;
}
public final void setLevel(PokerLevel level) {
this.level = level;
}
public final PokerType getType() {
return type;
}
public final void setType(PokerType type) {
this.type = type;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((level == null) ? 0 : level.hashCode());
result = prime * result + ((type == null) ? 0 : type.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Poker other = (Poker) obj;
if (level != other.level)
return false;
return type == other.type;
}
@Override
public String toString() {
return level.getLevel() + " ";
}
}

View File

@ -0,0 +1,62 @@
package org.nico.ratel.landlords.entity;
import org.nico.ratel.landlords.enums.SellType;
import org.nico.ratel.landlords.helper.PokerHelper;
import java.util.List;
public class PokerSell {
private int score;
private SellType sellType;
private List<Poker> sellPokers;
private int coreLevel;
public PokerSell(SellType sellType, List<Poker> sellPokers, int coreLevel) {
this.score = PokerHelper.parseScore(sellType, coreLevel);
this.sellType = sellType;
this.sellPokers = sellPokers;
this.coreLevel = coreLevel;
}
public final int getCoreLevel() {
return coreLevel;
}
public final void setCoreLevel(int coreLevel) {
this.coreLevel = coreLevel;
}
public final int getScore() {
return score;
}
public final void setScore(int score) {
this.score = score;
}
public final SellType getSellType() {
return sellType;
}
public final void setSellType(SellType sellType) {
this.sellType = sellType;
}
public final List<Poker> getSellPokers() {
return sellPokers;
}
public final void setSellPokers(List<Poker> sellPokers) {
this.sellPokers = sellPokers;
}
@Override
public String toString() {
return sellType + "\t| " + score + "\t|" + sellPokers;
}
}

View File

@ -0,0 +1,215 @@
package org.nico.ratel.landlords.entity;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.locks.ReentrantLock;
import org.nico.noson.annotations.JsonIgnore;
import org.nico.ratel.landlords.enums.RoomStatus;
import org.nico.ratel.landlords.enums.RoomType;
public class Room {
private int id;
private String roomOwner;
private RoomStatus status;
private RoomType type;
private Map<Integer, ClientSide> clientSideMap;
private LinkedList<ClientSide> clientSideList;
private int landlordId = -1;
private List<Poker> landlordPokers;
private PokerSell lastPokerShell;
private int lastSellClient = -1;
private int currentSellClient = -1;
private int difficultyCoefficient;
private long lastFlushTime;
private long createTime;
private int firstSellClient;
/** 观战者列表 */
private List<ClientSide> watcherList = new ArrayList<>(5);
private int scoreRate = 1;
private int baseScore = 3;
public Room() {
}
public Room(int id) {
this.id = id;
this.clientSideMap = new ConcurrentSkipListMap<>();
this.clientSideList = new LinkedList<>();
this.status = RoomStatus.WAIT;
this.createTime = System.currentTimeMillis();
}
public int getScore() {
return this.baseScore * this.scoreRate;
}
public int getBaseScore() {
return this.baseScore;
}
public void setBaseScore(int baseScore) {
this.baseScore = baseScore;
}
public int getScoreRate() {
return this.scoreRate;
}
public void setScoreRate(int scoreRate) {
this.scoreRate = scoreRate;
}
public void initScoreRate() {
this.scoreRate = 1;
}
public void increaseRate() {
this.scoreRate *= 2;
}
public final long getCreateTime() {
return createTime;
}
public final void setCreateTime(long createTime) {
this.createTime = createTime;
}
public final int getDifficultyCoefficient() {
return difficultyCoefficient;
}
public final void setDifficultyCoefficient(int difficultyCoefficient) {
this.difficultyCoefficient = difficultyCoefficient;
}
public final RoomType getType() {
return type;
}
public final void setType(RoomType type) {
this.type = type;
}
public final PokerSell getLastPokerShell() {
return lastPokerShell;
}
public final void setLastPokerShell(PokerSell lastPokerShell) {
this.lastPokerShell = lastPokerShell;
}
public final int getCurrentSellClient() {
return currentSellClient;
}
public final void setCurrentSellClient(int currentSellClient) {
this.currentSellClient = currentSellClient;
}
public long getLastFlushTime() {
return lastFlushTime;
}
public void setLastFlushTime(long lastFlushTime) {
this.lastFlushTime = lastFlushTime;
}
public int getLastSellClient() {
return lastSellClient;
}
public void setLastSellClient(int lastSellClient) {
this.lastSellClient = lastSellClient;
}
public int getLandlordId() {
return landlordId;
}
public void setLandlordId(int landlordId) {
this.landlordId = landlordId;
}
public LinkedList<ClientSide> getClientSideList() {
return clientSideList;
}
public void setClientSideList(LinkedList<ClientSide> clientSideList) {
this.clientSideList = clientSideList;
}
public List<Poker> getLandlordPokers() {
return landlordPokers;
}
public void setLandlordPokers(List<Poker> landlordPokers) {
this.landlordPokers = landlordPokers;
}
public final String getRoomOwner() {
return roomOwner;
}
public final void setRoomOwner(String roomOwner) {
this.roomOwner = roomOwner;
}
public final int getId() {
return id;
}
public final void setId(int id) {
this.id = id;
}
public final RoomStatus getStatus() {
return status;
}
public final void setStatus(RoomStatus status) {
this.status = status;
}
public final Map<Integer, ClientSide> getClientSideMap() {
return clientSideMap;
}
public final void setClientSideMap(Map<Integer, ClientSide> clientSideMap) {
this.clientSideMap = clientSideMap;
}
public int getFirstSellClient() {
return firstSellClient;
}
public void setFirstSellClient(int firstSellClient) {
this.firstSellClient = firstSellClient;
}
public List<ClientSide> getWatcherList() {
return watcherList;
}
}

View File

@ -0,0 +1,945 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: ServerTransferDataProtoc.proto
package org.nico.ratel.landlords.entity;
public final class ServerTransferData {
private ServerTransferData() {
}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistryLite registry) {
}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistry registry) {
registerAllExtensions(
(com.google.protobuf.ExtensionRegistryLite) registry);
}
public interface ServerTransferDataProtocOrBuilder extends
// @@protoc_insertion_point(interface_extends:org.nico.ratel.landlords.entity.ServerTransferDataProtoc)
com.google.protobuf.MessageOrBuilder {
/**
* <code>string code = 1;</code>
*/
java.lang.String getCode();
/**
* <code>string code = 1;</code>
*/
com.google.protobuf.ByteString
getCodeBytes();
/**
* <code>string data = 2;</code>
*/
java.lang.String getData();
/**
* <code>string data = 2;</code>
*/
com.google.protobuf.ByteString
getDataBytes();
/**
* <code>string info = 3;</code>
*/
java.lang.String getInfo();
/**
* <code>string info = 3;</code>
*/
com.google.protobuf.ByteString
getInfoBytes();
}
/**
* Protobuf type {@code org.nico.ratel.landlords.entity.ServerTransferDataProtoc}
*/
public static final class ServerTransferDataProtoc extends
com.google.protobuf.GeneratedMessageV3 implements
// @@protoc_insertion_point(message_implements:org.nico.ratel.landlords.entity.ServerTransferDataProtoc)
ServerTransferDataProtocOrBuilder {
private static final long serialVersionUID = 0L;
// Use ServerTransferDataProtoc.newBuilder() to construct.
private ServerTransferDataProtoc(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
super(builder);
}
private ServerTransferDataProtoc() {
code_ = "";
data_ = "";
info_ = "";
}
@java.lang.Override
public final com.google.protobuf.UnknownFieldSet
getUnknownFields() {
return this.unknownFields;
}
private ServerTransferDataProtoc(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
this();
if (extensionRegistry == null) {
throw new java.lang.NullPointerException();
}
int mutable_bitField0_ = 0;
com.google.protobuf.UnknownFieldSet.Builder unknownFields =
com.google.protobuf.UnknownFieldSet.newBuilder();
try {
boolean done = false;
while (!done) {
int tag = input.readTag();
switch (tag) {
case 0:
done = true;
break;
case 10: {
java.lang.String s = input.readStringRequireUtf8();
code_ = s;
break;
}
case 18: {
java.lang.String s = input.readStringRequireUtf8();
data_ = s;
break;
}
case 26: {
java.lang.String s = input.readStringRequireUtf8();
info_ = s;
break;
}
default: {
if (!parseUnknownFieldProto3(
input, unknownFields, extensionRegistry, tag)) {
done = true;
}
break;
}
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
throw e.setUnfinishedMessage(this);
} catch (java.io.IOException e) {
throw new com.google.protobuf.InvalidProtocolBufferException(
e).setUnfinishedMessage(this);
} finally {
this.unknownFields = unknownFields.build();
makeExtensionsImmutable();
}
}
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return org.nico.ratel.landlords.entity.ServerTransferData.internal_static_org_nico_ratel_landlords_entity_ServerTransferDataProtoc_descriptor;
}
@java.lang.Override
protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
internalGetFieldAccessorTable() {
return org.nico.ratel.landlords.entity.ServerTransferData.internal_static_org_nico_ratel_landlords_entity_ServerTransferDataProtoc_fieldAccessorTable
.ensureFieldAccessorsInitialized(
org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc.class, org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc.Builder.class);
}
public static final int CODE_FIELD_NUMBER = 1;
private volatile java.lang.Object code_;
/**
* <code>string code = 1;</code>
*/
public java.lang.String getCode() {
java.lang.Object ref = code_;
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
code_ = s;
return s;
}
}
/**
* <code>string code = 1;</code>
*/
public com.google.protobuf.ByteString
getCodeBytes() {
java.lang.Object ref = code_;
if (ref instanceof java.lang.String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
code_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
public static final int DATA_FIELD_NUMBER = 2;
private volatile java.lang.Object data_;
/**
* <code>string data = 2;</code>
*/
public java.lang.String getData() {
java.lang.Object ref = data_;
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
data_ = s;
return s;
}
}
/**
* <code>string data = 2;</code>
*/
public com.google.protobuf.ByteString
getDataBytes() {
java.lang.Object ref = data_;
if (ref instanceof java.lang.String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
data_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
public static final int INFO_FIELD_NUMBER = 3;
private volatile java.lang.Object info_;
/**
* <code>string info = 3;</code>
*/
public java.lang.String getInfo() {
java.lang.Object ref = info_;
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
info_ = s;
return s;
}
}
/**
* <code>string info = 3;</code>
*/
public com.google.protobuf.ByteString
getInfoBytes() {
java.lang.Object ref = info_;
if (ref instanceof java.lang.String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
info_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
private byte memoizedIsInitialized = -1;
@java.lang.Override
public final boolean isInitialized() {
byte isInitialized = memoizedIsInitialized;
if (isInitialized == 1) return true;
if (isInitialized == 0) return false;
memoizedIsInitialized = 1;
return true;
}
@java.lang.Override
public void writeTo(com.google.protobuf.CodedOutputStream output)
throws java.io.IOException {
if (!getCodeBytes().isEmpty()) {
com.google.protobuf.GeneratedMessageV3.writeString(output, 1, code_);
}
if (!getDataBytes().isEmpty()) {
com.google.protobuf.GeneratedMessageV3.writeString(output, 2, data_);
}
if (!getInfoBytes().isEmpty()) {
com.google.protobuf.GeneratedMessageV3.writeString(output, 3, info_);
}
unknownFields.writeTo(output);
}
@java.lang.Override
public int getSerializedSize() {
int size = memoizedSize;
if (size != -1) return size;
size = 0;
if (!getCodeBytes().isEmpty()) {
size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, code_);
}
if (!getDataBytes().isEmpty()) {
size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, data_);
}
if (!getInfoBytes().isEmpty()) {
size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, info_);
}
size += unknownFields.getSerializedSize();
memoizedSize = size;
return size;
}
@java.lang.Override
public boolean equals(final java.lang.Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc)) {
return super.equals(obj);
}
org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc other = (org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc) obj;
boolean result = true;
result = result && getCode()
.equals(other.getCode());
result = result && getData()
.equals(other.getData());
result = result && getInfo()
.equals(other.getInfo());
result = result && unknownFields.equals(other.unknownFields);
return result;
}
@java.lang.Override
public int hashCode() {
if (memoizedHashCode != 0) {
return memoizedHashCode;
}
int hash = 41;
hash = (19 * hash) + getDescriptor().hashCode();
hash = (37 * hash) + CODE_FIELD_NUMBER;
hash = (53 * hash) + getCode().hashCode();
hash = (37 * hash) + DATA_FIELD_NUMBER;
hash = (53 * hash) + getData().hashCode();
hash = (37 * hash) + INFO_FIELD_NUMBER;
hash = (53 * hash) + getInfo().hashCode();
hash = (29 * hash) + unknownFields.hashCode();
memoizedHashCode = hash;
return hash;
}
public static org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc parseFrom(
java.nio.ByteBuffer data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc parseFrom(
java.nio.ByteBuffer data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc parseFrom(
com.google.protobuf.ByteString data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc parseFrom(
com.google.protobuf.ByteString data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc parseFrom(byte[] data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc parseFrom(
byte[] data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc parseFrom(java.io.InputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseWithIOException(PARSER, input);
}
public static org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc parseFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseWithIOException(PARSER, input, extensionRegistry);
}
public static org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc parseDelimitedFrom(java.io.InputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseDelimitedWithIOException(PARSER, input);
}
public static org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc parseDelimitedFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseDelimitedWithIOException(PARSER, input, extensionRegistry);
}
public static org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc parseFrom(
com.google.protobuf.CodedInputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseWithIOException(PARSER, input);
}
public static org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc parseFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseWithIOException(PARSER, input, extensionRegistry);
}
@java.lang.Override
public Builder newBuilderForType() {
return newBuilder();
}
public static Builder newBuilder() {
return DEFAULT_INSTANCE.toBuilder();
}
public static Builder newBuilder(org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc prototype) {
return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
}
@java.lang.Override
public Builder toBuilder() {
return this == DEFAULT_INSTANCE
? new Builder() : new Builder().mergeFrom(this);
}
@java.lang.Override
protected Builder newBuilderForType(
com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
Builder builder = new Builder(parent);
return builder;
}
/**
* Protobuf type {@code org.nico.ratel.landlords.entity.ServerTransferDataProtoc}
*/
public static final class Builder extends
com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
// @@protoc_insertion_point(builder_implements:org.nico.ratel.landlords.entity.ServerTransferDataProtoc)
org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtocOrBuilder {
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return org.nico.ratel.landlords.entity.ServerTransferData.internal_static_org_nico_ratel_landlords_entity_ServerTransferDataProtoc_descriptor;
}
@java.lang.Override
protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
internalGetFieldAccessorTable() {
return org.nico.ratel.landlords.entity.ServerTransferData.internal_static_org_nico_ratel_landlords_entity_ServerTransferDataProtoc_fieldAccessorTable
.ensureFieldAccessorsInitialized(
org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc.class, org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc.Builder.class);
}
// Construct using org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc.newBuilder()
private Builder() {
maybeForceBuilderInitialization();
}
private Builder(
com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
super(parent);
maybeForceBuilderInitialization();
}
private void maybeForceBuilderInitialization() {
if (com.google.protobuf.GeneratedMessageV3
.alwaysUseFieldBuilders) {
}
}
@java.lang.Override
public Builder clear() {
super.clear();
code_ = "";
data_ = "";
info_ = "";
return this;
}
@java.lang.Override
public com.google.protobuf.Descriptors.Descriptor
getDescriptorForType() {
return org.nico.ratel.landlords.entity.ServerTransferData.internal_static_org_nico_ratel_landlords_entity_ServerTransferDataProtoc_descriptor;
}
@java.lang.Override
public org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc getDefaultInstanceForType() {
return org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc.getDefaultInstance();
}
@java.lang.Override
public org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc build() {
org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc result = buildPartial();
if (!result.isInitialized()) {
throw newUninitializedMessageException(result);
}
return result;
}
@java.lang.Override
public org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc buildPartial() {
org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc result = new org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc(this);
result.code_ = code_;
result.data_ = data_;
result.info_ = info_;
onBuilt();
return result;
}
@java.lang.Override
public Builder clone() {
return (Builder) super.clone();
}
@java.lang.Override
public Builder setField(
com.google.protobuf.Descriptors.FieldDescriptor field,
java.lang.Object value) {
return (Builder) super.setField(field, value);
}
@java.lang.Override
public Builder clearField(
com.google.protobuf.Descriptors.FieldDescriptor field) {
return (Builder) super.clearField(field);
}
@java.lang.Override
public Builder clearOneof(
com.google.protobuf.Descriptors.OneofDescriptor oneof) {
return (Builder) super.clearOneof(oneof);
}
@java.lang.Override
public Builder setRepeatedField(
com.google.protobuf.Descriptors.FieldDescriptor field,
int index, java.lang.Object value) {
return (Builder) super.setRepeatedField(field, index, value);
}
@java.lang.Override
public Builder addRepeatedField(
com.google.protobuf.Descriptors.FieldDescriptor field,
java.lang.Object value) {
return (Builder) super.addRepeatedField(field, value);
}
@java.lang.Override
public Builder mergeFrom(com.google.protobuf.Message other) {
if (other instanceof org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc) {
return mergeFrom((org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc) other);
} else {
super.mergeFrom(other);
return this;
}
}
public Builder mergeFrom(org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc other) {
if (other == org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc.getDefaultInstance())
return this;
if (!other.getCode().isEmpty()) {
code_ = other.code_;
onChanged();
}
if (!other.getData().isEmpty()) {
data_ = other.data_;
onChanged();
}
if (!other.getInfo().isEmpty()) {
info_ = other.info_;
onChanged();
}
this.mergeUnknownFields(other.unknownFields);
onChanged();
return this;
}
@java.lang.Override
public final boolean isInitialized() {
return true;
}
@java.lang.Override
public Builder mergeFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc parsedMessage = null;
try {
parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
parsedMessage = (org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc) e.getUnfinishedMessage();
throw e.unwrapIOException();
} finally {
if (parsedMessage != null) {
mergeFrom(parsedMessage);
}
}
return this;
}
private java.lang.Object code_ = "";
/**
* <code>string code = 1;</code>
*/
public java.lang.String getCode() {
java.lang.Object ref = code_;
if (!(ref instanceof java.lang.String)) {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
code_ = s;
return s;
} else {
return (java.lang.String) ref;
}
}
/**
* <code>string code = 1;</code>
*/
public com.google.protobuf.ByteString
getCodeBytes() {
java.lang.Object ref = code_;
if (ref instanceof String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
code_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
/**
* <code>string code = 1;</code>
*/
public Builder setCode(
java.lang.String value) {
if (value == null) {
throw new NullPointerException();
}
code_ = value;
onChanged();
return this;
}
/**
* <code>string code = 1;</code>
*/
public Builder clearCode() {
code_ = getDefaultInstance().getCode();
onChanged();
return this;
}
/**
* <code>string code = 1;</code>
*/
public Builder setCodeBytes(
com.google.protobuf.ByteString value) {
if (value == null) {
throw new NullPointerException();
}
checkByteStringIsUtf8(value);
code_ = value;
onChanged();
return this;
}
private java.lang.Object data_ = "";
/**
* <code>string data = 2;</code>
*/
public java.lang.String getData() {
java.lang.Object ref = data_;
if (!(ref instanceof java.lang.String)) {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
data_ = s;
return s;
} else {
return (java.lang.String) ref;
}
}
/**
* <code>string data = 2;</code>
*/
public com.google.protobuf.ByteString
getDataBytes() {
java.lang.Object ref = data_;
if (ref instanceof String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
data_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
/**
* <code>string data = 2;</code>
*/
public Builder setData(
java.lang.String value) {
if (value == null) {
throw new NullPointerException();
}
data_ = value;
onChanged();
return this;
}
/**
* <code>string data = 2;</code>
*/
public Builder clearData() {
data_ = getDefaultInstance().getData();
onChanged();
return this;
}
/**
* <code>string data = 2;</code>
*/
public Builder setDataBytes(
com.google.protobuf.ByteString value) {
if (value == null) {
throw new NullPointerException();
}
checkByteStringIsUtf8(value);
data_ = value;
onChanged();
return this;
}
private java.lang.Object info_ = "";
/**
* <code>string info = 3;</code>
*/
public java.lang.String getInfo() {
java.lang.Object ref = info_;
if (!(ref instanceof java.lang.String)) {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
info_ = s;
return s;
} else {
return (java.lang.String) ref;
}
}
/**
* <code>string info = 3;</code>
*/
public com.google.protobuf.ByteString
getInfoBytes() {
java.lang.Object ref = info_;
if (ref instanceof String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
info_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
/**
* <code>string info = 3;</code>
*/
public Builder setInfo(
java.lang.String value) {
if (value == null) {
throw new NullPointerException();
}
info_ = value;
onChanged();
return this;
}
/**
* <code>string info = 3;</code>
*/
public Builder clearInfo() {
info_ = getDefaultInstance().getInfo();
onChanged();
return this;
}
/**
* <code>string info = 3;</code>
*/
public Builder setInfoBytes(
com.google.protobuf.ByteString value) {
if (value == null) {
throw new NullPointerException();
}
checkByteStringIsUtf8(value);
info_ = value;
onChanged();
return this;
}
@java.lang.Override
public final Builder setUnknownFields(
final com.google.protobuf.UnknownFieldSet unknownFields) {
return super.setUnknownFieldsProto3(unknownFields);
}
@java.lang.Override
public final Builder mergeUnknownFields(
final com.google.protobuf.UnknownFieldSet unknownFields) {
return super.mergeUnknownFields(unknownFields);
}
// @@protoc_insertion_point(builder_scope:org.nico.ratel.landlords.entity.ServerTransferDataProtoc)
}
// @@protoc_insertion_point(class_scope:org.nico.ratel.landlords.entity.ServerTransferDataProtoc)
private static final org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc DEFAULT_INSTANCE;
static {
DEFAULT_INSTANCE = new org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc();
}
public static org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc getDefaultInstance() {
return DEFAULT_INSTANCE;
}
private static final com.google.protobuf.Parser<ServerTransferDataProtoc>
PARSER = new com.google.protobuf.AbstractParser<ServerTransferDataProtoc>() {
@java.lang.Override
public ServerTransferDataProtoc parsePartialFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return new ServerTransferDataProtoc(input, extensionRegistry);
}
};
public static com.google.protobuf.Parser<ServerTransferDataProtoc> parser() {
return PARSER;
}
@java.lang.Override
public com.google.protobuf.Parser<ServerTransferDataProtoc> getParserForType() {
return PARSER;
}
@java.lang.Override
public org.nico.ratel.landlords.entity.ServerTransferData.ServerTransferDataProtoc getDefaultInstanceForType() {
return DEFAULT_INSTANCE;
}
}
private static final com.google.protobuf.Descriptors.Descriptor
internal_static_org_nico_ratel_landlords_entity_ServerTransferDataProtoc_descriptor;
private static final
com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
internal_static_org_nico_ratel_landlords_entity_ServerTransferDataProtoc_fieldAccessorTable;
public static com.google.protobuf.Descriptors.FileDescriptor
getDescriptor() {
return descriptor;
}
private static com.google.protobuf.Descriptors.FileDescriptor
descriptor;
static {
java.lang.String[] descriptorData = {
"\n\036ServerTransferDataProtoc.proto\022\037org.ni" +
"co.ratel.landlords.entity\"D\n\030ServerTrans" +
"ferDataProtoc\022\014\n\004code\030\001 \001(\t\022\014\n\004data\030\002 \001(" +
"\t\022\014\n\004info\030\003 \001(\tB5\n\037org.nico.ratel.landlo" +
"rds.entityB\022ServerTransferDatab\006proto3"
};
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
public com.google.protobuf.ExtensionRegistry assignDescriptors(
com.google.protobuf.Descriptors.FileDescriptor root) {
descriptor = root;
return null;
}
};
com.google.protobuf.Descriptors.FileDescriptor
.internalBuildGeneratedFileFrom(descriptorData,
new com.google.protobuf.Descriptors.FileDescriptor[]{
}, assigner);
internal_static_org_nico_ratel_landlords_entity_ServerTransferDataProtoc_descriptor =
getDescriptor().getMessageTypes().get(0);
internal_static_org_nico_ratel_landlords_entity_ServerTransferDataProtoc_fieldAccessorTable = new
com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
internal_static_org_nico_ratel_landlords_entity_ServerTransferDataProtoc_descriptor,
new java.lang.String[]{"Code", "Data", "Info",});
}
// @@protoc_insertion_point(outer_class_scope)
}

View File

@ -0,0 +1,85 @@
package org.nico.ratel.landlords.enums;
import java.io.Serializable;
public enum ClientEventCode implements Serializable {
CODE_CLIENT_NICKNAME_SET("设置昵称"),
CODE_CLIENT_EXIT("客户端退出"),
CODE_CLIENT_KICK("客户端被踢出"),
CODE_CLIENT_CONNECT("客户端加入成功"),
CODE_SHOW_OPTIONS("全局选项列表"),
CODE_SHOW_OPTIONS_SETTING("设置选项"),
CODE_SHOW_OPTIONS_PVP("玩家对战选项"),
CODE_SHOW_OPTIONS_PVE("人机对战选项"),
CODE_SHOW_ROOMS("展示房间列表"),
CODE_SHOW_POKERS("展示Poker"),
CODE_ROOM_CREATE_SUCCESS("创建房间成功"),
CODE_ROOM_JOIN_SUCCESS("加入房间成功"),
CODE_ROOM_JOIN_FAIL_BY_FULL("房间人数已满"),
CODE_ROOM_JOIN_FAIL_BY_INEXIST("加入-房间不存在"),
CODE_ROOM_PLAY_FAIL_BY_INEXIST1("出牌-房间不存在"),
CODE_GAME_STARTING("开始游戏"),
CODE_GAME_LANDLORD_ELECT("抢地主"),
CODE_GAME_LANDLORD_CONFIRM("地主确认"),
CODE_GAME_LANDLORD_CYCLE("地主一轮确认结束"),
CODE_GAME_POKER_PLAY("出牌回合"),
CODE_GAME_POKER_PLAY_REDIRECT("出牌重定向"),
CODE_GAME_POKER_PLAY_MISMATCH("出牌不匹配"),
CODE_GAME_POKER_PLAY_LESS("出牌太小"),
CODE_GAME_POKER_PLAY_PASS("不出"),
CODE_GAME_POKER_PLAY_CANT_PASS("不允许不出"),
CODE_GAME_POKER_PLAY_INVALID("无效"),
CODE_GAME_POKER_PLAY_ORDER_ERROR("顺序错误"),
CODE_GAME_OVER("游戏结束"),
CODE_PVE_DIFFICULTY_NOT_SUPPORT("人机难度不支持"),
CODE_GAME_READY("准备开始游戏"),
CODE_GAME_WATCH("观战"),
CODE_GAME_WATCH_SUCCESSFUL("观战成功");
private String msg;
private ClientEventCode(String msg) {
this.msg = msg;
}
public final String getMsg() {
return msg;
}
public final void setMsg(String msg) {
this.msg = msg;
}
}

View File

@ -0,0 +1,9 @@
package org.nico.ratel.landlords.enums;
public enum ClientRole {
PLAYER,
ROBOT
}

View File

@ -0,0 +1,18 @@
package org.nico.ratel.landlords.enums;
public enum ClientStatus {
TO_CHOOSE,
NO_READY,
READY,
WAIT,
CALL_LANDLORD,
PLAYING
}

View File

@ -0,0 +1,9 @@
package org.nico.ratel.landlords.enums;
public enum ClientType {
LANDLORD,
PEASANT
}

View File

@ -0,0 +1,113 @@
package org.nico.ratel.landlords.enums;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/**
* Poker level
*
* @author nico
*/
public enum PokerLevel {
LEVEL_3(3, "3", new Character[]{'3'}),
LEVEL_4(4, "4", new Character[]{'4'}),
LEVEL_5(5, "5", new Character[]{'5'}),
LEVEL_6(6, "6", new Character[]{'6'}),
LEVEL_7(7, "7", new Character[]{'7'}),
LEVEL_8(8, "8", new Character[]{'8'}),
LEVEL_9(9, "9", new Character[]{'9'}),
LEVEL_10(10, "10", new Character[]{'T', 't', '0'}),
LEVEL_J(11, "J", new Character[]{'J', 'j'}),
LEVEL_Q(12, "Q", new Character[]{'Q', 'q'}),
LEVEL_K(13, "K", new Character[]{'K', 'k'}),
LEVEL_A(14, "A", new Character[]{'A', 'a', '1'}),
LEVEL_2(15, "2", new Character[]{'2'}),
LEVEL_SMALL_KING(16, "S", new Character[]{'S', 's'}),
LEVEL_BIG_KING(17, "X", new Character[]{'X', 'x'}),
;
private int level;
private String name;
private Character[] alias;
private static Set<Character> aliasSet = new HashSet<>();
static {
for (PokerLevel level : PokerLevel.values()) {
PokerLevel.aliasSet.addAll(Arrays.asList(level.getAlias()));
}
}
private PokerLevel(int level, String name, Character[] alias) {
this.level = level;
this.name = name;
this.alias = alias;
}
public static boolean aliasContains(char key) {
return aliasSet.contains(key);
}
public final Character[] getAlias() {
return alias;
}
public final void setAlias(Character[] alias) {
this.alias = alias;
}
public final String getName() {
return name;
}
public final void setName(String name) {
this.name = name;
}
public final int getLevel() {
return level;
}
public final void setLevel(int level) {
this.level = level;
}
public static final PokerLevel parseByName(String name) {
if(name == null) {
return null;
}
for(PokerLevel level: PokerLevel.values()) {
if(level.name.equals(name.toUpperCase())) {
return level;
}
}
return null;
}
public static final PokerLevel parseByLevel(int l) {
for(PokerLevel level: PokerLevel.values()) {
if(level.level == l) {
return level;
}
}
return null;
}
}

View File

@ -0,0 +1,29 @@
package org.nico.ratel.landlords.enums;
/**
* Poker type Spade Heart Diamond Club
*
* @author nico
*/
public enum PokerType {
BLANK(" "),
DIAMOND("♦"),
CLUB("♣"),
SPADE("♠"),
HEART("♥");
private final String name;
PokerType(String name) {
this.name = name;
}
public final String getName() {
return name;
}
}

View File

@ -0,0 +1,28 @@
package org.nico.ratel.landlords.enums;
public enum RoomStatus {
BLANK("空闲"),
WAIT("等待"),
STARTING("开始"),
;
private String msg;
RoomStatus(String msg) {
this.msg = msg;
}
public final String getMsg() {
return msg;
}
public final void setMsg(String msg) {
this.msg = msg;
}
}

View File

@ -0,0 +1,24 @@
package org.nico.ratel.landlords.enums;
public enum RoomType {
PVP("玩家对战"),
PVE("人机对战"),
;
private String msg;
RoomType(String msg) {
this.msg = msg;
}
public final String getMsg() {
return msg;
}
public final void setMsg(String msg) {
this.msg = msg;
}
}

View File

@ -0,0 +1,56 @@
package org.nico.ratel.landlords.enums;
public enum SellType {
ILLEGAL("非合法"),
BOMB("炸弹"),
KING_BOMB("王炸"),
SINGLE("单个牌"),
DOUBLE("对子牌"),
THREE("三张牌"),
THREE_ZONES_SINGLE("三带单"),
THREE_ZONES_DOUBLE("三带对"),
FOUR_ZONES_SINGLE("四带单"),
FOUR_ZONES_DOUBLE("四带对"),
SINGLE_STRAIGHT("单顺子"),
DOUBLE_STRAIGHT("双顺子"),
THREE_STRAIGHT("三顺子"),
FOUR_STRAIGHT("四顺子"),
THREE_STRAIGHT_WITH_SINGLE("飞机带单牌"),
THREE_STRAIGHT_WITH_DOUBLE("飞机带对牌"),
FOUR_STRAIGHT_WITH_SINGLE("四顺子带单"),
FOUR_STRAIGHT_WITH_DOUBLE("四顺子带对"),
;
private String msg;
SellType(String msg) {
this.msg = msg;
}
public final String getMsg() {
return msg;
}
public final void setMsg(String msg) {
this.msg = msg;
}
}

View File

@ -0,0 +1,56 @@
package org.nico.ratel.landlords.enums;
import java.io.Serializable;
public enum ServerEventCode implements Serializable {
CODE_CLIENT_EXIT("玩家退出"),
CODE_CLIENT_OFFLINE("玩家离线"),
CODE_CLIENT_INFO_SET("设置客户端信息"),
CODE_CLIENT_NICKNAME_SET("设置昵称"),
CODE_CLIENT_HEAD_BEAT("不出"),
CODE_ROOM_CREATE("创建PVP房间"),
CODE_ROOM_CREATE_PVE("创建PVE房间"),
CODE_GET_ROOMS("获取房间列表"),
CODE_ROOM_JOIN("加入房间"),
CODE_GAME_STARTING("游戏开始"),
CODE_GAME_READY("玩家准备"),
CODE_GAME_LANDLORD_ELECT("抢地主"),
CODE_GAME_POKER_PLAY("出牌环节"),
CODE_GAME_POKER_PLAY_REDIRECT("出牌重定向"),
CODE_GAME_POKER_PLAY_PASS("不出"),
CODE_GAME_WATCH("观战"),
CODE_GAME_WATCH_EXIT("退出观战");
private String msg;
ServerEventCode(String msg) {
this.msg = msg;
}
public final String getMsg() {
return msg;
}
public final void setMsg(String msg) {
this.msg = msg;
}
}

View File

@ -0,0 +1,27 @@
package org.nico.ratel.landlords.exception;
public class LandlordException extends RuntimeException {
private static final long serialVersionUID = -5643145833569293539L;
public LandlordException() {
super();
}
public LandlordException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
public LandlordException(String message, Throwable cause) {
super(message, cause);
}
public LandlordException(String message) {
super(message);
}
public LandlordException(Throwable cause) {
super(cause);
}
}

View File

@ -0,0 +1,23 @@
package org.nico.ratel.landlords.features;
import java.util.*;
public class Features {
public final static String VERSION_1_3_0 = "v1.3.0";
public final static String READY = "READY";
private final static Map<String, List<String>> FEATURES = new HashMap<>();
static{
FEATURES.put(VERSION_1_3_0, Collections.singletonList(READY));
}
public static boolean supported(String clientVersion, String feature){
List<String> features = FEATURES.get(clientVersion);
if (Objects.isNull(features) || Objects.isNull(feature)){
return false;
}
return features.contains(feature.toUpperCase(Locale.ROOT));
}
}

View File

@ -0,0 +1,27 @@
package org.nico.ratel.landlords.handler;
import java.util.List;
import org.nico.ratel.landlords.transfer.TransferProtocolUtils;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
public class DefaultDecoder extends ByteToMessageDecoder {
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
int startIndex;
int endIndex;
if ((startIndex = in.indexOf(in.readerIndex(), in.writerIndex(), TransferProtocolUtils.PROTOCOL_HAED)) != -1 &&
(endIndex = in.indexOf(startIndex + 1, in.writerIndex(), TransferProtocolUtils.PROTOCOL_TAIL)) != -1) {
endIndex++;
byte[] bytes = new byte[endIndex - startIndex];
in.skipBytes(startIndex - in.readerIndex());
in.readBytes(bytes, 0, bytes.length);
out.add(bytes);
}
}
}

View File

@ -0,0 +1,37 @@
package org.nico.ratel.landlords.helper;
import java.util.LinkedHashMap;
import java.util.Map;
import org.nico.noson.Noson;
public class MapHelper {
private final Map<String, Object> data;
private MapHelper() {
this.data = new LinkedHashMap<>();
}
public static MapHelper newInstance() {
return new MapHelper();
}
public static Map<String, Object> parser(String json) {
return Noson.convert(json, Map.class);
}
public MapHelper put(String name, Object Object) {
this.data.put(name, Object);
return this;
}
public String json() {
return Noson.reversal(data);
}
public Map<String, Object> map() {
return data;
}
}

View File

@ -0,0 +1,632 @@
package org.nico.ratel.landlords.helper;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.entity.PokerSell;
import org.nico.ratel.landlords.enums.PokerLevel;
import org.nico.ratel.landlords.enums.PokerType;
import org.nico.ratel.landlords.enums.SellType;
import org.nico.ratel.landlords.utils.ListUtils;
public class PokerHelper {
/**
* Print the type of poker style
*/
public static int pokerPrinterType = 0;
public static int totalPrinters = 5;
/**
* The list of all pokers, by 54
*/
private static final List<Poker> basePokers = new ArrayList<>(54);
private static final Comparator<Poker> pokerComparator = (o1, o2) -> o1.getLevel().getLevel() - o2.getLevel().getLevel();
static {
PokerLevel[] pokerLevels = PokerLevel.values();
PokerType[] pokerTypes = PokerType.values();
for (PokerLevel level : pokerLevels) {
if (level == PokerLevel.LEVEL_BIG_KING) {
basePokers.add(new Poker(level, PokerType.BLANK));
continue;
}
if (level == PokerLevel.LEVEL_SMALL_KING) {
basePokers.add(new Poker(level, PokerType.BLANK));
continue;
}
for (PokerType type : pokerTypes) {
if (type == PokerType.BLANK) {
continue;
}
basePokers.add(new Poker(level, type));
}
}
}
public static void sortPoker(List<Poker> pokers) {
pokers.sort(pokerComparator);
}
public static List<Poker> clonePokers(List<Poker> pokers){
List<Poker> newPokers = new ArrayList<Poker>(pokers.size());
for(Poker poker: pokers) {
newPokers.add(new Poker(poker.getLevel(), poker.getType()));
}
return newPokers;
}
public static List<PokerSell> validSells(PokerSell lastPokerSell, List<Poker> pokers) {
List<PokerSell> sells = PokerHelper.parsePokerSells(pokers);
if(lastPokerSell == null) {
return sells;
}
List<PokerSell> validSells = new ArrayList<PokerSell>();
for(PokerSell sell: sells) {
if(sell.getSellType() == lastPokerSell.getSellType()) {
if(sell.getScore() > lastPokerSell.getScore() && sell.getSellPokers().size() == lastPokerSell.getSellPokers().size()) {
validSells.add(sell);
}
}
if(sell.getSellType() == SellType.KING_BOMB) {
validSells.add(sell);
}
}
if(lastPokerSell.getSellType() != SellType.BOMB) {
for(PokerSell sell: sells) {
if(sell.getSellType() == SellType.BOMB) {
validSells.add(sell);
}
}
}
return validSells;
}
public static int[] getIndexes(Character[] options, List<Poker> pokers) {
List<Poker> copyList = new ArrayList<>(pokers.size());
copyList.addAll(pokers);
int[] indexes = new int[options.length];
for (int index = 0; index < options.length; index++) {
char option = options[index];
boolean isTarget = false;
for (int pi = 0; pi < copyList.size(); pi++) {
Poker poker = copyList.get(pi);
if (poker == null) {
continue;
}
if (Arrays.asList(poker.getLevel().getAlias()).contains(option)) {
isTarget = true;
//Index start from 1, not 0
indexes[index] = pi + 1;
copyList.set(pi, null);
break;
}
}
if (!isTarget) {
return null;
}
}
Arrays.sort(indexes);
return indexes;
}
public static boolean checkPokerIndex(int[] indexes, List<Poker> pokers) {
if (indexes == null || indexes.length == 0) {
return false;
}
for (int index : indexes) {
if (index > pokers.size() || index < 1) {
return false;
}
}
return true;
}
public static PokerSell checkPokerType(List<Poker> pokers) {
if (pokers == null || pokers.isEmpty()) {
return new PokerSell(SellType.ILLEGAL, null, -1);
}
sortPoker(pokers);
int[] levelTable = new int[20];
for (Poker poker : pokers) {
levelTable[poker.getLevel().getLevel()]++;
}
int startIndex = -1;
int endIndex = -1;
int count = 0;
int singleCount = 0;
int doubleCount = 0;
int threeCount = 0;
int threeStartIndex = -1;
int threeEndIndex = -1;
int fourCount = 0;
int fourStartIndex = -1;
int fourEndIndex = -1;
for (int index = 0; index < levelTable.length; index++) {
int value = levelTable[index];
if (value == 0) {
continue;
}
endIndex = index;
count++;
if (startIndex == -1) {
startIndex = index;
}
if (value == 1) {
singleCount++;
} else if (value == 2) {
doubleCount++;
} else if (value == 3) {
if (threeStartIndex == -1) {
threeStartIndex = index;
}
threeEndIndex = index;
threeCount++;
} else if (value == 4) {
if (fourStartIndex == -1) {
fourStartIndex = index;
}
fourEndIndex = index;
fourCount++;
}
}
if (singleCount == doubleCount && singleCount == threeCount && singleCount == 0 && fourCount == 1) {
return new PokerSell(SellType.BOMB, pokers, startIndex);
}
if (singleCount == 2 && startIndex == PokerLevel.LEVEL_SMALL_KING.getLevel() && endIndex == PokerLevel.LEVEL_BIG_KING.getLevel()) {
return new PokerSell(SellType.KING_BOMB, pokers, PokerLevel.LEVEL_SMALL_KING.getLevel());
}
if (startIndex == endIndex) {
if (levelTable[startIndex] == 1) {
return new PokerSell(SellType.SINGLE, pokers, startIndex);
} else if (levelTable[startIndex] == 2) {
return new PokerSell(SellType.DOUBLE, pokers, startIndex);
} else if (levelTable[startIndex] == 3) {
return new PokerSell(SellType.THREE, pokers, startIndex);
}
}
if (endIndex - startIndex == count - 1 && endIndex < PokerLevel.LEVEL_2.getLevel()) {
if (levelTable[startIndex] == 1 && singleCount > 4 && doubleCount + threeCount + fourCount == 0) {
return new PokerSell(SellType.SINGLE_STRAIGHT, pokers, endIndex);
} else if (levelTable[startIndex] == 2 && doubleCount > 2 && singleCount + threeCount + fourCount == 0) {
return new PokerSell(SellType.DOUBLE_STRAIGHT, pokers, endIndex);
} else if (levelTable[startIndex] == 3 && threeCount > 1 && doubleCount + singleCount + fourCount == 0) {
return new PokerSell(SellType.THREE_STRAIGHT, pokers, endIndex);
} else if (levelTable[startIndex] == 4 && fourCount > 1 && doubleCount + threeCount + singleCount == 0) {
return new PokerSell(SellType.FOUR_STRAIGHT, pokers, endIndex);
}
}
if (threeCount != 0) {
if (singleCount != 0 && singleCount == threeCount && doubleCount == 0 && fourCount == 0) {
if (threeCount == 1) {
return new PokerSell(SellType.THREE_ZONES_SINGLE, pokers, threeEndIndex);
}
if (threeEndIndex - threeStartIndex + 1 == threeCount && threeEndIndex < PokerLevel.LEVEL_2.getLevel()) {
return new PokerSell(SellType.THREE_STRAIGHT_WITH_SINGLE, pokers, threeEndIndex);
}
} else if (doubleCount != 0 && doubleCount == threeCount && singleCount == 0 && fourCount == 0) {
if (threeCount == 1) {
return new PokerSell(SellType.THREE_ZONES_DOUBLE, pokers, threeEndIndex);
}
if (threeEndIndex - threeStartIndex + 1 == threeCount && threeEndIndex < PokerLevel.LEVEL_2.getLevel()) {
return new PokerSell(SellType.THREE_STRAIGHT_WITH_DOUBLE, pokers, threeEndIndex);
}
} else if (singleCount + doubleCount * 2 == threeCount && fourCount == 0) {
return new PokerSell(SellType.THREE_STRAIGHT_WITH_SINGLE, pokers, threeEndIndex);
}
}
if (fourCount != 0) {
if (singleCount != 0 && singleCount == fourCount * 2 && doubleCount == 0 && threeCount == 0) {
if (fourCount == 1) {
return new PokerSell(SellType.FOUR_ZONES_SINGLE, pokers, fourEndIndex);
}
if (fourEndIndex - fourStartIndex + 1 == fourCount && fourEndIndex < PokerLevel.LEVEL_2.getLevel()) {
return new PokerSell(SellType.FOUR_STRAIGHT_WITH_SINGLE, pokers, fourEndIndex);
}
} else if (doubleCount != 0 && doubleCount == fourCount * 2 && singleCount == 0 && threeCount == 0) {
if (fourCount == 1) {
return new PokerSell(SellType.FOUR_ZONES_DOUBLE, pokers, fourEndIndex);
}
if (fourEndIndex - fourStartIndex + 1 == fourCount && fourEndIndex < PokerLevel.LEVEL_2.getLevel()) {
return new PokerSell(SellType.FOUR_STRAIGHT_WITH_DOUBLE, pokers, fourEndIndex);
}
}
}
return new PokerSell(SellType.ILLEGAL, null, -1);
}
public static int parseScore(SellType sellType, int level) {
if (sellType == SellType.BOMB) {
return level * 4 + 999;
} else if (sellType == SellType.KING_BOMB) {
return Integer.MAX_VALUE;
} else if (sellType == SellType.SINGLE || sellType == SellType.DOUBLE || sellType == SellType.THREE) {
return level;
} else if (sellType == SellType.SINGLE_STRAIGHT || sellType == SellType.DOUBLE_STRAIGHT || sellType == SellType.THREE_STRAIGHT || sellType == SellType.FOUR_STRAIGHT) {
return level;
} else if (sellType == SellType.THREE_ZONES_SINGLE || sellType == SellType.THREE_STRAIGHT_WITH_SINGLE || sellType == SellType.THREE_ZONES_DOUBLE || sellType == SellType.THREE_STRAIGHT_WITH_DOUBLE) {
return level;
} else if (sellType == SellType.FOUR_ZONES_SINGLE || sellType == SellType.FOUR_STRAIGHT_WITH_SINGLE || sellType == SellType.FOUR_ZONES_DOUBLE || sellType == SellType.FOUR_STRAIGHT_WITH_DOUBLE) {
return level;
}
return -1;
}
public static List<Poker> getPoker(int[] indexes, List<Poker> pokers) {
List<Poker> resultPokers = new ArrayList<>(indexes.length);
for (int index : indexes) {
resultPokers.add(pokers.get(index - 1));
}
sortPoker(resultPokers);
return resultPokers;
}
public static boolean comparePoker(List<Poker> pres, List<Poker> currents) {
return true;
}
public static List<List<Poker>> distributePoker() {
Collections.shuffle(basePokers);
List<List<Poker>> pokersList = new ArrayList<List<Poker>>();
List<Poker> pokers1 = new ArrayList<>(17);
pokers1.addAll(basePokers.subList(0, 17));
List<Poker> pokers2 = new ArrayList<>(17);
pokers2.addAll(basePokers.subList(17, 34));
List<Poker> pokers3 = new ArrayList<>(17);
pokers3.addAll(basePokers.subList(34, 51));
List<Poker> pokers4 = new ArrayList<>(3);
pokers4.addAll(basePokers.subList(51, 54));
pokersList.add(pokers1);
pokersList.add(pokers2);
pokersList.add(pokers3);
pokersList.add(pokers4);
for (List<Poker> pokers : pokersList) {
sortPoker(pokers);
}
return pokersList;
}
public static String printPoker(List<Poker> pokers) {
sortPoker(pokers);
switch (pokerPrinterType) {
case 0:
return buildHandStringSharp(pokers);
case 1:
return buildHandStringRounded(pokers);
case 2:
return textOnly(pokers);
case 3:
return textOnlyNoType(pokers);
default:
return buildHandStringSharp(pokers);
}
}
private static String buildHandStringSharp(List<Poker> pokers) {
StringBuilder builder = new StringBuilder();
if (pokers != null && pokers.size() > 0) {
for (int index = 0; index < pokers.size(); index++) {
if (index == 0) {
builder.append("┌──┐");
} else {
builder.append("──┐");
}
}
builder.append(System.lineSeparator());
for (int index = 0; index < pokers.size(); index++) {
if (index == 0) {
builder.append("│");
}
String name = pokers.get(index).getLevel().getName();
builder.append(name).append(name.length() == 1 ? " " : "").append("|");
}
builder.append(System.lineSeparator());
for (int index = 0; index < pokers.size(); index++) {
if (index == 0) {
builder.append("│");
}
builder.append(pokers.get(index).getType().getName()).append(" |");
}
builder.append(System.lineSeparator());
for (int index = 0; index < pokers.size(); index++) {
if (index == 0) {
builder.append("└──┘");
} else {
builder.append("──┘");
}
}
}
return builder.toString();
}
private static String buildHandStringRounded(List<Poker> pokers) {
StringBuilder builder = new StringBuilder();
if (pokers != null && pokers.size() > 0) {
for (int index = 0; index < pokers.size(); index++) {
if (index == 0) {
builder.append("┌──╮");
} else {
builder.append("──╮");
}
}
builder.append(System.lineSeparator());
for (int index = 0; index < pokers.size(); index++) {
if (index == 0) {
builder.append("│");
}
String name = pokers.get(index).getLevel().getName();
builder.append(name).append(name.length() == 1 ? " " : "").append("|");
}
builder.append(System.lineSeparator());
for (int index = 0; index < pokers.size(); index++) {
if (index == 0) {
builder.append("│");
}
builder.append(pokers.get(index).getType().getName()).append(" |");
}
builder.append(System.lineSeparator());
for (int index = 0; index < pokers.size(); index++) {
if (index == 0) {
builder.append("└──╯");
} else {
builder.append("──╯");
}
}
}
return builder.toString();
}
private static String textOnly(List<Poker> pokers) {
StringBuilder builder = new StringBuilder();
if (pokers != null && pokers.size() > 0) {
for (Poker poker : pokers) {
String name = poker.getLevel().getName();
String type = poker.getType().getName();
builder.append(name).append(type);
}
}
return builder.toString();
}
public static String textOnlyNoType(List<Poker> pokers) {
StringBuilder builder = new StringBuilder();
if (pokers != null && pokers.size() > 0) {
for (Poker poker : pokers) {
String name = poker.getLevel().getName();
builder.append(name).append(" ");
}
}
return builder.toString();
}
public static int parsePokerColligationScore(List<Poker> pokers) {
int score = 0;
int count = 0;
int increase = 0;
int lastLevel = -1;
if (pokers != null && !pokers.isEmpty()) {
for (int index = 0; index < pokers.size(); index++) {
int level = pokers.get(index).getLevel().getLevel();
if (lastLevel == -1) {
increase++;
count++;
score += lastLevel;
} else {
if (level == lastLevel) {
++count;
} else {
count = 1;
}
if (level < PokerLevel.LEVEL_2.getLevel() && level - 1 == lastLevel) {
++increase;
} else {
increase = 1;
}
score += (count + (increase > 4 ? increase : 0)) * level;
}
if (level == PokerLevel.LEVEL_2.getLevel()) {
score += level * 2;
} else if (level > PokerLevel.LEVEL_2.getLevel()) {
score += level * 3;
}
lastLevel = level;
}
}
return score;
}
public static List<PokerSell> parsePokerSells(List<Poker> pokers) {
List<PokerSell> pokerSells = new ArrayList<>();
int size = pokers.size();
//all single or double
{
int count = 0;
int lastLevel = -1;
List<Poker> sellPokers = new ArrayList<>(4);
for (Poker poker : pokers) {
int level = poker.getLevel().getLevel();
if (lastLevel == -1) {
++count;
} else {
if (level == lastLevel) {
++count;
} else {
count = 1;
sellPokers.clear();
}
}
sellPokers.add(poker);
if (count == 1) {
pokerSells.add(new PokerSell(SellType.SINGLE, ListUtils.getList(sellPokers), poker.getLevel().getLevel()));
} else if (count == 2) {
pokerSells.add(new PokerSell(SellType.DOUBLE, ListUtils.getList(sellPokers), poker.getLevel().getLevel()));
} else if (count == 3) {
pokerSells.add(new PokerSell(SellType.THREE, ListUtils.getList(sellPokers), poker.getLevel().getLevel()));
} else if (count == 4) {
pokerSells.add(new PokerSell(SellType.BOMB, ListUtils.getList(sellPokers), poker.getLevel().getLevel()));
}
lastLevel = level;
}
}
//Shunzi
{
parsePokerSellStraight(pokerSells, SellType.SINGLE);
parsePokerSellStraight(pokerSells, SellType.DOUBLE);
parsePokerSellStraight(pokerSells, SellType.THREE);
parsePokerSellStraight(pokerSells, SellType.BOMB);
}
//Shunzi with args
{
for (int index = 0; index < pokerSells.size(); index++) {
PokerSell sell = pokerSells.get(index);
if (sell.getSellType() == SellType.THREE) {
parseArgs(pokerSells, sell, 1, SellType.SINGLE, SellType.THREE_ZONES_SINGLE);
parseArgs(pokerSells, sell, 1, SellType.DOUBLE, SellType.THREE_ZONES_DOUBLE);
} else if (sell.getSellType() == SellType.BOMB) {
parseArgs(pokerSells, sell, 2, SellType.SINGLE, SellType.FOUR_ZONES_SINGLE);
parseArgs(pokerSells, sell, 2, SellType.DOUBLE, SellType.FOUR_ZONES_DOUBLE);
} else if (sell.getSellType() == SellType.THREE_STRAIGHT) {
int count = sell.getSellPokers().size() / 3;
parseArgs(pokerSells, sell, count, SellType.SINGLE, SellType.THREE_STRAIGHT_WITH_SINGLE);
parseArgs(pokerSells, sell, count, SellType.DOUBLE, SellType.THREE_STRAIGHT_WITH_DOUBLE);
} else if (sell.getSellType() == SellType.FOUR_STRAIGHT) {
int count = (sell.getSellPokers().size() / 4) * 2;
parseArgs(pokerSells, sell, count, SellType.SINGLE, SellType.FOUR_STRAIGHT_WITH_SINGLE);
parseArgs(pokerSells, sell, count, SellType.DOUBLE, SellType.FOUR_STRAIGHT_WITH_DOUBLE);
}
}
}
//king boom
{
if (size > 1) {
if (pokers.get(size - 1).getLevel() == PokerLevel.LEVEL_BIG_KING && pokers.get(size - 2).getLevel() == PokerLevel.LEVEL_SMALL_KING) {
pokerSells.add(new PokerSell(SellType.KING_BOMB, ListUtils.getList(new Poker[]{pokers.get(size - 2), pokers.get(size - 1)}), PokerLevel.LEVEL_BIG_KING.getLevel()));
}
}
}
return pokerSells;
}
private static void parseArgs(List<PokerSell> pokerSells, PokerSell pokerSell, int deep, SellType sellType, SellType targetSellType) {
Set<Integer> existLevelSet = new HashSet<>();
for (Poker p : pokerSell.getSellPokers()) {
existLevelSet.add(p.getLevel().getLevel());
}
parseArgs(existLevelSet, pokerSells, new HashSet<>(), pokerSell, deep, sellType, targetSellType);
}
private static void parseArgs(Set<Integer> existLevelSet, List<PokerSell> pokerSells, Set<List<Poker>> pokersList, PokerSell pokerSell, int deep, SellType sellType, SellType targetSellType) {
if (deep == 0) {
List<Poker> allPokers = new ArrayList<>(pokerSell.getSellPokers());
for (List<Poker> ps : pokersList) {
allPokers.addAll(ps);
}
pokerSells.add(new PokerSell(targetSellType, allPokers, pokerSell.getCoreLevel()));
return;
}
for (int index = 0; index < pokerSells.size(); index++) {
PokerSell subSell = pokerSells.get(index);
if (subSell.getSellType() == sellType && !existLevelSet.contains(subSell.getCoreLevel())) {
pokersList.add(subSell.getSellPokers());
existLevelSet.add(subSell.getCoreLevel());
parseArgs(existLevelSet, pokerSells, pokersList, pokerSell, deep - 1, sellType, targetSellType);
existLevelSet.remove(subSell.getCoreLevel());
pokersList.remove(subSell.getSellPokers());
}
}
}
private static void parsePokerSellStraight(List<PokerSell> pokerSells, SellType sellType) {
int minLength = -1;
int width = -1;
SellType targetSellType = null;
if (sellType == SellType.SINGLE) {
minLength = 5;
width = 1;
targetSellType = SellType.SINGLE_STRAIGHT;
} else if (sellType == SellType.DOUBLE) {
minLength = 3;
width = 2;
targetSellType = SellType.DOUBLE_STRAIGHT;
} else if (sellType == SellType.THREE) {
minLength = 2;
width = 3;
targetSellType = SellType.THREE_STRAIGHT;
} else if (sellType == SellType.BOMB) {
minLength = 2;
width = 4;
targetSellType = SellType.FOUR_STRAIGHT;
}
int increase_1 = 0;
int lastLevel_1 = -1;
List<Poker> sellPokers_1 = new ArrayList<>(4);
for (int index = 0; index < pokerSells.size(); index++) {
PokerSell sell = pokerSells.get(index);
if (sell.getSellType() != sellType) {
continue;
}
int level = sell.getCoreLevel();
if (lastLevel_1 == -1) {
++increase_1;
} else {
if (level - 1 == lastLevel_1 && level != PokerLevel.LEVEL_2.getLevel()) {
++increase_1;
} else {
addPokers(pokerSells, minLength, width, targetSellType, increase_1, sellPokers_1);
increase_1 = 1;
}
}
sellPokers_1.addAll(sell.getSellPokers());
lastLevel_1 = level;
}
addPokers(pokerSells, minLength, width, targetSellType, increase_1, sellPokers_1);
}
private static void addPokers(List<PokerSell> pokerSells, int minLenght, int width, SellType targetSellType, int increase_1, List<Poker> sellPokers_1) {
if (increase_1 >= minLenght) {
for (int s = 0; s <= increase_1 - minLenght; s++) {
int len = minLenght + s;
for (int subIndex = 0; subIndex <= increase_1 - len; subIndex++) {
List<Poker> pokers = ListUtils.getList(sellPokers_1.subList(subIndex * width, (subIndex + len) * width));
pokerSells.add(new PokerSell(targetSellType, pokers, pokers.get(pokers.size() - 1).getLevel().getLevel()));
}
}
}
sellPokers_1.clear();
}
}

View File

@ -0,0 +1,17 @@
package org.nico.ratel.landlords.helper;
/**
*
* @author nico
* @version createTime2018114 6:29:32
*/
public class TimeHelper {
public static void sleep(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException ignored) {
}
}
}

View File

@ -0,0 +1,11 @@
package org.nico.ratel.landlords.print;
public class FormatPrinter {
private FormatPrinter() {
}
public static void printNotice(String format, Object... args) {
System.out.printf(format, args);
}
}

View File

@ -0,0 +1,37 @@
package org.nico.ratel.landlords.print;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.helper.PokerHelper;
public class SimplePrinter {
private final static SimpleDateFormat FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static int pokerDisplayFormat = 0;
public static void printPokers(List<Poker> pokers) {
System.out.println(PokerHelper.printPoker(pokers));
}
public static void printNotice(String msg) {
System.out.println(msg);
}
public static void printNotice(String msgKey, String locale) {
//TODO : read locale
Map<String, Map<String, String>> map = new HashMap<>();
map.put("english", new HashMap<>());
map.get("eng").put("caterpillar", "caterpillar's message!!");
System.out.println(map.get(locale).get(msgKey));
}
public static void serverLog(String msg) {
System.out.println(FORMAT.format(new Date()) + "-> " + msg);
}
}

View File

@ -0,0 +1,33 @@
package org.nico.ratel.landlords.print;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class SimpleWriter {
private static final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
public static String write(String message) {
return write("player", message);
}
public static String write(String nickname, String message) {
System.out.println();
System.out.printf("[%s@%s]$ ", nickname, message);
try {
return write();
} finally {
System.out.println();
}
}
public static String write() {
try {
return reader.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}

View File

@ -0,0 +1,20 @@
package org.nico.ratel.landlords.robot;
import java.util.List;
import org.nico.ratel.landlords.entity.ClientSide;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.entity.PokerSell;
/**
*
* @author nico
* @version createTime20181115 12:12:15
*/
public abstract class AbstractRobotDecisionMakers {
public abstract PokerSell howToPlayPokers(PokerSell lastPokerSell, ClientSide robot);
public abstract boolean howToChooseLandlord(List<Poker> leftPokers, List<Poker> rightPokers, List<Poker> myPokers);
}

View File

@ -0,0 +1,60 @@
package org.nico.ratel.landlords.robot;
import java.util.List;
import java.util.Random;
import org.nico.ratel.landlords.entity.ClientSide;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.entity.PokerSell;
import org.nico.ratel.landlords.enums.SellType;
import org.nico.ratel.landlords.helper.PokerHelper;
/**
* @author nico
* @date 2018-11-15 12:13:49
*/
public class EasyRobotDecisionMakers extends AbstractRobotDecisionMakers {
private static Random random = new Random();
@Override
public PokerSell howToPlayPokers(PokerSell lastPokerSell, ClientSide robot) {
if (lastPokerSell != null && lastPokerSell.getSellType() == SellType.KING_BOMB) {
return null;
}
List<PokerSell> sells = PokerHelper.parsePokerSells(robot.getPokers());
if (lastPokerSell == null) {
return sells.get(random.nextInt(sells.size()));
}
for (PokerSell sell : sells) {
if (sell.getSellType() == lastPokerSell.getSellType()) {
if (sell.getScore() > lastPokerSell.getScore() && sell.getSellPokers().size() == lastPokerSell.getSellPokers().size()) {
return sell;
}
}
}
if (lastPokerSell.getSellType() != SellType.BOMB) {
for (PokerSell sell : sells) {
if (sell.getSellType() == SellType.BOMB) {
return sell;
}
}
}
for (PokerSell sell : sells) {
if (sell.getSellType() == SellType.KING_BOMB) {
return sell;
}
}
return null;
}
@Override
public boolean howToChooseLandlord(List<Poker> leftPokers, List<Poker> rightPokers, List<Poker> myPokers) {
List<PokerSell> leftSells = PokerHelper.parsePokerSells(leftPokers);
List<PokerSell> mySells = PokerHelper.parsePokerSells(myPokers);
List<PokerSell> rightSells = PokerHelper.parsePokerSells(rightPokers);
return mySells.size() > leftSells.size() && mySells.size() > rightSells.size();
}
}

View File

@ -0,0 +1,139 @@
package org.nico.ratel.landlords.robot;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import org.nico.ratel.landlords.entity.ClientSide;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.entity.PokerSell;
import org.nico.ratel.landlords.enums.SellType;
import org.nico.ratel.landlords.helper.PokerHelper;
/**
* Trial game algorithm
*
* @author nico
* @date 2020-12-19 16:36
*/
public class MediumRobotDecisionMakers extends AbstractRobotDecisionMakers {
private static final Long DEDUCE_LIMIT = 100 * 3L;
public MediumRobotDecisionMakers() {}
@Override
public PokerSell howToPlayPokers(PokerSell lastPokerSell, ClientSide robot) {
if(lastPokerSell != null && lastPokerSell.getSellType() == SellType.KING_BOMB) {
return null;
}
List<Poker> selfPoker = PokerHelper.clonePokers(robot.getPokers());
List<Poker> leftPoker = PokerHelper.clonePokers(robot.getPre().getPokers());
List<Poker> rightPoker = PokerHelper.clonePokers(robot.getNext().getPokers());
PokerHelper.sortPoker(selfPoker);
PokerHelper.sortPoker(leftPoker);
PokerHelper.sortPoker(rightPoker);
List<List<Poker>> pokersList = new ArrayList<List<Poker>>();
pokersList.add(selfPoker);
pokersList.add(rightPoker);
pokersList.add(leftPoker);
List<PokerSell> sells = PokerHelper.validSells(lastPokerSell, selfPoker);
if(sells.size() == 0) {
return null;
}
PokerSell bestSell = null;
Long weight = null;
for(PokerSell sell: sells) {
List<Poker> pokers = PokerHelper.clonePokers(selfPoker);
pokers.removeAll(sell.getSellPokers());
if(pokers.size() == 0) {
return sell;
}
pokersList.set(0, pokers);
AtomicLong counter = new AtomicLong();
deduce(0, sell, 1, pokersList, counter);
if(weight == null) {
bestSell = sell;
weight = counter.get();
}else if (counter.get() > weight){
bestSell = sell;
weight = counter.get();
}
pokersList.set(0, selfPoker);
}
return bestSell;
}
private Boolean deduce(int sellCursor, PokerSell lastPokerSell, int cursor, List<List<Poker>> pokersList, AtomicLong counter) {
if(cursor > 2) {
cursor = 0;
}
if(sellCursor == cursor) {
lastPokerSell = null;
}
List<Poker> original = pokersList.get(cursor);
List<PokerSell> sells = PokerHelper.validSells(lastPokerSell, original);
if(sells.size() == 0) {
if(sellCursor != cursor) {
return deduce(sellCursor, lastPokerSell, cursor + 1, pokersList, counter);
}
}
for(PokerSell sell: sells) {
List<Poker> pokers = PokerHelper.clonePokers(original);
pokers.removeAll(sell.getSellPokers());
if(pokers.size() == 0) {
return cursor == 0;
}else {
pokersList.set(cursor, pokers);
Boolean suc = deduce(cursor, sell, cursor + 1, pokersList, counter);
if(cursor != 0) {
pokersList.set(cursor, original);
return suc;
}
if(Math.abs(counter.get()) > DEDUCE_LIMIT) {
pokersList.set(cursor, original);
return counter.get() > DEDUCE_LIMIT;
}
if(suc != null) {
counter.addAndGet((long)(suc ? 1 : -1));
}
pokersList.set(cursor, original);
}
}
return null;
}
private static String serialPokers(List<Poker> pokers){
if(pokers == null || pokers.size() == 0) {
return "n";
}
StringBuilder builder = new StringBuilder();
for(int index = 0; index < pokers.size(); index ++) {
builder.append(pokers.get(index).getLevel().getLevel()).append(index == pokers.size() - 1 ? "" : "_");
}
return builder.toString();
}
private static String serialPokersList(List<List<Poker>> pokersList){
StringBuilder builder = new StringBuilder();
for(int index = 0; index < pokersList.size(); index ++) {
List<Poker> pokers = pokersList.get(index);
builder.append(serialPokers(pokers)).append(index == pokersList.size() - 1 ? "" : "m");
}
return builder.toString();
}
@Override
public boolean howToChooseLandlord(List<Poker> leftPokers, List<Poker> rightPokers, List<Poker> myPokers) {
int leftScore = PokerHelper.parsePokerColligationScore(leftPokers);
int rightScore = PokerHelper.parsePokerColligationScore(rightPokers);
int myScore = PokerHelper.parsePokerColligationScore(myPokers);
return myScore >= (leftScore + rightScore) / 2;
}
}

View File

@ -0,0 +1,37 @@
package org.nico.ratel.landlords.robot;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.nico.ratel.landlords.entity.ClientSide;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.entity.PokerSell;
/**
* How does the machine decide on a better strategy to win the game
*
* @author nico
*/
public class RobotDecisionMakers {
private static final Map<Integer, AbstractRobotDecisionMakers> decisionMakersMap = new HashMap<Integer, AbstractRobotDecisionMakers>();
public static void init() {
decisionMakersMap.put(1, new EasyRobotDecisionMakers());
decisionMakersMap.put(2, new MediumRobotDecisionMakers());
}
public static boolean contains(int difficultyCoefficient) {
return decisionMakersMap.containsKey(difficultyCoefficient);
}
public static PokerSell howToPlayPokers(int difficultyCoefficient, PokerSell lastPokerSell, ClientSide robot){
return decisionMakersMap.get(difficultyCoefficient).howToPlayPokers(lastPokerSell, robot);
}
public static boolean howToChooseLandlord(int difficultyCoefficient, List<Poker> leftPokers, List<Poker> rightPokers, List<Poker> myPokers) {
return decisionMakersMap.get(difficultyCoefficient).howToChooseLandlord(leftPokers, rightPokers, myPokers);
}
}

View File

@ -0,0 +1,60 @@
package org.nico.ratel.landlords.transfer;
/**
* Byte manipulation tool
*
* @author nico
*/
public class ByteKit {
/**
* Target byte array
*/
private byte[] bytes;
public ByteKit(byte[] bytes) {
this.bytes = bytes;
}
/**
* Gets the index of the incoming array in the target array, not matched to return -1
*
* @param bs Incoming array
* @param start Matching start index
* @return Match index, not match to return -1
*/
public int indexOf(byte[] bs, int start) {
int targetIndex = -1;
if (bs == null) {
return targetIndex;
}
for (int index = start; index < bytes.length; index++) {
byte cbyte = bytes[index];
if (bs[0] == cbyte) {
boolean isEquals = true;
for (int sindex = 1; sindex < bs.length; sindex++) {
if (index + sindex >= bytes.length || bs[sindex] != bytes[index + sindex]) {
isEquals = false;
break;
}
}
if (isEquals) {
targetIndex = index;
break;
}
}
}
return targetIndex;
}
/**
* Gets the position of the byte byte in the byte array
*
* @param b Byte
* @param start Matching start index
* @return Match index, not match to return -1
*/
public int indexOf(byte b, int start) {
return indexOf(new byte[]{b}, start);
}
}

View File

@ -0,0 +1,81 @@
package org.nico.ratel.landlords.transfer;
public class ByteLink {
private ByteNode start;
private ByteNode current;
private int size;
public void append(byte b) {
if (start == null) {
start = new ByteNode(b);
current = start;
} else {
ByteNode node = new ByteNode(b);
current.setNext(node);
current = node;
}
size++;
}
public void append(byte[] bs) {
if (bs != null) {
for (byte b : bs) {
append(b);
}
}
}
public byte[] toArray() {
if (size == 0) {
return null;
}
byte[] bytes = new byte[size];
int index = 0;
ByteNode s = start.clone();
while (s != null) {
bytes[index++] = s.getB();
s = s.getNext();
}
return bytes;
}
public static class ByteNode {
private byte b;
private ByteNode next;
public ByteNode(byte b) {
this.b = b;
}
public ByteNode(byte b, ByteNode next) {
this.b = b;
this.next = next;
}
protected ByteNode clone() {
return new ByteNode(b, next);
}
public byte getB() {
return b;
}
public void setB(byte b) {
this.b = b;
}
public ByteNode getNext() {
return next;
}
public void setNext(ByteNode next) {
this.next = next;
}
}
}

View File

@ -0,0 +1,65 @@
package org.nico.ratel.landlords.transfer;
import org.nico.noson.Noson;
import org.nico.ratel.landlords.exception.LandlordException;
/**
* Protocol transport related tools
*
* @author nico
* @time 2018-11-01 20:43
*/
public class TransferProtocolUtils {
/**
* A protocol header that represents the beginning of an available stream of data
*/
public static final byte PROTOCOL_HAED = "#".getBytes()[0];
/**
* The end of the protocol used to represent the end of an available stream of data
*/
public static final byte PROTOCOL_TAIL = "$".getBytes()[0];
/**
* Serialize the poker list to transportable bytes
*
* @param obj Poker list
* @return Transportable byte array
*/
public static byte[] serialize(Object obj) {
ByteLink bl = new ByteLink();
bl.append(PROTOCOL_HAED);
bl.append(Noson.reversal(obj).getBytes());
bl.append(PROTOCOL_TAIL);
return bl.toArray();
}
/**
* Deserialize the byte stream as an object
*
* @param bytes Byte array
* @return Genericity
*/
public static <T> T unserialize(byte[] bytes, Class<T> clazz) {
ByteKit bk = new ByteKit(bytes);
int start = -1;
int end = -1;
int index = bk.indexOf(PROTOCOL_HAED, 0);
if (index != -1) start = index + 1;
index = bk.indexOf(PROTOCOL_TAIL, 0);
if (index != -1) end = index;
if (start != -1 && end != -1 && start > end) {
throw new LandlordException("Message format error, head and tail error.");
} else {
byte[] content = new byte[end - start];
System.arraycopy(bytes, start, content, 0, content.length);
return Noson.convert(new String(content), clazz);
}
}
}

View File

@ -0,0 +1,17 @@
package org.nico.ratel.landlords.utils;
import com.google.gson.Gson;
public class JsonUtils {
private static final Gson GSON = new Gson();
public static String toJson(Object o){
return GSON.toJson(o);
}
public static <T> T fromJson(String json, Class<T> clazz){
return GSON.fromJson(json, clazz);
}
}

View File

@ -0,0 +1,65 @@
package org.nico.ratel.landlords.utils;
import org.nico.ratel.landlords.entity.Poker;
import java.util.*;
public class LastCardsUtils {
private static final List<String> defSort = new ArrayList(){{
add("3");
add("4");
add("5");
add("6");
add("7");
add("8");
add("9");
add("10");
add("J");
add("Q");
add("K");
add("A");
add("2");
add("S");
add("X");
}};
public static String getLastCards(List<List<Poker>> pokers){
StringBuffer lastCards = new StringBuffer();
Map<String, Integer> lastCardMap = initLastCards();
for(int i = 0; i < pokers.size(); i++){
List<Poker> pokerList = pokers.get(i);
for(int a = 0; a < pokerList.size(); a++){
Poker poker = pokerList.get(a);
lastCardMap.put(poker.getLevel().getName(),(lastCardMap.get(poker.getLevel().getName())+1));
}
}
for(int i = 0; i < defSort.size(); i++){
String key = defSort.get(i);
lastCards.append(key + "["+lastCardMap.get(key)+"] ");
}
return lastCards.toString();
}
private static Map<String, Integer> initLastCards(){
Map<String, Integer> lastCardMap = new HashMap<>();
lastCardMap.put("A",0);
lastCardMap.put("2",0);
lastCardMap.put("3",0);
lastCardMap.put("4",0);
lastCardMap.put("5",0);
lastCardMap.put("6",0);
lastCardMap.put("7",0);
lastCardMap.put("8",0);
lastCardMap.put("9",0);
lastCardMap.put("10",0);
lastCardMap.put("J",0);
lastCardMap.put("Q",0);
lastCardMap.put("K",0);
lastCardMap.put("S",0);
lastCardMap.put("X",0);
return lastCardMap;
}
}

View File

@ -0,0 +1,28 @@
package org.nico.ratel.landlords.utils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ListUtils {
public static <T> List<T> getList(T[] array) {
List<T> list = new ArrayList<>(array.length);
Collections.addAll(list, array);
return list;
}
public static <T> List<T> getList(List<T>[] array) {
List<T> list = new ArrayList<>(array.length);
for (List<T> t : array) {
list.addAll(t);
}
return list;
}
public static <T> List<T> getList(List<T> source) {
List<T> list = new ArrayList<>(source.size());
list.addAll(source);
return list;
}
}

View File

@ -0,0 +1,12 @@
package org.nico.ratel.landlords.utils;
public class OptionsUtils {
public static int getOptions(String line) {
int option = -1;
try {
option = Integer.parseInt(line);
} catch (Exception ignored) {}
return option;
}
}

View File

@ -0,0 +1,10 @@
package org.nico.ratel.landlords.utils;
public class RegxUtils {
// private final static String POKER_SELECT_REGX = "^[2-9]"
// public static isRegularPokerSelect(String line) {
// 123456789t
// }
}

View File

@ -0,0 +1,48 @@
package org.nico.ratel.landlords.utils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
public class StreamUtils {
/**
* Convert input stream to string
*
* @param inStream Input stream
* @return {@link String}
*/
public static String convertToString(InputStream inStream) {
BufferedReader br = new BufferedReader(new InputStreamReader(inStream));
StringBuilder reqStr = new StringBuilder();
char[] buf = new char[2048];
int len;
try {
while ((len = br.read(buf)) != -1) {
reqStr.append(new String(buf, 0, len));
}
br.close();
} catch (IOException e) {
return null;
} finally {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return reqStr.toString();
}
public static String convertToString(URL url) throws IOException {
URLConnection con = url.openConnection();
con.setUseCaches(false);
con.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.193 Safari/537.36");
return convertToString(con.getInputStream());
}
}

View File

@ -0,0 +1,243 @@
package org.nico.ratel.landlords.helper.tests;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.entity.PokerSell;
import org.nico.ratel.landlords.enums.PokerLevel;
import org.nico.ratel.landlords.enums.PokerType;
import org.nico.ratel.landlords.enums.SellType;
import org.nico.ratel.landlords.helper.PokerHelper;
import java.util.ArrayList;
public class PokerHelperTest {
private ArrayList<Poker> pokers = new ArrayList<>();
@Before
public void setUp() {
pokers.add(new Poker(PokerLevel.LEVEL_3, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_4, PokerType.DIAMOND));
pokers.add(new Poker(PokerLevel.LEVEL_4, PokerType.DIAMOND));
pokers.add(new Poker(PokerLevel.LEVEL_5, PokerType.CLUB));
pokers.add(new Poker(PokerLevel.LEVEL_5, PokerType.CLUB));
pokers.add(new Poker(PokerLevel.LEVEL_5, PokerType.CLUB));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.SPADE));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
}
@Test
public void testComparePoker() {
Assert.assertTrue(PokerHelper.comparePoker(new ArrayList<>(), new ArrayList<>()));
}
@Test
public void testCheckPokerIndex() {
Assert.assertFalse(PokerHelper.checkPokerIndex(new int[]{}, new ArrayList<>()));
Assert.assertFalse(PokerHelper.checkPokerIndex(new int[]{2, -4_194_302}, new ArrayList<>()));
}
@Test
public void testGetIndexes() {
Assert.assertNull(PokerHelper.getIndexes(new Character[]{'3', '4', '5', '6', '7', '8'}, pokers));
Assert.assertNotNull(PokerHelper.getIndexes(new Character[]{}, new ArrayList<>()));
Assert.assertEquals(0, PokerHelper.getIndexes(new Character[]{}, new ArrayList<>()).length);
}
@Test
public void testGetPoker() {
Assert.assertEquals(PokerLevel.LEVEL_3, PokerHelper.getPoker(new int[]{1, 2}, pokers).get(0).getLevel());
Assert.assertEquals(PokerType.BLANK, PokerHelper.getPoker(new int[]{1, 2}, pokers).get(0).getType());
Assert.assertEquals(PokerLevel.LEVEL_4, PokerHelper.getPoker(new int[]{1, 2}, pokers).get(1).getLevel());
Assert.assertEquals(PokerType.DIAMOND, PokerHelper.getPoker(new int[]{1, 2}, pokers).get(1).getType());
}
@Test
public void testPrintPoker() {
Assert.assertNotNull(PokerHelper.printPoker(pokers));
}
@Test
public void testDistributePoker() {
Assert.assertNotNull(PokerHelper.distributePoker());
}
@Test
public void testCheckPokerType1() {
pokers.clear();
Assert.assertNull(PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(-1, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.ILLEGAL, PokerHelper.checkPokerType(pokers).getSellType());
pokers.add(new Poker(PokerLevel.LEVEL_SMALL_KING, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_BIG_KING, PokerType.DIAMOND));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(2147483647, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.KING_BOMB, PokerHelper.checkPokerType(pokers).getSellType());
}
@Test
public void testCheckPokerType2() {
pokers.clear();
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(7, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.SINGLE, PokerHelper.checkPokerType(pokers).getSellType());
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(7, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.DOUBLE, PokerHelper.checkPokerType(pokers).getSellType());
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(7, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.THREE, PokerHelper.checkPokerType(pokers).getSellType());
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(1027, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.BOMB, PokerHelper.checkPokerType(pokers).getSellType());
pokers.remove(pokers.size() - 1);
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.BLANK));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(7, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.THREE_ZONES_SINGLE, PokerHelper.checkPokerType(pokers).getSellType());
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.BLANK));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(7, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.THREE_ZONES_DOUBLE, PokerHelper.checkPokerType(pokers).getSellType());
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_9, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_10, PokerType.BLANK));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(8, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.THREE_STRAIGHT_WITH_SINGLE, PokerHelper.checkPokerType(pokers).getSellType());
pokers.add(new Poker(PokerLevel.LEVEL_9, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_10, PokerType.BLANK));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(8, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.THREE_STRAIGHT_WITH_DOUBLE, PokerHelper.checkPokerType(pokers).getSellType());
}
@Test
public void testCheckPokerType3() {
pokers.clear();
pokers.add(new Poker(PokerLevel.LEVEL_6, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_9, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_10, PokerType.BLANK));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(10, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.SINGLE_STRAIGHT, PokerHelper.checkPokerType(pokers).getSellType());
pokers.add(new Poker(PokerLevel.LEVEL_6, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_9, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_10, PokerType.BLANK));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(10, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.DOUBLE_STRAIGHT, PokerHelper.checkPokerType(pokers).getSellType());
pokers.add(new Poker(PokerLevel.LEVEL_6, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_9, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_10, PokerType.BLANK));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(10, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.THREE_STRAIGHT, PokerHelper.checkPokerType(pokers).getSellType());
pokers.add(new Poker(PokerLevel.LEVEL_6, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_9, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_10, PokerType.BLANK));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(10, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.FOUR_STRAIGHT, PokerHelper.checkPokerType(pokers).getSellType());
}
@Test
public void testCheckPokerType4() {
pokers.clear();
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_9, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_10, PokerType.BLANK));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(8, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.FOUR_ZONES_SINGLE, PokerHelper.checkPokerType(pokers).getSellType());
pokers.add(new Poker(PokerLevel.LEVEL_5, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_6, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(8, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.FOUR_STRAIGHT_WITH_SINGLE, PokerHelper.checkPokerType(pokers).getSellType());
}
@Test
public void testCheckPokerType5() {
pokers.clear();
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_9, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_9, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_10, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_10, PokerType.BLANK));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(8, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.FOUR_ZONES_DOUBLE, PokerHelper.checkPokerType(pokers).getSellType());
pokers.add(new Poker(PokerLevel.LEVEL_5, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_5, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_6, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_6, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(8, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.FOUR_STRAIGHT_WITH_DOUBLE, PokerHelper.checkPokerType(pokers).getSellType());
}
@Test
public void testCheckPokerType6() {
pokers.clear();
pokers.add(new Poker(PokerLevel.LEVEL_6, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_6, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_6, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_4, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_4, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_5, PokerType.BLANK));
PokerSell pokerSell = PokerHelper.checkPokerType(pokers);
Assert.assertEquals(pokers, pokerSell.getSellPokers());
Assert.assertEquals(8, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.THREE_STRAIGHT_WITH_SINGLE, pokerSell.getSellType());
}
}

View File

@ -0,0 +1,63 @@
package org.nico.ratel.landlords.robot.tests;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import org.nico.ratel.landlords.entity.ClientSide;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.entity.PokerSell;
import org.nico.ratel.landlords.enums.PokerLevel;
import org.nico.ratel.landlords.enums.PokerType;
import org.nico.ratel.landlords.enums.SellType;
import org.nico.ratel.landlords.helper.PokerHelper;
import org.nico.ratel.landlords.robot.MediumRobotDecisionMakers;
public class MediumRobotDecisionMakersTests {
private List<Poker> buildPokers(Object[] values){
List<Poker> pokers = new ArrayList<Poker>();
for(Object v: values) {
if(v == null){
continue;
}
if(v instanceof String) {
pokers.add(new Poker(PokerLevel.parseByName((String)v), PokerType.CLUB));
}else if(v instanceof Integer || v.getClass() == int.class) {
pokers.add(new Poker(PokerLevel.parseByLevel((int)v), PokerType.CLUB));
}
}
return pokers;
}
@Test
public void testMedium_1() {
ClientSide self = new ClientSide();
ClientSide right = new ClientSide();
ClientSide left = new ClientSide();
self.setPre(left);
self.setNext(right);
left.setPre(right);
left.setNext(self);
right.setPre(self);
right.setNext(left);
self.setPokers(buildPokers(new Object[] {3,3,3,4,4,4,5,6,8,8,11,12,13,13,14,15,15}));
right.setPokers(buildPokers(new Object[] {3,4,5,6,7,9,9,11,11,12,12,12,14,16}));
left.setPokers(buildPokers(new Object[] {6,6,7,7,7,8,8,9,9,10,10,10,10,11,13,14,14,17}));
// self.setPokers(buildPokers(new Object[] {9,9,3,4}));
// right.setPokers(buildPokers(new Object[] {3,3,9,9,10}));
// left.setPokers(buildPokers(new Object[] {6,6,8,8}));
MediumRobotDecisionMakers mediumRobot = new MediumRobotDecisionMakers();
PokerSell lastSell = PokerHelper.checkPokerType(buildPokers(new Object[] {5,5}));
PokerSell sell = mediumRobot.howToPlayPokers(lastSell, self);
if(sell == null) {
System.out.println("打不起");
}else {
System.out.println(PokerHelper.printPoker(sell.getSellPokers()));
}
}
}

View File

@ -0,0 +1,59 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>landlords-server</artifactId>
<name>landlords-server</name>
<description>This is a console version of the fight landlord game</description>
<parent>
<groupId>com.smallnico.ratel</groupId>
<artifactId>landlords</artifactId>
<version>1.4.0</version>
</parent>
<properties>
<start-class>org.nico.ratel.landlords.server.SimpleServer</start-class>
</properties>
<dependencies>
<dependency>
<groupId>com.smallnico.ratel</groupId>
<artifactId>landlords-common</artifactId>
<version>1.4.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>${start-class}</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
<fork>true</fork>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,73 @@
package org.nico.ratel.landlords.server;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.nico.ratel.landlords.entity.ClientSide;
import org.nico.ratel.landlords.entity.Room;
public class ServerContains {
/**
* Server port
*/
public static int port = 1024;
/**
* The map of server side
*/
private final static Map<Integer, Room> ROOM_MAP = new ConcurrentSkipListMap<>();
/**
* The list of client side
*/
public final static Map<Integer, ClientSide> CLIENT_SIDE_MAP = new ConcurrentSkipListMap<>();
public final static Map<String, Integer> CHANNEL_ID_MAP = new ConcurrentHashMap<>();
private final static AtomicInteger CLIENT_ATOMIC_ID = new AtomicInteger(1);
private final static AtomicInteger SERVER_ATOMIC_ID = new AtomicInteger(1);
public final static int getClientId() {
return CLIENT_ATOMIC_ID.getAndIncrement();
}
public final static int getServerId() {
return SERVER_ATOMIC_ID.getAndIncrement();
}
public final static ThreadPoolExecutor THREAD_EXCUTER = new ThreadPoolExecutor(500, 500, 0, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
/**
* Get room by id, with flush time
*
* @param id room id
* @return
*/
public static Room getRoom(int id) {
Room room = ROOM_MAP.get(id);
if (room != null) {
room.setLastFlushTime(System.currentTimeMillis());
}
return room;
}
public static Map<Integer, Room> getRoomMap() {
return ROOM_MAP;
}
public static Room removeRoom(int id) {
return ROOM_MAP.remove(id);
}
public static Room addRoom(Room room) {
return ROOM_MAP.put(room.getId(), room);
}
}

View File

@ -0,0 +1,24 @@
package org.nico.ratel.landlords.server;
import org.nico.ratel.landlords.server.proxy.ProtobufProxy;
import org.nico.ratel.landlords.server.proxy.WebsocketProxy;
public class SimpleServer {
public static void main(String[] args) throws InterruptedException {
if (args != null && args.length > 1) {
if (args[0].equalsIgnoreCase("-p") || args[0].equalsIgnoreCase("-port")) {
ServerContains.port = Integer.parseInt(args[1]);
}
}
new Thread(() -> {
try {
new ProtobufProxy().start(ServerContains.port);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new WebsocketProxy().start(ServerContains.port + 1);
}
}

View File

@ -0,0 +1,41 @@
package org.nico.ratel.landlords.server.event;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import org.nico.ratel.landlords.entity.ClientSide;
import org.nico.ratel.landlords.enums.ServerEventCode;
public interface ServerEventListener {
void call(ClientSide client, String data);
Map<ServerEventCode, ServerEventListener> LISTENER_MAP = new HashMap<>();
String LISTENER_PREFIX = "org.nico.ratel.landlords.server.event.ServerEventListener_";
@SuppressWarnings("unchecked")
static ServerEventListener get(ServerEventCode code) {
ServerEventListener listener = null;
try {
if (ServerEventListener.LISTENER_MAP.containsKey(code)) {
listener = ServerEventListener.LISTENER_MAP.get(code);
} else {
String eventListener = LISTENER_PREFIX + code.name();
Class<ServerEventListener> listenerClass = (Class<ServerEventListener>) Class.forName(eventListener);
try {
listener = listenerClass.getDeclaredConstructor().newInstance();
} catch (InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
}
ServerEventListener.LISTENER_MAP.put(code, listener);
}
return listener;
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
}

View File

@ -0,0 +1,50 @@
package org.nico.ratel.landlords.server.event;
import org.nico.ratel.landlords.channel.ChannelUtils;
import org.nico.ratel.landlords.entity.ClientSide;
import org.nico.ratel.landlords.entity.Room;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.enums.ClientRole;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.server.ServerContains;
public class ServerEventListener_CODE_CLIENT_EXIT implements ServerEventListener {
private static final Object locked = new Object();
@Override
public void call(ClientSide clientSide, String data) {
synchronized (locked){
Room room = ServerContains.getRoom(clientSide.getRoomId());
if (room == null) {
return;
}
String result = MapHelper.newInstance()
.put("roomId", room.getId())
.put("exitClientId", clientSide.getId())
.put("exitClientNickname", clientSide.getNickname())
.json();
for (ClientSide client : room.getClientSideList()) {
if (client.getRole() == ClientRole.PLAYER) {
ChannelUtils.pushToClient(client.getChannel(), ClientEventCode.CODE_CLIENT_EXIT, result);
client.init();
}
}
notifyWatcherClientExit(room, clientSide);
ServerContains.removeRoom(room.getId());
}
}
/**
* 退
*
* @param room
* @param player 退
*/
private void notifyWatcherClientExit(Room room, ClientSide player) {
for (ClientSide watcher : room.getWatcherList()) {
ChannelUtils.pushToClient(watcher.getChannel(), ClientEventCode.CODE_CLIENT_EXIT, player.getNickname());
}
}
}

View File

@ -0,0 +1,22 @@
package org.nico.ratel.landlords.server.event;
import org.nico.ratel.landlords.entity.ClientSide;
import org.nico.ratel.landlords.utils.JsonUtils;
import java.util.Map;
public class ServerEventListener_CODE_CLIENT_INFO_SET implements ServerEventListener {
private static final String DEFAULT_VERSION = "v1.2.8";
@Override
public void call(ClientSide client, String info) {
Map<?,?> infos = JsonUtils.fromJson(info, Map.class);
// Get client version
client.setVersion(DEFAULT_VERSION);
if (infos.containsKey("version")){
client.setVersion(String.valueOf(infos.get("version")));
}
}
}

Some files were not shown because too many files have changed in this diff Show More