انتقل إلى المحتوى
Pivotick
Main Navigation الرئيسية
البدء
الإعدادات
توثيق API المُولّد
المعرضالمشاريعجرّبه!

العربية

English
简体中文
Français
Deutsch
Português
Nederlands
日本語
Español

العربية

English
简体中文
Français
Deutsch
Português
Nederlands
日本語
Español

المظهر

Sidebar Navigation

البدء

مشاريع تستخدم Pivotick

الإعدادات

دوال الاستدعاء

طبقات الحواف

التبسيط

التخطيط

الرسم

المحاكاة

تخصيص الواجهة

الشريط الجانبي

التلميح

القائمة السياقية

المرشحات

وسيلة الإيضاح

جدول البيانات

تنسيق الواجهة

ترجمة الواجهة

الإضافات

واجهة Pivotick البرمجية

الاستكشاف والإثراء

حفظ نتائج الاستكشاف

التراجع والسجل

الأمان

توثيق API

المعرض

الأساسيات

تنسيق العقد

تنسيق الحواف

التخطيطات

الأحداث ودوال الاستدعاء

تخصيص الواجهة

التحرير والتأليف

الملاحظات والتعليقات

التصفية والبحث والتسلسل الهرمي

التحكم البرمجي

السمات والأداء

الاستكشاف والإثراء

نماذج مميزة

بسّط الرسم البياني ​

معظم هذا الرسم البياني عبارة عن تكرار: ثمانية عناوين IP في كلا الحدثين، وستة نطاقات في واحد، وتسعة ملفات مضيف، عشر مشاهد. UI.simplify.rules يطوي العقد التي تلعب نفس الدور في عقدة واحدة المجموعة المرسومة في مكانهم. البيانات لم تمس: graph.getNodes() لا يزال يُرجع كل عقدة.

هناك قاعدتان تعملان هنا بالترتيب. بواسطة المستشعر هو التطبيق الخاص: فهو يمنح كل رؤية مستشعرها الخاص كمفتاح، والعقد التي تتقاسم المفتاح تصبح مجموعة واحدة. المدمج في قاعدة الجار ثم طيها عقد من نوع واحد مرتبطة بنفس العقد تمامًا.

  • افتح الوضع Simplify على السكة لإيقاف تشغيل القاعدة أو تغيير المجموعة الأصغر.
  • انقر نقرًا مزدوجًا على مجموعة لإعادة أعضائها إلى اللوحة القماشية. اسحب الشريحة فوقهم إلى حركهم معًا. إنه × يطويها للخلف.
  • اختر مجموعة: يسرد الشريط الجانبي أعضائها، ولكل منهم سحب.

تغطي صفحة Simplify القواعد والقواعد المخصصة ومظهر المجموعة.

js
const plural = { ip: 'IPs', domain: 'domains', file: 'files', sighting: 'sightings' }

const simplify = {
    rules: [
        // An app rule: a key per node, and nodes sharing a key become one group.
        // It runs first, so the sightings split by sensor before the neighbour
        // rule would fold all ten of them together.
        {
            kind: 'custom',
            id: 'bySensor',
            label: 'By sensor',
            description: 'Sightings reported by the same sensor.',
            partition: (view) => new Map(view.nodes
                .filter(node => view.typeOf(node) === 'sighting')
                .map(node => [node.id, node.getData().sensor])),
        },
        // The built-in rule: one type, exactly the same neighbours, five or more.
        { kind: 'neighbours', minSize: 5 },
    ],
    typeLabel: (type, count) => `${count} ${plural[type] ?? type}`,
}
js
const options = {
    UI: {
        mode: 'full',
        // Off: this card is about neither the minimap nor the data dock.
        minimap: false,
        table: false,
        simplify,
    },
    // Longer links, so the labels under the groups have room.
    simulation: { physics: 'manual', d3LinkDistance: 70 },
    render: {
        nodeTypeAccessor: (node) => node.getData().type,
        nodeStyleMap: {
            event: { color: '#7c3aed', size: 16 },
            host: { color: '#475569', size: 14 },
            ip: { color: '#0ea5e9' },
            domain: { color: '#10b981' },
            file: { color: '#e11d48' },
            sighting: { color: '#f59e0b' },
        },
        // A group made by the app's rule names its sensor.
        groupStyle: (group) => group.rule === 'bySensor'
            ? { text: () => `${group.members.length} from ${group.members[0].getData().sensor}` }
            : undefined,
    },
}
js
// Two events share eight IPs, the first alone has six domains, a host has nine
// files, and the second event has ten sightings from two sensors.
const ips = Array.from({ length: 8 }, (_, i) => ({ id: `ip-${i}`, data: { type: 'ip', label: `198.51.100.${10 + i}` } }))
const domains = Array.from({ length: 6 }, (_, i) => ({ id: `dom-${i}`, data: { type: 'domain', label: `site-${i}.example` } }))
const files = Array.from({ length: 9 }, (_, i) => ({ id: `file-${i}`, data: { type: 'file', label: `sample-${i}.bin` } }))
const sightings = Array.from({ length: 10 }, (_, i) => ({
    id: `seen-${i}`,
    data: { type: 'sighting', label: `Sighting ${i + 1}`, sensor: i < 6 ? 'north' : 'south' },
}))

const data = {
    nodes: [
        { id: 'ev-1', data: { type: 'event', label: 'Event 1' } },
        { id: 'ev-2', data: { type: 'event', label: 'Event 2' } },
        { id: 'host', data: { type: 'host', label: 'Build host' } },
        ...ips, ...domains, ...files, ...sightings,
    ],
    edges: [
        ...ips.flatMap(ip => [{ from: 'ev-1', to: ip.id }, { from: 'ev-2', to: ip.id }]),
        ...domains.map(domain => ({ from: 'ev-1', to: domain.id })),
        ...files.map(file => ({ from: 'host', to: file.id })),
        ...sightings.map(sighting => ({ from: 'ev-2', to: sighting.id })),
        { from: 'ev-2', to: 'host' },
    ],
}
Pager
الصفحة التاليةالبدء