Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Huffman code #51

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 48 additions & 24 deletions src/pages/HammingCode.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,26 @@
nur Datenbits
</label>

<pre>Hamming-Code: {{ hammingCode.code }} (bereits korrigiert)</pre>
<pre>Hamming-Code: <span v-for="(bit, index) in hammingCode.code.split('')"
:key="index" v-bind:class="[index + 1 == hammingCode.errorBit ? 'errorbit' : '',
isPowerOfTwo(index+1) ? 'paritybit' : 'codebit']">{{bit}}</span> (bereits korrigiert)</pre>

<pre>Datenbits: {{ hammingCode.data }}</pre>

<pre>
Anzahl der Codebits: {{ hammingCode.numCodeBits }}
Anzahl der Paritybits: {{ hammingCode.numParityBits }}
Anzahl der Datenbits: {{ hammingCode.numDataBits }}
</pre>

<p>Formeln für die Paritybits:
<label>
<input type="checkbox" v-model="showCalulations" />
Berechnungen anzeigen
</label>
</p>
</pre
>

<p>
Formeln für die Paritybits:
<label>
<input type="checkbox" v-model="showCalulations" />
Berechnungen anzeigen
</label>
</p>
<pre>{{ hammingCode.getFormattedHammingCodeParityFormulas(false) }}</pre>

<p v-if="showCalulations">Berechnung der Paritybits:</p>
Expand Down Expand Up @@ -61,7 +67,7 @@ export default defineComponent({
const dataOnly = urlRef("dataOnly", false);

// url cleanup
code.value = code.value.replace(/[^01]/g, '');
code.value = code.value.replace(/[^01]/g, "");

let hammingCode = ref(new HammingCode(code.value, dataOnly.value));

Expand Down Expand Up @@ -107,7 +113,7 @@ export default defineComponent({
if (event.key !== "0" && event.key !== "1") {
event.preventDefault();
}
}
};

return {
code,
Expand All @@ -117,7 +123,8 @@ export default defineComponent({
dataBitCalculation,
parityBitCalculation,
codeBitCalculation,
onlyBinary
onlyBinary,
isPowerOfTwo,
};
},
});
Expand Down Expand Up @@ -169,6 +176,9 @@ class HammingCode {

getFormattedHammingCodeParityFormulas(valueMode?: boolean): string {
let output = "";

let numDigits = Math.ceil(Math.log10(this.numCodeBits));

for (let i = 0; i < this.parityBits.length; i++) {
const prefix = "[p" + (i + 1) + "]";

Expand All @@ -177,7 +187,7 @@ class HammingCode {
if (valueMode) {
return this.code[c - 1];
} else {
return "c" + c;
return "c" + c.toString().padEnd(numDigits);
}
})
.join(" ⊕ ");
Expand All @@ -189,15 +199,15 @@ class HammingCode {
return output;
}

getErrorBitMessage() : string {
getErrorBitMessage(): string {
if (this.errorBit == 0) {
return "Kein erkennbarer Fehler";
} else if (this.errorBit > this.code.length) {
return "Fehler nicht korrigierbar"
} else if (this.errorBit > 0 && this.errorBit <= this.code.length){
return "Fehler nicht korrigierbar";
} else if (this.errorBit > 0 && this.errorBit <= this.code.length) {
return "Fehler an der Stelle: " + this.errorBit;
} else {
return "Something went wrong :("
return "Something went wrong :(";
}
}

Expand Down Expand Up @@ -368,11 +378,25 @@ function replaceCharAt(value: string, index: number, replacement: string): strin
</script>

<style scoped>
input {
margin: 0em 0em 1em 0em;
}
input {
margin: 0em 0em 1em 0em;
}

label {
margin: 1em;
}
</style>
label {
margin: 1em;
}

.codebit {
color: green;
}

.errorbit {
text-decoration: underline;
text-decoration-color: springgreen;
text-decoration-thickness: 3px;
}

.paritybit {
color: blue;
}
</style>
167 changes: 167 additions & 0 deletions src/pages/HuffmanCode.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
<template>
<h1>Huffman-Code</h1>

<div class="columns">
<div class="column">
<table class="table is-striped is-bordered">
<thead>
<th>Zeichen</th>
<th>p</th>
<th v-if="isEditingMode" />
</thead>

<tbody>
<tr v-for="(row, index) in alphabet" :key="index">
<td>
<input v-if="isEditingMode" type="text" class="input" placeholder="Zeichen" v-model="row.char" />
<p v-else>{{ row.char }}</p>
</td>
<td>
<input v-if="isEditingMode" type="number" class="input" placeholder="p" v-model="row.probability" />
<p v-else>{{ row.probability }}</p>
</td>
<td v-if="isEditingMode">
<button class="button is-danger is-small" @click="deleteLetter(index)">
<i class="fas fa-trash-alt" />
X
</button>
</td>
</tr>

<tr v-if="isEditingMode">
<td colspan="3" style="text-align: center">
<button class="button is-success is-small" @click="addLetter">
<i class="fas fa-plus-circle" />
+
</button>
</td>
</tr>
</tbody>
</table>

<div class="column">
<button v-if="isEditingMode" class="button is-info is-fullwidth" @click="start">starten</button>
<button v-else class="button is-info is-fullwidth" @click="step">nächster Schritt</button>
</div>

<div v-if="!isEditingMode" class="column">
<button class="button is-danger is-fullwidth" @click="reset">zurücksetzen</button>
</div>
</div>
<div id="mynetwork" class="column"></div>
</div>
</template>

<script lang="ts">
import { defineComponent, computed, ref, watch, watchEffect, onMounted } from "vue";
import { Network, Edge as VisEdge, Node as VisNode, Options, Data } from "vis-network";
import { DataSet } from "vis-data";
import { useRoute, useRouter } from "vue-router";
import { useUrlRef } from "../url-ref";
import { VisData } from "vis-network/declarations/network/gephiParser";

export default defineComponent({
components: {},
setup() {
// example from the slides
const defaultAlphabet = [
{ char: "a", probability: 0.4 },
{ char: "b", probability: 0.2 },
{ char: "c", probability: 0.18 },
{ char: "d", probability: 0.11 },
{ char: "e", probability: 0.11 },
];
const alphabet = ref<Word[]>(defaultAlphabet);

const isEditingMode = ref<boolean>(true);

const deleteLetter = (index: number) => {
alphabet.value.splice(index, 1);
};

const addLetter = () => {
alphabet.value.push({ char: "", probability: 0.0 });
};

const huffmanGraph: HuffmanGraph = {
visEdgeData: new DataSet<VisEdge>(),
visNodeData: new DataSet<VisNode>(),
};

onMounted(() => {
setupGraph(huffmanGraph);
});

let huffmanCodeSimulation = runHuffmanCodeSimulation(alphabet.value, huffmanGraph);

const start = () => {
isEditingMode.value = false;
};

const reset = () => {
isEditingMode.value = true;
huffmanCodeSimulation.reset();
};

return { alphabet, isEditingMode, deleteLetter, addLetter, start, reset };
},
});

function setupGraph(huffmanGraph: HuffmanGraph) {
let container = document.getElementById("mynetwork");
if (container) {
var data = { nodes: huffmanGraph.visNodeData, edges: huffmanGraph.visEdgeData };

var options = {
layout: {
hierarchical: {
direction: "UD",
sortMethod: "directed",
},
},
physics: {
hierarchicalRepulsion: {
avoidOverlap: 1,
},
},
};
let network = new Network(container, data, options);
}
}

function runHuffmanCodeSimulation(alphabet: Word[], huffmanGraph: HuffmanGraph) {
let root: HuffmanTreeNode | null = null;

function mergeWords() {}

function selectWords() {}

function step() {}

function reset() {}

return { step, reset };
}

interface HuffmanGraph {
visEdgeData: DataSet<VisEdge>;
visNodeData: DataSet<VisNode>;
}

interface HuffmanTreeNode {
word: Word;
left: HuffmanTreeNode | null;
right: HuffmanTreeNode | null;
}

interface Word {
char: string;
probability: number;
}
</script>
<style scoped>
#mynetwork {
height: 800px;
border: 1px solid lightgray;
}
</style>
8 changes: 8 additions & 0 deletions src/router/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import InterleavingGraph from "./../pages/InterleavingGraph.vue";
import CacheCalc from "./../pages/CacheCalc.vue";
import Stack from "./../pages/Stack.vue";
import Micro16Decompiler from "./../pages/Micro16Decompiler.vue";
import HuffmanCode from "./../pages/HuffmanCode.vue";

type PageEntry =
| {
Expand Down Expand Up @@ -229,6 +230,13 @@ const tools: PageEntry[] = [
category: getCategory(4),
internal: false,
},
{
name: "Huffman-Code WIP",
link: "huffman-code",
category: getCategory(4),
internal: true,
page: HuffmanCode,
},
{
name: "log2 - Wolfram Alpha",
link: "https://www.wolframalpha.com/",
Expand Down