class IdealAffinityAssignment {
    /** Topology version. */
    private final AffinityTopologyVersion topologyVersion;

    /** Assignment. */
    private final List<List<ClusterNode>> assignment;

    /** Ideal primaries. */
    private final Map<Object, Set<Integer>> idealPrimaries;

    /**
     * @param topologyVersion Topology version.
     * @param assignment Assignment.
     * @param idealPrimaries Ideal primaries.
     */
    private IdealAffinityAssignment(
        AffinityTopologyVersion topologyVersion,
        List<List<ClusterNode>> assignment,
        Map<Object, Set<Integer>> idealPrimaries
    ) {
        this.topologyVersion = topologyVersion;
        this.assignment = assignment;
        this.idealPrimaries = idealPrimaries;
    }

    /**
     * @param clusterNode Cluster node.
     */
    public Set<Integer> idealPrimaries(ClusterNode clusterNode) {
        Object consistentId = clusterNode.consistentId();

        assert consistentId != null : clusterNode;

        return idealPrimaries.getOrDefault(consistentId, Collections.emptySet());
    }

    /**
     * @param partition Partition.
     */
    public ClusterNode currentPrimary(int partition) {
        return assignment.get(partition).get(0);
    }

    /**
     *
     */
    public List<List<ClusterNode>> assignment() {
        return assignment;
    }

    /**
     *
     */
    public AffinityTopologyVersion topologyVersion() {
        return topologyVersion;
    }

    /**
     * @param nodes Nodes.
     * @param assignment Assignment.
     */
    public static Map<Object, Set<Integer>> calculatePrimaries(
        @Nullable List<ClusterNode> nodes,
        List<List<ClusterNode>> assignment
    ) {<FILL_FUNCTION_BODY>}

    /**
     * @param topVer Topology version.
     * @param assignment Assignment.
     */
    public static IdealAffinityAssignment create(AffinityTopologyVersion topVer, List<List<ClusterNode>> assignment) {
        return create(topVer, null, assignment);
    }

    /**
     * @param topVer Topology version.
     * @param nodes Nodes.
     * @param assignment Assignment.
     */
    public static IdealAffinityAssignment create(
        AffinityTopologyVersion topVer,
        @Nullable List<ClusterNode> nodes,
        List<List<ClusterNode>> assignment
    ) {
        return new IdealAffinityAssignment(topVer, assignment, calculatePrimaries(nodes, assignment));
    }

    /**
     * @param topVer Topology version.
     * @param assignment Assignment.
     * @param previousAssignment Previous assignment.
     */
    public static IdealAffinityAssignment createWithPreservedPrimaries(
        AffinityTopologyVersion topVer,
        List<List<ClusterNode>> assignment,
        IdealAffinityAssignment previousAssignment
    ) {
        return new IdealAffinityAssignment(topVer, assignment, previousAssignment.idealPrimaries);
    }
}

        int nodesSize = nodes != null ? nodes.size() : 100;

        Map<Object, Set<Integer>> primaryPartitions = U.newHashMap(nodesSize);

        for (int size = assignment.size(), p = 0; p < size; p++) {
            List<ClusterNode> affNodes = assignment.get(p);

            if (!affNodes.isEmpty()) {
                ClusterNode primary = affNodes.get(0);

                primaryPartitions.computeIfAbsent(primary.consistentId(),
                    id -> new HashSet<>(U.capacity(size / nodesSize * 2))).add(p);
            }
        }

        return primaryPartitions;
    
<no_super_class>