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

LogSeverity parameter instead of a lot of nearly identical functions. #233

Merged
merged 2 commits into from
Jul 26, 2023
Merged
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
14 changes: 7 additions & 7 deletions docs/Abstractions.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
**Abstractions**

Behave-graph is designed as a light weight library that can be plugged into other engines, such as Three.js or Babylon.js. In order to simplify pluggin into other engines, it defines the functionality required for interfacing with these engines as "abstractions", which can then be implemented by the engines.
Behave-graph is designed as a light weight library that can be plugged into other engines, such as Three.js or Babylon.js. In order to simplify pluggin into other engines, it defines the functionality required for interfacing with these engines as "abstractions", which can then be implemented by the engines.

This design is inspired by [Hardware Abstraction layers](https://en.wikipedia.org/wiki/Hardware_abstraction) present in operating systems. HALs, as they are called, are interfaces which are then implemented by drivers that enable that functionality. HALs allow for operating systems to easily be ported to different systems because the machine specific implementations for the operating systems are cordened off from the main operating system behind these HALs. Behave-graph takes this same approach.
This design is inspired by [Hardware Abstraction layers](https://en.wikipedia.org/wiki/Hardware_abstraction) present in operating systems. HALs, as they are called, are interfaces which are then implemented by drivers that enable that functionality. HALs allow for operating systems to easily be ported to different systems because the machine specific implementations for the operating systems are cordened off from the main operating system behind these HALs. Behave-graph takes this same approach.

Example abstractions in behave-graph:

* ILogger. The logging interface allows for behave-graph to report verbose, info, warning and error text messages. The command line graph-exec tool uses the driver DefaultLogger to output these messages to the console.
* ILifecycleEventEmitter. This interface is responsible for emitting when the behave-graph should start, tick and stop.
* IScene. This interface is responsible for doing basic scene manipulations. In the three example, this interface is implemented by the ThreeScene class that maps these operations to a Three.js-based scene graph.
- ILogger. The logging interface allows for behave-graph to report verbose, info, warning and error text messages. The command line graph-exec tool uses the driver DefaultLogger to output these messages to the console.
- ILifecycleEventEmitter. This interface is responsible for emitting when the behave-graph should start, tick and stop.
- IScene. This interface is responsible for doing basic scene manipulations. In the three example, this interface is implemented by the ThreeScene class that maps these operations to a Three.js-based scene graph.

For example here is the ILogger abstraction, you can see it is just a standard Typescript interface:

``` typescript
```typescript
export interface ILogger {
verbose(text: string): void;
info(text: string): void;
Expand All @@ -38,7 +38,7 @@ export class DefaultLogger implements ILogger {
}

warn(text: string): void {
Logger.warn(text);
Logger.warning(text);
}

error(text: string): void {
Expand Down
53 changes: 29 additions & 24 deletions packages/core/src/Diagnostics/Logger.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,27 @@
/* eslint-disable no-console */

import { EventEmitter } from '../Events/EventEmitter.js';
import { LogSeverity } from '../index.js';

export enum LogLevel {
Verbose = 0,
Info = 1,
Warn = 2,
Warning = 2,
Error = 3
}

export function logSeverityToLevel(severity: LogSeverity) {
switch (severity) {
case 'verbose':
return LogLevel.Verbose;
case 'info':
return LogLevel.Info;
case 'warning':
return LogLevel.Warning;
case 'error':
return LogLevel.Error;
}
}
export enum PrefixStyle {
None = 0,
Time = 1
Expand All @@ -19,14 +32,13 @@ const FgRed = '\x1b[31m';
const BgYellow = '\x1b[43m';
const Dim = '\x1b[2m';

export type LogMessage = { severity: LogSeverity; text: string };

export class Logger {
static logLevel = LogLevel.Info;
static prefixStyle = PrefixStyle.None;

public static readonly onVerbose = new EventEmitter<string>();
public static readonly onInfo = new EventEmitter<string>();
public static readonly onWarn = new EventEmitter<string>();
public static readonly onError = new EventEmitter<string>();
public static readonly onLog = new EventEmitter<LogMessage>();

static {
const prefix = (): string => {
Expand All @@ -38,36 +50,29 @@ export class Logger {
}
};

Logger.onVerbose.addListener((text: string) => {
if (Logger.logLevel > LogLevel.Verbose) return;
console.log(prefix() + `${Dim}${text}${Reset}`);
});
Logger.onInfo.addListener((text: string) => {
if (Logger.logLevel > LogLevel.Info) return;
console.log(prefix() + `${text}`);
});
Logger.onWarn.addListener((text: string) => {
if (Logger.logLevel > LogLevel.Warn) return;
console.warn(prefix() + `${BgYellow}${text}${Reset}`);
});
Logger.onError.addListener((text: string) => {
console.error(prefix() + `${FgRed}${text}}${Reset}`);
Logger.onLog.addListener((logMessage: LogMessage) => {
if (Logger.logLevel > logSeverityToLevel(logMessage.severity)) return;
console.log(prefix() + logMessage.text);
});
}

static log(severity: LogSeverity, text: string) {
this.onLog.emit({ severity, text });
}

static verbose(text: string) {
this.onVerbose.emit(text);
this.onLog.emit({ severity: 'verbose', text });
}

static info(text: string) {
this.onInfo.emit(text);
this.onLog.emit({ severity: 'info', text });
}

static warn(text: string) {
this.onWarn.emit(text);
static warning(text: string) {
this.onLog.emit({ severity: 'warning', text });
}

static error(text: string) {
this.onError.emit(text);
this.onLog.emit({ severity: 'error', text });
}
}
2 changes: 1 addition & 1 deletion packages/core/src/Graphs/IO/readGraphFromJSON.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export function readGraphFromJSON({
const nodesJson = graphJson?.nodes ?? [];

if (nodesJson.length === 0) {
Logger.warn('readGraphFromJSON: no nodes specified');
Logger.warning('readGraphFromJSON: no nodes specified');
}

const graphApi = makeGraphApi({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,9 @@
/* eslint-disable class-methods-use-this */
import { Logger } from '../../../../Diagnostics/Logger.js';
import { ILogger } from '../ILogger.js';
import { ILogger, LogSeverity } from '../ILogger.js';

export class DefaultLogger implements ILogger {
verbose(text: string): void {
Logger.verbose(text);
}

info(text: string): void {
Logger.info(text);
}

warn(text: string): void {
Logger.warn(text);
}

error(text: string): void {
Logger.error(text);
log(severity: LogSeverity, text: string): void {
Logger.log(severity, text);
}
}
6 changes: 2 additions & 4 deletions packages/core/src/Profiles/Core/Abstractions/ILogger.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
export type LogSeverity = 'verbose' | 'info' | 'warning' | 'error';
export interface ILogger {
verbose(text: string): void;
info(text: string): void;
warn(text: string): void;
error(text: string): void;
log(severity: LogSeverity, text: string): void;
}
63 changes: 30 additions & 33 deletions packages/core/src/Profiles/Core/Debug/AssertExpectTrue.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,33 @@
import { Assert } from '../../../Diagnostics/Assert.js';
import { Fiber } from '../../../Execution/Fiber.js';
import { IGraphApi } from '../../../Graphs/Graph.js';
import { FlowNode } from '../../../Nodes/FlowNode.js';
import { NodeDescription } from '../../../Nodes/Registry/NodeDescription.js';
import { Socket } from '../../../Sockets/Socket.js';
import {
makeFlowNodeDefinition,
NodeCategory
} from '../../../Nodes/NodeDefinitions.js';

export class ExpectTrue extends FlowNode {
public static Description = new NodeDescription(
'debug/expectTrue',
'Action',
'Assert Expect True',
(description, graph) => new ExpectTrue(description, graph)
);

constructor(description: NodeDescription, graph: IGraphApi) {
super(
description,
graph,
[
new Socket('flow', 'flow'),
new Socket('boolean', 'condition'),
new Socket('string', 'description')
],
[new Socket('flow', 'flow')]
);
}

triggered(fiber: Fiber, triggeredSocketName: string) {
Assert.mustBeTrue(
this.readInput('condition'),
this.readInput('description')
);
fiber.commit(this, 'flow');
export const ExpectTrue = makeFlowNodeDefinition({
typeName: 'debug/expectTrue',
category: NodeCategory.Action,
label: 'Assert Expect True',
in: () => {
return [
{
key: 'flow',
valueType: 'flow'
},
{
key: 'condition',
valueType: 'boolean'
},
{
key: 'description',
valueType: 'string'
}
];
},
initialState: undefined,
out: { flow: 'flow' },
triggered: ({ read, commit }) => {
Assert.mustBeTrue(read('condition'), read('description'));
commit('flow');
}
}
});
20 changes: 2 additions & 18 deletions packages/core/src/Profiles/Core/Debug/DebugLog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
makeFlowNodeDefinition,
NodeCategory
} from '../../../Nodes/NodeDefinitions.js';
import { ILogger } from '../Abstractions/ILogger.js';
import { ILogger, LogSeverity } from '../Abstractions/ILogger.js';

export const Log = makeFlowNodeDefinition({
typeName: 'debug/log',
Expand All @@ -22,23 +22,7 @@ export const Log = makeFlowNodeDefinition({
initialState: undefined,
triggered: ({ read, commit, graph: { getDependency } }) => {
const logger = getDependency<ILogger>('ILogger');

const text = read<string>('text');
switch (read<string>('severity')) {
case 'verbose':
logger?.verbose(text);
break;
case 'info':
logger?.info(text);
break;
case 'warning':
logger?.warn(text);
break;
case 'error':
logger?.error(text);
break;
}

logger?.log(read<LogSeverity>('severity'), read<string>('text'));
commit('flow');
}
});
2 changes: 1 addition & 1 deletion packages/core/src/Profiles/Core/registerCoreProfile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export const getCoreNodesMap = memo<Record<string, NodeDefinition>>(() => {

// actions
DebugLog,
AssertExpectTrue.Description,
AssertExpectTrue,

// events
LifecycleOnStart,
Expand Down
14 changes: 7 additions & 7 deletions website/docs/core-concepts/abstractions.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ sidebar_position: 5

# Abstractions

Behave-graph is designed as a light weight library that can be plugged into other engines, such as Three.js or Babylon.js. In order to simplify pluggin into other engines, it defines the functionality required for interfacing with these engines as "abstractions", which can then be implemented by the engines.
Behave-graph is designed as a light weight library that can be plugged into other engines, such as Three.js or Babylon.js. In order to simplify pluggin into other engines, it defines the functionality required for interfacing with these engines as "abstractions", which can then be implemented by the engines.

This design is inspired by [Hardware Abstraction layers](https://en.wikipedia.org/wiki/Hardware_abstraction) present in operating systems. HALs, as they are called, are interfaces which are then implemented by drivers that enable that functionality. HALs allow for operating systems to easily be ported to different systems because the machine specific implementations for the operating systems are cordened off from the main operating system behind these HALs. Behave-graph takes this same approach.
This design is inspired by [Hardware Abstraction layers](https://en.wikipedia.org/wiki/Hardware_abstraction) present in operating systems. HALs, as they are called, are interfaces which are then implemented by drivers that enable that functionality. HALs allow for operating systems to easily be ported to different systems because the machine specific implementations for the operating systems are cordened off from the main operating system behind these HALs. Behave-graph takes this same approach.

Example abstractions in behave-graph:

* **ILogger**. The logging interface allows for behave-graph to report verbose, info, warning and error text messages. The command line graph-exec tool uses the driver DefaultLogger to output these messages to the console.
* **ILifecycleEventEmitter**. This interface is responsible for emitting when the behave-graph should start, tick and stop.
* **IScene**. This interface is responsible for doing basic scene manipulations. In the three example, this interface is implemented by the ThreeScene class that maps these operations to a Three.js-based scene graph.
- **ILogger**. The logging interface allows for behave-graph to report verbose, info, warning and error text messages. The command line graph-exec tool uses the driver DefaultLogger to output these messages to the console.
- **ILifecycleEventEmitter**. This interface is responsible for emitting when the behave-graph should start, tick and stop.
- **IScene**. This interface is responsible for doing basic scene manipulations. In the three example, this interface is implemented by the ThreeScene class that maps these operations to a Three.js-based scene graph.

For example here is the ILogger abstraction, you can see it is just a standard Typescript interface:

Expand Down Expand Up @@ -41,11 +41,11 @@ export class DefaultLogger implements ILogger {
}

warn(text: string): void {
Logger.warn(text);
Logger.warning(text);
}

error(text: string): void {
Logger.error(text);
}
}
```
```
Loading