mediasfu-shared 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +228 -0
- package/dist/index.cjs +7707 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +7285 -0
- package/dist/index.js +7690 -0
- package/dist/index.js.map +1 -0
- package/package.json +78 -0
- package/src/ProducerClient/producerClientEmits/createDeviceClient.ts +68 -0
- package/src/consumers/addVideosGrid.ts +18 -0
- package/src/consumers/autoAdjust.ts +100 -0
- package/src/consumers/calculateRowsAndColumns.ts +51 -0
- package/src/consumers/changeVids.ts +753 -0
- package/src/consumers/checkGrid.ts +100 -0
- package/src/consumers/checkPermission.ts +89 -0
- package/src/consumers/checkScreenShare.ts +114 -0
- package/src/consumers/closeAndResize.ts +401 -0
- package/src/consumers/compareActiveNames.ts +122 -0
- package/src/consumers/compareScreenStates.ts +117 -0
- package/src/consumers/connectIps.ts +175 -0
- package/src/consumers/connectLocalIps.ts +103 -0
- package/src/consumers/connectRecvTransport.ts +158 -0
- package/src/consumers/connectSendTransport.ts +150 -0
- package/src/consumers/connectSendTransportAudio.ts +161 -0
- package/src/consumers/connectSendTransportScreen.ts +169 -0
- package/src/consumers/connectSendTransportVideo.ts +149 -0
- package/src/consumers/consumerResume.ts +25 -0
- package/src/consumers/controlMedia.ts +118 -0
- package/src/consumers/createSendTransport.ts +312 -0
- package/src/consumers/disconnectSendTransportAudio.ts +170 -0
- package/src/consumers/disconnectSendTransportScreen.ts +130 -0
- package/src/consumers/disconnectSendTransportVideo.ts +161 -0
- package/src/consumers/dispStreams.ts +694 -0
- package/src/consumers/generatePageContent.ts +118 -0
- package/src/consumers/getEstimate.ts +124 -0
- package/src/consumers/getPipedProducersAlt.ts +96 -0
- package/src/consumers/getProducersPiped.ts +89 -0
- package/src/consumers/getVideos.ts +107 -0
- package/src/consumers/mixStreams.ts +97 -0
- package/src/consumers/onScreenChanges.ts +106 -0
- package/src/consumers/prepopulateUserMedia.ts +18 -0
- package/src/consumers/processConsumerTransports.ts +157 -0
- package/src/consumers/processConsumerTransportsAudio.ts +121 -0
- package/src/consumers/rePort.ts +123 -0
- package/src/consumers/reUpdateInter.ts +289 -0
- package/src/consumers/readjust.ts +170 -0
- package/src/consumers/receiveAllPipedTransports.ts +77 -0
- package/src/consumers/receiveRoomMessages.ts +55 -0
- package/src/consumers/reorderStreams.ts +246 -0
- package/src/consumers/requestScreenShare.ts +103 -0
- package/src/consumers/resumePauseAudioStreams.ts +174 -0
- package/src/consumers/resumePauseStreams.ts +110 -0
- package/src/consumers/resumeSendTransportAudio.ts +143 -0
- package/src/consumers/signalNewConsumerTransport.ts +179 -0
- package/src/consumers/socketReceiveMethods/joinConsumeRoom.ts +130 -0
- package/src/consumers/socketReceiveMethods/newPipeProducer.ts +138 -0
- package/src/consumers/socketReceiveMethods/producerClosed.ts +102 -0
- package/src/consumers/startShareScreen.ts +124 -0
- package/src/consumers/stopShareScreen.ts +241 -0
- package/src/consumers/streamSuccessAudio.ts +297 -0
- package/src/consumers/streamSuccessAudioSwitch.ts +315 -0
- package/src/consumers/streamSuccessScreen.ts +255 -0
- package/src/consumers/streamSuccessVideo.ts +373 -0
- package/src/consumers/switchUserAudio.ts +140 -0
- package/src/consumers/switchUserVideo.ts +201 -0
- package/src/consumers/switchUserVideoAlt.ts +331 -0
- package/src/consumers/trigger.ts +250 -0
- package/src/consumers/updateMiniCardsGrid.ts +150 -0
- package/src/consumers/updateParticipantAudioDecibels.ts +56 -0
- package/src/index.ts +119 -0
- package/src/methods/background/launchBackground.ts +16 -0
- package/src/methods/breakoutRooms/breakoutRoomUpdated.ts +161 -0
- package/src/methods/breakoutRooms/handleStartBreakout.ts +96 -0
- package/src/methods/breakoutRooms/handleStopBreakout.ts +72 -0
- package/src/methods/breakoutRooms/index.ts +4 -0
- package/src/methods/breakoutRooms/launchBreakoutRooms.ts +31 -0
- package/src/methods/coHost/launchCoHost.ts +28 -0
- package/src/methods/coHostMethods/index.ts +2 -0
- package/src/methods/coHostMethods/modifyCoHostSettings.ts +94 -0
- package/src/methods/displaySettings/index.ts +1 -0
- package/src/methods/displaySettings/launchDisplaySettings.ts +31 -0
- package/src/methods/displaySettings/modifyDisplaySettings.ts +242 -0
- package/src/methods/exit/confirmExit.ts +60 -0
- package/src/methods/exit/index.ts +2 -0
- package/src/methods/exit/launchConfirmExit.ts +29 -0
- package/src/methods/index.ts +5 -0
- package/src/methods/mediaSettings/launchMediaSettings.ts +61 -0
- package/src/methods/menu/launchMenuModal.ts +28 -0
- package/src/methods/message/index.ts +1 -0
- package/src/methods/message/launchMessages.ts +27 -0
- package/src/methods/message/sendMessage.ts +175 -0
- package/src/methods/participants/index.ts +3 -0
- package/src/methods/participants/launchParticipants.ts +25 -0
- package/src/methods/participants/messageParticipants.ts +78 -0
- package/src/methods/participants/muteParticipants.ts +79 -0
- package/src/methods/participants/removeParticipants.ts +97 -0
- package/src/methods/polls/handleCreatePoll.ts +66 -0
- package/src/methods/polls/handleEndPoll.ts +64 -0
- package/src/methods/polls/handleVotePoll.ts +76 -0
- package/src/methods/polls/index.ts +3 -0
- package/src/methods/polls/launchPoll.ts +25 -0
- package/src/methods/prejoin/handleCreateRoom.ts +441 -0
- package/src/methods/prejoin/handleJoinRoom.ts +153 -0
- package/src/methods/prejoin/index.ts +14 -0
- package/src/methods/recording/checkPauseState.ts +57 -0
- package/src/methods/recording/checkResumeState.ts +42 -0
- package/src/methods/recording/confirmRecording.ts +241 -0
- package/src/methods/recording/launchRecording.ts +114 -0
- package/src/methods/recording/recordPauseTimer.ts +52 -0
- package/src/methods/recording/recordResumeTimer.ts +92 -0
- package/src/methods/recording/recordStartTimer.ts +106 -0
- package/src/methods/recording/recordUpdateTimer.ts +49 -0
- package/src/methods/recording/startRecording.ts +268 -0
- package/src/methods/recording/stopRecording.ts +124 -0
- package/src/methods/recording/updateRecording.ts +245 -0
- package/src/methods/requests/index.ts +1 -0
- package/src/methods/requests/launchRequests.ts +25 -0
- package/src/methods/requests/respondToRequests.ts +108 -0
- package/src/methods/settings/index.ts +2 -0
- package/src/methods/settings/launchSettings.ts +25 -0
- package/src/methods/settings/modifySettings.ts +99 -0
- package/src/methods/stream/clickVideo.ts +337 -0
- package/src/methods/stream/index.ts +3 -0
- package/src/methods/stream/switchAudio.ts +73 -0
- package/src/methods/stream/switchVideo.ts +148 -0
- package/src/methods/stream/switchVideoAlt.ts +152 -0
- package/src/methods/utils/checkLimitsAndMakeRequest.ts +103 -0
- package/src/methods/utils/validateAlphanumeric.ts +41 -0
- package/src/methods/waiting/index.ts +1 -0
- package/src/methods/waiting/launchWaiting.ts +26 -0
- package/src/methods/waiting/respondToWaiting.ts +82 -0
- package/src/methods/welcome/handleWelcomeRequest.ts +189 -0
- package/src/methods/welcome/index.ts +5 -0
- package/src/methods/whiteboard/handleStartWhiteboard.ts +65 -0
- package/src/methods/whiteboard/handleStopWhiteboard.ts +48 -0
- package/src/methods/whiteboard/index.ts +4 -0
- package/src/methods/whiteboard/launchConfigureWhiteboard.ts +29 -0
- package/src/producers/producerEmits/joinConRoom.ts +153 -0
- package/src/sockets/SocketManager.ts +232 -0
- package/src/types/shared-base-types.ts +752 -0
- package/src/types/types.ts +84 -0
package/package.json
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mediasfu-shared",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Framework-agnostic shared logic for MediaSFU - works with React, Vue, Angular, Svelte, and any JavaScript framework",
|
|
5
|
+
"main": "dist/index.cjs",
|
|
6
|
+
"module": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
},
|
|
15
|
+
"./consumers": {
|
|
16
|
+
"types": "./dist/consumers/index.d.ts",
|
|
17
|
+
"import": "./dist/consumers/index.js",
|
|
18
|
+
"require": "./dist/consumers/index.cjs"
|
|
19
|
+
},
|
|
20
|
+
"./methods": {
|
|
21
|
+
"types": "./dist/methods/index.d.ts",
|
|
22
|
+
"import": "./dist/methods/index.js",
|
|
23
|
+
"require": "./dist/methods/index.cjs"
|
|
24
|
+
},
|
|
25
|
+
"./types": {
|
|
26
|
+
"types": "./dist/types/index.d.ts",
|
|
27
|
+
"import": "./dist/types/index.js",
|
|
28
|
+
"require": "./dist/types/index.cjs"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"dist",
|
|
33
|
+
"src",
|
|
34
|
+
"README.md",
|
|
35
|
+
"LICENSE"
|
|
36
|
+
],
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "tsc && vite build",
|
|
39
|
+
"dev": "vite build --watch",
|
|
40
|
+
"type-check": "tsc --noEmit"
|
|
41
|
+
},
|
|
42
|
+
"keywords": [
|
|
43
|
+
"mediasfu",
|
|
44
|
+
"shared",
|
|
45
|
+
"webrtc",
|
|
46
|
+
"video-conferencing",
|
|
47
|
+
"breakout-rooms",
|
|
48
|
+
"screen-sharing",
|
|
49
|
+
"recording",
|
|
50
|
+
"framework-agnostic",
|
|
51
|
+
"typescript"
|
|
52
|
+
],
|
|
53
|
+
"author": "MediaSFU",
|
|
54
|
+
"license": "MIT",
|
|
55
|
+
"repository": {
|
|
56
|
+
"type": "git",
|
|
57
|
+
"url": "https://github.com/MediaSFU/MediaSFU-Shared"
|
|
58
|
+
},
|
|
59
|
+
"homepage": "https://github.com/MediaSFU/MediaSFU-Shared",
|
|
60
|
+
"bugs": {
|
|
61
|
+
"url": "https://github.com/MediaSFU/MediaSFU-Shared/issues",
|
|
62
|
+
"email": "info@mediasfu.com"
|
|
63
|
+
},
|
|
64
|
+
"peerDependencies": {
|
|
65
|
+
"mediasoup-client": "^3.16.0",
|
|
66
|
+
"socket.io-client": "^4.8.0"
|
|
67
|
+
},
|
|
68
|
+
"dependencies": {
|
|
69
|
+
"universal-cookie": "^7.2.2"
|
|
70
|
+
},
|
|
71
|
+
"devDependencies": {
|
|
72
|
+
"mediasoup-client": "^3.16.0",
|
|
73
|
+
"socket.io-client": "^4.8.0",
|
|
74
|
+
"typescript": "^5.9.3",
|
|
75
|
+
"vite": "^7.1.9",
|
|
76
|
+
"vite-plugin-dts": "^4.3.0"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import * as mediasoupClient from "mediasoup-client";
|
|
2
|
+
import type { RtpCapabilities, Device } from 'mediasoup-client/lib/types';
|
|
3
|
+
|
|
4
|
+
export interface CreateDeviceClientOptions {
|
|
5
|
+
rtpCapabilities: RtpCapabilities | null;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
// Export the type definition for the function
|
|
10
|
+
export type CreateDeviceClientType = (options: CreateDeviceClientOptions) => Promise<Device | null>;
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Creates a mediasoup client device with the provided RTP capabilities.
|
|
15
|
+
*
|
|
16
|
+
* @param {CreateDeviceClientOptions} options - The options for creating the device client.
|
|
17
|
+
* @param {RTPCapabilities} options.rtpCapabilities - The RTP capabilities required for the device.
|
|
18
|
+
* @returns {Promise<Device | null>} A promise that resolves to the created Device or null if creation fails.
|
|
19
|
+
* @throws {Error} Throws an error if the required parameters are not provided or if device creation is not supported.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* const device = await createDeviceClient({ rtpCapabilities });
|
|
23
|
+
* if (device) {
|
|
24
|
+
* console.log("Device created successfully");
|
|
25
|
+
* } else {
|
|
26
|
+
* console.log("Failed to create device");
|
|
27
|
+
* }
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
export const createDeviceClient = async ({
|
|
31
|
+
rtpCapabilities
|
|
32
|
+
}: CreateDeviceClientOptions): Promise<Device | null> => {
|
|
33
|
+
try {
|
|
34
|
+
// Validate input parameters
|
|
35
|
+
if (!rtpCapabilities) {
|
|
36
|
+
throw new Error(
|
|
37
|
+
"Both rtpCapabilities and mediasoupClient must be provided."
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Create a mediasoup client device
|
|
42
|
+
const device: (Device | null) = new mediasoupClient.Device();
|
|
43
|
+
|
|
44
|
+
// Remove orientation capabilities
|
|
45
|
+
rtpCapabilities.headerExtensions = rtpCapabilities!.headerExtensions!.filter(
|
|
46
|
+
(ext) => ext.uri !== "urn:3gpp:video-orientation"
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
// Load the provided RTP capabilities into the device
|
|
50
|
+
await device!.load({
|
|
51
|
+
routerRtpCapabilities: rtpCapabilities,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
return device;
|
|
55
|
+
} catch ( error ) {
|
|
56
|
+
// Handle specific errors, e.g., UnsupportedError
|
|
57
|
+
if ( error as Error && (error as Error).name === "UnsupportedError" ) {
|
|
58
|
+
// Handle unsupported device creation
|
|
59
|
+
console.error("Device creation is not supported by this browser.");
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
throw error; // Propagate other errors
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Stub export for addVideosGrid
|
|
2
|
+
// This is a React component in the original and not needed for the shared package
|
|
3
|
+
|
|
4
|
+
export interface AddVideosGridParameters {
|
|
5
|
+
[key: string]: any;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface AddVideosGridOptions {
|
|
9
|
+
parameters: AddVideosGridParameters;
|
|
10
|
+
[key: string]: any; // Accept any additional properties
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type AddVideosGridType = (options: AddVideosGridOptions) => Promise<void>;
|
|
14
|
+
|
|
15
|
+
export const addVideosGrid: AddVideosGridType = async () => {
|
|
16
|
+
// Stub implementation - actual logic handled in framework-specific packages
|
|
17
|
+
console.warn('addVideosGrid called on shared package - should be implemented in framework package');
|
|
18
|
+
};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { EventType } from '../types/types';
|
|
2
|
+
|
|
3
|
+
export interface AutoAdjustOptions {
|
|
4
|
+
n: number;
|
|
5
|
+
eventType: EventType;
|
|
6
|
+
shareScreenStarted: boolean;
|
|
7
|
+
shared: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type AutoAdjustType = (options: AutoAdjustOptions) => Promise<number[]>;
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Adjusts values based on the provided options and the number of participants.
|
|
15
|
+
*
|
|
16
|
+
* @function
|
|
17
|
+
* @async
|
|
18
|
+
* @param {AutoAdjustOptions} options - The options for auto adjustment.
|
|
19
|
+
* @param {number} options.n - The number of participants.
|
|
20
|
+
* @param {string} options.eventType - The type of event (e.g., 'broadcast', 'chat', 'conference').
|
|
21
|
+
* @param {boolean} options.shareScreenStarted - Indicates if screen sharing has started.
|
|
22
|
+
* @param {boolean} options.shared - Indicates if something is shared.
|
|
23
|
+
*
|
|
24
|
+
* @returns {Promise<number[]>} A promise that resolves to an array containing the adjusted values.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* import { autoAdjust } from 'mediasfu-reactjs';
|
|
28
|
+
*
|
|
29
|
+
* const options = {
|
|
30
|
+
* n: 10,
|
|
31
|
+
* eventType: 'conference',
|
|
32
|
+
* shareScreenStarted: false,
|
|
33
|
+
* shared: false,
|
|
34
|
+
* };
|
|
35
|
+
*
|
|
36
|
+
* autoAdjust(options)
|
|
37
|
+
* .then(values => {
|
|
38
|
+
* console.log('Adjusted values:', values);
|
|
39
|
+
* })
|
|
40
|
+
* .catch(error => {
|
|
41
|
+
* console.error('Error adjusting values:', error);
|
|
42
|
+
* });
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
export async function autoAdjust({
|
|
46
|
+
n,
|
|
47
|
+
eventType, shareScreenStarted, shared
|
|
48
|
+
}: AutoAdjustOptions): Promise<number[]> {
|
|
49
|
+
|
|
50
|
+
// Default values
|
|
51
|
+
let val1 = 6;
|
|
52
|
+
let val2 = 12 - val1;
|
|
53
|
+
|
|
54
|
+
// Adjust values based on eventType and other conditions
|
|
55
|
+
if (eventType === 'broadcast') {
|
|
56
|
+
val1 = 0;
|
|
57
|
+
val2 = 12 - val1;
|
|
58
|
+
} else if (
|
|
59
|
+
eventType === 'chat' ||
|
|
60
|
+
(eventType === 'conference' && !(shareScreenStarted || shared))
|
|
61
|
+
) {
|
|
62
|
+
val1 = 12;
|
|
63
|
+
val2 = 12 - val1;
|
|
64
|
+
} else {
|
|
65
|
+
if (shareScreenStarted || shared) {
|
|
66
|
+
val2 = 10;
|
|
67
|
+
val1 = 12 - val2;
|
|
68
|
+
} else {
|
|
69
|
+
// Adjust values based on the number of participants (n)
|
|
70
|
+
if (n === 0) {
|
|
71
|
+
val1 = 1;
|
|
72
|
+
val2 = 12 - val1;
|
|
73
|
+
} else if (n >= 1 && n < 4) {
|
|
74
|
+
val1 = 4;
|
|
75
|
+
val2 = 12 - val1;
|
|
76
|
+
} else if (n >= 4 && n < 6) {
|
|
77
|
+
val1 = 6;
|
|
78
|
+
val2 = 12 - val1;
|
|
79
|
+
} else if (n >= 6 && n < 9) {
|
|
80
|
+
val1 = 6;
|
|
81
|
+
val2 = 12 - val1;
|
|
82
|
+
} else if (n >= 9 && n < 12) {
|
|
83
|
+
val1 = 6;
|
|
84
|
+
val2 = 12 - val1;
|
|
85
|
+
} else if (n >= 12 && n < 20) {
|
|
86
|
+
val1 = 8;
|
|
87
|
+
val2 = 12 - val1;
|
|
88
|
+
} else if (n >= 20 && n < 50) {
|
|
89
|
+
val1 = 8;
|
|
90
|
+
val2 = 12 - val1;
|
|
91
|
+
} else {
|
|
92
|
+
val1 = 10;
|
|
93
|
+
val2 = 12 - val1;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Return an array with adjusted values
|
|
99
|
+
return [val1, val2];
|
|
100
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export interface CalculateRowsAndColumnsOptions {
|
|
2
|
+
n: number;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
// Export the type definition for the function
|
|
6
|
+
export type CalculateRowsAndColumnsType = (options: CalculateRowsAndColumnsOptions) => [number, number];
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Calculates the number of rows and columns needed to display a given number of items in a grid.
|
|
10
|
+
*
|
|
11
|
+
* @function
|
|
12
|
+
* @param {CalculateRowsAndColumnsOptions} options - The options for calculating rows and columns.
|
|
13
|
+
* @param {number} options.n - The number of items to display.
|
|
14
|
+
* @returns {[number, number]} A tuple containing the number of rows and columns.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* import { calculateRowsAndColumns } from 'mediasfu-reactjs';
|
|
18
|
+
*
|
|
19
|
+
* const options = {
|
|
20
|
+
* n: 10,
|
|
21
|
+
* };
|
|
22
|
+
*
|
|
23
|
+
* const [rows, cols] = calculateRowsAndColumns(options);
|
|
24
|
+
* console.log(`Rows: ${rows}, Columns: ${cols}`); // Outputs: Rows: 4, Columns: 3
|
|
25
|
+
*/
|
|
26
|
+
export function calculateRowsAndColumns({ n }: CalculateRowsAndColumnsOptions): [number, number] {
|
|
27
|
+
// Calculate the square root of n
|
|
28
|
+
const sqrt = Math.sqrt(n);
|
|
29
|
+
|
|
30
|
+
// Initialize columns based on the floor of the square root
|
|
31
|
+
let cols = Math.floor(sqrt);
|
|
32
|
+
|
|
33
|
+
// Calculate the number of rows needed to display n videos
|
|
34
|
+
let rows = Math.ceil(n / cols);
|
|
35
|
+
|
|
36
|
+
// Calculate the product of rows and columns
|
|
37
|
+
let prod = rows * cols;
|
|
38
|
+
|
|
39
|
+
// Adjust rows and columns until the product is greater than or equal to n
|
|
40
|
+
while (prod < n) {
|
|
41
|
+
if (cols < rows) {
|
|
42
|
+
cols++;
|
|
43
|
+
} else {
|
|
44
|
+
rows++;
|
|
45
|
+
}
|
|
46
|
+
prod = rows * cols;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Return an array with the calculated number of rows and columns
|
|
50
|
+
return [rows, cols];
|
|
51
|
+
}
|