Skip to content

Commit

Permalink
Merge pull request #1588 from CaliOpen/frontend/pi-score
Browse files Browse the repository at this point in the history
[frontend] replace pi illustration by a pi score
  • Loading branch information
iamdey authored Apr 4, 2023
2 parents f744687 + 236caf4 commit aa265b4
Show file tree
Hide file tree
Showing 26 changed files with 837 additions and 880 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ and this project adheres to
[Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Changed

- Replace PI message illustration by a PI score (A to E).

## [0.25.3] 2023-02-28

### Fixed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ import * as React from 'react';
import classnames from 'classnames';
import './style.scss';

interface Props {
interface Props extends React.HTMLAttributes<HTMLSpanElement> {
inline?: boolean;
nowrap?: boolean;
className?: string;
size?: 'small';
weight?: 'strong';
children: React.ReactNode;
children?: React.ReactNode;
}

function TextBlock({
inline = false,
nowrap = true,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint-disable max-classes-per-file,camelcase */
import { IDraftMessagePayload } from 'src/modules/message/types';
import { PI, MessagePI, PrivacyFeature } from 'src/modules/pi/types';
import { v4 as uuidv4 } from 'uuid';
import { Participant } from './Participant';

Expand Down Expand Up @@ -46,6 +47,12 @@ export class Message {

participants: Array<Participant> = [];

pi_message?: MessagePI;

privacy_features?: PrivacyFeature;

pi?: PI;

raw_msg_id: string;

subject?: string = '';
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { useLingui } from '@lingui/react';
import * as React from 'react';
import { PI } from 'src/modules/pi/types';
import { computeScoreLetter } from '../../services/pi';
import svgSrc from './PI-score.svg';

const colors = 'E0D699,C1EDFE,AFD9EF,9CC7DC,7198A7';

interface Props extends React.HTMLAttributes<HTMLEmbedElement> {
average: number;
title?: string;
}

export default function PiScore({ title, average, ...props }: Props) {
const { i18n } = useLingui();

const score = computeScoreLetter(average);

return (
<embed
src={`${svgSrc}?score=${score}&colors=${colors}`}
title={
title ||
i18n._(
'pi-score.default-title',
{ score },
{ message: 'This is scored as {score}.' }
)
}
{...props}
/>
);
}
1 change: 1 addition & 0 deletions src/frontend/web_application/src/modules/pi/index.jsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { default as MultidimensionalPi } from './components/MultidimensionalPi';
export { default as BackgroundImage } from './components/BackgroundImage';
export { default as PiScore } from './components/PiScore';
export * from './services/pi';

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import {
computeScoreLetter,
getAngles,
getAveragePI,
getAveragePIMessage,
PI_PROPERTIES,
} from '.';

describe('MultidimensionalPi > services > pi', () => {
describe('getAngles', () => {
it('gives 360 / 3 or n props', () => {
expect(getAngles()).toEqual(360 / PI_PROPERTIES.length);
});
});
describe('getAveragePI', () => {
it('gives a basic average value', () => {
expect(
getAveragePI(
{
comportment: 5,
technic: 10,
context: 15,
version: 1,
},
PI_PROPERTIES
)
).toEqual((5 + 10 + 15) / 3);
});
});

describe('getAveragePIMessage', () => {
it('gives a basic average PIMessage value ', () => {
expect(
getAveragePIMessage({
message: {
pi_message: {
content: 5,
transport: 10,
social: 15,
rab: 20,
version: 1,
},
},
})
).toEqual((5 + 10 + 15) / 3);
});
});

describe('computeScoreLetter', () => {
it('calc', () => {
expect(computeScoreLetter(100)).toEqual('A');
expect(computeScoreLetter(90)).toEqual('A');
expect(computeScoreLetter(81)).toEqual('A');
expect(computeScoreLetter(80)).toEqual('B');
expect(computeScoreLetter(66)).toEqual('B');
expect(computeScoreLetter(61)).toEqual('B');
expect(computeScoreLetter(60)).toEqual('C');
expect(computeScoreLetter(50)).toEqual('C');
expect(computeScoreLetter(41)).toEqual('C');
expect(computeScoreLetter(40)).toEqual('D');
expect(computeScoreLetter(33)).toEqual('D');
expect(computeScoreLetter(30)).toEqual('D');
expect(computeScoreLetter(21)).toEqual('D');
expect(computeScoreLetter(20)).toEqual('E');
expect(computeScoreLetter(10)).toEqual('E');
expect(computeScoreLetter(0)).toEqual('E');
});

it('calc above min/max', () => {
expect(computeScoreLetter(150)).toEqual('A');
expect(computeScoreLetter(-100)).toEqual('E');
});
});
});
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { PI, MessagePI } from '../../types';

export const PI_PROPERTIES = ['comportment', 'technic', 'context'];
export const PI_MESSAGE_PROPERTIES = ['content', 'transport', 'social'];
export const PI_LEVEL_DISABLED = 'disabled-pi';
Expand All @@ -6,7 +8,7 @@ export const PI_LEVEL_BAD = 'bad';
export const PI_LEVEL_GOOD = 'good';
export const PI_LEVEL_SUPER = 'super';

export const getPiClass = (piAggregate) => {
export const getPiClass = (piAggregate: number | any) => {
if (Number.isNaN(piAggregate)) return PI_LEVEL_DISABLED;

if (piAggregate < 25) return PI_LEVEL_UGLY;
Expand All @@ -24,7 +26,7 @@ export const getAngles = () => {
return 360 / piLength;
};

export const getAveragePI = (pi, piProps = PI_PROPERTIES) => {
export const getAveragePI = (pi: PI | MessagePI | void, piProps: string[]) => {
if (!pi) return NaN;

return Math.round(
Expand All @@ -34,3 +36,23 @@ export const getAveragePI = (pi, piProps = PI_PROPERTIES) => {

export const getAveragePIMessage = ({ message }) =>
getAveragePI(message.pi_message, PI_MESSAGE_PROPERTIES);

export type ScoreLetter = 'A' | 'B' | 'C' | 'D' | 'E';

export const computeScoreLetter = (percent: number) => {
let key = Math.ceil(percent / 20);
if (key < 1) {
key = 1;
}
if (key > 5) {
key = 5;
}

// reverse: A eq 0; E eq 4;
const baseCharCode = 5 - key;

return String.fromCharCode(65 + baseCharCode) as ScoreLetter;
};

export const computePiScoreLetter = (pi: PI) =>
computeScoreLetter(getAveragePI(pi, PI_PROPERTIES));
20 changes: 19 additions & 1 deletion src/frontend/web_application/src/modules/pi/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,24 @@ export interface PI {
// [additional: string]: any, // XXX: not sure how to type `additionalProperties`
}

export interface MessagePI {
transport: number;
social: number;
content: number;
}

type PrivacyFeatureKey =
| 'is_internal'
| 'is_spam'
| 'message_encrypted'
| 'message_encrypted_method'
| 'message_signed'
| 'nb_external_hops'
| 'spam_score'
| 'transport_signed';

type PrivacyFeatureValue = 'False' | 'True' | string;

export interface PrivacyFeature {
[key: string]: any;
[key: PrivacyFeatureKey | string]: PrivacyFeatureValue;
}
Loading

0 comments on commit aa265b4

Please sign in to comment.