Passed
Pull Request — master (#167)
by Vincent
10:23
created

build(Builder)   A

Complexity

Conditions 1

Size

Total Lines 7
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 7
dl 0
loc 7
ccs 5
cts 5
cp 1
c 1
b 0
f 0
cc 1
crap 1
rs 10
1
/*
2
 * This file is part of Araknemu.
3
 *
4
 * Araknemu is free software: you can redistribute it and/or modify
5
 * it under the terms of the GNU Lesser General Public License as published by
6
 * the Free Software Foundation, either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * Araknemu is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General Public License
15
 * along with Araknemu.  If not, see <https://www.gnu.org/licenses/>.
16
 *
17
 * Copyright (c) 2017-2020 Vincent Quatrevieux
18
 */
19
20
package fr.quatrevieux.araknemu.game.admin.server;
21
22
import com.sun.management.OperatingSystemMXBean;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Use classes from the Java API instead of Sun classes.
Loading history...
23
import fr.quatrevieux.araknemu.Araknemu;
24
import fr.quatrevieux.araknemu.game.GameService;
25
import fr.quatrevieux.araknemu.game.admin.AbstractCommand;
26
import fr.quatrevieux.araknemu.game.admin.AdminPerformer;
27
import fr.quatrevieux.araknemu.game.fight.FightService;
28
import fr.quatrevieux.araknemu.game.player.PlayerService;
29
30
import java.lang.management.ManagementFactory;
31
import java.time.Duration;
32
import java.time.Instant;
33
import java.util.List;
34
35
/**
36
 * Display information about the server
37
 */
38
public final class Info extends AbstractCommand {
39
    private final Araknemu app;
40
    private final PlayerService playerService;
41
    private final GameService gameService;
42
    private final FightService fightService;
43
44 1
    public Info(Araknemu app, PlayerService playerService, GameService gameService, FightService fightService) {
45 1
        this.app = app;
46 1
        this.playerService = playerService;
47 1
        this.gameService = gameService;
48 1
        this.fightService = fightService;
49 1
    }
50
51
    @Override
52
    protected void build(Builder builder) {
53 1
        builder
54 1
            .description("Display information about the server")
55 1
            .help(formatter -> formatter
56 1
                .synopsis("info")
57 1
                .example("${server} info", "Display server info")
58
            )
59
        ;
60 1
    }
61
62
    @Override
63
    public String name() {
64 1
        return "info";
65
    }
66
67
    @Override
68
    public void execute(AdminPerformer performer, List<String> arguments) {
69 1
        performer.success("===== Server information =====");
70 1
        performer.info(
71
            "Uptime : {} (started at : {})",
72 1
            formatDuration(Duration.between(app.startDate(), Instant.now())),
73 1
            app.startDate()
74
        );
75 1
        performer.info("Online : {} sessions and {} players", gameService.sessions().size(), playerService.online().size());
76 1
        performer.info("Fights : {} fights with {} fighters",
77 1
            fightService.fights().size(),
78 1
            fightService.fights().stream().mapToLong(fight -> fight.fighters().size()).sum()
79
        );
80 1
        performer.info(
81
            "RAM usage : {} / {}",
82 1
            formatBytes(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()),
83 1
            formatBytes(Runtime.getRuntime().totalMemory())
84
        );
85 1
        performer.info("Number of threads : {}", Thread.activeCount());
86 1
        performer.info("CPU Usage {}%", cpuUsage());
87 1
    }
88
89
    private String formatDuration(Duration duration) {
90 1
        final StringBuilder formatted = new StringBuilder();
91
92 1
        if (duration.toDays() > 0) {
93
            formatted.append(duration.toDays()).append(" days ");
94
        }
95
96 1
        if (duration.toHours() % 24 > 0) {
97
            formatted.append(duration.toHours() % 24).append(" hours ");
98
        }
99
100 1
        formatted.append(duration.toMinutes() % 60).append(" minutes");
101
102 1
        return formatted.toString();
103
    }
104
105
    private static String formatBytes(long bytes) {
106 1
        final long absB = bytes == Long.MIN_VALUE ? Long.MAX_VALUE : Math.abs(bytes);
107
108 1
        if (absB < 1024) {
109
            return bytes + " B";
110
        }
111
112 1
        long value = absB;
113
114 1
        final char[] units = new char[] {'K', 'M', 'G'};
115
116 1
        int currentUnit = 0;
117
118 1
        for (int i = 40; i >= 0 && absB > 0xfffccccccccccccL >> i; i -= 10) {
119 1
            value >>= 10;
120 1
            ++currentUnit;
121
        }
122
123 1
        value *= Long.signum(bytes);
124
125 1
        return String.format("%.1f %ciB", value / 1024.0, units[currentUnit]);
126
    }
127
128
    private int cpuUsage() {
129 1
        final OperatingSystemMXBean os = ManagementFactory.getPlatformMXBean(OperatingSystemMXBean.class);
130
131 1
        return (int) (100 * os.getProcessCpuLoad());
132
    }
133
}
134