YnM Statisztika Sopel py

**Live ** YnM Statisztika

<link href="/css/ynm.statisztika.css" rel="stylesheet">

<?php
// PHP code to process log files and generate $nodes and $links
$logFiles = glob("/home/ai/.sopel/szobak/magyar-*.log"); // Collect all log files
$users = []; // Array to store user activity count
$interactions = []; // Array to store interactions between users

// Process each log file
foreach ($logFiles as $logFile) {
    $logData = file($logFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); // Read file line by line
    foreach ($logData as $line) {
        // Parse lines with a specific format
        if (preg_match('/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\+\d{2}:\d{2}\s+<YnM-Bridge>\s+\[(.*?)\](.*)/', $line, $matches)) {
            $user = trim($matches[1]); // Extract user name
            $message = trim($matches[2]); // Extract message

            // Count user activity
            if (!isset($users[$user])) {
                $users[$user] = 0;
            }
            $users[$user]++;

            // Count interactions (mentions)
            if (preg_match('/@(\w+)/', $message, $mentioned)) {
                $mentionedUser = $mentioned[1];
                $pair = [$user, $mentionedUser];
                sort($pair); // Sort the pair to ensure consistency
                $pairKey = implode("-", $pair); // Create a unique key for the pair

                if (!isset($interactions[$pairKey])) {
                    $interactions[$pairKey] = 0;
                }
                $interactions[$pairKey]++;
            }
        }
    }
}

// Sort users and interactions in descending order
arsort($users);
arsort($interactions);

// Generate nodes and links for the D3.js visualization
$allUsers = array_keys($users); // List of all users

$nodes = [];
foreach ($allUsers as $user) {
    $nodes[] = "{ id: '" . addslashes($user) . "' }"; // Add each user to the nodes list
}

$links = [];
foreach ($interactions as $pair => $count) {
    list($user1, $user2) = explode("-", $pair);
    // Ensure both users in the pair exist in the nodes array
    if (in_array($user1, $allUsers) && in_array($user2, $allUsers)) {
        $links[] = "{ source: '" . addslashes($user1) . "', target: '" . addslashes($user2) . "', value: $count }";
    }
}
?>

<script src="https://d3js.org/d3.v7.min.js"></script>

<h2 class="ynm-statisztika text-center">Kapcsolati háló</h2>

<!-- SVG container for network diagram -->
<div class="svg-container text-center">
    <svg viewBox="0 0 800 600" preserveAspectRatio="xMidYMid meet"></svg>
</div>

<h2 class="ynm-statisztika text-center">Felhasználói aktivitás</h2>

<!-- D3.js bar chart for user activity -->
<div class="svg-container text-center">
    <svg id="activity-chart" width="100%" height="400"></svg>
</div>

<!-- Empty SVG for network diagram (second diagram) -->
<div class="svg-container text-center">
    <svg viewBox="0 0 100% 100%" preserveAspectRatio="xMidYMid meet"></svg>
</div>

<h2 class="mt-4 text-center">Ki kivel beszélt</h2>
<table class="table table-bordered table-striped">
    <thead class="table-dark">
        <tr><th>Páros</th><th>Üzenetek száma</th></tr>
    </thead>
    <tbody>
    <?php foreach ($interactions as $pair => $count) { ?>
        <tr><td><?php echo htmlspecialchars($pair); ?></td><td><?php echo $count; ?></td></tr>
    <?php } ?>
    </tbody>
</table>

<h2 class="mt-4 text-center">Felhasználói aktivitás</h2>
<table class="table table-bordered table-striped">
    <thead class="table-dark">
        <tr><th>Felhasználó</th><th>Üzenetek száma</th></tr>
    </thead>
    <tbody>
    <?php foreach ($users as $user => $count) { ?>
        <tr><td><?php echo htmlspecialchars($user); ?></td><td><?php echo $count; ?></td></tr>
    <?php } ?>
    </tbody>
</table>

<?php
// Ensure all users in the interactions are added to nodes
$allUsers = array_keys($users);  // List of users from message activity

$nodes = [];
foreach ($allUsers as $user) {
    $nodes[] = "{ id: '" . addslashes($user) . "' }"; // Add each user to the nodes list
}

$links = [];
foreach ($interactions as $pair => $count) {
    list($user1, $user2) = explode("-", $pair);
    // Ensure both users in the pair exist in the nodes array
    if (in_array($user1, $allUsers) && in_array($user2, $allUsers)) {
        $links[] = "{ source: '" . addslashes($user1) . "', target: '" . addslashes($user2) . "', value: $count }";
    }
}
?>
<script>
// D3.js bar chart for user activity

const usersData = <?php echo json_encode($users); ?>; // Data passed from PHP to JavaScript

const margin = { top: 20, right: 20, bottom: 40, left: 50 };
const width = 800 - margin.left - margin.right;
const height = 400 - margin.top - margin.bottom;

const svg1 = d3.select("#activity-chart")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

const x = d3.scaleBand()
    .domain(Object.keys(usersData))
    .range([0, width])
    .padding(0.1);

const y = d3.scaleLinear()
    .domain([0, d3.max(Object.values(usersData))])
    .nice()
    .range([height, 0]);

const colorScale = d3.scaleLinear()
    .domain([0, d3.max(Object.values(usersData))])
    .range(["lightblue", "darkblue"]);

// Add X and Y axes
svg1.append("g")
    .selectAll(".x-axis")
    .data(Object.keys(usersData))
    .enter()
    .append("text")
    .attr("x", (d, i) => x(d) + x.bandwidth() / 2)
    .attr("y", height + 20)
    .attr("text-anchor", "middle")
    .style("font-size", "12px")
    .text(d => d);

svg1.append("g")
    .selectAll(".y-axis")
    .data([0])
    .enter()
    .append("g")
    .call(d3.axisLeft(y))
    .attr("transform", "translate(0, 0)");

// Add bars (rectangles) to the chart
svg1.selectAll(".bar")
    .data(Object.entries(usersData))
    .enter()
    .append("rect")
    .attr("class", "bar")
    .attr("x", d => x(d[0]))
    .attr("y", d => y(d[1]))
    .attr("width", x.bandwidth())
    .attr("height", d => height - y(d[1]))
    .attr("fill", d => colorScale(d[1]));

// Add labels above the bars
svg1.selectAll(".label")
    .data(Object.entries(usersData))
    .enter()
    .append("text")
    .attr("class", "label")
    .attr("x", d => x(d[0]) + x.bandwidth() / 2)
    .attr("y", d => y(d[1]) - 5)
    .attr("text-anchor", "middle")
    .style("font-size", "12px")
    .text(d => d[1]);

// D3.js network diagram for interactions

const nodes = [
    <?php echo implode(",", $nodes); ?>
].filter(node => node.id !== "markuslajos");  // Filter out "markuslajos"

const links = [
    <?php echo implode(",", $links); ?>
];

const svg2 = d3.select("svg"),
      simulation = d3.forceSimulation(nodes)
        .force("link", d3.forceLink(links).id(d => d.id).distance(100))
        .force("charge", d3.forceManyBody().strength(-300))
        .force("center", d3.forceCenter(width / 2, height / 2))
        .on("tick", ticked);

const colorScale2 = d3.scaleLinear()
    .domain([1, d3.max(links, d => d.value)])
    .range(["green", "red"]);

const link = svg2.append("g")
    .attr("class", "links")
    .selectAll("line")
    .data(links)
    .enter().append("line")
    .attr("class", "link")
    .style("stroke", d => colorScale2(d.value))
    .style("stroke-width", 2);

const node = svg2.append("g")
    .attr("class", "nodes")
    .selectAll("circle")
    .data(nodes)
    .enter().append("circle")
    .attr("class", "node")
    .attr("r", 10)
    .style("fill", (d, i) => d3.schemeCategory10[i % 10]);

node.append("title").text(d => d.id);

const connectedGroup = svg2.append("g")
    .attr("class", "connectedGroup");

connectedGroup.selectAll("text")
    .data(nodes)
    .enter().append("text")
    .attr("x", d => d.x)
    .attr("y", d => d.y - 25)
    .text(d => d.id)
    .style("font-size", "12px")
    .style("text-anchor", "middle")
    .style("fill", "black");

function ticked() {
    link.attr("x1", d => d.source.x)
        .attr("y1", d => d.source.y)
        .attr("x2", d => d.target.x)
        .attr("y2", d => d.target.y);

    node.attr("cx", d => d.x)
        .attr("cy", d => d.y);

    node.attr("cx", function(d) {
        return Math.max(10, Math.min(width - 10, d.x));
    })
    .attr("cy", function(d) {
        return Math.max(10, Math.min(height - 10, d.y));
    });

    connectedGroup.selectAll("text")
        .attr("x", d => d.x)
        .attr("y", d => d.y - 25);
}
</script>