package happy.research.pgp;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
public class TrustChainPGP extends AbstractPGP
{
protected Performance firePerformanceTest(final List<PGPNode> nodes)
{
int numNodes = nodes.size();
int coversCount[] = new int[numNodes];
double coverages[] = new double[numNodes];
double accuracies[] = new double[numNodes];
double distances[] = new double[numNodes];
// compute trust values
double trusts[][] = new double[numNodes][numNodes];
for (int i = 0; i < numNodes; i++)
{
PGPNode entity = nodes.get(i);
for (int j = 0; j < numNodes; j++)
{
if (j == i)
{
trusts[i][j] = TrustType.COMPLETED_TRUST.getTrustValue();
continue;
}
PGPNode target = nodes.get(j);
if (entity.getTns().containsKey(target))
{
trusts[i][j] = entity.getTns().get(target).getTrustValue();
continue;
}
// find chains between entity and target
List<List<Integer>> chains = findChains(entity, target, 4);
if (chains == null || chains.size() <= 0)
{
trusts[i][j] = -1.0;
continue;
}
// printChains(chains);
PGPNode parentNode, currentNode;
double chains_sum = 0.0;
int count = 0;
for (List<Integer> chain : chains)
{
parentNode = entity;
double chain_trustness = 1.0;
for (int k = 1; k < chain.size(); k++)
{
currentNode = nodes.get(chain.get(k));
TrustType tt = parentNode.getNeighborus().get(currentNode);
chain_trustness *= tt.getTrustValue();
parentNode = currentNode;
}
if (chain_trustness > 0)
{
count++;
chains_sum += chain_trustness;
}
}
trusts[i][j] = chains_sum / count;
}
}
// compute validity
for (int i = 0; i < numNodes; i++)
{
PGPNode entity = nodes.get(i);
int coverage_count = 0, accuracy_count = 0;
for (int j = 0; j < numNodes; j++)
{
if (j == i) continue;
PGPNode target = nodes.get(j);
if (entity.getTns().containsKey(target)) continue;
double positive_sum = 0.0, negative_sum = 0.0;
int count = 0;
for (Entry<PGPNode, CertificateType> entry : target.getSigners().entrySet())
{
PGPNode signer = entry.getKey();
CertificateType ct = entry.getValue();
double trust = trusts[i][signer.getKeyId()];
if (trust > 0)
{
count++;
if (ct == CertificateType.VALID)
positive_sum += trust * ct.getInherentValue();
else if (ct == CertificateType.INVALID)
negative_sum += trust * ct.getInherentValue();
}
}
if (count > 0)
{
coverage_count++;
double validity = (Math.abs(positive_sum) - Math.abs(negative_sum))
/ (Math.abs(positive_sum) + Math.abs(negative_sum));
double distance = Math.abs(validity - target.getCertificate().getInherentValue());
distances[i] += distance;
if (distance <= ACCURACY_THRESHOLD) accuracy_count++;
logger.debug("Entity " + i + "'s distance to target " + j + " = " + distance);
}
}
coversCount[i] = coverage_count;
int needsCoverCount = numNodes - 1 - entity.getTns().size();
coverages[i] = (coversCount[i] + 0.0) / needsCoverCount;
accuracies[i] = (accuracy_count + 0.0) / needsCoverCount;
if (coversCount[i] > 0)
distances[i] /= coversCount[i];
}
return calculatePerformance(AbstractPGP.TRUSTCHAIN_PGP, coversCount, coverages, distances, accuracies);
}
protected List<List<Integer>> findChains(PGPNode entity, PGPNode target, int maxDepth)
{
List<List<Integer>> chains = new ArrayList<>();
for (Entry<PGPNode, TrustType> entry : entity.getTns().entrySet())
{
PGPNode tn = entry.getKey();
List<PGPNode> exceptions = new ArrayList<>();
exceptions.add(entity);
exceptions.addAll(entity.getTns().keySet());
List<List<Integer>> subchains = findChainPaths(tn, target, maxDepth - 1, exceptions);
for (List<Integer> subchain : subchains)
{
List<Integer> chain = new ArrayList<>();
chain.add(entity.getKeyId());
chain.addAll(subchain);
chains.add(chain);
}
}
return chains;
}
protected void printChains(List<List<Integer>> chains)
{
for (List<Integer> chain : chains)
{
for (int j = 0; j < chain.size(); j++)
{
if (j == chain.size() - 1)
System.out.print(chain.get(j));
else
System.out.print(chain.get(j) + " --> ");
}
System.out.println();
}
}
private List<List<Integer>> findChainPaths(PGPNode entity,
PGPNode target, int maxDepth, List<PGPNode> exceptions)
{
if (maxDepth <= 0) return null;
List<List<Integer>> chains = new ArrayList<>();
for (Entry<PGPNode, TrustType> entry : entity.getTns().entrySet())
{
PGPNode tn = entry.getKey();
if (exceptions.contains(tn)) continue;
List<Integer> chain = new ArrayList<>();
if (target.getSigners().containsKey(tn))
{
chain.add(entity.getKeyId());
chain.add(tn.getKeyId());
chain.add(target.getKeyId());
chains.add(chain);
continue;
} else if (maxDepth - 1 <= 0)
{
return chains;
} else
{
chain.add(entity.getKeyId());
exceptions.add(tn);
List<List<Integer>> subchains = findChainPaths(tn, target, maxDepth - 1, exceptions);
if (subchains != null && subchains.size() > 0)
{
for (int i = 0; i < subchains.size(); i++)
{
List<Integer> tempchain = new ArrayList<>();
tempchain.addAll(chain);
tempchain.addAll(subchains.get(i));
chains.add(tempchain);
}
}
}
}
return chains;
}
}